This commit is contained in:
kodjomoustapha 2024-01-08 13:30:40 +01:00
parent 55bd7209c3
commit 16e261ded3
4 changed files with 77 additions and 175 deletions

View file

@ -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;
}
}

View file

@ -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)

View file

@ -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);
}

View file

@ -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'];
}
}