Merge pull request #9 from kodjodevf/dev

Dev
This commit is contained in:
Moustapha Kodjo Amadou
2023-12-29 16:51:15 +01:00
committed by GitHub
11 changed files with 547 additions and 10 deletions

View File

@@ -333,7 +333,8 @@ See [`MDocument` model](https://github.com/kodjodevf/mangayomi/blob/main/lib/eva
- `String` substringBeforeLast(`String text`, `String pattern`) - `String` substringBeforeLast(`String text`, `String pattern`)
### Crypto utils ### Crypto utils
- `String` evalJs(`String code`); - `String` unpackJs(`String code`);
- `Future<String>` evalJs(`String code`);
- `String` deobfuscateJsPassword(`String inputString`) - `String` deobfuscateJsPassword(`String inputString`)
- `String` encryptAESCryptoJS(`String plainText`, `String passphrase`) - `String` encryptAESCryptoJS(`String plainText`, `String passphrase`)
- `String` decryptAESCryptoJS(`String encrypted`, `String passphrase`) - `String` decryptAESCryptoJS(`String encrypted`, `String passphrase`)

View File

@@ -168,7 +168,7 @@ class DataLifeEngine extends MProvider {
final res = await http('GET', json.encode({"url": url})); final res = await http('GET', json.encode({"url": url}));
final masterUrl = substringBefore( final masterUrl = substringBefore(
substringAfter( substringAfter(
substringAfter(substringAfter(evalJs(res), "sources:"), "file:\""), substringAfter(substringAfter(unpackJs(res), "sources:"), "file:\""),
"src:\""), "src:\""),
'"'); '"');
final masterPlaylistRes = final masterPlaylistRes =
@@ -203,7 +203,7 @@ class DataLifeEngine extends MProvider {
return []; return [];
} }
final masterUrl = final masterUrl =
substringBefore(substringAfter(evalJs(js.first), "{file:\""), "\"}"); substringBefore(substringAfter(unpackJs(js.first), "{file:\""), "\"}");
final masterPlaylistRes = final masterPlaylistRes =
await http('GET', json.encode({"url": masterUrl})); await http('GET', json.encode({"url": masterUrl}));
List<MVideo> videos = []; List<MVideo> videos = [];

View File

@@ -9,6 +9,7 @@ import 'src/ar/okanime/source.dart';
import 'src/en/aniwave/source.dart'; import 'src/en/aniwave/source.dart';
import 'src/en/dramacool/source.dart'; import 'src/en/dramacool/source.dart';
import 'src/en/gogoanime/source.dart'; import 'src/en/gogoanime/source.dart';
import 'src/fr/animesama/source.dart';
import 'src/hi/yomovies/source.dart'; import 'src/hi/yomovies/source.dart';
import 'src/en/kisskh/source.dart'; import 'src/en/kisskh/source.dart';
import 'src/en/uhdmovies/source.dart'; import 'src/en/uhdmovies/source.dart';
@@ -40,7 +41,8 @@ void main() {
...datalifeengineSourcesList, ...datalifeengineSourcesList,
filma24, filma24,
dramacoolSource, dramacoolSource,
yomoviesSource yomoviesSource,
animesamaSource
]; ];
final List<Map<String, dynamic>> jsonList = final List<Map<String, dynamic>> jsonList =
_sourcesList.map((source) => source.toJson()).toList(); _sourcesList.map((source) => source.toJson()).toList();

View File

