+
This commit is contained in:
parent
55bd7209c3
commit
16e261ded3
4 changed files with 77 additions and 175 deletions
|
|
@ -2,7 +2,9 @@ import 'dart:convert';
|
|||
import 'package:dart_eval/dart_eval.dart';
|
||||
import 'package:dart_eval/dart_eval_bridge.dart';
|
||||
import 'package:dart_eval/stdlib/core.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:mangayomi/eval/model/m_bridge.dart';
|
||||
|
||||
/// dart_eval wrapper for [Client]
|
||||
class $Client implements $Instance {
|
||||
|
|
@ -236,84 +238,82 @@ class $Client implements $Instance {
|
|||
|
||||
static $Value? _get(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
final url = args[0]!.$value as Uri;
|
||||
final headers = (args[1]?.$value as Map<$Value, $Value>?)?.map(
|
||||
(key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
final headers = _toMapString(args[1]?.$value);
|
||||
|
||||
final request = (target!.$value as Client).get(url, headers: headers);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)));
|
||||
return $Future.wrap(request
|
||||
.then((value) => $Response.wrap(value.message()))
|
||||
.onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __post = $Function(_post);
|
||||
|
||||
static $Value? _post(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
final url = args[0]!.$value as Uri;
|
||||
final headers = (args[1]?.$value as Map<$Value, $Value>?)?.map(
|
||||
(key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
final body = args[2]?.$value as Object?;
|
||||
final headers = _toMapString(args[1]?.$value);
|
||||
final body = _toBodyObject(args[2]?.$value);
|
||||
final encoding = args[3]?.$value as Encoding?;
|
||||
|
||||
final request = (target!.$value as Client)
|
||||
.post(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)));
|
||||
return $Future.wrap(request
|
||||
.then((value) => $Response.wrap(value.message()))
|
||||
.onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __put = $Function(_put);
|
||||
|
||||
static $Value? _put(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
final url = args[0]!.$value as Uri;
|
||||
final headers = (args[1]?.$value as Map<$Value, $Value>?)?.map(
|
||||
(key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
final body = args[2]?.$value as Object?;
|
||||
final headers = _toMapString(args[1]?.$value);
|
||||
final body = _toBodyObject(args[2]?.$value);
|
||||
final encoding = args[3]?.$value as Encoding?;
|
||||
|
||||
final request = (target!.$value as Client)
|
||||
.put(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)));
|
||||
return $Future.wrap(request
|
||||
.then((value) => $Response.wrap(value.message()))
|
||||
.onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __delete = $Function(_delete);
|
||||
|
||||
static $Value? _delete(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
final url = args[0]!.$value as Uri;
|
||||
final headers = (args[1]?.$value as Map<$Value, $Value>?)?.map(
|
||||
(key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
final body = args[2]?.$value as Object?;
|
||||
final headers = _toMapString(args[1]?.$value);
|
||||
final body = _toBodyObject(args[2]?.$value);
|
||||
final encoding = args[3]?.$value as Encoding?;
|
||||
|
||||
final request = (target!.$value as Client)
|
||||
.delete(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)));
|
||||
return $Future.wrap(request
|
||||
.then((value) => $Response.wrap(value.message()))
|
||||
.onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __patch = $Function(_patch);
|
||||
|
||||
static $Value? _patch(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
final url = args[0]!.$value as Uri;
|
||||
final headers = (args[1]?.$value as Map<$Value, $Value>?)?.map(
|
||||
(key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
final body = args[2]?.$value as Object?;
|
||||
final headers = _toMapString(args[1]?.$value);
|
||||
final body = _toBodyObject(args[2]?.$value);
|
||||
final encoding = args[3]?.$value as Encoding?;
|
||||
|
||||
final request = (target!.$value as Client)
|
||||
.patch(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)));
|
||||
return $Future
|
||||
.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __read = $Function(_read);
|
||||
|
||||
static $Value? _read(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
final url = args[0]!.$value as Uri;
|
||||
final headers = (args[1]?.$value as Map<$Value, $Value>?)?.map(
|
||||
(key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
final headers = _toMapString(args[1]?.$value);
|
||||
|
||||
final request = (target!.$value as Client).read(url, headers: headers);
|
||||
return $Future.wrap(request.then((value) => $String(value)));
|
||||
return $Future
|
||||
.wrap(request.then((value) => $String(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __readBytes = $Function(_readBytes);
|
||||
|
|
@ -326,7 +326,8 @@ class $Client implements $Instance {
|
|||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
|
||||
final request = (target!.$value as Client).readBytes(url, headers: headers);
|
||||
return $Future.wrap(request.then((value) => $List.wrap(value)));
|
||||
return $Future
|
||||
.wrap(request.then((value) => $List.wrap(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __close = $Function(_close);
|
||||
|
|
@ -679,3 +680,50 @@ class $ByteStream implements $Instance {
|
|||
_superclass.$setProperty(runtime, identifier, value);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String>? _toMapString(Map<$Value, $Value>? value) {
|
||||
return value?.map((key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
}
|
||||
|
||||
Object? _toBodyObject(Object? value) {
|
||||
Object? body;
|
||||
if (value is Map<$Value, $Value>) {
|
||||
body = value.map((key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
} else if (value is List<$Value>) {
|
||||
body = value.map((e) => e.$reified).toList();
|
||||
} else {
|
||||
body = value;
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
extension FutureResponseExtension<T> on Future<T> {
|
||||
Future<T> onErrorMessage() {
|
||||
onError((error, stackTrace) {
|
||||
if (kDebugMode) {
|
||||
print("Http error: $error");
|
||||
}
|
||||
botToast(error.toString());
|
||||
throw error.toString();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
extension ResponseExtension on Response {
|
||||
Response message() {
|
||||
final cloudflare = [403, 503].contains(statusCode) &&
|
||||
["cloudflare-nginx", "cloudflare"].contains(headers["server"]);
|
||||
if (kDebugMode) {
|
||||
print(
|
||||
"${request?.method}: ${request?.url}, statusCode: $statusCode ${cloudflare ? "Failed to bypass Cloudflare" : ""}");
|
||||
}
|
||||
if (cloudflare) {
|
||||
botToast("$statusCode Failed to bypass Cloudflare");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -271,22 +271,6 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
|
|||
false),
|
||||
]),
|
||||
),
|
||||
'rapidCloudExtractor': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future, [
|
||||
BridgeTypeRef(CoreTypes.list, [$MVideo.$type])
|
||||
])),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'url',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false),
|
||||
BridgeParameter(
|
||||
'prefix',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false),
|
||||
]),
|
||||
),
|
||||
'sendVidExtractor': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future, [
|
||||
|
|
@ -834,10 +818,6 @@ class $MProvider extends MProvider with $Bridge<MProvider> {
|
|||
args[0]!.$value, args[1]?.$value, args[2]?.$value)
|
||||
.then((value) =>
|
||||
$List.wrap(value.map((e) => _toMVideo(e)).toList())))),
|
||||
"rapidCloudExtractor" => $Function((_, __, List<$Value?> args) => $Future
|
||||
.wrap(MBridge.rapidCloudExtractor(args[0]!.$value, args[1]?.$value)
|
||||
.then((value) =>
|
||||
$List.wrap(value.map((e) => _toMVideo(e)).toList())))),
|
||||
"sendVidExtractor" => $Function((_, __, List<$Value?> args) =>
|
||||
$Future.wrap(MBridge.sendVidExtractor(
|
||||
args[0]!.$value, args[1]?.$value, args[2]?.$value)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import 'package:mangayomi/services/anime_extractors/gogocdn_extractor.dart';
|
|||
import 'package:mangayomi/services/anime_extractors/mp4upload_extractor.dart';
|
||||
import 'package:mangayomi/services/anime_extractors/mytv_extractor.dart';
|
||||
import 'package:mangayomi/services/anime_extractors/okru_extractor.dart';
|
||||
import 'package:mangayomi/services/anime_extractors/rapidcloud_extractor.dart';
|
||||
import 'package:mangayomi/services/anime_extractors/sendvid_extractor.dart';
|
||||
import 'package:mangayomi/services/anime_extractors/sibnet_extractor.dart';
|
||||
import 'package:mangayomi/services/anime_extractors/streamlare_extractor.dart';
|
||||
|
|
@ -695,11 +694,6 @@ class MBridge {
|
|||
.videosFromUrl(url, prefix: prefix, suffix: suffix);
|
||||
}
|
||||
|
||||
static Future<List<Video>> rapidCloudExtractor(
|
||||
String url, String prefix) async {
|
||||
return await RapidCloudExtractor().videosFromUrl(url, prefix);
|
||||
}
|
||||
|
||||
static String encryptAESCryptoJS(String plainText, String passphrase) {
|
||||
return CryptoAES.encryptAESCryptoJS(plainText, passphrase);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,120 +0,0 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:async';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mangayomi/models/video.dart';
|
||||
import 'package:mangayomi/utils/cryptoaes/crypto_aes.dart';
|
||||
import 'package:mangayomi/utils/extensions.dart';
|
||||
|
||||
class RapidCloudExtractor {
|
||||
static const serverUrl = ['https://megacloud.tv', 'https://rapid-cloud.co'];
|
||||
static const sourceUrl = [
|
||||
'/embed-2/ajax/e-1/getSources?id=',
|
||||
'/ajax/embed-6-v2/getSources?id='
|
||||
];
|
||||
static const sourceSpliter = ['/e-1/', '/embed-6-v2/'];
|
||||
static const sourceKey = ['1', '6'];
|
||||
|
||||
final http.Client client = http.Client();
|
||||
|
||||
Future<(String, String)> cipherTextCleaner(String data, String type) async {
|
||||
final response = await http.get(Uri.parse(
|
||||
'https://raw.githubusercontent.com/Claudemirovsky/keys/e$type/key'));
|
||||
final List indexPairs = json.decode(response.body);
|
||||
|
||||
String password = '';
|
||||
String ciphertext = data;
|
||||
int currentIndex = 0;
|
||||
|
||||
for (List item in indexPairs) {
|
||||
final start = item.first + currentIndex;
|
||||
final end = start + item.last;
|
||||
final passSubstr = data.substring(start, end);
|
||||
password += passSubstr;
|
||||
ciphertext = ciphertext.replaceFirst(passSubstr, '');
|
||||
currentIndex += item[1] as int;
|
||||
}
|
||||
return (ciphertext, password);
|
||||
}
|
||||
|
||||
Future<String> decrypt(String ciphered, String type) async {
|
||||
final result = await cipherTextCleaner(ciphered, type);
|
||||
|
||||
final res = CryptoAES.decryptAESCryptoJS(result.$1, result.$2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<List<Video>> videosFromUrl(String url, String name) async {
|
||||
try {
|
||||
final type = url.startsWith('https://megacloud.tv') ? 0 : 1;
|
||||
final keyType = sourceKey[type];
|
||||
|
||||
final id = url.split(sourceSpliter[type]).last.split('?').first;
|
||||
final srcRes =
|
||||
await http.get(Uri.parse('${serverUrl[type]}${sourceUrl[type]}$id'));
|
||||
final data = Data.fromJson(json.decode(srcRes.body));
|
||||
|
||||
final decrypted = json.decode(await decrypt(data.sources!, keyType));
|
||||
final videoList = <Video>[];
|
||||
final fileURL = decrypted[0]["file"];
|
||||
const separator = "#EXT-X-STREAM-INF:";
|
||||
final masterPlaylistResponse = await http.get(Uri.parse(fileURL));
|
||||
final masterPlaylist = masterPlaylistResponse.body;
|
||||
if (masterPlaylist.contains(separator) && decrypted[0]["type"] == "hls") {
|
||||
for (var it
|
||||
in masterPlaylist.substringAfter(separator).split(separator)) {
|
||||
final quality =
|
||||
"${it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",").substringBefore("\n")}p";
|
||||
|
||||
var videoUrl = it.substringAfter("\n").substringBefore("\n");
|
||||
|
||||
if (!videoUrl.startsWith("http")) {
|
||||
videoUrl =
|
||||
"${fileURL.split("/").sublist(0, fileURL.split("/").length - 1).join("/")}/$videoUrl";
|
||||
}
|
||||
|
||||
videoList.add(Video(videoUrl, "$name - $quality", videoUrl,
|
||||
subtitles: data.tracks != null && data.tracks!.isEmpty
|
||||
? []
|
||||
: data.tracks!
|
||||
.map((e) =>
|
||||
Track(file: e.file ?? "", label: e.label ?? ""))
|
||||
.toList()));
|
||||
}
|
||||
} else {
|
||||
videoList.add(Video(fileURL, name, fileURL,
|
||||
subtitles: data.tracks != null && data.tracks!.isEmpty
|
||||
? []
|
||||
: data.tracks!
|
||||
.map((e) => Track(file: e.file ?? "", label: e.label ?? ""))
|
||||
.toList()));
|
||||
}
|
||||
return videoList;
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Data {
|
||||
String? sources;
|
||||
List<Track>? tracks;
|
||||
bool? encrypted;
|
||||
|
||||
Data({
|
||||
this.sources,
|
||||
this.tracks,
|
||||
this.encrypted,
|
||||
});
|
||||
|
||||
Data.fromJson(Map<String, dynamic> json) {
|
||||
sources = json['sources'];
|
||||
if (json['tracks'] != null) {
|
||||
tracks = <Track>[];
|
||||
json['tracks'].forEach((v) {
|
||||
tracks!.add(Track.fromJson(v));
|
||||
});
|
||||
}
|
||||
encrypted = json['encrypted'];
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue