Added pahe extractor

This commit is contained in:
kodjomoustapha
2024-03-02 16:12:06 +01:00
parent 7a7e18d40e
commit 7e0f7033e3
2 changed files with 115 additions and 21 deletions

View File

@@ -60,9 +60,7 @@ class AnimePahe extends MProvider {
MManga anime = MManga(); MManga anime = MManga();
final id = substringBefore(substringAfterLast(url, "?anime_id="), "&name="); final id = substringBefore(substringAfterLast(url, "?anime_id="), "&name=");
final name = substringAfterLast(url, "&name="); final name = substringAfterLast(url, "&name=");
print(name);
final session = await getSession(name, id); final session = await getSession(name, id);
print(session);
final res = final res =
(await client.get(Uri.parse("$baseUrl/anime/$session?anime_id=$id"))) (await client.get(Uri.parse("$baseUrl/anime/$session?anime_id=$id")))
.body; .body;
@@ -134,35 +132,125 @@ class AnimePahe extends MProvider {
@override @override
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
final res = (await client.get(Uri.parse("$baseUrl$url"))); final res = (await client.get(Uri.parse("$baseUrl$url")));
final document = parseHtml(res.body); final document = parseHtml(res.body);
final downloadLinks = document.select("div#pickDownload > a");
final buttons = document.select("div#resolutionMenu > button"); final buttons = document.select("div#resolutionMenu > button");
List<MVideo> videos = []; List<MVideo> videos = [];
for (var i = 0; i < buttons.length; i++) { for (var i = 0; i < buttons.length; i++) {
final btn = buttons[i]; final btn = buttons[i];
final kwikLink = btn.attr("data-src"); final kwikLink = btn.attr("data-src");
final quality = btn.text; final quality = btn.text;
final ress = (await client.get(Uri.parse(kwikLink), final paheWinLink = downloadLinks[i].attr("href");
headers: {"Referer": "https://animepahe.com"})); if (getPreferenceValue(source.id, "preffered_link_type")) {
final script = substringAfterLast( final noRedirectClient =
xpath(ress.body, '//script[contains(text(),"eval(function")]/text()') Client(source, json.encode({"followRedirects": false}));
.first, final kwikHeaders =
"eval(function("); (await noRedirectClient.get(Uri.parse("${paheWinLink}/i"))).headers;
final videoUrl = substringBefore( final kwikUrl =
substringAfter( "https://${substringAfterLast(getMapValue(json.encode(kwikHeaders), "location"), "https://")}";
unpackJsAndCombine("eval(function($script"), "const source=\\'"), final reskwik = (await client
"\\';"); .get(Uri.parse(kwikUrl), headers: {"Referer": "https://kwik.cx/"}));
MVideo video = MVideo(); final matches = RegExp(r'\("(\S+)",\d+,"(\S+)",(\d+),(\d+)')
video .firstMatch(reskwik.body);
..url = videoUrl final token = decrypt(matches!.group(1)!, matches.group(2)!,
..originalUrl = videoUrl matches.group(3)!, int.parse(matches.group(4)!));
..quality = quality final url = RegExp(r'action="([^"]+)"').firstMatch(token)!.group(1)!;
..headers = {"referer": "https://kwik.cx"}; final tok = RegExp(r'value="([^"]+)"').firstMatch(token)!.group(1)!;
videos.add(video); var code = 419;
var tries = 0;
String location = "";
while (code != 302 && tries < 20) {
String cookie =
getMapValue(json.encode(res.request.headers), "cookie");
cookie +=
"; ${getMapValue(json.encode(reskwik.headers), "set-cookie").replaceAll("path=/;", "")}";
final resNo =
await Client(source, json.encode({"followRedirects": false}))
.post(Uri.parse(url), headers: {
"referer": reskwik.request.url.toString(),
"cookie": cookie,
"user-agent":
getMapValue(json.encode(res.request.headers), "user-agent")
}, body: {
"_token": tok
});
code = resNo.statusCode;
tries++;
location = getMapValue(json.encode(resNo.headers), "location");
}
if (tries > 19) {
throw ("Failed to extract the stream uri from kwik.");
}
MVideo video = MVideo();
video
..url = location
..originalUrl = location
..quality = quality;
videos.add(video);
} else {
final ress = (await client.get(Uri.parse(kwikLink),
headers: {"Referer": "https://animepahe.com"}));
final script = substringAfterLast(
xpath(ress.body,
'//script[contains(text(),"eval(function")]/text()')
.first,
"eval(function(");
final videoUrl = substringBefore(
substringAfter(unpackJsAndCombine("eval(function($script"),
"const source=\\'"),
"\\';");
MVideo video = MVideo();
video
..url = videoUrl
..originalUrl = videoUrl
..quality = quality
..headers = {"referer": "https://kwik.cx"};
videos.add(video);
}
} }
return sortVideos(videos); return sortVideos(videos);
} }
String getString(String ctn, int sep) {
int b = 10;
String cm =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/";
final n = cm.substring(0, b);
double mx = 0;
for (var index = 0; index < ctn.length; index++) {
mx += (int.tryParse(ctn[ctn.length - index - 1], radix: 10) ?? 0.0)
.toInt() *
(pow(sep, index));
}
var m = '';
while (mx > 0) {
m = n[(mx % b).toInt()] + m;
mx = (mx - (mx % b)) / b;
}
return m.isNotEmpty ? m : '0';
}
String decrypt(String fS, String key, String v1, int v2) {
var html = "";
var i = 0;
final ld = int.parse(v1);
while (i < fS.length) {
var s = "";
while (fS[i] != key[v2]) {
s += fS[i];
i++;
}
for (var index = 0; index < key.length; index++) {
s = s.replaceAll(key[index], index.toString());
}
html += String.fromCharCode(int.parse(getString(s, v2)) - ld);
i++;
}
return html;
}
List<MVideo> sortVideos(List<MVideo> videos) { List<MVideo> sortVideos(List<MVideo> videos) {
String quality = getPreferenceValue(source.id, "preferred_quality"); String quality = getPreferenceValue(source.id, "preferred_quality");
@@ -208,6 +296,12 @@ class AnimePahe extends MProvider {
"https://animepahe.ru", "https://animepahe.ru",
"https://animepahe.org" "https://animepahe.org"
]), ]),
SwitchPreferenceCompat(
key: "preffered_link_type",
title: "Use HLS links",
summary:
"Enable this if you are having Cloudflare issues.\n|Note that this will break the ability to seek inside of the video unless the episode is downloaded in advance.",
value: false),
ListPreference( ListPreference(
key: "preferred_quality", key: "preferred_quality",
title: "Preferred Quality", title: "Preferred Quality",

View File

@@ -1,7 +1,7 @@
import '../../../../model/source.dart'; import '../../../../model/source.dart';
Source get animepaheSource => _animepaheSource; Source get animepaheSource => _animepaheSource;
const _animepaheVersion = "0.0.25"; const _animepaheVersion = "0.0.3";
const _animepaheSourceCodeUrl = const _animepaheSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/anime/src/en/animepahe/animepahe.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/anime/src/en/animepahe/animepahe.dart";
Source _animepaheSource = Source( Source _animepaheSource = Source(