- remove cronet_http & cupertino_http - use rhttp package as default http client - fix #198 #200 crashes on multiple downloads - fix #162 #102 unable to download with forbidden characters in the name (as it is fixed this can cause reading problems concerning chapters downloaded before this version) - now supports all features on all platforms such as VPNs and HTTP proxies thanks to rhttp package
107 lines
4.1 KiB
Dart
107 lines
4.1 KiB
Dart
import 'dart:convert';
|
|
import 'package:html/dom.dart';
|
|
import 'package:http_interceptor/http_interceptor.dart';
|
|
import 'package:mangayomi/eval/dart/model/m_bridge.dart';
|
|
import 'package:mangayomi/models/video.dart';
|
|
import 'package:html/parser.dart' as parser;
|
|
import 'package:mangayomi/services/http/m_client.dart';
|
|
import 'package:mangayomi/utils/extensions/string_extensions.dart';
|
|
|
|
class GogoCdnExtractor {
|
|
final InterceptedClient client =
|
|
MClient.init(reqcopyWith: {'useDartHttpClient': true});
|
|
final JsonCodec json = const JsonCodec();
|
|
|
|
Future<List<Video>> videosFromUrl(String serverUrl) async {
|
|
try {
|
|
final response = await client.get(Uri.parse(serverUrl));
|
|
final document = response.body;
|
|
|
|
Document parsedResponse = parser.parse(response.body);
|
|
final iv = parsedResponse
|
|
.querySelector('div.wrapper')!
|
|
.attributes["class"]!
|
|
.split('container-')
|
|
.last;
|
|
|
|
final secretKey = parsedResponse
|
|
.querySelector('body[class]')!
|
|
.attributes["class"]!
|
|
.split('container-')
|
|
.last;
|
|
RegExp(r'container-(\d+)').firstMatch(document)?.group(1);
|
|
final decryptionKey =
|
|
RegExp(r'videocontent-(\d+)').firstMatch(document)?.group(1);
|
|
final encryptAjaxParams = MBridge.cryptoHandler(
|
|
RegExp(r'data-value="([^"]+)').firstMatch(document)?.group(1) ?? "",
|
|
iv,
|
|
secretKey,
|
|
false,
|
|
).substringAfter("&");
|
|
|
|
final httpUrl = Uri.parse(serverUrl);
|
|
final host = "https://${httpUrl.host}/";
|
|
final id = httpUrl.queryParameters['id'];
|
|
final encryptedId = MBridge.cryptoHandler(id ?? "", iv, secretKey, true);
|
|
|
|
final token = httpUrl.queryParameters['token'];
|
|
final qualityPrefix = token != null ? "Gogostream - " : "Vidstreaming - ";
|
|
|
|
final encryptAjaxUrl =
|
|
"${host}encrypt-ajax.php?id=$encryptedId&$encryptAjaxParams&alias=$id";
|
|
|
|
final encryptAjaxResponse = await client.get(Uri.parse(encryptAjaxUrl),
|
|
headers: {"X-Requested-With": "XMLHttpRequest"});
|
|
final jsonResponse = encryptAjaxResponse.body;
|
|
final data = json.decode(jsonResponse)["data"];
|
|
final decryptedData =
|
|
MBridge.cryptoHandler(data ?? "", iv, decryptionKey!, false);
|
|
final videoList = <Video>[];
|
|
final autoList = <Video>[];
|
|
final array = json.decode(decryptedData)["source"];
|
|
if (array != null &&
|
|
array is List &&
|
|
array.length == 1 &&
|
|
array[0]["type"] == "hls") {
|
|
final fileURL = array[0]["file"].toString().trim();
|
|
const separator = "#EXT-X-STREAM-INF:";
|
|
final masterPlaylistResponse = await client.get(Uri.parse(fileURL));
|
|
final masterPlaylist = masterPlaylistResponse.body;
|
|
if (masterPlaylist.contains(separator)) {
|
|
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, "$qualityPrefix$quality", videoUrl));
|
|
}
|
|
} else {
|
|
videoList.add(Video(fileURL, "${qualityPrefix}Original", fileURL));
|
|
}
|
|
} else if (array != null && array is List) {
|
|
for (var it in array) {
|
|
final label =
|
|
it["label"].toString().toLowerCase().trim().replaceAll(" ", "");
|
|
final fileURL = it["file"].toString().trim();
|
|
final videoHeaders = {"Referer": serverUrl};
|
|
if (label == "auto") {
|
|
autoList.add(Video(fileURL, "$qualityPrefix$label", fileURL,
|
|
headers: videoHeaders));
|
|
} else {
|
|
videoList.add(Video(fileURL, "$qualityPrefix$label", fileURL,
|
|
headers: videoHeaders));
|
|
}
|
|
}
|
|
}
|
|
return videoList + autoList;
|
|
} catch (e) {
|
|
return [];
|
|
}
|
|
}
|
|
}
|