@@ -204,7 +204,13 @@ class Aniwave extends MProvider {
final hosterSelection = preferenceHosterSelection(source.id); final hosterSelection = preferenceHosterSelection(source.id);
final typeSelection = preferenceTypeSelection(source.id); final typeSelection = preferenceTypeSelection(source.id);
if (typeSelection.contains(type.toLowerCase())) { if (typeSelection.contains(type.toLowerCase())) {
if (url.contains("mp4upload") && if (url.contains("vidplay") || url.contains("mcloud")) {
final hosterName =
url.contains("vidplay") ? "VidPlay" : "MyCloud";
if (hosterSelection.contains(hosterName.toLowerCase())) {
a = await vidsrcExtractor(url, hosterName, type);
}
} else if (url.contains("mp4upload") &&
hosterSelection.contains("mp4upload")) { hosterSelection.contains("mp4upload")) {
a = await mp4UploadExtractor(url, null, "", type); a = await mp4UploadExtractor(url, null, "", type);
} else if (url.contains("streamtape") && } else if (url.contains("streamtape") &&
@@ -305,6 +311,111 @@ class Aniwave extends MProvider {
return vrf; return vrf;
} }
Future<List<MVideo>> vidsrcExtractor(
String url, String name, String type) async {
List<String> keys = json.decode(await http(
'GET',
json.encode({
"url":
"https://raw.githubusercontent.com/Claudemirovsky/worstsource-keys/keys/keys.json"
})));
final host = Uri.parse(url).host;
final apiUrl = await getApiUrl(url, keys);
final headers = {
"Accept": "application/json, text/javascript, */*; q=0.01",
"Host": host,
"Referer": Uri.decodeComponent(url),
"X-Requested-With": "XMLHttpRequest"
};
final res =
await http('GET', json.encode({"url": apiUrl, "headers": headers}));
if (res == "error") return [];
String masterUrl =
((json.decode(res)['result']['sources'] as List<Map<String, dynamic>>)
.first)['file'];
final tracks = (json.decode(res)['result']['tracks'] as List)
.where((e) => e['kind'] == 'captions' ? true : false)
.toList();
List<MTrack> subtitles = [];
for (var sub in tracks) {
try {
MTrack subtitle = MTrack();
subtitle
..label = sub["label"]
..file = sub["file"];
subtitles.add(subtitle);
} catch (_) {}
}
List<MVideo> videoList = [];
final masterPlaylistRes =
await http('GET', json.encode({"url": masterUrl}));
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:")
.split("#EXT-X-STREAM-INF:")) {
final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
String videoUrl = substringBefore(substringAfter(it, "\n"), "\n");
if (!videoUrl.startsWith("http")) {
videoUrl =
"${masterUrl.split("/").sublist(0, masterUrl.split("/").length - 1).join("/")}/$videoUrl";
}
MVideo video = MVideo();
video
..url = videoUrl
..originalUrl = videoUrl
..quality = "$name - $type - $quality"
..headers = {"Referer": "https://$host/"}
..subtitles = subtitles;
videoList.add(video);
}
return videoList;
}
Future<String> getApiUrl(String url, List<String> keyList) async {
final host = Uri.parse(url).host;
final paramsToString = Uri.parse(url)
.queryParameters
.entries
.map((e) => "${e.key}=${e.value}")
.join("&");
var vidId = substringBefore(substringAfterLast(url, "/"), "?");
var encodedID = encodeID(vidId, keyList);
final apiSlug = await callFromFuToken(host, encodedID);
String apiUrlString = "";
apiUrlString += "https://$host/$apiSlug";
if (paramsToString.isNotEmpty) {
apiUrlString += "?$paramsToString";
}
return apiUrlString;
}
String encodeID(String vidId, List<String> keyList) {
var rc4Key1 = keyList[0];
var rc4Key2 = keyList[1];
final rc4 = rc4Encrypt(rc4Key1, vidId.codeUnits);
final rc41 = rc4Encrypt(rc4Key2, rc4);
return base64.encode(rc41).replaceAll("/", "_").trim();
}
Future<String> callFromFuToken(String host, String data) async {
final fuTokenScript =
await http('GET', json.encode({"url": "https://$host/futoken"}));
String js = "";
js += "(function";
js += substringBefore(
substringAfter(substringAfter(fuTokenScript, "window"), "function")
.replaceAll("jQuery.ajax(", ""),
"+location.search");
js += "}(\"$data\"))";
final jsRes = await evalJs(js);
if (jsRes == "error") return "";
return jsRes;
}
@override @override
List<dynamic> getFilterList(MSource source) { List<dynamic> getFilterList(MSource source) {
return [ return [

View File

@@ -13,4 +13,5 @@ Source _aniwave = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/anime/src/en/aniwave/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/anime/src/en/aniwave/icon.png",
sourceCodeUrl: _aniwaveCodeUrl, sourceCodeUrl: _aniwaveCodeUrl,
version: _aniwaveVersion, version: _aniwaveVersion,
appMinVerReq: "0.1.5",
isManga: false); isManga: false);

View File

@@ -0,0 +1,405 @@
import 'package:mangayomi/bridge_lib.dart';
import 'dart:convert';
class AnimeSama extends MProvider {
AnimeSama();
@override
Future<MPages> getPopular(MSource source, int page) async {
final data = {"url": "${source.baseUrl}/#$page"};
final doc = await http('GET', json.encode(data));
final regex = RegExp(r"""^\s*carteClassique\(\s*.*?\s*,\s*"(.*?)".*\)""",
multiLine: true);
var matches = regex.allMatches(doc).toList();
List<List<RegExpMatch>> chunks = chunked(matches, 5);
List<MManga> seasons = [];
if (page > 0 && page <= chunks.length) {
for (RegExpMatch match in chunks[page - 1]) {
seasons.addAll(await fetchAnimeSeasons(
"${source.baseUrl}/catalogue/${match.group(1)}"));
}
}
return MPages(seasons, page < chunks.length);
}
@override
Future<MPages> getLatestUpdates(MSource source, int page) async {
final res = await http('GET', json.encode({"url": source.baseUrl}));
var document = parseHtml(res);
final latest = document
.select("h2")
.where((MElement e) =>
e.outerHtml.toLowerCase().contains("derniers ajouts"))
.toList();
final seasonElements = (latest.first.nextElementSibling as MElement)
.select(".scrollBarStyled > div")
.toList();
List<MManga> seasons = [];
for (var seasonElement in seasonElements) {
seasons.addAll(await fetchAnimeSeasons(
(seasonElement as MElement).getElementsByTagName("a").first.getHref));
}
return MPages(seasons, false);
}
@override
Future<MPages> search(
MSource source, String query, int page, FilterList filterList) async {
final filters = filterList.filters;
final res = await http('GET',
json.encode({"url": "${source.baseUrl}/catalogue/listing_all.php"}));
var databaseElements = parseHtml(res).select(".cardListAnime");
List<MElement> elements = [];
elements = databaseElements
.where((MElement element) => element.select("h1, p").any((MElement e) =>
e.text.toLowerCase().contains(query.toLowerCase().trim())))
.toList();
for (var filter in filters) {
if (filter.type == "TypeFilter") {
final types = (filter.state as List).where((e) => e.state).toList();
elements = elements
.where((MElement element) =>
types.isEmpty ||
types.any((p) => element.className.contains(p.value)))
.toList();
} else if (filter.type == "LanguageFilter") {
final language = (filter.state as List).where((e) => e.state).toList();
elements = elements
.where((MElement element) =>
language.isEmpty ||
language.any((p) => element.className.contains(p.value)))
.toList();
} else if (filter.type == "GenreFilter") {
final included = (filter.state as List)
.where((e) => e.state == 1 ? true : false)
.toList();
final excluded = (filter.state as List)
.where((e) => e.state == 2 ? true : false)
.toList();
if (included.isNotEmpty) {
elements = elements
.where((MElement element) =>
included.every((p) => element.className.contains(p.value)))
.toList();
}
if (excluded.isNotEmpty) {
elements = elements
.where((MElement element) =>
excluded.every((p) => element.className.contains(p.value)))
.toList();
}
}
}
List<List<MElement>> chunks = chunked(elements, 5);
if (chunks.isEmpty) return MPages([], false);
List<MManga> seasons = [];
for (var seasonElement in chunks[page - 1]) {
seasons.addAll(await fetchAnimeSeasons(
seasonElement.getElementsByTagName("a").first.getHref));
}
return MPages(seasons, page < chunks.length);
}
@override
Future<MManga> getDetail(MSource source, String url) async {
var animeUrl =
"${source.baseUrl}${substringBeforeLast(Uri.parse(url).path, "/")}";
var movie =
int.tryParse(url.split("#").length >= 2 ? url.split("#")[1] : "");
List<Map<String, dynamic>> playersList = [];
for (var lang in ["vostfr", "vf"]) {
final players = await fetchPlayers("$animeUrl/$lang");
if (players.isNotEmpty) {
playersList.add({"players": players, "lang": lang});
}
}
int maxLength = 0;
for (var sublist in playersList) {
for (var innerList in sublist["players"]) {
if (innerList.length > maxLength) {
maxLength = innerList.length;
}
}
}
List<MChapter>? episodesList = [];
for (var episodeNumber = 0; episodeNumber < maxLength; episodeNumber++) {
List<String> langs = [];
List<Map<String, dynamic>> players = [];
for (var playerListt in playersList) {
for (var player in playerListt["players"]) {
if (player.length > episodeNumber) {
langs.add(playerListt["lang"]);
players.add(
{"lang": playerListt["lang"], "player": player[episodeNumber]});
}
}
}
MChapter episode = MChapter();
episode.name = movie == null ? 'Episode ${episodeNumber + 1}' : 'Film';
episode.scanlator = langs.toSet().toList().join(', ').toUpperCase();
episode.url = json.encode(players);
episodesList.add(episode);
}
MManga anime = MManga();
anime.chapters =
movie == null ? episodesList.reversed.toList() : [episodesList[movie]];
return anime;
}
@override
Future<List<MVideo>> getVideoList(MSource source, String url) async {
final players = json.decode(url);
List<MVideo> videos = [];
for (var player in players) {
String lang = (player["lang"] as String).toUpperCase();
String playerUrl = player["player"];
List<MVideo> a = [];
if (playerUrl.contains("sendvid")) {
a = await sendVidExtractor(playerUrl, null, lang);
} else if (playerUrl.contains("anime-sama.fr")) {
MVideo video = MVideo();
video
..url = playerUrl
..originalUrl = playerUrl
..quality = "${lang} - AS Player";
a = [video];
} else if (playerUrl.contains("sibnet.ru")) {
a = await sibnetExtractor(playerUrl, lang);
}
videos.addAll(a);
}
return sortVideos(videos, source.id);
}
@override
List<dynamic> getFilterList(MSource source) {
return [
GroupFilter("TypeFilter", "Type", [
CheckBoxFilter("Anime", "Anime"),
CheckBoxFilter("Film", "Film"),
CheckBoxFilter("Autres", "Autres"),
]),
GroupFilter("LanguageFilter", "Langue", [
CheckBoxFilter("VF", "VF"),
CheckBoxFilter("VOSTFR", "VOSTFR"),
]),
GroupFilter("GenreFilter", "Genre", [
TriStateFilter("Action", "Action"),
TriStateFilter("Aventure", "Aventure"),
TriStateFilter("Combats", "Combats"),
TriStateFilter("Comédie", "Comédie"),
TriStateFilter("Drame", "Drame"),
TriStateFilter("Ecchi", "Ecchi"),
TriStateFilter("École", "School-Life"),
TriStateFilter("Fantaisie", "Fantasy"),
TriStateFilter("Horreur", "Horreur"),
TriStateFilter("Isekai", "Isekai"),
TriStateFilter("Josei", "Josei"),
TriStateFilter("Mystère", "Mystère"),
TriStateFilter("Psychologique", "Psychologique"),
TriStateFilter("Quotidien", "Slice-of-Life"),
TriStateFilter("Romance", "Romance"),
TriStateFilter("Seinen", "Seinen"),
TriStateFilter("Shônen", "Shônen"),
TriStateFilter("Shôjo", "Shôjo"),
TriStateFilter("Sports", "Sports"),
TriStateFilter("Surnaturel", "Surnaturel"),
TriStateFilter("Tournois", "Tournois"),
TriStateFilter("Yaoi", "Yaoi"),
TriStateFilter("Yuri", "Yuri"),
]),
];
}
@override
List<dynamic> getSourcePreferences(MSource source) {
return [
ListPreference(
key: "preferred_quality",
title: "Qualité préférée",
summary: "",
valueIndex: 0,
entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080", "720", "480", "360"]),
ListPreference(
key: "voices_preference",
title: "Préférence des voix",
summary: "",
valueIndex: 0,
entries: ["Préférer VOSTFR", "Préférer VF"],
entryValues: ["vostfr", "vf"]),
];
}
Future<List<MManga>> fetchAnimeSeasons(String url) async {
final res = await http('GET', json.encode({"url": url}));
var document = parseHtml(res);
String animeName = document.getElementById("titreOeuvre")?.text ?? "";
var seasonRegex =
RegExp("^\\s*panneauAnime\\(\"(.*)\", \"(.*)\"\\)", multiLine: true);
var scripts = document
.select("h2 + p + div > script, h2 + div > script")
.map((MElement element) => element.text)
.toList()
.join("");
List<MManga> animeList = [];
List<RegExpMatch> seasonRegexReg = seasonRegex.allMatches(scripts).toList();
for (var animeIndex = 0; animeIndex < seasonRegexReg.length; animeIndex++) {
final seasonName = seasonRegexReg[animeIndex].group(1);
final seasonStem = seasonRegexReg[animeIndex].group(2);
if (seasonStem.toLowerCase().contains("film")) {
var moviesUrl = "$url/$seasonStem";
var movies = await fetchPlayers(moviesUrl);
if (movies.isNotEmpty) {
var movieNameRegex =
RegExp("^\\s*newSPF\\(\"(.*)\"\\);", multiLine: true);
var moviesDoc = await http('GET', json.encode({"url": moviesUrl}));
List<RegExpMatch> matches =
movieNameRegex.allMatches(moviesDoc).toList();
for (var i = 0; i < movies.length; i++) {
var title = "";
if (animeIndex == 0 && movies.length == 1) {
title = animeName;
} else if (matches.length > i) {
title = "$animeName ${(matches[i]).group(1)}";
} else if (movies.length == 1) {
title = "$animeName Film";
} else {
title = "$animeName Film ${i + 1}";
}
MManga anime = MManga();
anime.imageUrl = document.getElementById("coverOeuvre")?.getSrc;
anime.genre = (document.xpathFirst(
'//h2[contains(text(),"Genres")]/following-sibling::a/text()') ??
"")
.split(",");
anime.description = document.xpathFirst(
'//h2[contains(text(),"Synopsis")]/following-sibling::p/text()') ??
"";
anime.name = title;
anime.link = "$moviesUrl#$i";
anime.status = MStatus.completed;
animeList.add(anime);
}
}
} else {
MManga anime = MManga();
anime.imageUrl = document.getElementById("coverOeuvre")?.getSrc;
anime.genre = (document.xpathFirst(
'//h2[contains(text(),"Genres")]/following-sibling::a/text()') ??
"")
.split(",");
anime.description = document.xpathFirst(
'//h2[contains(text(),"Synopsis")]/following-sibling::p/text()') ??
"";
anime.name =
'$animeName ${substringBefore(seasonName, ',').replaceAll('"', "")}';
anime.link = "$url/$seasonStem";
animeList.add(anime);
}
}
return animeList;
}
Future<List<List<String>>> fetchPlayers(String url) async {
var docUrl = "$url/episodes.js";
List<List<String>> players = [];
var response = await http('GET', json.encode({"url": docUrl}));
if (response == "error") {
return [];
}
var sanitizedDoc = sanitizeEpisodesJs(response);
for (var i = 1; i <= 8; i++) {
final numPlayers = getPlayers("eps$i", sanitizedDoc);
if (numPlayers != null) players.add(numPlayers);
}
final asPlayers = getPlayers("epsAS", sanitizedDoc);
if (asPlayers != null) players.add(asPlayers);
if (players.isEmpty) return [];
List<List<String>> finalPlayers = [];
for (var i = 0; i <= players[0].length; i++) {
for (var playerList in players) {
if (playerList.length > i) {
finalPlayers.add(playerList);
}
}
}
return finalPlayers.toSet().toList();
}
List<String>? getPlayers(String playerName, String doc) {
var playerRegex = RegExp('$playerName\\s*=\\s*(\\[.*?\\])', dotAll: true);
var match = playerRegex.firstMatch(doc);
if (match == null) return null;
final regex = RegExp(r"""https?://[^\s\',\[\]]+""");
final matches = regex.allMatches(match.group(1));
List<String> urls = [];
for (var match in matches.toList()) {
urls.add((match as RegExpMatch).group(0).toString());
}
return urls;
}
String sanitizeEpisodesJs(String doc) {
return doc.replaceAll(
RegExp(r'(?<=\[|\,)\s*\"\s*(https?://[^\s\"]+)\s*\"\s*(?=\,|\])'), '');
}
List<List<dynamic>> chunked(List<dynamic> list, int size) {
List<List<dynamic>> chunks = [];
for (int i = 0; i < list.length; i += size) {
int end = list.length;
if (i + size < list.length) {
end = i + size;
}
chunks.add(list.sublist(i, end));
}
return chunks;
}
List<MVideo> sortVideos(List<MVideo> videos, int sourceId) {
String quality = getPreferenceValue(sourceId, "preferred_quality");
String voice = getPreferenceValue(sourceId, "voices_preference");
videos.sort((MVideo a, MVideo b) {
int qualityMatchA = 0;
if (a.quality.contains(quality) &&
a.quality.toLowerCase().contains(voice)) {
qualityMatchA = 1;
}
int qualityMatchB = 0;
if (b.quality.contains(quality) &&
b.quality.toLowerCase().contains(voice)) {
qualityMatchB = 1;
}
if (qualityMatchA != qualityMatchB) {
return qualityMatchB - qualityMatchA;
}
final regex = RegExp(r'(\d+)p');
final matchA = regex.firstMatch(a.quality);
final matchB = regex.firstMatch(b.quality);
final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0;
final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0;
return qualityNumB - qualityNumA;
});
return videos;
}
}
AnimeSama main() {
return AnimeSama();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,17 @@
import '../../../../model/source.dart';
Source get animesamaSource => _animesama;
const animesamaVersion = "0.0.1";
const animesamaCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/anime/src/fr/animesama/animesama.dart";
Source _animesama = Source(
name: "Anime-Sama",
baseUrl: "https://anime-sama.fr",
lang: "fr",
typeSource: "single",
iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/anime/src/fr/animesama/icon.png",
sourceCodeUrl: animesamaCodeUrl,
appMinVerReq: "0.1.5",
version: animesamaVersion,
isManga: false);

View File

@@ -362,7 +362,7 @@ class OtakuFr extends MProvider {
return []; return [];
} }
final masterUrl = final masterUrl =
substringBefore(substringAfter(evalJs(js.first), "{file:\""), "\"}"); substringBefore(substringAfter(unpackJs(js.first), "{file:\""), "\"}");
final masterPlaylistRes = final masterPlaylistRes =
await http('GET', json.encode({"url": masterUrl})); await http('GET', json.encode({"url": masterUrl}));
List<MVideo> videos = []; List<MVideo> videos = [];

View File

@@ -152,7 +152,7 @@ class NimeGami extends MProvider {
'//script[contains(text(), "eval") and contains(text(), "p,a,c,k,e,d")]/text()'); '//script[contains(text(), "eval") and contains(text(), "p,a,c,k,e,d")]/text()');
if (script.isNotEmpty) { if (script.isNotEmpty) {
final videoUrl = substringBefore( final videoUrl = substringBefore(
substringAfter(substringAfter(evalJs(script.first), "sources:[", ""), substringAfter(substringAfter(unpackJs(script.first), "sources:[", ""),
"file\":\"", ""), "file\":\"", ""),
'"'); '"');
if (videoUrl.isNotEmpty) { if (videoUrl.isNotEmpty) {

View File

@@ -181,7 +181,7 @@ class MangaHere extends MProvider {
res, "//script[contains(text(),'function(p,a,c,k,e,d)')]/text()") res, "//script[contains(text(),'function(p,a,c,k,e,d)')]/text()")
.first .first
.replaceAll("eval", ""); .replaceAll("eval", "");
String deobfuscatedScript = evalJs(script); String deobfuscatedScript = unpackJs(script);
int a = deobfuscatedScript.indexOf("newImgs=['") + 10; int a = deobfuscatedScript.indexOf("newImgs=['") + 10;
int b = deobfuscatedScript.indexOf("'];"); int b = deobfuscatedScript.indexOf("'];");
List<String> urls = deobfuscatedScript.substring(a, b).split("','"); List<String> urls = deobfuscatedScript.substring(a, b).split("','");
@@ -197,7 +197,7 @@ class MangaHere extends MProvider {
String secretKeyScript = res String secretKeyScript = res
.substring(secretKeyScriptLocation, secretKeyScriptEndLocation) .substring(secretKeyScriptLocation, secretKeyScriptEndLocation)
.replaceAll("eval", ""); .replaceAll("eval", "");
String secretKeyDeobfuscatedScript = evalJs(secretKeyScript); String secretKeyDeobfuscatedScript = unpackJs(secretKeyScript);
int secretKeyStartLoc = secretKeyDeobfuscatedScript.indexOf("'"); int secretKeyStartLoc = secretKeyDeobfuscatedScript.indexOf("'");
int secretKeyEndLoc = secretKeyDeobfuscatedScript.indexOf(";"); int secretKeyEndLoc = secretKeyDeobfuscatedScript.indexOf(";");
@@ -231,7 +231,7 @@ class MangaHere extends MProvider {
} }
} }
} }
String deobfuscatedScript = evalJs(responseText.replaceAll("eval", "")); String deobfuscatedScript = unpackJs(responseText.replaceAll("eval", ""));
int baseLinkStartPos = deobfuscatedScript.indexOf("pix=") + 5; int baseLinkStartPos = deobfuscatedScript.indexOf("pix=") + 5;
int baseLinkEndPos = int baseLinkEndPos =