dart format

This commit is contained in:
Moustapha Kodjo Amadou
2025-03-01 13:38:06 +01:00
parent 2388636458
commit 7d5e95679d
325 changed files with 6715 additions and 5516 deletions

View File

@@ -50,5 +50,5 @@ List<Source> dartAnimesourceList = [
animesvision, animesvision,
diziwatchSource, diziwatchSource,
aniZoneSource, aniZoneSource,
animeonlineninjaSource animeonlineninjaSource,
]; ];

View File

@@ -6,8 +6,10 @@ class DataLifeEngine extends MProvider {
MSource source; MSource source;
final Client client = final Client client = Client(
Client(source, json.encode({"useDartHttpClient": true})); source,
json.encode({"useDartHttpClient": true}),
);
@override @override
bool get supportsLatest => false; bool get supportsLatest => false;
@@ -18,8 +20,9 @@ class DataLifeEngine extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = final res =
(await client.get(Uri.parse("$baseUrl${getPath(source)}page/$page"))) (await client.get(
.body; Uri.parse("$baseUrl${getPath(source)}page/$page"),
)).body;
return animeFromElement(res); return animeFromElement(res);
} }
@@ -38,21 +41,25 @@ class DataLifeEngine extends MProvider {
final headers = { final headers = {
"Host": Uri.parse(baseUrl).host, "Host": Uri.parse(baseUrl).host,
"Origin": baseUrl, "Origin": baseUrl,
"Referer": "$baseUrl/" "Referer": "$baseUrl/",
}; };
final cleanQuery = query.replaceAll(" ", "+"); final cleanQuery = query.replaceAll(" ", "+");
if (page == 1) { if (page == 1) {
res = (await client.post( res =
(await client.post(
Uri.parse( Uri.parse(
"$baseUrl?do=search&subaction=search&story=$cleanQuery"), "$baseUrl?do=search&subaction=search&story=$cleanQuery",
headers: headers)) ),
.body; headers: headers,
)).body;
} else { } else {
res = (await client.post( res =
(await client.post(
Uri.parse( Uri.parse(
"$baseUrl?do=search&subaction=search&search_start=$page&full_search=0&result_from=11&story=$cleanQuery"), "$baseUrl?do=search&subaction=search&search_start=$page&full_search=0&result_from=11&story=$cleanQuery",
headers: headers)) ),
.body; headers: headers,
)).body;
} }
} else { } else {
String url = ""; String url = "";
@@ -76,8 +83,9 @@ class DataLifeEngine extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
String res = String res =
(await client.get(Uri.parse("$baseUrl${getUrlWithoutDomain(url)}"))) (await client.get(
.body; Uri.parse("$baseUrl${getUrlWithoutDomain(url)}"),
)).body;
MManga anime = MManga(); MManga anime = MManga();
final description = xpath(res, '//span[@itemprop="description"]/text()'); final description = xpath(res, '//span[@itemprop="description"]/text()');
anime.description = description.isNotEmpty ? description.first : ""; anime.description = description.isNotEmpty ? description.first : "";
@@ -96,9 +104,12 @@ class DataLifeEngine extends MProvider {
} }
} else { } else {
final doc = parseHtml(res); final doc = parseHtml(res);
final elements = doc final elements =
doc
.select(".hostsblock div:has(a)") .select(".hostsblock div:has(a)")
.where((MElement e) => e.outerHtml.contains("loadVideo('https://")) .where(
(MElement e) => e.outerHtml.contains("loadVideo('https://"),
)
.toList(); .toList();
if (elements.isNotEmpty) { if (elements.isNotEmpty) {
for (var element in elements) { for (var element in elements) {
@@ -110,8 +121,12 @@ class DataLifeEngine extends MProvider {
.replaceAll("vf", " VF"); .replaceAll("vf", " VF");
ep.url = element ep.url = element
.select("a") .select("a")
.map((MElement e) => substringBefore( .map(
substringAfter(e.attr('onclick'), "loadVideo('"), "')")) (MElement e) => substringBefore(
substringAfter(e.attr('onclick'), "loadVideo('"),
"')",
),
)
.toList() .toList()
.join(",") .join(",")
.replaceAll("/vd.php?u=", ""); .replaceAll("/vd.php?u=", "");
@@ -124,8 +139,12 @@ class DataLifeEngine extends MProvider {
ep.url = doc ep.url = doc
.select("a") .select("a")
.where((MElement e) => e.outerHtml.contains("loadVideo('https://")) .where((MElement e) => e.outerHtml.contains("loadVideo('https://"))
.map((MElement e) => substringBefore( .map(
substringAfter(e.attr('onclick'), "loadVideo('"), "')")) (MElement e) => substringBefore(
substringAfter(e.attr('onclick'), "loadVideo('"),
"')",
),
)
.toList() .toList()
.join(",") .join(",")
.replaceAll("/vd.php?u=", ""); .replaceAll("/vd.php?u=", "");
@@ -145,8 +164,12 @@ class DataLifeEngine extends MProvider {
List<MVideo> a = []; List<MVideo> a = [];
if (sUrl.contains("dood") || sUrl.contains("d000")) { if (sUrl.contains("dood") || sUrl.contains("d000")) {
a = await doodExtractor(sUrl, "DoodStream"); a = await doodExtractor(sUrl, "DoodStream");
} else if (["streamhide", "guccihide", "streamvid", "dhtpre"] } else if ([
.any((a) => sUrl.contains(a))) { "streamhide",
"guccihide",
"streamvid",
"dhtpre",
].any((a) => sUrl.contains(a))) {
a = await streamHideExtractor(sUrl); a = await streamHideExtractor(sUrl);
} else if (sUrl.contains("uqload")) { } else if (sUrl.contains("uqload")) {
a = await uqloadExtractor(sUrl); a = await uqloadExtractor(sUrl);
@@ -192,14 +215,17 @@ class DataLifeEngine extends MProvider {
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
final masterUrl = substringBefore( final masterUrl = substringBefore(
substringAfter( substringAfter(
substringAfter( substringAfter(substringAfter(unpackJs(res), "sources:"), "file:\""),
substringAfter(unpackJs(res), "sources:"), "file:\""), "src:\"",
"src:\""), ),
'"'); '"',
);
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
List<MVideo> videos = []; List<MVideo> videos = [];
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -226,12 +252,16 @@ class DataLifeEngine extends MProvider {
if (js.isEmpty) { if (js.isEmpty) {
return []; return [];
} }
final masterUrl = final masterUrl = substringBefore(
substringBefore(substringAfter(unpackJs(js.first), "{file:\""), "\"}"); substringAfter(unpackJs(js.first), "{file:\""),
"\"}",
);
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
List<MVideo> videos = []; List<MVideo> videos = [];
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -259,8 +289,10 @@ class DataLifeEngine extends MProvider {
return []; return [];
} }
final videoUrl = final videoUrl = substringBefore(
substringBefore(substringAfter(js.first, "sources: [\""), '"'); substringAfter(js.first, "sources: [\""),
'"',
);
MVideo video = MVideo(); MVideo video = MVideo();
video video
..url = videoUrl ..url = videoUrl
@@ -271,22 +303,23 @@ class DataLifeEngine extends MProvider {
} }
Future<List<MVideo>> vidmolyExtractor(String url) async { Future<List<MVideo>> vidmolyExtractor(String url) async {
final headers = { final headers = {'Referer': 'https://vidmoly.to'};
'Referer': 'https://vidmoly.to',
};
List<MVideo> videos = []; List<MVideo> videos = [];
final playListUrlResponse = (await client.get(Uri.parse(url))).body; final playListUrlResponse = (await client.get(Uri.parse(url))).body;
final playlistUrl = final playlistUrl =
RegExp(r'file:"(\S+?)"').firstMatch(playListUrlResponse)?.group(1) ?? RegExp(r'file:"(\S+?)"').firstMatch(playListUrlResponse)?.group(1) ??
""; "";
if (playlistUrl.isEmpty) return []; if (playlistUrl.isEmpty) return [];
final masterPlaylistRes = final masterPlaylistRes = await client.get(
await client.get(Uri.parse(playlistUrl), headers: headers); Uri.parse(playlistUrl),
headers: headers,
);
if (masterPlaylistRes.statusCode == 200) { if (masterPlaylistRes.statusCode == 200) {
for (var it for (var it in substringAfter(
in substringAfter(masterPlaylistRes.body, "#EXT-X-STREAM-INF:") masterPlaylistRes.body,
.split("#EXT-X-STREAM-INF:")) { "#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -321,7 +354,8 @@ class DataLifeEngine extends MProvider {
value: "https://wiflix-hd.vip", value: "https://wiflix-hd.vip",
dialogTitle: "Changer l'url de base", dialogTitle: "Changer l'url de base",
dialogMessage: "", dialogMessage: "",
text: "https://wiflix-hd.vip"), text: "https://wiflix-hd.vip",
),
if (source.name == "French Anime") if (source.name == "French Anime")
EditTextPreference( EditTextPreference(
key: "overrideBaseUrl", key: "overrideBaseUrl",
@@ -330,7 +364,8 @@ class DataLifeEngine extends MProvider {
value: "https://french-anime.com", value: "https://french-anime.com",
dialogTitle: "Changer l'url de base", dialogTitle: "Changer l'url de base",
dialogMessage: "", dialogMessage: "",
text: "https://french-anime.com"), text: "https://french-anime.com",
),
]; ];
} }
@@ -360,20 +395,20 @@ class DataLifeEngine extends MProvider {
SelectFilterOption("Seinen", "/genre/seinen/"), SelectFilterOption("Seinen", "/genre/seinen/"),
SelectFilterOption("Horreur", "/genre/horreur/"), SelectFilterOption("Horreur", "/genre/horreur/"),
SelectFilterOption("Tranche de vie", "/genre/tranchedevie/"), SelectFilterOption("Tranche de vie", "/genre/tranchedevie/"),
SelectFilterOption("Psychologique", "/genre/psychologique/") SelectFilterOption("Psychologique", "/genre/psychologique/"),
]), ]),
if (source.name == "French Anime") if (source.name == "French Anime")
SelectFilter("GenresFilter", "Genres", 0, [ SelectFilter("GenresFilter", "Genres", 0, [
SelectFilterOption("<Sélectionner>", ""), SelectFilterOption("<Sélectionner>", ""),
SelectFilterOption("Animes VF", "/animes-vf/"), SelectFilterOption("Animes VF", "/animes-vf/"),
SelectFilterOption("Animes VOSTFR", "/animes-vostfr/"), SelectFilterOption("Animes VOSTFR", "/animes-vostfr/"),
SelectFilterOption("Films VF et VOSTFR", "/films-vf-vostfr/") SelectFilterOption("Films VF et VOSTFR", "/films-vf-vostfr/"),
]), ]),
if (source.name == "Wiflix") if (source.name == "Wiflix")
SelectFilter("CategoriesFilter", "Catégories", 0, [ SelectFilter("CategoriesFilter", "Catégories", 0, [
SelectFilterOption("<Sélectionner>", ""), SelectFilterOption("<Sélectionner>", ""),
SelectFilterOption("Séries", "/serie-en-streaming/"), SelectFilterOption("Séries", "/serie-en-streaming/"),
SelectFilterOption("Films", "/film-en-streaming/") SelectFilterOption("Films", "/film-en-streaming/"),
]), ]),
if (source.name == "Wiflix") if (source.name == "Wiflix")
SelectFilter("GenresFilter", "Genres", 0, [ SelectFilter("GenresFilter", "Genres", 0, [
@@ -381,17 +416,25 @@ class DataLifeEngine extends MProvider {
SelectFilterOption("Action", "/film-en-streaming/action/"), SelectFilterOption("Action", "/film-en-streaming/action/"),
SelectFilterOption("Animation", "/film-en-streaming/animation/"), SelectFilterOption("Animation", "/film-en-streaming/animation/"),
SelectFilterOption( SelectFilterOption(
"Arts Martiaux", "/film-en-streaming/arts-martiaux/"), "Arts Martiaux",
"/film-en-streaming/arts-martiaux/",
),
SelectFilterOption("Aventure", "/film-en-streaming/aventure/"), SelectFilterOption("Aventure", "/film-en-streaming/aventure/"),
SelectFilterOption("Biopic", "/film-en-streaming/biopic/"), SelectFilterOption("Biopic", "/film-en-streaming/biopic/"),
SelectFilterOption("Comédie", "/film-en-streaming/comedie/"), SelectFilterOption("Comédie", "/film-en-streaming/comedie/"),
SelectFilterOption( SelectFilterOption(
"Comédie Dramatique", "/film-en-streaming/comedie-dramatique/"), "Comédie Dramatique",
"/film-en-streaming/comedie-dramatique/",
),
SelectFilterOption( SelectFilterOption(
"Épouvante Horreur", "/film-en-streaming/horreur/"), "Épouvante Horreur",
"/film-en-streaming/horreur/",
),
SelectFilterOption("Drame", "/film-en-streaming/drame/"), SelectFilterOption("Drame", "/film-en-streaming/drame/"),
SelectFilterOption( SelectFilterOption(
"Documentaire", "/film-en-streaming/documentaire/"), "Documentaire",
"/film-en-streaming/documentaire/",
),
SelectFilterOption("Espionnage", "/film-en-streaming/espionnage/"), SelectFilterOption("Espionnage", "/film-en-streaming/espionnage/"),
SelectFilterOption("Famille", "/film-en-streaming/famille/"), SelectFilterOption("Famille", "/film-en-streaming/famille/"),
SelectFilterOption("Fantastique", "/film-en-streaming/fantastique/"), SelectFilterOption("Fantastique", "/film-en-streaming/fantastique/"),
@@ -401,7 +444,9 @@ class DataLifeEngine extends MProvider {
SelectFilterOption("Policier", "/film-en-streaming/policier/"), SelectFilterOption("Policier", "/film-en-streaming/policier/"),
SelectFilterOption("Romance", "/film-en-streaming/romance/"), SelectFilterOption("Romance", "/film-en-streaming/romance/"),
SelectFilterOption( SelectFilterOption(
"Science-Fiction", "/film-en-streaming/science-fiction/"), "Science-Fiction",
"/film-en-streaming/science-fiction/",
),
SelectFilterOption("Spectacles", "/film-en-streaming/spectacles/"), SelectFilterOption("Spectacles", "/film-en-streaming/spectacles/"),
SelectFilterOption("Thriller", "/film-en-streaming/thriller/"), SelectFilterOption("Thriller", "/film-en-streaming/thriller/"),
SelectFilterOption("Western", "/film-en-streaming/western/"), SelectFilterOption("Western", "/film-en-streaming/western/"),

View File

@@ -7,13 +7,17 @@ const _datalifeengineSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/multisrc/datalifeengine/datalifeengine.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/multisrc/datalifeengine/datalifeengine.dart";
List<Source> get datalifeengineSourcesList => _datalifeengineSourcesList; List<Source> get datalifeengineSourcesList => _datalifeengineSourcesList;
List<Source> _datalifeengineSourcesList = [ List<Source> _datalifeengineSourcesList =
[
//French Anime (FR) //French Anime (FR)
frenchanimeSource, frenchanimeSource,
//Wiflix (FR) //Wiflix (FR)
wiflixSource, wiflixSource,
] ]
.map((e) => e .map(
(e) =>
e
..sourceCodeUrl = _datalifeengineSourceCodeUrl ..sourceCodeUrl = _datalifeengineSourceCodeUrl
..version = _datalifeengineVersion) ..version = _datalifeengineVersion,
)
.toList(); .toList();

View File

@@ -13,9 +13,12 @@ class DopeFlix extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = (await client.get(Uri.parse( final res =
"$baseUrl/${getPreferenceValue(source.id, "preferred_popular_page")}?page=$page"))) (await client.get(
.body; Uri.parse(
"$baseUrl/${getPreferenceValue(source.id, "preferred_popular_page")}?page=$page",
),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@@ -109,25 +112,32 @@ class DopeFlix extends MProvider {
final resS = final resS =
(await client.get(Uri.parse("$baseUrl/ajax/v2/tv/seasons/$id"))).body; (await client.get(Uri.parse("$baseUrl/ajax/v2/tv/seasons/$id"))).body;
final seasonIds = final seasonIds = xpath(
xpath(resS, '//a[@class="dropdown-item ss-item"]/@data-id'); resS,
final seasonNames = '//a[@class="dropdown-item ss-item"]/@data-id',
xpath(resS, '//a[@class="dropdown-item ss-item"]/text()'); );
final seasonNames = xpath(
resS,
'//a[@class="dropdown-item ss-item"]/text()',
);
for (int i = 0; i < seasonIds.length; i++) { for (int i = 0; i < seasonIds.length; i++) {
final seasonId = seasonIds[i]; final seasonId = seasonIds[i];
final seasonName = seasonNames[i]; final seasonName = seasonNames[i];
final html = (await client final html =
.get(Uri.parse("$baseUrl/ajax/v2/season/episodes/$seasonId"))) (await client.get(
.body; Uri.parse("$baseUrl/ajax/v2/season/episodes/$seasonId"),
)).body;
final epsHtmls = parseHtml(html).select("div.eps-item"); final epsHtmls = parseHtml(html).select("div.eps-item");
for (var epH in epsHtmls) { for (var epH in epsHtmls) {
final epHtml = epH.outerHtml; final epHtml = epH.outerHtml;
final episodeId = final episodeId =
xpath(epHtml, '//div[contains(@class,"eps-item")]/@data-id') xpath(
.first; epHtml,
'//div[contains(@class,"eps-item")]/@data-id',
).first;
final epNum = final epNum =
xpath(epHtml, '//div[@class="episode-number"]/text()').first; xpath(epHtml, '//div[@class="episode-number"]/text()').first;
final epName = xpath(epHtml, '//h3[@class="film-name"]/text()').first; final epName = xpath(epHtml, '//h3[@class="film-name"]/text()').first;
@@ -157,8 +167,10 @@ class DopeFlix extends MProvider {
final resSource = final resSource =
(await client.get(Uri.parse("$baseUrl/ajax/sources/$id"))).body; (await client.get(Uri.parse("$baseUrl/ajax/sources/$id"))).body;
final vidUrl = final vidUrl = substringBefore(
substringBefore(substringAfter(resSource, "\"link\":\""), "\""); substringAfter(resSource, "\"link\":\""),
"\"",
);
List<MVideo> a = []; List<MVideo> a = [];
String masterUrl = ""; String masterUrl = "";
String type = ""; String type = "";
@@ -168,10 +180,11 @@ class DopeFlix extends MProvider {
final id = substringBefore(substringAfter(vidUrl, "/embed-4/"), "?"); final id = substringBefore(substringAfter(vidUrl, "/embed-4/"), "?");
final serverUrl = substringBefore(vidUrl, "/embed"); final serverUrl = substringBefore(vidUrl, "/embed");
final resServer = (await client.get( final resServer =
(await client.get(
Uri.parse("$serverUrl/ajax/embed-4/getSources?id=$id"), Uri.parse("$serverUrl/ajax/embed-4/getSources?id=$id"),
headers: {"X-Requested-With": "XMLHttpRequest"})) headers: {"X-Requested-With": "XMLHttpRequest"},
.body; )).body;
final encrypted = getMapValue(resServer, "encrypted"); final encrypted = getMapValue(resServer, "encrypted");
String videoResJson = ""; String videoResJson = "";
@@ -192,10 +205,12 @@ class DopeFlix extends MProvider {
index += item.last; index += item.last;
} }
videoResJson = decryptAESCryptoJS(ciphertext, password); videoResJson = decryptAESCryptoJS(ciphertext, password);
masterUrl = ((json.decode(videoResJson) as List<Map<String, dynamic>>) masterUrl =
((json.decode(videoResJson) as List<Map<String, dynamic>>)
.first)['file']; .first)['file'];
type = ((json.decode(videoResJson) as List<Map<String, dynamic>>) type =
((json.decode(videoResJson) as List<Map<String, dynamic>>)
.first)['type']; .first)['type'];
} else { } else {
masterUrl = masterUrl =
@@ -207,7 +222,8 @@ class DopeFlix extends MProvider {
.first)['type']; .first)['type'];
} }
final tracks = (json.decode(resServer)['tracks'] as List) final tracks =
(json.decode(resServer)['tracks'] as List)
.where((e) => e['kind'] == 'captions' ? true : false) .where((e) => e['kind'] == 'captions' ? true : false)
.toList(); .toList();
List<MTrack> subtitles = []; List<MTrack> subtitles = [];
@@ -227,8 +243,10 @@ class DopeFlix extends MProvider {
final masterPlaylistRes = final masterPlaylistRes =
(await client.get(Uri.parse(masterUrl))).body; (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -264,13 +282,15 @@ class DopeFlix extends MProvider {
} }
Future<List<List<int>>> generateIndexPairs() async { Future<List<List<int>>> generateIndexPairs() async {
final res = (await client.get(Uri.parse( final res =
"https://rabbitstream.net/js/player/prod/e4-player.min.js"))) (await client.get(
.body; Uri.parse("https://rabbitstream.net/js/player/prod/e4-player.min.js"),
)).body;
String script = substringBefore(substringAfter(res, "const "), "()"); String script = substringBefore(substringAfter(res, "const "), "()");
script = script.substring(0, script.lastIndexOf(',')); script = script.substring(0, script.lastIndexOf(','));
final list = script final list =
script
.split(",") .split(",")
.map((String e) { .map((String e) {
String value = substringAfter(e, "="); String value = substringAfter(e, "=");
@@ -283,9 +303,10 @@ class DopeFlix extends MProvider {
.toList() .toList()
.skip(1) .skip(1)
.toList(); .toList();
return chunked(list, 2) return chunked(
.map((List<int> list) => list.reversed.toList()) list,
.toList(); 2,
).map((List<int> list) => list.reversed.toList()).toList();
} }
List<List<int>> chunked(List<int> list, int size) { List<List<int>> chunked(List<int> list, int size) {
@@ -316,7 +337,9 @@ class DopeFlix extends MProvider {
animeList.add(anime); animeList.add(anime);
} }
final pages = xpath( final pages = xpath(
res, '//ul[contains(@class,"pagination")]/li/a[@title="Next"]/@title'); res,
'//ul[contains(@class,"pagination")]/li/a[@title="Next"]/@title',
);
return MPages(animeList, pages.isNotEmpty); return MPages(animeList, pages.isNotEmpty);
} }
@@ -326,13 +349,13 @@ class DopeFlix extends MProvider {
SelectFilter("TypeFilter", "Type", 0, [ SelectFilter("TypeFilter", "Type", 0, [
SelectFilterOption("All", "all"), SelectFilterOption("All", "all"),
SelectFilterOption("Movies", "movies"), SelectFilterOption("Movies", "movies"),
SelectFilterOption("TV Shows", "tv") SelectFilterOption("TV Shows", "tv"),
]), ]),
SelectFilter("QualityFilter", "Quality", 0, [ SelectFilter("QualityFilter", "Quality", 0, [
SelectFilterOption("All", "all"), SelectFilterOption("All", "all"),
SelectFilterOption("HD", "HD"), SelectFilterOption("HD", "HD"),
SelectFilterOption("SD", "SD"), SelectFilterOption("SD", "SD"),
SelectFilterOption("CAM", "CAM") SelectFilterOption("CAM", "CAM"),
]), ]),
SelectFilter("ReleaseYearFilter", "Released at", 0, [ SelectFilter("ReleaseYearFilter", "Released at", 0, [
SelectFilterOption("All", "all"), SelectFilterOption("All", "all"),
@@ -343,7 +366,7 @@ class DopeFlix extends MProvider {
SelectFilterOption("2020", "2020"), SelectFilterOption("2020", "2020"),
SelectFilterOption("2019", "2019"), SelectFilterOption("2019", "2019"),
SelectFilterOption("2018", "2018"), SelectFilterOption("2018", "2018"),
SelectFilterOption("Older", "older-2018") SelectFilterOption("Older", "older-2018"),
]), ]),
SeparatorFilter(), SeparatorFilter(),
GroupFilter("GenresFilter", "Genre", [ GroupFilter("GenresFilter", "Genre", [
@@ -374,7 +397,7 @@ class DopeFlix extends MProvider {
CheckBoxFilter("TV Movie", "8"), CheckBoxFilter("TV Movie", "8"),
CheckBoxFilter("War", "17"), CheckBoxFilter("War", "17"),
CheckBoxFilter("War & Politics", "28"), CheckBoxFilter("War & Politics", "28"),
CheckBoxFilter("Western", "6") CheckBoxFilter("Western", "6"),
]), ]),
GroupFilter("CountriesFilter", "Countries", [ GroupFilter("CountriesFilter", "Countries", [
CheckBoxFilter("Argentina", "11"), CheckBoxFilter("Argentina", "11"),
@@ -412,7 +435,7 @@ class DopeFlix extends MProvider {
CheckBoxFilter("Taiwan", "119"), CheckBoxFilter("Taiwan", "119"),
CheckBoxFilter("Thailand", "57"), CheckBoxFilter("Thailand", "57"),
CheckBoxFilter("United Kingdom", "180"), CheckBoxFilter("United Kingdom", "180"),
CheckBoxFilter("United States of America", "129") CheckBoxFilter("United States of America", "129"),
]), ]),
]; ];
} }
@@ -427,7 +450,8 @@ class DopeFlix extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["dopebox.to", "dopebox.se"], entries: ["dopebox.to", "dopebox.se"],
entryValues: ["https://dopebox.to", "https://dopebox.se"]), entryValues: ["https://dopebox.to", "https://dopebox.se"],
),
if (source.name == "SFlix") if (source.name == "SFlix")
ListPreference( ListPreference(
key: "preferred_domain", key: "preferred_domain",
@@ -435,14 +459,16 @@ class DopeFlix extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["sflix.to", "sflix.se"], entries: ["sflix.to", "sflix.se"],
entryValues: ["https://sflix.to", "https://sflix.se"]), entryValues: ["https://sflix.to", "https://sflix.se"],
),
ListPreference( ListPreference(
key: "preferred_quality", key: "preferred_quality",
title: "Preferred Quality", title: "Preferred Quality",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["1080p", "720p", "480p", "360p"], entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080p", "720p", "480p", "360p"]), entryValues: ["1080p", "720p", "480p", "360p"],
),
ListPreference( ListPreference(
key: "preferred_subLang", key: "preferred_subLang",
title: "Preferred sub language", title: "Preferred sub language",
@@ -459,7 +485,7 @@ class DopeFlix extends MProvider {
"Portuguese", "Portuguese",
"Romanian", "Romanian",
"Russian", "Russian",
"Spanish" "Spanish",
], ],
entryValues: [ entryValues: [
"Arabic", "Arabic",
@@ -472,22 +498,25 @@ class DopeFlix extends MProvider {
"Portuguese", "Portuguese",
"Romanian", "Romanian",
"Russian", "Russian",
"Spanish" "Spanish",
]), ],
),
ListPreference( ListPreference(
key: "preferred_latest_page", key: "preferred_latest_page",
title: "Preferred latest page", title: "Preferred latest page",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Movies", "TV Shows"], entries: ["Movies", "TV Shows"],
entryValues: ["Latest Movies", "Latest TV Shows"]), entryValues: ["Latest Movies", "Latest TV Shows"],
),
ListPreference( ListPreference(
key: "preferred_popular_page", key: "preferred_popular_page",
title: "Preferred popular page", title: "Preferred popular page",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Movies", "TV Shows"], entries: ["Movies", "TV Shows"],
entryValues: ["movie", "tv-show"]), entryValues: ["movie", "tv-show"],
),
]; ];
} }

View File

@@ -7,13 +7,17 @@ const _dopeflixSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/multisrc/dopeflix/dopeflix.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/multisrc/dopeflix/dopeflix.dart";
List<Source> get dopeflixSourcesList => _dopeflixSourcesList; List<Source> get dopeflixSourcesList => _dopeflixSourcesList;
List<Source> _dopeflixSourcesList = [ List<Source> _dopeflixSourcesList =
[
//DopeBox (EN) //DopeBox (EN)
dopeboxSource, dopeboxSource,
//SFlix (EN) //SFlix (EN)
sflixSource, sflixSource,
] ]
.map((e) => e .map(
(e) =>
e
..sourceCodeUrl = _dopeflixSourceCodeUrl ..sourceCodeUrl = _dopeflixSourceCodeUrl
..version = _dopeflixVersion) ..version = _dopeflixVersion,
)
.toList(); .toList();

View File

@@ -7,13 +7,17 @@ const _zorothemeSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/multisrc/zorotheme/zorotheme.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/multisrc/zorotheme/zorotheme.dart";
List<Source> get zorothemeSourcesList => _zorothemeSourcesList; List<Source> get zorothemeSourcesList => _zorothemeSourcesList;
List<Source> _zorothemeSourcesList = [ List<Source> _zorothemeSourcesList =
[
//AniWatch.to (EN) //AniWatch.to (EN)
aniwatchSource, aniwatchSource,
//Kaido.to (EN) //Kaido.to (EN)
kaidoSource, kaidoSource,
] ]
.map((e) => e .map(
(e) =>
e
..sourceCodeUrl = _zorothemeSourceCodeUrl ..sourceCodeUrl = _zorothemeSourceCodeUrl
..version = _zorothemeVersion) ..version = _zorothemeVersion,
)
.toList(); .toList();

View File

@@ -10,18 +10,20 @@ class ZoroTheme extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = (await client final res =
.get(Uri.parse("${source.baseUrl}/most-popular?page=$page"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/most-popular?page=$page"),
)).body;
return animeElementM(res); return animeElementM(res);
} }
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client final res =
.get(Uri.parse("${source.baseUrl}/recently-updated?page=$page"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/recently-updated?page=$page"),
)).body;
return animeElementM(res); return animeElementM(res);
} }
@@ -122,28 +124,36 @@ class ZoroTheme extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"Currently Airing": 0, "Finished Airing": 1} {"Currently Airing": 0, "Finished Airing": 1},
]; ];
final res = (await client.get(Uri.parse("${source.baseUrl}$url"))).body; final res = (await client.get(Uri.parse("${source.baseUrl}$url"))).body;
MManga anime = MManga(); MManga anime = MManga();
final status = xpath(res, final status = xpath(
'//*[@class="anisc-info"]/div[contains(text(),"Status:")]/span[2]/text()'); res,
'//*[@class="anisc-info"]/div[contains(text(),"Status:")]/span[2]/text()',
);
if (status.isNotEmpty) { if (status.isNotEmpty) {
anime.status = parseStatus(status.first, statusList); anime.status = parseStatus(status.first, statusList);
} }
final author = xpath(res, final author = xpath(
'//*[@class="anisc-info"]/div[contains(text(),"Studios:")]/span/text()'); res,
'//*[@class="anisc-info"]/div[contains(text(),"Studios:")]/span/text()',
);
if (author.isNotEmpty) { if (author.isNotEmpty) {
anime.author = author.first.replaceAll("Studios:", ""); anime.author = author.first.replaceAll("Studios:", "");
} }
final description = xpath(res, final description = xpath(
'//*[@class="anisc-info"]/div[contains(text(),"Overview:")]/text()'); res,
'//*[@class="anisc-info"]/div[contains(text(),"Overview:")]/text()',
);
if (description.isNotEmpty) { if (description.isNotEmpty) {
anime.description = description.first.replaceAll("Overview:", ""); anime.description = description.first.replaceAll("Overview:", "");
} }
final genre = xpath(res, final genre = xpath(
'//*[@class="anisc-info"]/div[contains(text(),"Genres:")]/a/text()'); res,
'//*[@class="anisc-info"]/div[contains(text(),"Genres:")]/a/text()',
);
anime.genre = genre; anime.genre = genre;
final id = substringAfterLast(url, '-'); final id = substringAfterLast(url, '-');
@@ -177,11 +187,13 @@ class ZoroTheme extends MProvider {
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
final id = substringAfterLast(url, '?ep='); final id = substringAfterLast(url, '?ep=');
final res = (await client.get( final res =
(await client.get(
Uri.parse( Uri.parse(
"${source.baseUrl}/ajax${ajaxRoute('${source.baseUrl}')}/episode/servers?episodeId=$id"), "${source.baseUrl}/ajax${ajaxRoute('${source.baseUrl}')}/episode/servers?episodeId=$id",
headers: {"referer": "${source.baseUrl}/$url"})) ),
.body; headers: {"referer": "${source.baseUrl}/$url"},
)).body;
final html = json.decode(res)["html"]; final html = json.decode(res)["html"];
final serverElements = parseHtml(html).select("div.server-item"); final serverElements = parseHtml(html).select("div.server-item");
@@ -194,11 +206,13 @@ class ZoroTheme extends MProvider {
final id = serverElement.attr("data-id"); final id = serverElement.attr("data-id");
final subDub = serverElement.attr("data-type"); final subDub = serverElement.attr("data-type");
final resE = (await client.get( final resE =
(await client.get(
Uri.parse( Uri.parse(
"${source.baseUrl}/ajax${ajaxRoute('${source.baseUrl}')}/episode/sources?id=$id"), "${source.baseUrl}/ajax${ajaxRoute('${source.baseUrl}')}/episode/sources?id=$id",
headers: {"referer": "${source.baseUrl}/$url"})) ),
.body; headers: {"referer": "${source.baseUrl}/$url"},
)).body;
String epUrl = substringBefore(substringAfter(resE, "\"link\":\""), "\""); String epUrl = substringBefore(substringAfter(resE, "\"link\":\""), "\"");
List<MVideo> a = []; List<MVideo> a = [];
if (hosterSelection.contains(name) && typeSelection.contains(subDub)) { if (hosterSelection.contains(name) && typeSelection.contains(subDub)) {
@@ -222,30 +236,36 @@ class ZoroTheme extends MProvider {
Future<List<MVideo>> rapidCloudExtractor(String url, String name) async { Future<List<MVideo>> rapidCloudExtractor(String url, String name) async {
final serverUrl = ['https://megacloud.tv', 'https://rapid-cloud.co']; final serverUrl = ['https://megacloud.tv', 'https://rapid-cloud.co'];
final serverType = url.startsWith('https://megacloud.tv') || url.startsWith('https://megacloud.club') ? 0 : 1; final serverType =
url.startsWith('https://megacloud.tv') ||
url.startsWith('https://megacloud.club')
? 0
: 1;
final sourceUrl = [ final sourceUrl = [
'/embed-2/ajax/e-1/getSources?id=', '/embed-2/ajax/e-1/getSources?id=',
'/ajax/embed-6-v2/getSources?id=' '/ajax/embed-6-v2/getSources?id=',
]; ];
final sourceSpliter = ['/e-1/', '/embed-6-v2/']; final sourceSpliter = ['/e-1/', '/embed-6-v2/'];
final id = url.split(sourceSpliter[serverType]).last.split('?').first; final id = url.split(sourceSpliter[serverType]).last.split('?').first;
String resServer = ""; String resServer = "";
if (serverType == 0) { if (serverType == 0) {
resServer = resServer = await evaluateJavascriptViaWebview(
await evaluateJavascriptViaWebview("https://megacloud.tv/about", { "https://megacloud.tv/about",
"X-Requested-With": "org.lineageos.jelly" {"X-Requested-With": "org.lineageos.jelly"},
}, [ [
cryptoStr, cryptoStr,
decodePng, decodePng,
getSrcStr, getSrcStr,
"getSources('$id').then(s => window.flutter_inappwebview.callHandler('setResponse', JSON.stringify(s)))" "getSources('$id').then(s => window.flutter_inappwebview.callHandler('setResponse', JSON.stringify(s)))",
]); ],
);
} else { } else {
resServer = (await client.get( resServer =
(await client.get(
Uri.parse('${serverUrl[serverType]}${sourceUrl[serverType]}$id'), Uri.parse('${serverUrl[serverType]}${sourceUrl[serverType]}$id'),
headers: {"X-Requested-With": "XMLHttpRequest"})) headers: {"X-Requested-With": "XMLHttpRequest"},
.body; )).body;
} }
final encrypted = getMapValue(resServer, "encrypted"); final encrypted = getMapValue(resServer, "encrypted");
@@ -268,16 +288,19 @@ class ZoroTheme extends MProvider {
videoResJson = decryptAESCryptoJS(ciphertext, password); videoResJson = decryptAESCryptoJS(ciphertext, password);
} else { } else {
videoResJson = json.encode( videoResJson = json.encode(
(json.decode(resServer)["sources"] as List<Map<String, dynamic>>)); (json.decode(resServer)["sources"] as List<Map<String, dynamic>>),
);
} }
String masterUrl = String masterUrl =
((json.decode(videoResJson) as List<Map<String, dynamic>>) ((json.decode(videoResJson) as List<Map<String, dynamic>>)
.first)['file']; .first)['file'];
String type = ((json.decode(videoResJson) as List<Map<String, dynamic>>) String type =
((json.decode(videoResJson) as List<Map<String, dynamic>>)
.first)['type']; .first)['type'];
final tracks = (json.decode(resServer)['tracks'] as List) final tracks =
(json.decode(resServer)['tracks'] as List)
.where((e) => e['kind'] == 'captions' ? true : false) .where((e) => e['kind'] == 'captions' ? true : false)
.toList(); .toList();
List<MTrack> subtitles = []; List<MTrack> subtitles = [];
@@ -295,8 +318,10 @@ class ZoroTheme extends MProvider {
if (type == "hls") { if (type == "hls") {
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -330,19 +355,22 @@ class ZoroTheme extends MProvider {
Future<List<List<int>>> generateIndexPairs(int serverType) async { Future<List<List<int>>> generateIndexPairs(int serverType) async {
final jsPlayerUrl = [ final jsPlayerUrl = [
"https://megacloud.tv/js/player/a/prod/e1-player.min.js", "https://megacloud.tv/js/player/a/prod/e1-player.min.js",
"https://rapid-cloud.co/js/player/prod/e6-player-v2.min.js" "https://rapid-cloud.co/js/player/prod/e6-player-v2.min.js",
]; ];
final scriptText = final scriptText =
(await client.get(Uri.parse(jsPlayerUrl[serverType]))).body; (await client.get(Uri.parse(jsPlayerUrl[serverType]))).body;
final switchCode = scriptText.substring( final switchCode = scriptText.substring(
scriptText.lastIndexOf('switch'), scriptText.indexOf('=partKey')); scriptText.lastIndexOf('switch'),
scriptText.indexOf('=partKey'),
);
List<int> indexes = []; List<int> indexes = [];
for (var variableMatch for (var variableMatch
in RegExp(r'=(\w+)').allMatches(switchCode).toList()) { in RegExp(r'=(\w+)').allMatches(switchCode).toList()) {
final regex = RegExp( final regex = RegExp(
',${(variableMatch as RegExpMatch).group(1)}=((?:0x)?([0-9a-fA-F]+))'); ',${(variableMatch as RegExpMatch).group(1)}=((?:0x)?([0-9a-fA-F]+))',
);
Match? match = regex.firstMatch(scriptText); Match? match = regex.firstMatch(scriptText);
if (match != null) { if (match != null) {
@@ -374,13 +402,19 @@ class ZoroTheme extends MProvider {
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = xpath( final urls = xpath(
res, '//*[@class^="flw-item"]/div[@class="film-detail"]/h3/a/@href'); res,
'//*[@class^="flw-item"]/div[@class="film-detail"]/h3/a/@href',
);
final names = xpath(res, final names = xpath(
'//*[@class^="flw-item"]/div[@class="film-detail"]/h3/a/@data-jname'); res,
'//*[@class^="flw-item"]/div[@class="film-detail"]/h3/a/@data-jname',
);
final images = xpath( final images = xpath(
res, '//*[@class^="flw-item"]/div[@class="film-poster"]/img/@data-src'); res,
'//*[@class^="flw-item"]/div[@class="film-poster"]/img/@data-src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
anime.name = names[i]; anime.name = names[i];
@@ -388,8 +422,11 @@ class ZoroTheme extends MProvider {
anime.link = urls[i]; anime.link = urls[i];
animeList.add(anime); animeList.add(anime);
} }
final nextPage = final nextPage = xpath(
xpath(res, '//li[@class="page-item"]/a[@title="Next"]/@href', ""); res,
'//li[@class="page-item"]/a[@title="Next"]/@href',
"",
);
return MPages(animeList, !nextPage.isEmpty); return MPages(animeList, !nextPage.isEmpty);
} }
@@ -403,7 +440,7 @@ class ZoroTheme extends MProvider {
List<SelectFilterOption> yearList = [ List<SelectFilterOption> yearList = [
for (var i = 1917; i < 2024; i++) for (var i = 1917; i < 2024; i++)
SelectFilterOption(i.toString(), i.toString()), SelectFilterOption(i.toString(), i.toString()),
SelectFilterOption("All", "") SelectFilterOption("All", ""),
]; ];
@override @override
@@ -416,13 +453,13 @@ class ZoroTheme extends MProvider {
SelectFilterOption("OVA", "3"), SelectFilterOption("OVA", "3"),
SelectFilterOption("ONA", "4"), SelectFilterOption("ONA", "4"),
SelectFilterOption("Special", "5"), SelectFilterOption("Special", "5"),
SelectFilterOption("Music", "6") SelectFilterOption("Music", "6"),
]), ]),
SelectFilter("StatusFilter", "Status", 0, [ SelectFilter("StatusFilter", "Status", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
SelectFilterOption("Finished Airing", "1"), SelectFilterOption("Finished Airing", "1"),
SelectFilterOption("Currently Airing", "2"), SelectFilterOption("Currently Airing", "2"),
SelectFilterOption("Not yet aired", "3") SelectFilterOption("Not yet aired", "3"),
]), ]),
SelectFilter("RatedFilter", "Rated", 0, [ SelectFilter("RatedFilter", "Rated", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
@@ -431,7 +468,7 @@ class ZoroTheme extends MProvider {
SelectFilterOption("PG-13", "3"), SelectFilterOption("PG-13", "3"),
SelectFilterOption("R", "4"), SelectFilterOption("R", "4"),
SelectFilterOption("R+", "5"), SelectFilterOption("R+", "5"),
SelectFilterOption("Rx", "6") SelectFilterOption("Rx", "6"),
]), ]),
SelectFilter("ScoreFilter", "Score", 0, [ SelectFilter("ScoreFilter", "Score", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
@@ -444,20 +481,20 @@ class ZoroTheme extends MProvider {
SelectFilterOption("(7) Good", "7"), SelectFilterOption("(7) Good", "7"),
SelectFilterOption("(8) Very Good", "8"), SelectFilterOption("(8) Very Good", "8"),
SelectFilterOption("(9) Great", "9"), SelectFilterOption("(9) Great", "9"),
SelectFilterOption("(10) Masterpiece", "10") SelectFilterOption("(10) Masterpiece", "10"),
]), ]),
SelectFilter("SeasonFilter", "Season", 0, [ SelectFilter("SeasonFilter", "Season", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
SelectFilterOption("Spring", "1"), SelectFilterOption("Spring", "1"),
SelectFilterOption("Summer", "2"), SelectFilterOption("Summer", "2"),
SelectFilterOption("Fall", "3"), SelectFilterOption("Fall", "3"),
SelectFilterOption("Winter", "4") SelectFilterOption("Winter", "4"),
]), ]),
SelectFilter("LanguageFilter", "Language", 0, [ SelectFilter("LanguageFilter", "Language", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
SelectFilterOption("SUB", "1"), SelectFilterOption("SUB", "1"),
SelectFilterOption("DUB", "2"), SelectFilterOption("DUB", "2"),
SelectFilterOption("SUB & DUB", "3") SelectFilterOption("SUB & DUB", "3"),
]), ]),
SelectFilter("SortFilter", "Sort by", 0, [ SelectFilter("SortFilter", "Sort by", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
@@ -467,14 +504,18 @@ class ZoroTheme extends MProvider {
SelectFilterOption("Score", "score"), SelectFilterOption("Score", "score"),
SelectFilterOption("Name A-Z", "name_az"), SelectFilterOption("Name A-Z", "name_az"),
SelectFilterOption("Released Date", "released_date"), SelectFilterOption("Released Date", "released_date"),
SelectFilterOption("Most Watched", "most_watched") SelectFilterOption("Most Watched", "most_watched"),
]), ]),
SelectFilter( SelectFilter(
"StartYearFilter", "Start year", 0, yearList.reversed.toList()), "StartYearFilter",
"Start year",
0,
yearList.reversed.toList(),
),
SelectFilter("StartMonthFilter", "Start month", 0, [ SelectFilter("StartMonthFilter", "Start month", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
for (var i = 1; i < 13; i++) for (var i = 1; i < 13; i++)
SelectFilterOption(i.toString(), i.toString()) SelectFilterOption(i.toString(), i.toString()),
]), ]),
SelectFilter("StartDayFilter", "Start day", 0, [ SelectFilter("StartDayFilter", "Start day", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
@@ -485,12 +526,12 @@ class ZoroTheme extends MProvider {
SelectFilter("EndmonthFilter", "End month", 0, [ SelectFilter("EndmonthFilter", "End month", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
for (var i = 1; i < 32; i++) for (var i = 1; i < 32; i++)
SelectFilterOption(i.toString(), i.toString()) SelectFilterOption(i.toString(), i.toString()),
]), ]),
SelectFilter("EndDayFilter", "End day", 0, [ SelectFilter("EndDayFilter", "End day", 0, [
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
for (var i = 1; i < 32; i++) for (var i = 1; i < 32; i++)
SelectFilterOption(i.toString(), i.toString()) SelectFilterOption(i.toString(), i.toString()),
]), ]),
GroupFilter("GenreFilter", "Genre", [ GroupFilter("GenreFilter", "Genre", [
CheckBoxFilter("Action", "1"), CheckBoxFilter("Action", "1"),
@@ -535,7 +576,7 @@ class ZoroTheme extends MProvider {
CheckBoxFilter("Thriller", "41"), CheckBoxFilter("Thriller", "41"),
CheckBoxFilter("Vampire", "32"), CheckBoxFilter("Vampire", "32"),
CheckBoxFilter("Yaoi", "33"), CheckBoxFilter("Yaoi", "33"),
CheckBoxFilter("Yuri", "34") CheckBoxFilter("Yuri", "34"),
]), ]),
]; ];
} }
@@ -549,7 +590,8 @@ class ZoroTheme extends MProvider {
summary: "", summary: "",
valueIndex: 1, valueIndex: 1,
entries: ["1080p", "720p", "480p", "360p"], entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080", "720", "480", "360"]), entryValues: ["1080", "720", "480", "360"],
),
if (source.name == "HiAnime") if (source.name == "HiAnime")
ListPreference( ListPreference(
key: "preferred_server1", key: "preferred_server1",
@@ -557,7 +599,8 @@ class ZoroTheme extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["HD-1", "HD-2", "StreamTape"], entries: ["HD-1", "HD-2", "StreamTape"],
entryValues: ["HD-1", "HD-2", "StreamTape"]), entryValues: ["HD-1", "HD-2", "StreamTape"],
),
if (source.name != "HiAnime") if (source.name != "HiAnime")
ListPreference( ListPreference(
key: "preferred_server1", key: "preferred_server1",
@@ -565,14 +608,16 @@ class ZoroTheme extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Vidstreaming", "VidCloud", "StreamTape"], entries: ["Vidstreaming", "VidCloud", "StreamTape"],
entryValues: ["Vidstreaming", "VidCloud", "StreamTape"]), entryValues: ["Vidstreaming", "VidCloud", "StreamTape"],
),
ListPreference( ListPreference(
key: "preferred_type1", key: "preferred_type1",
title: "Preferred Type", title: "Preferred Type",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Sub", "Dub"], entries: ["Sub", "Dub"],
entryValues: ["sub", "dub"]), entryValues: ["sub", "dub"],
),
if (source.name != "HiAnime") if (source.name != "HiAnime")
MultiSelectListPreference( MultiSelectListPreference(
key: "hoster_selection1", key: "hoster_selection1",
@@ -580,7 +625,8 @@ class ZoroTheme extends MProvider {
summary: "", summary: "",
entries: ["Vidstreaming", "VidCloud", "StreamTape"], entries: ["Vidstreaming", "VidCloud", "StreamTape"],
entryValues: ["Vidstreaming", "VidCloud", "StreamTape"], entryValues: ["Vidstreaming", "VidCloud", "StreamTape"],
values: ["Vidstreaming", "VidCloud", "StreamTape"]), values: ["Vidstreaming", "VidCloud", "StreamTape"],
),
if (source.name == "HiAnime") if (source.name == "HiAnime")
MultiSelectListPreference( MultiSelectListPreference(
key: "hoster_selection1", key: "hoster_selection1",
@@ -588,14 +634,16 @@ class ZoroTheme extends MProvider {
summary: "", summary: "",
entries: ["HD-1", "HD-2", "StreamTape"], entries: ["HD-1", "HD-2", "StreamTape"],
entryValues: ["HD-1", "HD-2", "StreamTape"], entryValues: ["HD-1", "HD-2", "StreamTape"],
values: ["HD-1", "HD-2", "StreamTape"]), values: ["HD-1", "HD-2", "StreamTape"],
),
MultiSelectListPreference( MultiSelectListPreference(
key: "type_selection_new", key: "type_selection_new",
title: "Enable/Disable Types", title: "Enable/Disable Types",
summary: "", summary: "",
entries: ["Sub", "Dub", "Raw"], entries: ["Sub", "Dub", "Raw"],
entryValues: ["sub", "dub"], entryValues: ["sub", "dub"],
values: ["sub", "dub", "raw"]), values: ["sub", "dub", "raw"],
),
]; ];
} }

View File

@@ -10,18 +10,24 @@ class AnimeWorldIndia extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = (await client.get(Uri.parse( final res =
"${source.baseUrl}/advanced-search/page/$page/?s_lang=${source.lang}&s_orderby=viewed"))) (await client.get(
.body; Uri.parse(
"${source.baseUrl}/advanced-search/page/$page/?s_lang=${source.lang}&s_orderby=viewed",
),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client.get(Uri.parse( final res =
"${source.baseUrl}/advanced-search/page/$page/?s_lang=${source.lang}&s_orderby=update"))) (await client.get(
.body; Uri.parse(
"${source.baseUrl}/advanced-search/page/$page/?s_lang=${source.lang}&s_orderby=update",
),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@@ -80,7 +86,9 @@ class AnimeWorldIndia extends MProvider {
anime.status = MStatus.completed; anime.status = MStatus.completed;
} else { } else {
final eps = xpath( final eps = xpath(
res, '//ul/li/a[contains(@href,"${source.baseUrl}/watch")]/text()'); res,
'//ul/li/a[contains(@href,"${source.baseUrl}/watch")]/text()',
);
if (eps.isNotEmpty) { if (eps.isNotEmpty) {
final epParts = eps.first final epParts = eps.first
.substring(3) .substring(3)
@@ -101,19 +109,26 @@ class AnimeWorldIndia extends MProvider {
.xpath('//li[contains(text(),"Producers:")]/span/a/text()') .xpath('//li[contains(text(),"Producers:")]/span/a/text()')
.join(', '); .join(', ');
anime.genre = document.xpath( anime.genre = document.xpath(
'//span[@class="leading-6"]/a[contains(@class,"border-opacity-30")]/text()'); '//span[@class="leading-6"]/a[contains(@class,"border-opacity-30")]/text()',
final seasonsJson = json.decode(substringBeforeLast( );
final seasonsJson =
json.decode(
substringBeforeLast(
substringBefore( substringBefore(
substringAfter(res, "var season_list = "), "var season_label ="), substringAfter(res, "var season_list = "),
";")) as List<Map<String, dynamic>>; "var season_label =",
),
";",
),
)
as List<Map<String, dynamic>>;
bool isSingleSeason = seasonsJson.length == 1; bool isSingleSeason = seasonsJson.length == 1;
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
for (var i = 0; i < seasonsJson.length; i++) { for (var i = 0; i < seasonsJson.length; i++) {
final seasonJson = seasonsJson[i]; final seasonJson = seasonsJson[i];
final seasonName = isSingleSeason ? "" : "Season ${i + 1}"; final seasonName = isSingleSeason ? "" : "Season ${i + 1}";
final episodesJson = final episodesJson =
(seasonJson["episodes"]["all"] as List<Map<String, dynamic>>) (seasonJson["episodes"]["all"] as List<Map<String, dynamic>>).reversed
.reversed
.toList(); .toList();
for (var j = 0; j < episodesJson.length; j++) { for (var j = 0; j < episodesJson.length; j++) {
final episodeJson = episodesJson[j]; final episodeJson = episodesJson[j];
@@ -148,16 +163,24 @@ class AnimeWorldIndia extends MProvider {
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
final res = (await client.get(Uri.parse("${source.baseUrl}$url"))).body; final res = (await client.get(Uri.parse("${source.baseUrl}$url"))).body;
var resJson = substringBefore( var resJson = substringBefore(
substringAfterLast(res, "\"players\":"), ",\"noplayer\":"); substringAfterLast(res, "\"players\":"),
var streams = (json.decode(resJson) as List<Map<String, dynamic>>) ",\"noplayer\":",
.where((e) => );
var streams =
(json.decode(resJson) as List<Map<String, dynamic>>)
.where(
(e) =>
(e["type"] == "stream" ? true : false) && (e["type"] == "stream" ? true : false) &&
(e["url"] as String).isNotEmpty) (e["url"] as String).isNotEmpty,
)
.toList() .toList()
.where((e) => language(source.lang).isEmpty || .where(
(e) =>
language(source.lang).isEmpty ||
language(source.lang) == e["language"] language(source.lang) == e["language"]
? true ? true
: false) : false,
)
.toList(); .toList();
List<MVideo> videos = []; List<MVideo> videos = [];
for (var stream in streams) { for (var stream in streams) {
@@ -183,9 +206,11 @@ class AnimeWorldIndia extends MProvider {
"${source.baseUrl}${getUrlWithoutDomain(element.selectFirst("img").getSrc)}"; "${source.baseUrl}${getUrlWithoutDomain(element.selectFirst("img").getSrc)}";
animeList.add(anime); animeList.add(anime);
} }
final hasNextPage = xpath(res, final hasNextPage =
'//li/span[@class="page-numbers current"]/parent::li//following-sibling::li/a/@href') xpath(
.isNotEmpty; res,
'//li/span[@class="page-numbers current"]/parent::li//following-sibling::li/a/@href',
).isNotEmpty;
return MPages(animeList, hasNextPage); return MPages(animeList, hasNextPage);
} }
@@ -199,7 +224,7 @@ class AnimeWorldIndia extends MProvider {
"ml": "malayalam", "ml": "malayalam",
"mr": "marathi", "mr": "marathi",
"ta": "tamil", "ta": "tamil",
"te": "telugu" "te": "telugu",
}; };
return languages[lang] ?? ""; return languages[lang] ?? "";
} }
@@ -208,17 +233,23 @@ class AnimeWorldIndia extends MProvider {
List<MVideo> videos = []; List<MVideo> videos = [];
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
final streamCode = substringBefore( final streamCode = substringBefore(
substringAfter(substringAfter(res, "sniff("), ", \""), '"'); substringAfter(substringAfter(res, "sniff("), ", \""),
'"',
);
final streamUrl = final streamUrl =
"${substringBefore(url, "/watch")}/m3u8/$streamCode/master.txt?s=1&cache=1"; "${substringBefore(url, "/watch")}/m3u8/$streamCode/master.txt?s=1&cache=1";
final masterPlaylistRes = (await client.get(Uri.parse(streamUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(streamUrl))).body;
List<MTrack> audios = []; List<MTrack> audios = [];
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-MEDIA:TYPE=AUDIO") for (var it in substringAfter(
.split("#EXT-X-MEDIA:TYPE=AUDIO")) { masterPlaylistRes,
final line = "#EXT-X-MEDIA:TYPE=AUDIO",
substringBefore(substringAfter(it, "#EXT-X-MEDIA:TYPE=AUDIO"), "\n"); ).split("#EXT-X-MEDIA:TYPE=AUDIO")) {
final line = substringBefore(
substringAfter(it, "#EXT-X-MEDIA:TYPE=AUDIO"),
"\n",
);
final audioUrl = substringBefore(substringAfter(line, "URI=\""), "\""); final audioUrl = substringBefore(substringAfter(line, "URI=\""), "\"");
MTrack audio = MTrack(); MTrack audio = MTrack();
audio audio
@@ -227,8 +258,10 @@ class AnimeWorldIndia extends MProvider {
audios.add(audio); audios.add(audio);
} }
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -299,7 +332,7 @@ class AnimeWorldIndia extends MProvider {
SelectFilterOption("1993", "1993"), SelectFilterOption("1993", "1993"),
SelectFilterOption("1992", "1992"), SelectFilterOption("1992", "1992"),
SelectFilterOption("1991", "1991"), SelectFilterOption("1991", "1991"),
SelectFilterOption("1990", "1990") SelectFilterOption("1990", "1990"),
]), ]),
SelectFilter("SortFilter", "Sort", 0, [ SelectFilter("SortFilter", "Sort", 0, [
SelectFilterOption("Default", "default"), SelectFilterOption("Default", "default"),
@@ -353,7 +386,8 @@ class AnimeWorldIndia extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["1080p", "720p", "480p", "360p", "240p"], entries: ["1080p", "720p", "480p", "360p", "240p"],
entryValues: ["1080", "720", "480", "360", "240"]), entryValues: ["1080", "720", "480", "360", "240"],
),
]; ];
} }

View File

@@ -20,8 +20,10 @@ List<String> _languages = [
]; ];
List<Source> get animeworldindiaSourcesList => _animeworldindiaSourcesList; List<Source> get animeworldindiaSourcesList => _animeworldindiaSourcesList;
List<Source> _animeworldindiaSourcesList = _languages List<Source> _animeworldindiaSourcesList =
.map((e) => Source( _languages
.map(
(e) => Source(
name: 'AnimeWorld India', name: 'AnimeWorld India',
baseUrl: "https://anime-world.in", baseUrl: "https://anime-world.in",
lang: e, lang: e,
@@ -29,5 +31,7 @@ List<Source> _animeworldindiaSourcesList = _languages
iconUrl: _iconUrl, iconUrl: _iconUrl,
version: _animeworldindiaVersion, version: _animeworldindiaVersion,
itemType: ItemType.anime, itemType: ItemType.anime,
sourceCodeUrl: _animeworldindiaSourceCodeUrl)) sourceCodeUrl: _animeworldindiaSourceCodeUrl,
),
)
.toList(); .toList();

View File

@@ -9,17 +9,23 @@ class Nyaa extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = (await client.get(Uri.parse( final res =
"${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=&s=downloads&o=desc&p=$page"))) (await client.get(
.body; Uri.parse(
"${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=&s=downloads&o=desc&p=$page",
),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client.get(Uri.parse( final res =
"${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=$page"))) (await client.get(
.body; Uri.parse(
"${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=$page",
),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@@ -78,8 +84,8 @@ class Nyaa extends MProvider {
SelectFilterOption("Date", "id"), SelectFilterOption("Date", "id"),
SelectFilterOption("Seeders", "seeders"), SelectFilterOption("Seeders", "seeders"),
SelectFilterOption("Leechers", "leechers"), SelectFilterOption("Leechers", "leechers"),
SelectFilterOption("Download", "downloads") SelectFilterOption("Download", "downloads"),
]) ]),
]; ];
} }
@@ -92,7 +98,8 @@ class Nyaa extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Anime", "Live Action"], entries: ["Anime", "Live Action"],
entryValues: ["1_0", "4_0"]), entryValues: ["1_0", "4_0"],
),
]; ];
} }
@@ -100,17 +107,21 @@ class Nyaa extends MProvider {
List<MManga> animeList = []; List<MManga> animeList = [];
final document = parseHtml(res); final document = parseHtml(res);
final values = document final values = document.select(
.select("body > div > div.table-responsive > table > tbody > tr"); "body > div > div.table-responsive > table > tbody > tr",
);
for (var value in values) { for (var value in values) {
MManga anime = MManga(); MManga anime = MManga();
anime.imageUrl = anime.imageUrl =
"${source.baseUrl}${getUrlWithoutDomain(value.selectFirst("td:nth-child(1) > a > img").getSrc)}"; "${source.baseUrl}${getUrlWithoutDomain(value.selectFirst("td:nth-child(1) > a > img").getSrc)}";
MElement firstElement = value MElement firstElement =
value
.select("td > a") .select("td > a")
.where((MElement e) => .where(
(MElement e) =>
e.outerHtml.contains("/view/") && e.outerHtml.contains("/view/") &&
!e.outerHtml.contains("#comments")) !e.outerHtml.contains("#comments"),
)
.toList() .toList()
.first; .first;
anime.link = anime.link =
@@ -120,8 +131,10 @@ class Nyaa extends MProvider {
} }
final hasNextPage = final hasNextPage =
xpath(res, '//ul[@class="pagination"]/li[contains(text(),"»")]/a/@href') xpath(
.isNotEmpty; res,
'//ul[@class="pagination"]/li[contains(text(),"»")]/a/@href',
).isNotEmpty;
return MPages(animeList, hasNextPage); return MPages(animeList, hasNextPage);
} }

View File

@@ -16,4 +16,5 @@ Source _nyaaSource = Source(
iconUrl: _iconUrl, iconUrl: _iconUrl,
version: _nyaaVersion, version: _nyaaVersion,
itemType: ItemType.anime, itemType: ItemType.anime,
sourceCodeUrl: _nyaaSourceCodeUrl); sourceCodeUrl: _nyaaSourceCodeUrl,
);

View File

@@ -30,9 +30,10 @@ class OkAnime extends MProvider {
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client final res =
.get(Uri.parse("${source.baseUrl}/espisode-list?page=$page"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/espisode-list?page=$page"),
)).body;
List<MManga> animeList = []; List<MManga> animeList = [];
String path = '//*[contains(@class,"anime-card")]'; String path = '//*[contains(@class,"anime-card")]';
final urls = xpath(res, '$path/div[@class="anime-title")]/h4/a/@href'); final urls = xpath(res, '$path/div[@class="anime-title")]/h4/a/@href');
@@ -46,8 +47,10 @@ class OkAnime extends MProvider {
anime.link = urls[i]; anime.link = urls[i];
animeList.add(anime); animeList.add(anime);
} }
final nextPage = final nextPage = xpath(
xpath(res, '//li[@class="page-item"]/a[@rel="next"]/@href'); res,
'//li[@class="page-item"]/a[@rel="next"]/@href',
);
return MPages(animeList, nextPage.isNotEmpty); return MPages(animeList, nextPage.isNotEmpty);
} }
@@ -73,34 +76,40 @@ class OkAnime extends MProvider {
anime.link = urls[i]; anime.link = urls[i];
animeList.add(anime); animeList.add(anime);
} }
final nextPage = final nextPage = xpath(
xpath(res, '//li[@class="page-item"]/a[@rel="next"]/@href'); res,
'//li[@class="page-item"]/a[@rel="next"]/@href',
);
return MPages(animeList, nextPage.isNotEmpty); return MPages(animeList, nextPage.isNotEmpty);
} }
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"يعرض الان": 0, "مكتمل": 1} {"يعرض الان": 0, "مكتمل": 1},
]; ];
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
MManga anime = MManga(); MManga anime = MManga();
final status = xpath(res, final status = xpath(
'//*[@class="full-list-info" and contains(text(),"حالة الأنمي")]/small/a/text()'); res,
'//*[@class="full-list-info" and contains(text(),"حالة الأنمي")]/small/a/text()',
);
if (status.isNotEmpty) { if (status.isNotEmpty) {
anime.status = parseStatus(status.first, statusList); anime.status = parseStatus(status.first, statusList);
} }
anime.description = xpath(res, '//*[@class="review-content"]/text()').first; anime.description = xpath(res, '//*[@class="review-content"]/text()').first;
anime.genre = xpath(res, '//*[@class="review-author-info"]/a/text()'); anime.genre = xpath(res, '//*[@class="review-author-info"]/a/text()');
final epUrls = xpath(res, final epUrls =
'//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h5/a/@href') xpath(
.reversed res,
.toList(); '//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h5/a/@href',
final names = xpath(res, ).reversed.toList();
'//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h5/a/text()') final names =
.reversed xpath(
.toList(); res,
'//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h5/a/text()',
).reversed.toList();
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
for (var i = 0; i < epUrls.length; i++) { for (var i = 0; i < epUrls.length; i++) {
@@ -152,14 +161,16 @@ class OkAnime extends MProvider {
summary: "", summary: "",
valueIndex: 1, valueIndex: 1,
entries: ["1080p", "720p", "480p", "360p"], entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080", "720", "480", "360"]), entryValues: ["1080", "720", "480", "360"],
),
MultiSelectListPreference( MultiSelectListPreference(
key: "hoster_selection", key: "hoster_selection",
title: "Enable/Disable Hosts", title: "Enable/Disable Hosts",
summary: "", summary: "",
entries: ["Dood", "Voe", "Mp4upload", "VidBom", "Okru"], entries: ["Dood", "Voe", "Mp4upload", "VidBom", "Okru"],
entryValues: ["Dood", "Voe", "Mp4upload", "VidBom", "Okru"], entryValues: ["Dood", "Voe", "Mp4upload", "VidBom", "Okru"],
values: ["Dood", "Voe", "Mp4upload", "VidBom", "Okru"]), values: ["Dood", "Voe", "Mp4upload", "VidBom", "Okru"],
),
]; ];
} }

View File

@@ -13,4 +13,5 @@ Source _okanimeSource = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/ar/okanime/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/ar/okanime/icon.png",
sourceCodeUrl: _okanimeSourceCodeUrl, sourceCodeUrl: _okanimeSourceCodeUrl,
version: _okanimeVersion, version: _okanimeVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -23,9 +23,11 @@ class AnimeToast extends MProvider {
MManga anime = MManga(); MManga anime = MManga();
anime.name = element.selectFirst("div.item-thumbnail a").attr("title"); anime.name = element.selectFirst("div.item-thumbnail a").attr("title");
anime.link = getUrlWithoutDomain( anime.link = getUrlWithoutDomain(
element.selectFirst("div.item-thumbnail a").attr("href")); element.selectFirst("div.item-thumbnail a").attr("href"),
anime.imageUrl = );
element.selectFirst("div.item-thumbnail a img").attr("src"); anime.imageUrl = element
.selectFirst("div.item-thumbnail a img")
.attr("src");
animeList.add(anime); animeList.add(anime);
} }
return MPages(animeList, false); return MPages(animeList, false);
@@ -46,7 +48,9 @@ class AnimeToast extends MProvider {
animeList.add(anime); animeList.add(anime);
} }
return MPages( return MPages(
animeList, document.selectFirst("li.next a")?.attr("href") != null); animeList,
document.selectFirst("li.next a")?.attr("href") != null,
);
} }
@override @override
@@ -106,7 +110,8 @@ class AnimeToast extends MProvider {
MChapter ep = MChapter(); MChapter ep = MChapter();
ep.name = document.selectFirst("h1.light-title")?.text ?? "Film"; ep.name = document.selectFirst("h1.light-title")?.text ?? "Film";
ep.url = getUrlWithoutDomain( ep.url = getUrlWithoutDomain(
document.selectFirst("link[rel=canonical]").attr("href")); document.selectFirst("link[rel=canonical]").attr("href"),
);
episodesList.add(ep); episodesList.add(ep);
} }
anime.chapters = episodesList.reversed.toList(); anime.chapters = episodesList.reversed.toList();
@@ -134,16 +139,24 @@ class AnimeToast extends MProvider {
final doc = parseHtml((await client.get(Uri.parse(sUrl))).body); final doc = parseHtml((await client.get(Uri.parse(sUrl))).body);
final nUrl = doc.selectFirst("#player-embed a").attr("href"); final nUrl = doc.selectFirst("#player-embed a").attr("href");
final nDoc = parseHtml((await client.get(Uri.parse(nUrl))).body); final nDoc = parseHtml((await client.get(Uri.parse(nUrl))).body);
epcu = int.tryParse(substringAfter( epcu =
int.tryParse(
substringAfter(
document.selectFirst("div.tab-pane a.current-link")?.text ?? "", document.selectFirst("div.tab-pane a.current-link")?.text ?? "",
"Ep.")) ?? "Ep.",
),
) ??
100; 100;
ep = nDoc.select("div.tab-pane a"); ep = nDoc.select("div.tab-pane a");
} }
} else { } else {
epcu = int.tryParse(substringAfter( epcu =
int.tryParse(
substringAfter(
document.selectFirst("div.tab-pane a.current-link")?.text ?? "", document.selectFirst("div.tab-pane a.current-link")?.text ?? "",
"Ep.")) ?? "Ep.",
),
) ??
100; 100;
ep = document.select("div.tab-pane a"); ep = document.select("div.tab-pane a");
} }
@@ -218,14 +231,16 @@ class AnimeToast extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Voe", "DoodStream", "Filemoon", "Mp4upload"], entries: ["Voe", "DoodStream", "Filemoon", "Mp4upload"],
entryValues: ["voe", "doodStream", "filemoon", "mp4upload"]), entryValues: ["voe", "doodStream", "filemoon", "mp4upload"],
),
MultiSelectListPreference( MultiSelectListPreference(
key: "hoster_selection", key: "hoster_selection",
title: "Hoster auswählen", title: "Hoster auswählen",
summary: "", summary: "",
entries: ["Voe", "DoodStream", "Filemoon", "Mp4upload"], entries: ["Voe", "DoodStream", "Filemoon", "Mp4upload"],
entryValues: ["voe", "dood", "filemoon", "mp4upload"], entryValues: ["voe", "dood", "filemoon", "mp4upload"],
values: ["voe", "dood", "filemoon", "mp4upload"]), values: ["voe", "dood", "filemoon", "mp4upload"],
),
]; ];
} }
} }

View File

@@ -13,4 +13,5 @@ Source _animetoast = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/de/animetoast/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/de/animetoast/icon.png",
sourceCodeUrl: _animetoastCodeUrl, sourceCodeUrl: _animetoastCodeUrl,
version: _animetoastVersion, version: _animetoastVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -22,9 +22,11 @@ class AnimePahe extends MProvider {
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client.get(Uri.parse("$baseUrl/api?m=airing&page=$page"), final res =
headers: headers)) (await client.get(
.body; Uri.parse("$baseUrl/api?m=airing&page=$page"),
headers: headers,
)).body;
final jsonResult = json.decode(res); final jsonResult = json.decode(res);
final hasNextPage = jsonResult["current_page"] < jsonResult["last_page"]; final hasNextPage = jsonResult["current_page"] < jsonResult["last_page"];
List<MManga> animeList = []; List<MManga> animeList = [];
@@ -41,10 +43,11 @@ class AnimePahe extends MProvider {
@override @override
Future<MPages> search(String query, int page, FilterList filterList) async { Future<MPages> search(String query, int page, FilterList filterList) async {
final res = (await client.get( final res =
(await client.get(
Uri.parse("$baseUrl/api?m=search&l=8&q=$query"), Uri.parse("$baseUrl/api?m=search&l=8&q=$query"),
headers: headers)) headers: headers,
.body; )).body;
final jsonResult = json.decode(res); final jsonResult = json.decode(res);
List<MManga> animeList = []; List<MManga> animeList = [];
for (var item in jsonResult["data"]) { for (var item in jsonResult["data"]) {
@@ -60,16 +63,17 @@ class AnimePahe extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"Currently Airing": 0, "Finished Airing": 1} {"Currently Airing": 0, "Finished Airing": 1},
]; ];
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=");
final session = await getSession(name, id); final session = await getSession(name, id);
final res = (await client.get( final res =
(await client.get(
Uri.parse("$baseUrl/anime/$session?anime_id=$id"), Uri.parse("$baseUrl/anime/$session?anime_id=$id"),
headers: headers)) headers: headers,
.body; )).body;
final document = parseHtml(res); final document = parseHtml(res);
final status = final status =
(document.xpathFirst('//div/p[contains(text(),"Status:")]/text()') ?? (document.xpathFirst('//div/p[contains(text(),"Status:")]/text()') ??
@@ -85,8 +89,10 @@ class AnimePahe extends MProvider {
.replaceAll("Studio:\n", "") .replaceAll("Studio:\n", "")
.trim(); .trim();
anime.imageUrl = document.selectFirst("div.anime-poster a").attr("href"); anime.imageUrl = document.selectFirst("div.anime-poster a").attr("href");
anime.genre = anime.genre = xpath(
xpath(res, '//*[contains(@class,"anime-genre")]/ul/li/text()'); res,
'//*[contains(@class,"anime-genre")]/ul/li/text()',
);
final synonyms = final synonyms =
(document.xpathFirst('//div/p[contains(text(),"Synonyms:")]/text()') ?? (document.xpathFirst('//div/p[contains(text(),"Synonyms:")]/text()') ??
"") "")
@@ -105,7 +111,10 @@ class AnimePahe extends MProvider {
} }
Future<List<MChapter>> recursivePages( Future<List<MChapter>> recursivePages(
String url, String res, String session) async { String url,
String res,
String session,
) async {
final jsonResult = json.decode(res); final jsonResult = json.decode(res);
final page = jsonResult["current_page"]; final page = jsonResult["current_page"];
final hasNextPage = page < jsonResult["last_page"]; final hasNextPage = page < jsonResult["last_page"];
@@ -128,13 +137,15 @@ class AnimePahe extends MProvider {
} }
Future<String> getSession(String title, String animeId) async { Future<String> getSession(String title, String animeId) async {
final res = (await client.get(Uri.parse("$baseUrl/api?m=search&q=$title"), final res =
headers: headers)) (await client.get(
.body; Uri.parse("$baseUrl/api?m=search&q=$title"),
headers: headers,
)).body;
return substringBefore( return substringBefore(
substringAfter( substringAfter(substringAfter(res, "\"id\":$animeId"), "\"session\":\""),
substringAfter(res, "\"id\":$animeId"), "\"session\":\""), "\"",
"\""); );
} }
@override @override
@@ -150,24 +161,35 @@ class AnimePahe extends MProvider {
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 audio = btn.attr("data-audio"); // Get audio type (jpn/eng). Japanese or Dubbed. final audio = btn.attr(
"data-audio",
); // Get audio type (jpn/eng). Japanese or Dubbed.
final kwikLink = btn.attr("data-src"); final kwikLink = btn.attr("data-src");
final quality = btn.text; final quality = btn.text;
final paheWinLink = downloadLinks[i].attr("href"); final paheWinLink = downloadLinks[i].attr("href");
if (getPreferenceValue(source.id, "preffered_link_type")) { if (getPreferenceValue(source.id, "preffered_link_type")) {
final noRedirectClient = Client(source, final noRedirectClient = Client(
json.encode({"followRedirects": false, "useDartHttpClient": true})); source,
json.encode({"followRedirects": false, "useDartHttpClient": true}),
);
final kwikHeaders = final kwikHeaders =
(await noRedirectClient.get(Uri.parse("${paheWinLink}/i"))).headers; (await noRedirectClient.get(Uri.parse("${paheWinLink}/i"))).headers;
final kwikUrl = final kwikUrl =
"https://${substringAfterLast(getMapValue(json.encode(kwikHeaders), "location"), "https://")}"; "https://${substringAfterLast(getMapValue(json.encode(kwikHeaders), "location"), "https://")}";
final reskwik = (await client final reskwik = (await client.get(
.get(Uri.parse(kwikUrl), headers: {"Referer": "https://kwik.cx/"})); Uri.parse(kwikUrl),
final matches = RegExp(r'\("(\S+)",\d+,"(\S+)",(\d+),(\d+)') headers: {"Referer": "https://kwik.cx/"},
.firstMatch(reskwik.body); ));
final token = decrypt(matches!.group(1)!, matches.group(2)!, final matches = RegExp(
matches.group(3)!, int.parse(matches.group(4)!)); r'\("(\S+)",\d+,"(\S+)",(\d+),(\d+)',
).firstMatch(reskwik.body);
final token = decrypt(
matches!.group(1)!,
matches.group(2)!,
matches.group(3)!,
int.parse(matches.group(4)!),
);
final url = RegExp(r'action="([^"]+)"').firstMatch(token)!.group(1)!; final url = RegExp(r'action="([^"]+)"').firstMatch(token)!.group(1)!;
final tok = RegExp(r'value="([^"]+)"').firstMatch(token)!.group(1)!; final tok = RegExp(r'value="([^"]+)"').firstMatch(token)!.group(1)!;
var code = 419; var code = 419;
@@ -175,22 +197,27 @@ class AnimePahe extends MProvider {
String location = ""; String location = "";
while (code != 302 && tries < 20) { while (code != 302 && tries < 20) {
String cookie = String cookie = getMapValue(
getMapValue(json.encode(res.request.headers), "cookie"); json.encode(res.request.headers),
"cookie",
);
cookie += cookie +=
"; ${getMapValue(json.encode(reskwik.headers), "set-cookie").replaceAll("path=/;", "")}"; "; ${getMapValue(json.encode(reskwik.headers), "set-cookie").replaceAll("path=/;", "")}";
final resNo = await Client( final resNo = await Client(
source, source,
json.encode( json.encode({"followRedirects": false, "useDartHttpClient": true}),
{"followRedirects": false, "useDartHttpClient": true})) ).post(
.post(Uri.parse(url), headers: { Uri.parse(url),
headers: {
"referer": reskwik.request.url.toString(), "referer": reskwik.request.url.toString(),
"cookie": cookie, "cookie": cookie,
"user-agent": "user-agent": getMapValue(
getMapValue(json.encode(res.request.headers), "user-agent") json.encode(res.request.headers),
}, body: { "user-agent",
"_token": tok ),
}); },
body: {"_token": tok},
);
code = resNo.statusCode; code = resNo.statusCode;
tries++; tries++;
location = getMapValue(json.encode(resNo.headers), "location"); location = getMapValue(json.encode(resNo.headers), "location");
@@ -205,17 +232,24 @@ class AnimePahe extends MProvider {
..quality = quality; ..quality = quality;
videos.add(video); videos.add(video);
} else { } else {
final ress = (await client.get(Uri.parse(kwikLink), final ress = (await client.get(
headers: {"Referer": "https://animepahe.com"})); Uri.parse(kwikLink),
headers: {"Referer": "https://animepahe.com"},
));
final script = substringAfterLast( final script = substringAfterLast(
xpath(ress.body, xpath(
'//script[contains(text(),"eval(function")]/text()') ress.body,
.first, '//script[contains(text(),"eval(function")]/text()',
"eval(function("); ).first,
"eval(function(",
);
final videoUrl = substringBefore( final videoUrl = substringBefore(
substringAfter(unpackJsAndCombine("eval(function($script"), substringAfter(
"const source=\\'"), unpackJsAndCombine("eval(function($script"),
"\\';"); "const source=\\'",
),
"\\';",
);
MVideo video = MVideo(); MVideo video = MVideo();
video video
..url = videoUrl ..url = videoUrl
@@ -235,7 +269,8 @@ class AnimePahe extends MProvider {
final n = cm.substring(0, b); final n = cm.substring(0, b);
double mx = 0; double mx = 0;
for (var index = 0; index < ctn.length; index++) { for (var index = 0; index < ctn.length; index++) {
mx += (int.tryParse(ctn[ctn.length - index - 1], radix: 10) ?? 0.0) mx +=
(int.tryParse(ctn[ctn.length - index - 1], radix: 10) ?? 0.0)
.toInt() * .toInt() *
(pow(sep, index)); (pow(sep, index));
} }
@@ -269,8 +304,10 @@ class AnimePahe extends MProvider {
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");
String preferredAudio = getPreferenceValue(source.id, "preferred_audio"); // get user's audio preference String preferredAudio = getPreferenceValue(
source.id,
"preferred_audio",
); // get user's audio preference
videos.sort((MVideo a, MVideo b) { videos.sort((MVideo a, MVideo b) {
// Prioritize audio first. // Prioritize audio first.
@@ -314,28 +351,27 @@ class AnimePahe extends MProvider {
title: "Preferred domain", title: "Preferred domain",
summary: "", summary: "",
valueIndex: 1, valueIndex: 1,
entries: [ entries: ["animepahe.com", "animepahe.ru", "animepahe.org"],
"animepahe.com",
"animepahe.ru",
"animepahe.org"
],
entryValues: [ entryValues: [
"https://animepahe.com", "https://animepahe.com",
"https://animepahe.ru", "https://animepahe.ru",
"https://animepahe.org" "https://animepahe.org",
]), ],
),
SwitchPreferenceCompat( SwitchPreferenceCompat(
key: "preffered_link_type", key: "preffered_link_type",
title: "Use HLS links", title: "Use HLS links",
summary: "Enable this if you are having Cloudflare issues.", summary: "Enable this if you are having Cloudflare issues.",
value: false), value: false,
),
ListPreference( ListPreference(
key: "preferred_quality", key: "preferred_quality",
title: "Preferred Quality", title: "Preferred Quality",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["1080p", "720p", "360p"], entries: ["1080p", "720p", "360p"],
entryValues: ["1080", "720", "360"]), entryValues: ["1080", "720", "360"],
),
ListPreference( ListPreference(
key: "preferred_audio", // Add new preference for audio key: "preferred_audio", // Add new preference for audio
@@ -343,7 +379,8 @@ class AnimePahe extends MProvider {
summary: "Select your preferred audio language (Japanese or English).", summary: "Select your preferred audio language (Japanese or English).",
valueIndex: 0, // Default to Japanese (or whichever you prefer) valueIndex: 0, // Default to Japanese (or whichever you prefer)
entries: ["Japanese", "English"], entries: ["Japanese", "English"],
entryValues: ["jpn", "eng"]), entryValues: ["jpn", "eng"],
),
]; ];
} }
} }

View File

@@ -13,4 +13,5 @@ Source _animepaheSource = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/animepahe/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/animepahe/icon.png",
sourceCodeUrl: _animepaheSourceCodeUrl, sourceCodeUrl: _animepaheSourceCodeUrl,
version: _animepaheVersion, version: _animepaheVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

File diff suppressed because it is too large Load Diff

View File

@@ -13,4 +13,5 @@ Source _gogoanimeSource = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/gogoanime/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/gogoanime/icon.png",
sourceCodeUrl: _gogoanimeSourceCodeUrl, sourceCodeUrl: _gogoanimeSourceCodeUrl,
version: _gogoanimeVersion, version: _gogoanimeVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -10,17 +10,21 @@ class NineAnimeTv extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = (await client final res =
.get(Uri.parse("${source.baseUrl}/filter?sort=all&page=$page"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/filter?sort=all&page=$page"),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client.get(Uri.parse( final res =
"${source.baseUrl}/filter?sort=recently_updated&page=$page"))) (await client.get(
.body; Uri.parse(
"${source.baseUrl}/filter?sort=recently_updated&page=$page",
),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@@ -116,30 +120,36 @@ class NineAnimeTv extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"Currently Airing": 0, "Finished Airing": 1} {"Currently Airing": 0, "Finished Airing": 1},
]; ];
final res = (await client.get(Uri.parse("${source.baseUrl}$url"))).body; final res = (await client.get(Uri.parse("${source.baseUrl}$url"))).body;
MManga anime = MManga(); MManga anime = MManga();
final document = parseHtml(res); final document = parseHtml(res);
final infoElement = document.selectFirst("div.film-infor"); final infoElement = document.selectFirst("div.film-infor");
final status = infoElement.xpathFirst( final status =
'//div[contains(text(),"Status:")]/following-sibling::div/span/text()') ?? infoElement.xpathFirst(
'//div[contains(text(),"Status:")]/following-sibling::div/span/text()',
) ??
""; "";
anime.status = parseStatus(status, statusList); anime.status = parseStatus(status, statusList);
anime.description = anime.description =
infoElement.selectFirst("div.film-description > p")?.text ?? ""; infoElement.selectFirst("div.film-description > p")?.text ?? "";
anime.author = infoElement.xpathFirst( anime.author =
'//div[contains(text(),"Studios:")]/following-sibling::div/a/text()') ?? infoElement.xpathFirst(
'//div[contains(text(),"Studios:")]/following-sibling::div/a/text()',
) ??
""; "";
anime.genre = infoElement.xpath( anime.genre = infoElement.xpath(
'//div[contains(text(),"Genre:")]/following-sibling::div/a/text()'); '//div[contains(text(),"Genre:")]/following-sibling::div/a/text()',
);
final id = parseHtml(res).selectFirst("div[data-id]").attr("data-id"); final id = parseHtml(res).selectFirst("div[data-id]").attr("data-id");
final resEp = final resEp =
(await client.get(Uri.parse("${source.baseUrl}/ajax/episode/list/$id"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/ajax/episode/list/$id"),
)).body;
final html = json.decode(resEp)["html"]; final html = json.decode(resEp)["html"];
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
@@ -163,9 +173,10 @@ class NineAnimeTv extends MProvider {
@override @override
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
final res = (await client.get( final res =
Uri.parse("${source.baseUrl}/ajax/episode/servers?episodeId=$url"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/ajax/episode/servers?episodeId=$url"),
)).body;
final html = json.decode(res)["html"]; final html = json.decode(res)["html"];
@@ -178,9 +189,10 @@ class NineAnimeTv extends MProvider {
final name = serverElement.text; final name = serverElement.text;
final id = serverElement.attr("data-id"); final id = serverElement.attr("data-id");
final subDub = serverElement.attr("data-type"); final subDub = serverElement.attr("data-type");
final res = (await client final res =
.get(Uri.parse("${source.baseUrl}/ajax/episode/sources?id=$id"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/ajax/episode/sources?id=$id"),
)).body;
final epUrl = json.decode(res)["link"]; final epUrl = json.decode(res)["link"];
List<MVideo> a = []; List<MVideo> a = [];
@@ -214,17 +226,22 @@ class NineAnimeTv extends MProvider {
Future<List<MVideo>> rapidCloudExtractor(String url, String name) async { Future<List<MVideo>> rapidCloudExtractor(String url, String name) async {
final serverUrl = ['https://megacloud.tv', 'https://rapid-cloud.co']; final serverUrl = ['https://megacloud.tv', 'https://rapid-cloud.co'];
final serverType = url.startsWith('https://megacloud.tv') || url.startsWith('https://megacloud.club') ? 0 : 1; final serverType =
url.startsWith('https://megacloud.tv') ||
url.startsWith('https://megacloud.club')
? 0
: 1;
final sourceUrl = [ final sourceUrl = [
'/embed-2/ajax/e-1/getSources?id=', '/embed-2/ajax/e-1/getSources?id=',
'/ajax/embed-6-v2/getSources?id=' '/ajax/embed-6-v2/getSources?id=',
]; ];
final sourceSpliter = ['/e-1/', '/embed-6-v2/']; final sourceSpliter = ['/e-1/', '/embed-6-v2/'];
final id = url.split(sourceSpliter[serverType]).last.split('?').first; final id = url.split(sourceSpliter[serverType]).last.split('?').first;
final resServer = (await client.get( final resServer =
(await client.get(
Uri.parse('${serverUrl[serverType]}${sourceUrl[serverType]}$id'), Uri.parse('${serverUrl[serverType]}${sourceUrl[serverType]}$id'),
headers: {"X-Requested-With": "XMLHttpRequest"})) headers: {"X-Requested-With": "XMLHttpRequest"},
.body; )).body;
final encrypted = getMapValue(resServer, "encrypted"); final encrypted = getMapValue(resServer, "encrypted");
String videoResJson = ""; String videoResJson = "";
List<MVideo> videos = []; List<MVideo> videos = [];
@@ -245,16 +262,19 @@ class NineAnimeTv extends MProvider {
videoResJson = decryptAESCryptoJS(ciphertext, password); videoResJson = decryptAESCryptoJS(ciphertext, password);
} else { } else {
videoResJson = json.encode( videoResJson = json.encode(
(json.decode(resServer)["sources"] as List<Map<String, dynamic>>)); (json.decode(resServer)["sources"] as List<Map<String, dynamic>>),
);
} }
String masterUrl = String masterUrl =
((json.decode(videoResJson) as List<Map<String, dynamic>>) ((json.decode(videoResJson) as List<Map<String, dynamic>>)
.first)['file']; .first)['file'];
String type = ((json.decode(videoResJson) as List<Map<String, dynamic>>) String type =
((json.decode(videoResJson) as List<Map<String, dynamic>>)
.first)['type']; .first)['type'];
final tracks = (json.decode(resServer)['tracks'] as List) final tracks =
(json.decode(resServer)['tracks'] as List)
.where((e) => e['kind'] == 'captions' ? true : false) .where((e) => e['kind'] == 'captions' ? true : false)
.toList(); .toList();
List<MTrack> subtitles = []; List<MTrack> subtitles = [];
@@ -272,8 +292,10 @@ class NineAnimeTv extends MProvider {
if (type == "hls") { if (type == "hls") {
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -307,19 +329,22 @@ class NineAnimeTv extends MProvider {
Future<List<List<int>>> generateIndexPairs(int serverType) async { Future<List<List<int>>> generateIndexPairs(int serverType) async {
final jsPlayerUrl = [ final jsPlayerUrl = [
"https://megacloud.tv/js/player/a/prod/e1-player.min.js", "https://megacloud.tv/js/player/a/prod/e1-player.min.js",
"https://rapid-cloud.co/js/player/prod/e6-player-v2.min.js" "https://rapid-cloud.co/js/player/prod/e6-player-v2.min.js",
]; ];
final scriptText = final scriptText =
(await client.get(Uri.parse(jsPlayerUrl[serverType]))).body; (await client.get(Uri.parse(jsPlayerUrl[serverType]))).body;
final switchCode = scriptText.substring( final switchCode = scriptText.substring(
scriptText.lastIndexOf('switch'), scriptText.indexOf('=partKey')); scriptText.lastIndexOf('switch'),
scriptText.indexOf('=partKey'),
);
List<int> indexes = []; List<int> indexes = [];
for (var variableMatch for (var variableMatch
in RegExp(r'=(\w+)').allMatches(switchCode).toList()) { in RegExp(r'=(\w+)').allMatches(switchCode).toList()) {
final regex = RegExp( final regex = RegExp(
',${(variableMatch as RegExpMatch).group(1)}=((?:0x)?([0-9a-fA-F]+))'); ',${(variableMatch as RegExpMatch).group(1)}=((?:0x)?([0-9a-fA-F]+))',
);
Match? match = regex.firstMatch(scriptText); Match? match = regex.firstMatch(scriptText);
if (match != null) { if (match != null) {
@@ -391,13 +416,13 @@ class NineAnimeTv extends MProvider {
CheckBoxFilter("Super Power", "31"), CheckBoxFilter("Super Power", "31"),
CheckBoxFilter("Supernatural", "37"), CheckBoxFilter("Supernatural", "37"),
CheckBoxFilter("Thriller", "41"), CheckBoxFilter("Thriller", "41"),
CheckBoxFilter("Vampire", "32") CheckBoxFilter("Vampire", "32"),
]), ]),
GroupFilter("SeasonFilter", "Season", [ GroupFilter("SeasonFilter", "Season", [
CheckBoxFilter("Fall", "3"), CheckBoxFilter("Fall", "3"),
CheckBoxFilter("Summer", "2"), CheckBoxFilter("Summer", "2"),
CheckBoxFilter("Spring", "1"), CheckBoxFilter("Spring", "1"),
CheckBoxFilter("Winter", "4") CheckBoxFilter("Winter", "4"),
]), ]),
GroupFilter("YearFilter", "Year", [ GroupFilter("YearFilter", "Year", [
CheckBoxFilter("2024", "2024"), CheckBoxFilter("2024", "2024"),
@@ -423,7 +448,7 @@ class NineAnimeTv extends MProvider {
CheckBoxFilter("2004", "2004"), CheckBoxFilter("2004", "2004"),
CheckBoxFilter("2003", "2003"), CheckBoxFilter("2003", "2003"),
CheckBoxFilter("2002", "2002"), CheckBoxFilter("2002", "2002"),
CheckBoxFilter("2001", "2001") CheckBoxFilter("2001", "2001"),
]), ]),
SelectFilter("SortFilter", "Sort by", 0, [ SelectFilter("SortFilter", "Sort by", 0, [
SelectFilterOption("All", "all"), SelectFilterOption("All", "all"),
@@ -433,7 +458,7 @@ class NineAnimeTv extends MProvider {
SelectFilterOption("Score", "score"), SelectFilterOption("Score", "score"),
SelectFilterOption("Name A-Z", "name_az"), SelectFilterOption("Name A-Z", "name_az"),
SelectFilterOption("Released Date", "released_date"), SelectFilterOption("Released Date", "released_date"),
SelectFilterOption("Most Watched", "most_watched") SelectFilterOption("Most Watched", "most_watched"),
]), ]),
GroupFilter("TypeFilter", "Type", [ GroupFilter("TypeFilter", "Type", [
CheckBoxFilter("Movie", "1"), CheckBoxFilter("Movie", "1"),
@@ -441,16 +466,18 @@ class NineAnimeTv extends MProvider {
CheckBoxFilter("OVA", "3"), CheckBoxFilter("OVA", "3"),
CheckBoxFilter("ONA", "4"), CheckBoxFilter("ONA", "4"),
CheckBoxFilter("Special", "5"), CheckBoxFilter("Special", "5"),
CheckBoxFilter("Music", "6") CheckBoxFilter("Music", "6"),
]), ]),
SelectFilter("StatusFilter", "Status", 0, [ SelectFilter("StatusFilter", "Status", 0, [
SelectFilterOption("All", "all"), SelectFilterOption("All", "all"),
SelectFilterOption("Finished Airing", "1"), SelectFilterOption("Finished Airing", "1"),
SelectFilterOption("Currently Airing", "2"), SelectFilterOption("Currently Airing", "2"),
SelectFilterOption("Not yet aired", "3") SelectFilterOption("Not yet aired", "3"),
]),
GroupFilter("LanguageFilter", "Language", [
CheckBoxFilter("Sub", "sub"),
CheckBoxFilter("Dub", "dub"),
]), ]),
GroupFilter("LanguageFilter", "Language",
[CheckBoxFilter("Sub", "sub"), CheckBoxFilter("Dub", "dub")]),
]; ];
} }
@@ -463,35 +490,40 @@ class NineAnimeTv extends MProvider {
summary: "", summary: "",
valueIndex: 1, valueIndex: 1,
entries: ["1080p", "720p", "480p", "360p"], entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080", "720", "480", "360"]), entryValues: ["1080", "720", "480", "360"],
),
ListPreference( ListPreference(
key: "preferred_server", key: "preferred_server",
title: "Preferred server", title: "Preferred server",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Vidstreaming", "VidCloud"], entries: ["Vidstreaming", "VidCloud"],
entryValues: ["Vidstreaming", "VidCloud"]), entryValues: ["Vidstreaming", "VidCloud"],
),
ListPreference( ListPreference(
key: "preferred_type", key: "preferred_type",
title: "Preferred Type", title: "Preferred Type",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Sub", "Dub"], entries: ["Sub", "Dub"],
entryValues: ["sub", "dub"]), entryValues: ["sub", "dub"],
),
MultiSelectListPreference( MultiSelectListPreference(
key: "hoster_selection", key: "hoster_selection",
title: "Enable/Disable Hosts", title: "Enable/Disable Hosts",
summary: "", summary: "",
entries: ["Vidstreaming", "VidCloud"], entries: ["Vidstreaming", "VidCloud"],
entryValues: ["Vidstreaming", "Vidcloud"], entryValues: ["Vidstreaming", "Vidcloud"],
values: ["Vidstreaming", "Vidcloud"]), values: ["Vidstreaming", "Vidcloud"],
),
MultiSelectListPreference( MultiSelectListPreference(
key: "type_selection", key: "type_selection",
title: "Enable/Disable Types", title: "Enable/Disable Types",
summary: "", summary: "",
entries: ["Sub", "Dub"], entries: ["Sub", "Dub"],
entryValues: ["sub", "dub"], entryValues: ["sub", "dub"],
values: ["sub", "dub"]), values: ["sub", "dub"],
),
]; ];
} }

View File

@@ -13,4 +13,5 @@ Source _nineanimetv = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/nineanimetv/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/nineanimetv/icon.png",
sourceCodeUrl: _nineanimetvCodeUrl, sourceCodeUrl: _nineanimetvCodeUrl,
version: _nineanimetvVersion, version: _nineanimetvVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -13,4 +13,5 @@ Source _uhdmoviesSource = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/uhdmovies/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/uhdmovies/icon.png",
sourceCodeUrl: _uhdmoviesSourceCodeUrl, sourceCodeUrl: _uhdmoviesSourceCodeUrl,
version: _uhdmoviesVersion, version: _uhdmoviesVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -27,9 +27,10 @@ class UHDMovies extends MProvider {
@override @override
Future<MPages> search(String query, int page, FilterList filterList) async { Future<MPages> search(String query, int page, FilterList filterList) async {
final res = (await client.get( final res =
Uri.parse("$baseUrl/page/$page/?s=${query.replaceAll(" ", "+")}"))) (await client.get(
.body; Uri.parse("$baseUrl/page/$page/?s=${query.replaceAll(" ", "+")}"),
)).body;
return animeFromElement(res); return animeFromElement(res);
} }
@@ -43,10 +44,14 @@ class UHDMovies extends MProvider {
anime.description = description.first; anime.description = description.first;
} }
anime.status = MStatus.ongoing; anime.status = MStatus.ongoing;
final episodesTitles = xpath(res, final episodesTitles = xpath(
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/a[contains(@class, "maxbutton") or contains(@href, "?sid=")]/text()'); res,
final episodesUrls = xpath(res, '//*[contains(@style, "center") or contains(@class, "maxbutton")]/a[contains(@class, "maxbutton") or contains(@href, "?sid=")]/text()',
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/a[contains(@class, "maxbutton") or contains(@href, "?sid=")]/@href'); );
final episodesUrls = xpath(
res,
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/a[contains(@class, "maxbutton") or contains(@href, "?sid=")]/@href',
);
bool isSeries = false; bool isSeries = false;
if (episodesTitles.first.contains("Episode") || if (episodesTitles.first.contains("Episode") ||
episodesTitles.first.contains("Zip") || episodesTitles.first.contains("Zip") ||
@@ -56,8 +61,10 @@ class UHDMovies extends MProvider {
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
if (!isSeries) { if (!isSeries) {
List<String> moviesTitles = []; List<String> moviesTitles = [];
moviesTitles = xpath(res, moviesTitles = xpath(
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/parent::p//preceding-sibling::p[contains(@style, "center")]/text()'); res,
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/parent::p//preceding-sibling::p[contains(@style, "center")]/text()',
);
List<String> titles = []; List<String> titles = [];
if (moviesTitles.isEmpty) { if (moviesTitles.isEmpty) {
moviesTitles = xpath(res, '//p[contains(@style, "center")]/text()'); moviesTitles = xpath(res, '//p[contains(@style, "center")]/text()');
@@ -82,8 +89,10 @@ class UHDMovies extends MProvider {
} }
} else { } else {
List<String> seasonTitles = []; List<String> seasonTitles = [];
final episodeTitles = xpath(res, final episodeTitles = xpath(
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/parent::p//preceding-sibling::p[contains(@style, "center") and not(text()^="Episode")]/text()'); res,
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/parent::p//preceding-sibling::p[contains(@style, "center") and not(text()^="Episode")]/text()',
);
List<String> titles = []; List<String> titles = [];
for (var title in episodeTitles) { for (var title in episodeTitles) {
if (title.isNotEmpty) { if (title.isNotEmpty) {
@@ -132,7 +141,8 @@ class UHDMovies extends MProvider {
value: "https://uhdmovies.fans", value: "https://uhdmovies.fans",
dialogTitle: "Currently used domain", dialogTitle: "Currently used domain",
dialogMessage: "", dialogMessage: "",
text: "https://uhdmovies.fans"), text: "https://uhdmovies.fans",
),
]; ];
} }
@@ -146,8 +156,9 @@ class UHDMovies extends MProvider {
final link = links[i]; final link = links[i];
String decodedLink = link; String decodedLink = link;
if (!link.contains("workers.dev")) { if (!link.contains("workers.dev")) {
decodedLink = utf8 decodedLink = utf8.decode(
.decode(base64Url.decode(substringAfter(link, "download?url="))); base64Url.decode(substringAfter(link, "download?url=")),
);
} }
MVideo video = MVideo(); MVideo video = MVideo();
video video
@@ -184,18 +195,25 @@ class UHDMovies extends MProvider {
final js = xpath(lastDoc, '//script[contains(text(), "/?go=")]/text()'); final js = xpath(lastDoc, '//script[contains(text(), "/?go=")]/text()');
if (js.isEmpty) return ""; if (js.isEmpty) return "";
String script = js.first; String script = js.first;
String nextUrl = String nextUrl = substringBefore(
substringBefore(substringAfter(script, "\"href\",\""), '"'); substringAfter(script, "\"href\",\""),
'"',
);
if (!nextUrl.contains("http")) return ""; if (!nextUrl.contains("http")) return "";
String cookieName = substringAfter(nextUrl, "go="); String cookieName = substringAfter(nextUrl, "go=");
String cookieValue = String cookieValue = substringBefore(
substringBefore(substringAfter(script, "'$cookieName', '"), "'"); substringAfter(script, "'$cookieName', '"),
final response = (await client.get(Uri.parse(nextUrl), "'",
headers: {"referer": url, "Cookie": "$cookieName=$cookieValue"})) );
.body; final response =
(await client.get(
Uri.parse(nextUrl),
headers: {"referer": url, "Cookie": "$cookieName=$cookieValue"},
)).body;
final lastRes = final lastRes = parseHtml(
parseHtml(response).selectFirst("meta[http-equiv]").attr("content"); response,
).selectFirst("meta[http-equiv]").attr("content");
return substringAfter(lastRes, "url="); return substringAfter(lastRes, "url=");
} }
@@ -222,9 +240,12 @@ class UHDMovies extends MProvider {
final name = xpath(html, '//input/@name').first; final name = xpath(html, '//input/@name').first;
final value = xpath(html, '//input/@value').first; final value = xpath(html, '//input/@value').first;
final body = {"$name": value}; final body = {"$name": value};
final response = (await client.post(Uri.parse(urlR.first), final response =
headers: {"referer": url}, body: body)) (await client.post(
.body; Uri.parse(urlR.first),
headers: {"referer": url},
body: body,
)).body;
return recursiveDoc(url, response); return recursiveDoc(url, response);
} }
} }

View File

@@ -21,16 +21,23 @@ class AnimeOnlineNinja extends MProvider {
@override @override
Future<MPages> search(String query, int page, FilterList filterList) async { Future<MPages> search(String query, int page, FilterList filterList) async {
String pageStr = page == 1 ? "" : "page/$page/"; String pageStr = page == 1 ? "" : "page/$page/";
final res = (await client.get(Uri.parse( final res =
"${source.baseUrl}/$pageStr?s=${query.replaceAll(" ", "+")}"))) (await client.get(
.body; Uri.parse(
return parseAnimeList(res, "${source.baseUrl}/$pageStr?s=${query.replaceAll(" ", "+")}",
),
)).body;
return parseAnimeList(
res,
selector: "div.result-item div.image a", selector: "div.result-item div.image a",
hasNextPage: parseHtml(res) hasNextPage:
parseHtml(res)
.selectFirst( .selectFirst(
"div.pagination > *:last-child:not(span):not(.current)") "div.pagination > *:last-child:not(span):not(.current)",
)
?.text != ?.text !=
null); null,
);
} }
@override @override
@@ -39,7 +46,8 @@ class AnimeOnlineNinja extends MProvider {
MManga anime = MManga(); MManga anime = MManga();
final document = parseHtml(res); final document = parseHtml(res);
anime.description = document.selectFirst("div#info").text; anime.description = document.selectFirst("div#info").text;
anime.genre = document anime.genre =
document
.selectFirst("div.sheader") .selectFirst("div.sheader")
.select("div.data > div.sgeneros > a") .select("div.data > div.sgeneros > a")
.map((e) => e.text) .map((e) => e.text)
@@ -82,12 +90,16 @@ class AnimeOnlineNinja extends MProvider {
final type = player.attr("data-type"); final type = player.attr("data-type");
final id = player.attr("data-post"); final id = player.attr("data-post");
final num = player.attr("data-nume"); final num = player.attr("data-nume");
final resUrl = (await client.get(Uri.parse( final resUrl =
"${source.baseUrl}/wp-json/dooplayer/v1/post/$id?type=$type&source=$num"))) (await client.get(
.body; Uri.parse(
final url = "${source.baseUrl}/wp-json/dooplayer/v1/post/$id?type=$type&source=$num",
substringBefore(substringAfter(resUrl, "\"embed_url\":\""), "\",") ),
.replaceAll("\\", ""); )).body;
final url = substringBefore(
substringAfter(resUrl, "\"embed_url\":\""),
"\",",
).replaceAll("\\", "");
videos.addAll(await extractVideos(url, name)); videos.addAll(await extractVideos(url, name));
} }
return sortVideos(videos, source.id); return sortVideos(videos, source.id);
@@ -100,8 +112,11 @@ class AnimeOnlineNinja extends MProvider {
return await extractFromMulti(url); return await extractFromMulti(url);
} else if (["filemoon", "moon", "filemooon"].any((a) => url.contains(a))) { } else if (["filemoon", "moon", "filemooon"].any((a) => url.contains(a))) {
a = await filemoonExtractor(url, "$lang Filemoon - ", ""); a = await filemoonExtractor(url, "$lang Filemoon - ", "");
} else if (["https://dood", "https://ds2play", "https://d0"] } else if ([
.any((a) => url.contains(a))) { "https://dood",
"https://ds2play",
"https://d0",
].any((a) => url.contains(a))) {
a = await doodExtractor(url, "$lang DoodStream"); a = await doodExtractor(url, "$lang DoodStream");
} else if (["streamtape", "stp", "stape"].any((a) => url.contains(a))) { } else if (["streamtape", "stp", "stape"].any((a) => url.contains(a))) {
a = await streamTapeExtractor(url, "$lang StreamTape"); a = await streamTapeExtractor(url, "$lang StreamTape");
@@ -111,8 +126,10 @@ class AnimeOnlineNinja extends MProvider {
final resUrl = (await client.get(Uri.parse(url))).body; final resUrl = (await client.get(Uri.parse(url))).body;
final jsData = final jsData =
parseHtml(resUrl).selectFirst("script:contains(sources)").text; parseHtml(resUrl).selectFirst("script:contains(sources)").text;
final videoUrl = final videoUrl = substringBefore(
substringBefore(substringAfter(jsData, "{file:\""), "\""); substringAfter(jsData, "{file:\""),
"\"",
);
MVideo video = MVideo(); MVideo video = MVideo();
video video
@@ -121,13 +138,20 @@ class AnimeOnlineNinja extends MProvider {
..quality = "$lang WolfStream"; ..quality = "$lang WolfStream";
a = [video]; a = [video];
} else if (["wishembed", "streamwish", "strwish", "wish"] } else if ([
.any((a) => url.contains(a))) { "wishembed",
"streamwish",
"strwish",
"wish",
].any((a) => url.contains(a))) {
a = await streamWishExtractor(url, "$lang StreamWish"); a = await streamWishExtractor(url, "$lang StreamWish");
} else if (url.contains("mp4upload")) { } else if (url.contains("mp4upload")) {
a = await mp4UploadExtractor(url, null, "$lang", ""); a = await mp4UploadExtractor(url, null, "$lang", "");
} else if (["vidhide", "filelions.top", "vid."] } else if ([
.any((a) => url.contains(a))) { "vidhide",
"filelions.top",
"vid.",
].any((a) => url.contains(a))) {
a = await streamHideExtractor(url, lang); a = await streamHideExtractor(url, lang);
} }
videos.addAll(a); videos.addAll(a);
@@ -139,14 +163,17 @@ class AnimeOnlineNinja extends MProvider {
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
final masterUrl = substringBefore( final masterUrl = substringBefore(
substringAfter( substringAfter(
substringAfter( substringAfter(substringAfter(unpackJs(res), "sources:"), "file:\""),
substringAfter(unpackJs(res), "sources:"), "file:\""), "src:\"",
"src:\""), ),
'"'); '"',
);
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
List<MVideo> videos = []; List<MVideo> videos = [];
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -168,16 +195,20 @@ class AnimeOnlineNinja extends MProvider {
} }
Future<List<MVideo>> uqloadExtractor(String url, String lang) async { Future<List<MVideo>> uqloadExtractor(String url, String lang) async {
final Client client = final Client client = Client(
Client(source, json.encode({"useDartHttpClient": true})); source,
json.encode({"useDartHttpClient": true}),
);
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
final js = xpath(res, '//script[contains(text(), "sources:")]/text()'); final js = xpath(res, '//script[contains(text(), "sources:")]/text()');
if (js.isEmpty) { if (js.isEmpty) {
return []; return [];
} }
final videoUrl = final videoUrl = substringBefore(
substringBefore(substringAfter(js.first, "sources: [\""), '"'); substringAfter(js.first, "sources: [\""),
'"',
);
MVideo video = MVideo(); MVideo video = MVideo();
video video
..url = videoUrl ..url = videoUrl
@@ -200,12 +231,16 @@ class AnimeOnlineNinja extends MProvider {
} }
List<MVideo> videos = []; List<MVideo> videos = [];
for (var element in document.select("div.ODDIV $langSelector > li")) { for (var element in document.select("div.ODDIV $langSelector > li")) {
final hosterUrl = final hosterUrl = substringBefore(
substringBefore(substringAfter(element.attr("onclick"), "('"), "')"); substringAfter(element.attr("onclick"), "('"),
"')",
);
String lang = ""; String lang = "";
if (langSelector == "div") { if (langSelector == "div") {
lang = substringBefore( lang = substringBefore(
substringAfter(element.parent?.attr("class"), "OD_", ""), " "); substringAfter(element.parent?.attr("class"), "OD_", ""),
" ",
);
} else { } else {
lang = prefLang; lang = prefLang;
} }
@@ -215,8 +250,11 @@ class AnimeOnlineNinja extends MProvider {
return videos; return videos;
} }
MPages parseAnimeList(String res, MPages parseAnimeList(
{String selector = "article.w_item_a > a", bool hasNextPage = false}) { String res, {
String selector = "article.w_item_a > a",
bool hasNextPage = false,
}) {
final elements = parseHtml(res).select(selector); final elements = parseHtml(res).select(selector);
List<MManga> animeList = []; List<MManga> animeList = [];
for (var element in elements) { for (var element in elements) {
@@ -225,7 +263,8 @@ class AnimeOnlineNinja extends MProvider {
MManga anime = MManga(); MManga anime = MManga();
final img = element.selectFirst("img"); final img = element.selectFirst("img");
anime.name = img.attr("alt"); anime.name = img.attr("alt");
anime.imageUrl = img?.attr("data-src") ?? anime.imageUrl =
img?.attr("data-src") ??
img?.attr("data-lazy-src") ?? img?.attr("data-lazy-src") ??
img?.attr("srcset") ?? img?.attr("srcset") ??
img?.getSrc; img?.getSrc;
@@ -245,7 +284,8 @@ class AnimeOnlineNinja extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["SUB", "All", "ES", "LAT"], entries: ["SUB", "All", "ES", "LAT"],
entryValues: ["SUB", "", "ES", "LAT"]), entryValues: ["SUB", "", "ES", "LAT"],
),
ListPreference( ListPreference(
key: "preferred_server1", key: "preferred_server1",
title: "Preferred server", title: "Preferred server",
@@ -260,7 +300,7 @@ class AnimeOnlineNinja extends MProvider {
"saidochesto.top", "saidochesto.top",
"VidHide", "VidHide",
"StreamWish", "StreamWish",
"Mp4Upload" "Mp4Upload",
], ],
entryValues: [ entryValues: [
"Filemoon", "Filemoon",
@@ -271,8 +311,9 @@ class AnimeOnlineNinja extends MProvider {
"saidochesto.top", "saidochesto.top",
"VidHide", "VidHide",
"StreamWish", "StreamWish",
"Mp4Upload" "Mp4Upload",
]), ],
),
]; ];
} }

View File

@@ -13,4 +13,5 @@ Source _animeonlineninjaSource = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/es/animeonlineninja/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/es/animeonlineninja/icon.png",
sourceCodeUrl: _animeonlineninjaSourceCodeUrl, sourceCodeUrl: _animeonlineninjaSourceCodeUrl,
version: _animeonlineninjaVersion, version: _animeonlineninjaVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -11,15 +11,20 @@ class AnimeSama extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final doc = (await client.get(Uri.parse("${source.baseUrl}/#$page"))).body; final doc = (await client.get(Uri.parse("${source.baseUrl}/#$page"))).body;
final regex = RegExp(r"""^\s*carteClassique\(\s*.*?\s*,\s*"(.*?)".*\)""", final regex = RegExp(
multiLine: true); r"""^\s*carteClassique\(\s*.*?\s*,\s*"(.*?)".*\)""",
multiLine: true,
);
var matches = regex.allMatches(doc).toList(); var matches = regex.allMatches(doc).toList();
List<List<RegExpMatch>> chunks = chunked(matches, 5); List<List<RegExpMatch>> chunks = chunked(matches, 5);
List<MManga> seasons = []; List<MManga> seasons = [];
if (page > 0 && page <= chunks.length) { if (page > 0 && page <= chunks.length) {
for (RegExpMatch match in chunks[page - 1]) { for (RegExpMatch match in chunks[page - 1]) {
seasons.addAll(await fetchAnimeSeasons( seasons.addAll(
"${source.baseUrl}/catalogue/${match.group(1)}")); await fetchAnimeSeasons(
"${source.baseUrl}/catalogue/${match.group(1)}",
),
);
} }
} }
return MPages(seasons, page < chunks.length); return MPages(seasons, page < chunks.length);
@@ -29,18 +34,26 @@ class AnimeSama extends MProvider {
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client.get(Uri.parse(source.baseUrl))).body; final res = (await client.get(Uri.parse(source.baseUrl))).body;
var document = parseHtml(res); var document = parseHtml(res);
final latest = document final latest =
document
.select("h2") .select("h2")
.where((MElement e) => .where(
e.outerHtml.toLowerCase().contains("derniers épisodes ajoutés")) (MElement e) => e.outerHtml.toLowerCase().contains(
"derniers épisodes ajoutés",
),
)
.toList(); .toList();
final seasonElements = (latest.first.parent.nextElementSibling as MElement) final seasonElements =
(latest.first.parent.nextElementSibling as MElement)
.select("div") .select("div")
.toList(); .toList();
List<MManga> seasons = []; List<MManga> seasons = [];
for (var seasonElement in seasonElements) { for (var seasonElement in seasonElements) {
seasons.addAll(await fetchAnimeSeasons( seasons.addAll(
(seasonElement as MElement).getElementsByTagName("a").first.getHref)); await fetchAnimeSeasons(
(seasonElement as MElement).getElementsByTagName("a").first.getHref,
),
);
} }
return MPages(seasons, false); return MPages(seasons, false);
} }
@@ -48,47 +61,72 @@ class AnimeSama extends MProvider {
@override @override
Future<MPages> search(String query, int page, FilterList filterList) async { Future<MPages> search(String query, int page, FilterList filterList) async {
final filters = filterList.filters; final filters = filterList.filters;
final res = (await client final res =
.get(Uri.parse("${source.baseUrl}/catalogue/listing_all.php"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/catalogue/listing_all.php"),
)).body;
var databaseElements = parseHtml(res).select(".cardListAnime"); var databaseElements = parseHtml(res).select(".cardListAnime");
List<MElement> elements = []; List<MElement> elements = [];
elements = databaseElements elements =
.where((MElement element) => element.select("h1, p").any((MElement e) => databaseElements
e.text.toLowerCase().contains(query.toLowerCase().trim()))) .where(
(MElement element) => element
.select("h1, p")
.any(
(MElement e) => e.text.toLowerCase().contains(
query.toLowerCase().trim(),
),
),
)
.toList(); .toList();
for (var filter in filters) { for (var filter in filters) {
if (filter.type == "TypeFilter") { if (filter.type == "TypeFilter") {
final types = (filter.state as List).where((e) => e.state).toList(); final types = (filter.state as List).where((e) => e.state).toList();
elements = elements elements =
.where((MElement element) => elements
.where(
(MElement element) =>
types.isEmpty || types.isEmpty ||
types.any((p) => element.className.contains(p.value))) types.any((p) => element.className.contains(p.value)),
)
.toList(); .toList();
} else if (filter.type == "LanguageFilter") { } else if (filter.type == "LanguageFilter") {
final language = (filter.state as List).where((e) => e.state).toList(); final language = (filter.state as List).where((e) => e.state).toList();
elements = elements elements =
.where((MElement element) => elements
.where(
(MElement element) =>
language.isEmpty || language.isEmpty ||
language.any((p) => element.className.contains(p.value))) language.any((p) => element.className.contains(p.value)),
)
.toList(); .toList();
} else if (filter.type == "GenreFilter") { } else if (filter.type == "GenreFilter") {
final included = (filter.state as List) final included =
(filter.state as List)
.where((e) => e.state == 1 ? true : false) .where((e) => e.state == 1 ? true : false)
.toList(); .toList();
final excluded = (filter.state as List) final excluded =
(filter.state as List)
.where((e) => e.state == 2 ? true : false) .where((e) => e.state == 2 ? true : false)
.toList(); .toList();
if (included.isNotEmpty) { if (included.isNotEmpty) {
elements = elements elements =
.where((MElement element) => elements
included.every((p) => element.className.contains(p.value))) .where(
(MElement element) => included.every(
(p) => element.className.contains(p.value),
),
)
.toList(); .toList();
} }
if (excluded.isNotEmpty) { if (excluded.isNotEmpty) {
elements = elements elements =
.where((MElement element) => elements
excluded.every((p) => element.className.contains(p.value))) .where(
(MElement element) => excluded.every(
(p) => element.className.contains(p.value),
),
)
.toList(); .toList();
} }
} }
@@ -97,8 +135,11 @@ class AnimeSama extends MProvider {
if (chunks.isEmpty) return MPages([], false); if (chunks.isEmpty) return MPages([], false);
List<MManga> seasons = []; List<MManga> seasons = [];
for (var seasonElement in chunks[page - 1]) { for (var seasonElement in chunks[page - 1]) {
seasons.addAll(await fetchAnimeSeasons( seasons.addAll(
seasonElement.getElementsByTagName("a").first.getHref)); await fetchAnimeSeasons(
seasonElement.getElementsByTagName("a").first.getHref,
),
);
} }
return MPages(seasons, page < chunks.length); return MPages(seasons, page < chunks.length);
@@ -108,8 +149,9 @@ class AnimeSama extends MProvider {
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
var animeUrl = var animeUrl =
"${source.baseUrl}${substringBeforeLast(getUrlWithoutDomain(url), "/")}"; "${source.baseUrl}${substringBeforeLast(getUrlWithoutDomain(url), "/")}";
var movie = var movie = int.tryParse(
int.tryParse(url.split("#").length >= 2 ? url.split("#")[1] : ""); url.split("#").length >= 2 ? url.split("#")[1] : "",
);
List<Map<String, dynamic>> playersList = []; List<Map<String, dynamic>> playersList = [];
for (var lang in ["vostfr", "vf"]) { for (var lang in ["vostfr", "vf"]) {
final players = await fetchPlayers("$animeUrl/$lang"); final players = await fetchPlayers("$animeUrl/$lang");
@@ -181,22 +223,23 @@ class AnimeSama extends MProvider {
} }
Future<List<MVideo>> vidmolyExtractor(String url, String lang) async { Future<List<MVideo>> vidmolyExtractor(String url, String lang) async {
final headers = { final headers = {'Referer': 'https://vidmoly.to'};
'Referer': 'https://vidmoly.to',
};
List<MVideo> videos = []; List<MVideo> videos = [];
final playListUrlResponse = (await client.get(Uri.parse(url))).body; final playListUrlResponse = (await client.get(Uri.parse(url))).body;
final playlistUrl = final playlistUrl =
RegExp(r'file:"(\S+?)"').firstMatch(playListUrlResponse)?.group(1) ?? RegExp(r'file:"(\S+?)"').firstMatch(playListUrlResponse)?.group(1) ??
""; "";
if (playlistUrl.isEmpty) return []; if (playlistUrl.isEmpty) return [];
final masterPlaylistRes = final masterPlaylistRes = await client.get(
await client.get(Uri.parse(playlistUrl), headers: headers); Uri.parse(playlistUrl),
headers: headers,
);
if (masterPlaylistRes.statusCode == 200) { if (masterPlaylistRes.statusCode == 200) {
for (var it for (var it in substringAfter(
in substringAfter(masterPlaylistRes.body, "#EXT-X-STREAM-INF:") masterPlaylistRes.body,
.split("#EXT-X-STREAM-INF:")) { "#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -230,8 +273,10 @@ class AnimeSama extends MProvider {
if (masterUrl.contains(".m3u8")) { if (masterUrl.contains(".m3u8")) {
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -317,14 +362,16 @@ class AnimeSama extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["1080p", "720p", "480p", "360p"], entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080", "720", "480", "360"]), entryValues: ["1080", "720", "480", "360"],
),
ListPreference( ListPreference(
key: "voices_preference", key: "voices_preference",
title: "Préférence des voix", title: "Préférence des voix",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Préférer VOSTFR", "Préférer VF"], entries: ["Préférer VOSTFR", "Préférer VF"],
entryValues: ["vostfr", "vf"]), entryValues: ["vostfr", "vf"],
),
]; ];
} }
@@ -349,8 +396,10 @@ class AnimeSama extends MProvider {
var moviesUrl = "$url/$seasonStem"; var moviesUrl = "$url/$seasonStem";
var movies = await fetchPlayers(moviesUrl); var movies = await fetchPlayers(moviesUrl);
if (movies.isNotEmpty) { if (movies.isNotEmpty) {
var movieNameRegex = var movieNameRegex = RegExp(
RegExp("^\\s*newSPF\\(\"(.*)\"\\);", multiLine: true); "^\\s*newSPF\\(\"(.*)\"\\);",
multiLine: true,
);
var moviesDoc = (await client.get(Uri.parse(moviesUrl))).body; var moviesDoc = (await client.get(Uri.parse(moviesUrl))).body;
List<RegExpMatch> matches = List<RegExpMatch> matches =
movieNameRegex.allMatches(moviesDoc).toList(); movieNameRegex.allMatches(moviesDoc).toList();
@@ -369,11 +418,14 @@ class AnimeSama extends MProvider {
MManga anime = MManga(); MManga anime = MManga();
anime.imageUrl = document.getElementById("coverOeuvre")?.getSrc; anime.imageUrl = document.getElementById("coverOeuvre")?.getSrc;
anime.genre = (document.xpathFirst( anime.genre = (document.xpathFirst(
'//h2[contains(text(),"Genres")]/following-sibling::a/text()') ?? '//h2[contains(text(),"Genres")]/following-sibling::a/text()',
) ??
"") "")
.split(","); .split(",");
anime.description = document.xpathFirst( anime.description =
'//h2[contains(text(),"Synopsis")]/following-sibling::p/text()') ?? document.xpathFirst(
'//h2[contains(text(),"Synopsis")]/following-sibling::p/text()',
) ??
""; "";
anime.name = title; anime.name = title;
@@ -386,11 +438,14 @@ class AnimeSama extends MProvider {
MManga anime = MManga(); MManga anime = MManga();
anime.imageUrl = document.getElementById("coverOeuvre")?.getSrc; anime.imageUrl = document.getElementById("coverOeuvre")?.getSrc;
anime.genre = (document.xpathFirst( anime.genre = (document.xpathFirst(
'//h2[contains(text(),"Genres")]/following-sibling::a/text()') ?? '//h2[contains(text(),"Genres")]/following-sibling::a/text()',
) ??
"") "")
.split(","); .split(",");
anime.description = document.xpathFirst( anime.description =
'//h2[contains(text(),"Synopsis")]/following-sibling::p/text()') ?? document.xpathFirst(
'//h2[contains(text(),"Synopsis")]/following-sibling::p/text()',
) ??
""; "";
anime.name = anime.name =
'$animeName ${substringBefore(seasonName, ',').replaceAll('"', "")}'; '$animeName ${substringBefore(seasonName, ',').replaceAll('"', "")}';
@@ -448,7 +503,9 @@ class AnimeSama extends MProvider {
String sanitizeEpisodesJs(String doc) { String sanitizeEpisodesJs(String doc) {
return doc.replaceAll( return doc.replaceAll(
RegExp(r'(?<=\[|\,)\s*\"\s*(https?://[^\s\"]+)\s*\"\s*(?=\,|\])'), ''); RegExp(r'(?<=\[|\,)\s*\"\s*(https?://[^\s\"]+)\s*\"\s*(?=\,|\])'),
'',
);
} }
List<List<dynamic>> chunked(List<dynamic> list, int size) { List<List<dynamic>> chunked(List<dynamic> list, int size) {

View File

@@ -13,4 +13,5 @@ Source _animesama = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/fr/animesama/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/fr/animesama/icon.png",
sourceCodeUrl: animesamaCodeUrl, sourceCodeUrl: animesamaCodeUrl,
version: animesamaVersion, version: animesamaVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -16,12 +16,18 @@ class AnimesUltra extends MProvider {
final res = (await client.get(Uri.parse(baseUrl))).body; final res = (await client.get(Uri.parse(baseUrl))).body;
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = xpath(res, final urls = xpath(
'//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/@href'); res,
final names = xpath(res, '//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/@href',
'//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/img/@title'); );
final images = xpath(res, final names = xpath(
'//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/img/@data-src'); res,
'//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/img/@title',
);
final images = xpath(
res,
'//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/img/@data-src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -39,12 +45,18 @@ class AnimesUltra extends MProvider {
final res = (await client.get(Uri.parse(baseUrl))).body; final res = (await client.get(Uri.parse(baseUrl))).body;
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = xpath(res, final urls = xpath(
'//*[@class="block_area block_area_home"]/div[@class="tab-content"]/div[contains(@class,"block_area-content block_area-list")]/div[@class="film_list-wrap"]/div[@class="flw-item"]/div[@class="film-poster"]/a/@href'); res,
final names = xpath(res, '//*[@class="block_area block_area_home"]/div[@class="tab-content"]/div[contains(@class,"block_area-content block_area-list")]/div[@class="film_list-wrap"]/div[@class="flw-item"]/div[@class="film-poster"]/a/@href',
'//*[@class="block_area block_area_home"]/div[@class="tab-content"]/div[contains(@class,"block_area-content block_area-list")]/div[@class="film_list-wrap"]/div[@class="flw-item"]/div[@class="film-poster"]/a/@title'); );
final images = xpath(res, final names = xpath(
'//*[@class="block_area block_area_home"]/div[@class="tab-content"]/div[contains(@class,"block_area-content block_area-list")]/div[@class="film_list-wrap"]/div[@class="flw-item"]/div[@class="film-poster"]/img/@data-src'); res,
'//*[@class="block_area block_area_home"]/div[@class="tab-content"]/div[contains(@class,"block_area-content block_area-list")]/div[@class="film_list-wrap"]/div[@class="flw-item"]/div[@class="film-poster"]/a/@title',
);
final images = xpath(
res,
'//*[@class="block_area block_area_home"]/div[@class="tab-content"]/div[contains(@class,"block_area-content block_area-list")]/div[@class="film_list-wrap"]/div[@class="flw-item"]/div[@class="film-poster"]/img/@data-src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -60,9 +72,12 @@ class AnimesUltra extends MProvider {
@override @override
Future<MPages> search(String query, int page, FilterList filterList) async { Future<MPages> search(String query, int page, FilterList filterList) async {
query = query.trim().replaceAll(" ", "+"); query = query.trim().replaceAll(" ", "+");
final res = (await client.get(Uri.parse( final res =
"$baseUrl/index.php?do=search&subaction=search&story=$query"))) (await client.get(
.body; Uri.parse(
"$baseUrl/index.php?do=search&subaction=search&story=$query",
),
)).body;
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = xpath(res, '//*[@class="film-poster"]/a/@href'); final urls = xpath(res, '//*[@class="film-poster"]/a/@href');
@@ -83,7 +98,7 @@ class AnimesUltra extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"En cours": 0, "Terminé": 1} {"En cours": 0, "Terminé": 1},
]; ];
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
@@ -92,17 +107,25 @@ class AnimesUltra extends MProvider {
anime.description = anime.description =
xpath(res, '//*[@class="film-description m-hide"]/text()').first; xpath(res, '//*[@class="film-description m-hide"]/text()').first;
final status = xpath(res, final status =
'//*[@class="item item-title" and contains(text(),"Status:")]/span[2]/text()') xpath(
.first; res,
'//*[@class="item item-title" and contains(text(),"Status:")]/span[2]/text()',
).first;
anime.status = parseStatus(status, statusList); anime.status = parseStatus(status, statusList);
anime.genre = xpath(res, anime.genre = xpath(
'//*[@class="item item-list" and contains(text(),"Genres:")]/a/text()'); res,
'//*[@class="item item-list" and contains(text(),"Genres:")]/a/text()',
);
anime.author = doc.xpathFirst( anime.author = doc.xpathFirst(
'//*[@class="item item-title" and contains(text(),"Studio:")]/span[2]/text()'); '//*[@class="item item-title" and contains(text(),"Studio:")]/span[2]/text()',
final episodesLength = int.parse(substringBefore( );
doc.xpathFirst('//*[@class="film-stats"]/span[7]/text()'), "/") final episodesLength = int.parse(
.replaceAll("Ep", "")); substringBefore(
doc.xpathFirst('//*[@class="film-stats"]/span[7]/text()'),
"/",
).replaceAll("Ep", ""),
);
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
for (var i = 0; i < episodesLength; i++) { for (var i = 0; i < episodesLength; i++) {
@@ -119,18 +142,23 @@ class AnimesUltra extends MProvider {
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
final resHtml = (await client.get(Uri.parse(url))).body; final resHtml = (await client.get(Uri.parse(url))).body;
final id = url.split('/')[4].split('-')[0]; final id = url.split('/')[4].split('-')[0];
final resServer = (await client final resServer =
.get(Uri.parse("$baseUrl/engine/ajax/full-story.php?newsId=$id"))) (await client.get(
.body; Uri.parse("$baseUrl/engine/ajax/full-story.php?newsId=$id"),
)).body;
final serverIds = final serverIds = xpath(
xpath(resHtml, '//*[@class="ps__-list"]/div/@data-server-id'); resHtml,
'//*[@class="ps__-list"]/div/@data-server-id',
);
final serverNames = xpath(resHtml, '//*[@class="ps__-list"]/div/a/text()'); final serverNames = xpath(resHtml, '//*[@class="ps__-list"]/div/a/text()');
List<String> serverUrls = []; List<String> serverUrls = [];
for (var id in serverIds) { for (var id in serverIds) {
final serversUrls = xpath(jsonDecode(resServer)["html"], final serversUrls =
'//*[@id="content_player_${id}"]/text()') xpath(
.first; jsonDecode(resServer)["html"],
'//*[@id="content_player_${id}"]/text()',
).first;
serverUrls.add(serversUrls); serverUrls.add(serversUrls);
} }
List<MVideo> videos = []; List<MVideo> videos = [];
@@ -140,10 +168,13 @@ class AnimesUltra extends MProvider {
List<MVideo> a = []; List<MVideo> a = [];
if (name.contains("Sendvid")) { if (name.contains("Sendvid")) {
a = await sendVidExtractorr( a = await sendVidExtractorr(
url.replaceAll("https:////", "https://"), ""); url.replaceAll("https:////", "https://"),
"",
);
} else if (name.contains("Sibnet")) { } else if (name.contains("Sibnet")) {
a = await sibnetExtractor( a = await sibnetExtractor(
"https://video.sibnet.ru/shell.php?videoid=$url"); "https://video.sibnet.ru/shell.php?videoid=$url",
);
} else if (name.contains("Mytv")) { } else if (name.contains("Mytv")) {
a = await myTvExtractor("https://www.myvi.tv/embed/$url"); a = await myTvExtractor("https://www.myvi.tv/embed/$url");
} else if (name.contains("Fmoon")) { } else if (name.contains("Fmoon")) {
@@ -170,8 +201,10 @@ class AnimesUltra extends MProvider {
if (masterUrl.contains(".m3u8")) { if (masterUrl.contains(".m3u8")) {
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";

View File

@@ -14,4 +14,5 @@ Source _animesultraSource = Source(
sourceCodeUrl: _animesultraSourceCodeUrl, sourceCodeUrl: _animesultraSourceCodeUrl,
version: _animesultraVersion, version: _animesultraVersion,
itemType: ItemType.anime, itemType: ItemType.anime,
isFullData: false); isFullData: false,
);

View File

@@ -58,7 +58,7 @@ class AniZone extends MProvider {
"status": [], "status": [],
"season": [], "season": [],
"lang": [], "lang": [],
"genre": [] "genre": [],
}; };
// Regroupement des filtres avec une logique générique // Regroupement des filtres avec une logique générique
@@ -67,7 +67,7 @@ class AniZone extends MProvider {
"LanguageFilter": "lang", "LanguageFilter": "lang",
"SaisonFilter": "season", "SaisonFilter": "season",
"StatusFilter": "status", "StatusFilter": "status",
"GenreFilter": "genre" "GenreFilter": "genre",
}; };
for (var filter in filterList.filters) { for (var filter in filterList.filters) {
@@ -99,8 +99,10 @@ class AniZone extends MProvider {
final description = xpath(doc, '//p[contains(@class,"short")]/text()'); final description = xpath(doc, '//p[contains(@class,"short")]/text()');
anime.description = description.isNotEmpty ? description.first : ""; anime.description = description.isNotEmpty ? description.first : "";
final statusList = xpath(doc, final statusList = xpath(
'//div[contains(@class,"col2")]//div[contains(@class,"item")]//div[contains(@class,"item-content")]/text()'); doc,
'//div[contains(@class,"col2")]//div[contains(@class,"item")]//div[contains(@class,"item-content")]/text()',
);
if (statusList.isNotEmpty) { if (statusList.isNotEmpty) {
if (statusList[0] == "Terminer") { if (statusList[0] == "Terminer") {
anime.status = MStatus.completed; anime.status = MStatus.completed;
@@ -113,8 +115,10 @@ class AniZone extends MProvider {
anime.status = MStatus.unknown; anime.status = MStatus.unknown;
} }
anime.genre = xpath(doc, anime.genre = xpath(
'//div[contains(@class,"item")]//div[contains(@class,"item-content")]//a[contains(@href,"genre")]/text()'); doc,
'//div[contains(@class,"item")]//div[contains(@class,"item-content")]//a[contains(@href,"genre")]/text()',
);
final regex = RegExp(r'(\d+)$'); final regex = RegExp(r'(\d+)$');
final match = regex.firstMatch(url); final match = regex.firstMatch(url);
@@ -123,14 +127,16 @@ class AniZone extends MProvider {
throw Exception('Numéro de l\'épisode non trouvé dans l\'URL.'); throw Exception('Numéro de l\'épisode non trouvé dans l\'URL.');
} }
final res = (await client.get(Uri.parse( final res =
"${source.baseUrl}/ajax/episode/list/${match.group(1)}"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/ajax/episode/list/${match.group(1)}"),
)).body;
List<MChapter> episodesList = []; List<MChapter> episodesList = [];
final episodeElements = final episodeElements = parseHtml(
parseHtml(json.decode(res)["html"]).select(".ep-item"); json.decode(res)["html"],
).select(".ep-item");
// Associer chaque titre à son URL et récupérer les vidéos // Associer chaque titre à son URL et récupérer les vidéos
for (var element in episodeElements) { for (var element in episodeElements) {
@@ -152,16 +158,24 @@ class AniZone extends MProvider {
@override @override
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
final videoRes = (await client final videoRes =
.get(Uri.parse(url), headers: {"Referer": "${source.baseUrl}/"})) (await client.get(
.body; Uri.parse(url),
headers: {"Referer": "${source.baseUrl}/"},
)).body;
final lang = xpath(videoRes.replaceAll(r'\', ''), final lang = xpath(
'//div[contains(@class,"item server-item")]/@data-type'); videoRes.replaceAll(r'\', ''),
final links = xpath(videoRes.replaceAll(r'\', ''), '//div[contains(@class,"item server-item")]/@data-type',
'//div[contains(@class,"item server-item")]/@data-id'); );
final playersNames = xpath(videoRes.replaceAll(r'\', ''), final links = xpath(
'//div[contains(@class,"item server-item")]/text()'); videoRes.replaceAll(r'\', ''),
'//div[contains(@class,"item server-item")]/@data-id',
);
final playersNames = xpath(
videoRes.replaceAll(r'\', ''),
'//div[contains(@class,"item server-item")]/text()',
);
List<Map<String, String>> players = []; List<Map<String, String>> players = [];
for (int j = 0; j < links.length; j++) { for (int j = 0; j < links.length; j++) {
// schema of players https://v1.animesz.xyz/ajax/episode/servers?episodeId=(id_episode) // schema of players https://v1.animesz.xyz/ajax/episode/servers?episodeId=(id_episode)
@@ -215,14 +229,17 @@ class AniZone extends MProvider {
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
final masterUrl = substringBefore( final masterUrl = substringBefore(
substringAfter( substringAfter(
substringAfter( substringAfter(substringAfter(unpackJs(res), "sources:"), "file:\""),
substringAfter(unpackJs(res), "sources:"), "file:\""), "src:\"",
"src:\""), ),
'"'); '"',
);
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
List<MVideo> videos = []; List<MVideo> videos = [];
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -314,7 +331,7 @@ class AniZone extends MProvider {
CheckBoxFilter("Vampire", "32"), CheckBoxFilter("Vampire", "32"),
CheckBoxFilter("Yaoi", "33"), CheckBoxFilter("Yaoi", "33"),
CheckBoxFilter("Yuri", "34"), CheckBoxFilter("Yuri", "34"),
]) ]),
]; ];
} }
@@ -327,14 +344,16 @@ class AniZone extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["1080p", "720p", "480p", "360p"], entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080", "720", "480", "360"]), entryValues: ["1080", "720", "480", "360"],
),
ListPreference( ListPreference(
key: "voices_preference", key: "voices_preference",
title: "Préférence des voix", title: "Préférence des voix",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["Préférer VOSTFR", "Préférer VF"], entries: ["Préférer VOSTFR", "Préférer VF"],
entryValues: ["vostfr", "vf"]), entryValues: ["vostfr", "vf"],
),
]; ];
} }
@@ -383,8 +402,10 @@ class AniZone extends MProvider {
if (masterUrl.contains(".m3u8")) { if (masterUrl.contains(".m3u8")) {
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -437,7 +458,8 @@ class AniZone extends MProvider {
final masterPlaylistRes = await client.get(Uri.parse(masterUrl)); final masterPlaylistRes = await client.get(Uri.parse(masterUrl));
if (masterPlaylistRes.statusCode != 200) { if (masterPlaylistRes.statusCode != 200) {
print( print(
"Error lors de la récupération de la playlist M3U8 : ${masterPlaylistRes.statusCode}"); "Error lors de la récupération de la playlist M3U8 : ${masterPlaylistRes.statusCode}",
);
return []; return [];
} }

View File

@@ -13,4 +13,5 @@ Source _aniZoneSource = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/fr/anizone/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/fr/anizone/icon.png",
sourceCodeUrl: _aniZoneSourceCodeUrl, sourceCodeUrl: _aniZoneSourceCodeUrl,
version: _aniZoneVersion, version: _aniZoneVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -46,8 +46,9 @@ class FrAnime extends MProvider {
var seasonsJson = seasons.first; var seasonsJson = seasons.first;
if (url.contains("s=")) { if (url.contains("s=")) {
int seasonNumber = int seasonNumber = int.parse(
int.parse(substringBefore(substringAfter(url, "s="), "&")); substringBefore(substringAfter(url, "s="), "&"),
);
seasonsJson = seasons[seasonNumber - 1]; seasonsJson = seasons[seasonNumber - 1];
} }
@@ -103,8 +104,9 @@ class FrAnime extends MProvider {
videoBaseUrl += "/$animeId/"; videoBaseUrl += "/$animeId/";
if (url.contains("s=")) { if (url.contains("s=")) {
int seasonNumber = int seasonNumber = int.parse(
int.parse(substringBefore(substringAfter(url, "s="), "&")); substringBefore(substringAfter(url, "s="), "&"),
);
videoBaseUrl += "${seasonNumber - 1}/"; videoBaseUrl += "${seasonNumber - 1}/";
seasonsJson = seasons[seasonNumber - 1]; seasonsJson = seasons[seasonNumber - 1];
} else { } else {
@@ -141,17 +143,21 @@ class FrAnime extends MProvider {
MVideo video = MVideo(); MVideo video = MVideo();
final playerUrl = (await client.get(Uri.parse(apiUrl), final playerUrl =
headers: {"Referer": "https://franime.fr/"})) (await client.get(
.body; Uri.parse(apiUrl),
headers: {"Referer": "https://franime.fr/"},
)).body;
List<MVideo> a = []; List<MVideo> a = [];
print(playerName); print(playerName);
if (playerName.contains("vido")) { if (playerName.contains("vido")) {
videos.add(video videos.add(
video
..url = playerUrl ..url = playerUrl
..originalUrl = playerUrl ..originalUrl = playerUrl
..quality = "FRAnime (Vido)"); ..quality = "FRAnime (Vido)",
);
} else if (playerName.contains("sendvid")) { } else if (playerName.contains("sendvid")) {
a = await sendVidExtractorr(playerUrl, ""); a = await sendVidExtractorr(playerUrl, "");
} else if (playerName.contains("sibnet")) { } else if (playerName.contains("sibnet")) {
@@ -165,7 +171,7 @@ class FrAnime extends MProvider {
MPages animeResList(String res) { MPages animeResList(String res) {
final statusList = [ final statusList = [
{"EN COURS": 0, "TERMINÉ": 1} {"EN COURS": 0, "TERMINÉ": 1},
]; ];
List<MManga> animeList = []; List<MManga> animeList = [];
@@ -233,7 +239,7 @@ class FrAnime extends MProvider {
MPages animeSeachFetch(String res, String query) { MPages animeSeachFetch(String res, String query) {
final statusList = [ final statusList = [
{"EN COURS": 0, "TERMINÉ": 1} {"EN COURS": 0, "TERMINÉ": 1},
]; ];
List<MManga> animeList = []; List<MManga> animeList = [];
final jsonResList = json.decode(res); final jsonResList = json.decode(res);
@@ -241,20 +247,23 @@ class FrAnime extends MProvider {
MManga anime = MManga(); MManga anime = MManga();
final titleO = getMapValue(json.encode(animeJson), "titleO"); final titleO = getMapValue(json.encode(animeJson), "titleO");
final titleAlt = final titleAlt = getMapValue(
getMapValue(json.encode(animeJson), "titles", encode: true); json.encode(animeJson),
final containsEn = getMapValue(titleAlt, "en") "titles",
.toString() encode: true,
.toLowerCase() );
.contains(query.toLowerCase()); final containsEn = getMapValue(
final containsEnJp = getMapValue(titleAlt, "en_jp") titleAlt,
.toString() "en",
.toLowerCase() ).toString().toLowerCase().contains(query.toLowerCase());
.contains(query.toLowerCase()); final containsEnJp = getMapValue(
final containsJaJp = getMapValue(titleAlt, "ja_jp") titleAlt,
.toString() "en_jp",
.toLowerCase() ).toString().toLowerCase().contains(query.toLowerCase());
.contains(query.toLowerCase()); final containsJaJp = getMapValue(
titleAlt,
"ja_jp",
).toString().toLowerCase().contains(query.toLowerCase());
final containsTitleO = titleO.toLowerCase().contains(query.toLowerCase()); final containsTitleO = titleO.toLowerCase().contains(query.toLowerCase());
if (containsEn || containsEnJp || containsJaJp || containsTitleO) { if (containsEn || containsEnJp || containsJaJp || containsTitleO) {
@@ -319,16 +328,19 @@ class FrAnime extends MProvider {
} }
Future<String> dataBase() async { Future<String> dataBase() async {
return (await client.get(Uri.parse("https://api.franime.fr/api/animes/"), return (await client.get(
headers: {"Referer": "https://franime.fr/"})) Uri.parse("https://api.franime.fr/api/animes/"),
.body; headers: {"Referer": "https://franime.fr/"},
)).body;
} }
String databaseAnimeByTitleO(String res, String titleO) { String databaseAnimeByTitleO(String res, String titleO) {
final datas = json.decode(res) as List<Map<String, dynamic>>; final datas = json.decode(res) as List<Map<String, dynamic>>;
for (var data in datas) { for (var data in datas) {
String title = String title = (data["titleO"] as String).replaceAll(
(data["titleO"] as String).replaceAll(RegExp("[^A-Za-z0-9 ]"), ""); RegExp("[^A-Za-z0-9 ]"),
"",
);
if (title.replaceAll(" ", "-").toLowerCase() == "${titleO}") { if (title.replaceAll(" ", "-").toLowerCase() == "${titleO}") {
return json.encode(data); return json.encode(data);
} }
@@ -351,8 +363,10 @@ class FrAnime extends MProvider {
if (masterUrl.contains(".m3u8")) { if (masterUrl.contains(".m3u8")) {
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";

View File

@@ -15,4 +15,5 @@ Source _franimeSource = Source(
sourceCodeUrl: _franimeSourceCodeUrl, sourceCodeUrl: _franimeSourceCodeUrl,
version: _franimeVersion, version: _franimeVersion,
itemType: ItemType.anime, itemType: ItemType.anime,
isFullData: true); isFullData: true,
);

View File

@@ -16,12 +16,18 @@ class OtakuFr extends MProvider {
final res = final res =
(await client.get(Uri.parse("$baseUrl/en-cours/page/$page"))).body; (await client.get(Uri.parse("$baseUrl/en-cours/page/$page"))).body;
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = final urls = xpath(
xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href'); res,
final names = '//*[@class="list"]/article/div/div/figure/a/@href',
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@title'); );
final images = final names = xpath(
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@src'); res,
'//*[@class="list"]/article/div/div/figure/a/img/@title',
);
final images = xpath(
res,
'//*[@class="list"]/article/div/div/figure/a/img/@src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -43,12 +49,14 @@ class OtakuFr extends MProvider {
final namess = xpath(res, '//*[@class="episode"]/div/a/text()'); final namess = xpath(res, '//*[@class="episode"]/div/a/text()');
List<String> names = []; List<String> names = [];
for (var name in namess) { for (var name in namess) {
names.add(regExp( names.add(
regExp(
name, name,
r'(?<=\bS\d\s*|)\d{2}\s*(?=\b(Vostfr|vostfr|VF|Vf|vf|\(VF\)|\(vf\)|\(Vf\)|\(Vostfr\)\b))?', r'(?<=\bS\d\s*|)\d{2}\s*(?=\b(Vostfr|vostfr|VF|Vf|vf|\(VF\)|\(vf\)|\(Vf\)|\(Vostfr\)\b))?',
'', '',
0, 0,
0) 0,
)
.replaceAll(' vostfr', '') .replaceAll(' vostfr', '')
.replaceAll(' Vostfr', '') .replaceAll(' Vostfr', '')
.replaceAll(' VF', '') .replaceAll(' VF', '')
@@ -58,7 +66,8 @@ class OtakuFr extends MProvider {
.replaceAll(' (vf)', '') .replaceAll(' (vf)', '')
.replaceAll(' (vf)', '') .replaceAll(' (vf)', '')
.replaceAll(' (Vf)', '') .replaceAll(' (Vf)', '')
.replaceAll(' (Vostfr)', '')); .replaceAll(' (Vostfr)', ''),
);
} }
final images = xpath(res, '//*[@class="episode"]/div/figure/a/img/@src'); final images = xpath(res, '//*[@class="episode"]/div/figure/a/img/@src');
@@ -98,12 +107,18 @@ class OtakuFr extends MProvider {
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = final urls = xpath(
xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href'); res,
final names = '//*[@class="list"]/article/div/div/figure/a/@href',
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@title'); );
final images = final names = xpath(
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@src'); res,
'//*[@class="list"]/article/div/div/figure/a/img/@title',
);
final images = xpath(
res,
'//*[@class="list"]/article/div/div/figure/a/img/@src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -119,35 +134,48 @@ class OtakuFr extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"En cours": 0, "Terminé": 1} {"En cours": 0, "Terminé": 1},
]; ];
String res = String res =
(await client.get(Uri.parse("$baseUrl${getUrlWithoutDomain(url)}"))) (await client.get(
.body; Uri.parse("$baseUrl${getUrlWithoutDomain(url)}"),
)).body;
MManga anime = MManga(); MManga anime = MManga();
final originalUrl = xpath(res, final originalUrl = xpath(
'//*[@class="breadcrumb"]/li[@class="breadcrumb-item"][2]/a/@href'); res,
'//*[@class="breadcrumb"]/li[@class="breadcrumb-item"][2]/a/@href',
);
if (originalUrl.isNotEmpty) { if (originalUrl.isNotEmpty) {
res = (await client.get(Uri.parse(originalUrl.first))).body; res = (await client.get(Uri.parse(originalUrl.first))).body;
} }
final description = final description = xpath(
xpath(res, '//*[@class="episode fz-sm synop"]/p/text()'); res,
'//*[@class="episode fz-sm synop"]/p/text()',
);
if (description.isNotEmpty) { if (description.isNotEmpty) {
anime.description = description.first.replaceAll("Synopsis:", ""); anime.description = description.first.replaceAll("Synopsis:", "");
} }
final status = xpath(res, final status = xpath(
'//*[@class="list-unstyled"]/li[contains(text(),"Statut")]/text()'); res,
'//*[@class="list-unstyled"]/li[contains(text(),"Statut")]/text()',
);
if (status.isNotEmpty) { if (status.isNotEmpty) {
anime.status = anime.status = parseStatus(
parseStatus(status.first.replaceAll("Statut: ", ""), statusList); status.first.replaceAll("Statut: ", ""),
statusList,
);
} }
anime.genre = xpath(res, anime.genre = xpath(
'//*[@class="list-unstyled"]/li[contains(text(),"Genre")]/ul/li/a/text()'); res,
'//*[@class="list-unstyled"]/li[contains(text(),"Genre")]/ul/li/a/text()',
);
final epUrls = xpath(res, '//*[@class="list-episodes list-group"]/a/@href'); final epUrls = xpath(res, '//*[@class="list-episodes list-group"]/a/@href');
final dates = final dates = xpath(
xpath(res, '//*[@class="list-episodes list-group"]/a/span/text()'); res,
'//*[@class="list-episodes list-group"]/a/span/text()',
);
final names = xpath(res, '//*[@class="list-episodes list-group"]/a/text()'); final names = xpath(res, '//*[@class="list-episodes list-group"]/a/text()');
List<String> episodes = []; List<String> episodes = [];
@@ -155,7 +183,8 @@ class OtakuFr extends MProvider {
final date = dates[i]; final date = dates[i];
final name = names[i]; final name = names[i];
episodes.add( episodes.add(
"Episode ${regExp(name.replaceAll(date, ""), r".* (\d*) [VvfF]{1,1}", '', 1, 1)}"); "Episode ${regExp(name.replaceAll(date, ""), r".* (\d*) [VvfF]{1,1}", '', 1, 1)}",
);
} }
final dateUploads = parseDates(dates, "dd MMMM yyyy", "fr"); final dateUploads = parseDates(dates, "dd MMMM yyyy", "fr");
@@ -175,19 +204,23 @@ class OtakuFr extends MProvider {
@override @override
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
final res = final res =
(await client.get(Uri.parse("$baseUrl${getUrlWithoutDomain(url)}"))) (await client.get(
.body; Uri.parse("$baseUrl${getUrlWithoutDomain(url)}"),
)).body;
final servers = parseHtml(res).select("div.tab-content iframe[src]"); final servers = parseHtml(res).select("div.tab-content iframe[src]");
List<MVideo> videos = []; List<MVideo> videos = [];
final hosterSelection = preferenceHosterSelection(source.id); final hosterSelection = preferenceHosterSelection(source.id);
for (var url in servers) { for (var url in servers) {
final urll = url.getSrc != "about:blank" ? url.getSrc : url.getDataSrc; final urll = url.getSrc != "about:blank" ? url.getSrc : url.getDataSrc;
final resServer = (await client.get(Uri.parse(fixUrl(urll)), final resServer =
headers: {"X-Requested-With": "XMLHttpRequest"})) (await client.get(
.body; Uri.parse(fixUrl(urll)),
final serverUrl = headers: {"X-Requested-With": "XMLHttpRequest"},
fixUrl(regExp(resServer, r"data-url='([^']+)'", '', 1, 1)); )).body;
final serverUrl = fixUrl(
regExp(resServer, r"data-url='([^']+)'", '', 1, 1),
);
List<MVideo> a = []; List<MVideo> a = [];
if (serverUrl.contains("https://streamwish") && if (serverUrl.contains("https://streamwish") &&
hosterSelection.contains("Streamwish")) { hosterSelection.contains("Streamwish")) {
@@ -278,13 +311,13 @@ class OtakuFr extends MProvider {
SelectFilterOption("Suspense", "/genre/suspense/"), SelectFilterOption("Suspense", "/genre/suspense/"),
SelectFilterOption("Thriller", "/genre/thriller/"), SelectFilterOption("Thriller", "/genre/thriller/"),
SelectFilterOption("Tranche de vie", "/genre/tranche-de-vie/"), SelectFilterOption("Tranche de vie", "/genre/tranche-de-vie/"),
SelectFilterOption("Vampire", "/genre/vampire/") SelectFilterOption("Vampire", "/genre/vampire/"),
]), ]),
SelectFilter("SubPageFilter", "Sous page", 0, [ SelectFilter("SubPageFilter", "Sous page", 0, [
SelectFilterOption("<Selectionner>", ""), SelectFilterOption("<Selectionner>", ""),
SelectFilterOption("Terminé", "/termine/"), SelectFilterOption("Terminé", "/termine/"),
SelectFilterOption("Film", "/film/"), SelectFilterOption("Film", "/film/"),
]) ]),
]; ];
} }
@@ -298,14 +331,16 @@ class OtakuFr extends MProvider {
value: "https://otakufr.cc", value: "https://otakufr.cc",
dialogTitle: "Changer l'url de base", dialogTitle: "Changer l'url de base",
dialogMessage: "", dialogMessage: "",
text: "https://otakufr.cc"), text: "https://otakufr.cc",
),
ListPreference( ListPreference(
key: "preferred_quality", key: "preferred_quality",
title: "Qualité préférée", title: "Qualité préférée",
summary: "", summary: "",
valueIndex: 1, valueIndex: 1,
entries: ["1080p", "720p", "480p", "360p"], entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080", "720", "480", "360"]), entryValues: ["1080", "720", "480", "360"],
),
MultiSelectListPreference( MultiSelectListPreference(
key: "hoster_selection_", key: "hoster_selection_",
title: "Enable/Disable Hosts", title: "Enable/Disable Hosts",
@@ -318,7 +353,7 @@ class OtakuFr extends MProvider {
"Okru", "Okru",
"Voe", "Voe",
"Sibnet", "Sibnet",
"Upstream" "Upstream",
], ],
entryValues: [ entryValues: [
"Streamwish", "Streamwish",
@@ -328,7 +363,7 @@ class OtakuFr extends MProvider {
"Okru", "Okru",
"Voe", "Voe",
"Sibnet", "Sibnet",
"Upstream" "Upstream",
], ],
values: [ values: [
"Streamwish", "Streamwish",
@@ -338,8 +373,9 @@ class OtakuFr extends MProvider {
"Okru", "Okru",
"Voe", "Voe",
"Sibnet", "Sibnet",
"Upstream" "Upstream",
]), ],
),
]; ];
} }
@@ -389,8 +425,10 @@ class OtakuFr extends MProvider {
if (masterUrl.contains(".m3u8")) { if (masterUrl.contains(".m3u8")) {
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -433,12 +471,16 @@ class OtakuFr extends MProvider {
if (js.isEmpty) { if (js.isEmpty) {
return []; return [];
} }
final masterUrl = final masterUrl = substringBefore(
substringBefore(substringAfter(unpackJs(js.first), "{file:\""), "\"}"); substringAfter(unpackJs(js.first), "{file:\""),
"\"}",
);
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
List<MVideo> videos = []; List<MVideo> videos = [];
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";

View File

@@ -14,4 +14,5 @@ Source _otakufr = Source(
sourceCodeUrl: otakufrCodeUrl, sourceCodeUrl: otakufrCodeUrl,
version: otakufrVersion, version: otakufrVersion,
itemType: ItemType.anime, itemType: ItemType.anime,
isFullData: false); isFullData: false,
);

View File

@@ -13,4 +13,5 @@ Source _yomoviesSource = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/hi/yomovies/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/hi/yomovies/icon.png",
sourceCodeUrl: _yomoviesSourceCodeUrl, sourceCodeUrl: _yomoviesSourceCodeUrl,
version: _yomoviesVersion, version: _yomoviesVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -23,8 +23,8 @@ class YoMovies extends MProvider {
final document = parseHtml(res); final document = parseHtml(res);
return animeFromElement( return animeFromElement(
document.select("div.movies-list > div.ml-item"), document.select("div.movies-list > div.ml-item"),
document.selectFirst("ul.pagination > li.active + li")?.getHref != document.selectFirst("ul.pagination > li.active + li")?.getHref != null,
null); );
} }
@override @override
@@ -54,8 +54,8 @@ class YoMovies extends MProvider {
final document = parseHtml(res); final document = parseHtml(res);
return animeFromElement( return animeFromElement(
document.select("div.movies-list > div.ml-item"), document.select("div.movies-list > div.ml-item"),
document.selectFirst("ul.pagination > li.active + li")?.getHref != document.selectFirst("ul.pagination > li.active + li")?.getHref != null,
null); );
} }
@override @override
@@ -68,8 +68,10 @@ class YoMovies extends MProvider {
var infoElement = document.selectFirst("div.mvi-content"); var infoElement = document.selectFirst("div.mvi-content");
anime.description = infoElement.selectFirst("p.f-desc")?.text ?? ""; anime.description = infoElement.selectFirst("p.f-desc")?.text ?? "";
anime.genre = xpath(res, anime.genre = xpath(
'//div[@class="mvici-left" and contains(text(),"Genre:")]/p/a/text()'); res,
'//div[@class="mvici-left" and contains(text(),"Genre:")]/p/a/text()',
);
List<MChapter> episodeList = []; List<MChapter> episodeList = [];
final seasonListElements = document.select("div#seasons > div.tvseason"); final seasonListElements = document.select("div#seasons > div.tvseason");
@@ -124,14 +126,16 @@ class YoMovies extends MProvider {
value: "https://yomovies.boo", value: "https://yomovies.boo",
dialogTitle: "Override BaseUrl", dialogTitle: "Override BaseUrl",
dialogMessage: "", dialogMessage: "",
text: "https://yomovies.boo"), text: "https://yomovies.boo",
),
ListPreference( ListPreference(
key: "preferred_quality", key: "preferred_quality",
title: "Preferred quality", title: "Preferred quality",
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["1080p", "720p", "480p", "360p"], entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080", "720", "480", "360"]) entryValues: ["1080", "720", "480", "360"],
),
]; ];
} }
@@ -142,11 +146,15 @@ class YoMovies extends MProvider {
(await client.get(Uri.parse(url), headers: {"Referer": url})).body; (await client.get(Uri.parse(url), headers: {"Referer": url})).body;
final script = xpath(res, '//script[contains(text(),"sources:")]/text()'); final script = xpath(res, '//script[contains(text(),"sources:")]/text()');
if (script.isEmpty) return []; if (script.isEmpty) return [];
final masterUrl = final masterUrl = substringBefore(
substringBefore(substringAfter(script.first, "file:\""), '"'); substringAfter(script.first, "file:\""),
'"',
);
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -207,38 +215,57 @@ class YoMovies extends MProvider {
List<dynamic> getFilterList() { List<dynamic> getFilterList() {
return [ return [
HeaderFilter( HeaderFilter(
"Note: Only one selection at a time works, and it ignores text search"), "Note: Only one selection at a time works, and it ignores text search",
),
SeparatorFilter(), SeparatorFilter(),
SelectFilter("BollywoodFilter", "Bollywood", 0, [ SelectFilter("BollywoodFilter", "Bollywood", 0, [
SelectFilterOption("<select>", ""), SelectFilterOption("<select>", ""),
SelectFilterOption("Bollywood", "/genre/bollywood"), SelectFilterOption("Bollywood", "/genre/bollywood"),
SelectFilterOption("Trending", "/genre/top-rated"), SelectFilterOption("Trending", "/genre/top-rated"),
SelectFilterOption("Bollywood (2024)", SelectFilterOption(
"/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2024&wpas=1"), "Bollywood (2024)",
SelectFilterOption("Bollywood (2023)", "/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2024&wpas=1",
"/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2023&wpas=1"), ),
SelectFilterOption("Bollywood (2022)", SelectFilterOption(
"/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2022&wpas=1"), "Bollywood (2023)",
SelectFilterOption("Bollywood (2021)", "/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2023&wpas=1",
"/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2021&wpas=1"), ),
SelectFilterOption(
"Bollywood (2022)",
"/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2022&wpas=1",
),
SelectFilterOption(
"Bollywood (2021)",
"/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2021&wpas=1",
),
]), ]),
SelectFilter("DualAudioFilter", "Dual Audio", 0, [ SelectFilter("DualAudioFilter", "Dual Audio", 0, [
SelectFilterOption("<select>", ""), SelectFilterOption("<select>", ""),
SelectFilterOption("Dual Audio", "/genre/dual-audio"), SelectFilterOption("Dual Audio", "/genre/dual-audio"),
SelectFilterOption("Hollywood Dubbed", SelectFilterOption(
"/account/?ptype=post&tax_category%5B%5D=dual-audio&wpas=1"), "Hollywood Dubbed",
SelectFilterOption("South Dubbed", "/account/?ptype=post&tax_category%5B%5D=dual-audio&wpas=1",
"/account/?ptype=post&tax_category%5B%5D=dual-audio&tax_category%5B%5D=south-special&wpas=1"), ),
SelectFilterOption(
"South Dubbed",
"/account/?ptype=post&tax_category%5B%5D=dual-audio&tax_category%5B%5D=south-special&wpas=1",
),
]), ]),
SelectFilter("HollywoodFilter", "Hollywood", 0, [ SelectFilter("HollywoodFilter", "Hollywood", 0, [
SelectFilterOption("<select>", ""), SelectFilterOption("<select>", ""),
SelectFilterOption("Hollywood", "/genre/hollywood"), SelectFilterOption("Hollywood", "/genre/hollywood"),
SelectFilterOption("Hollywood (2023)", SelectFilterOption(
"/account/?ptype=post&tax_category%5B%5D=hollywood&tax_release-year=2023&wpas=1"), "Hollywood (2023)",
SelectFilterOption("Hollywood (2022)", "/account/?ptype=post&tax_category%5B%5D=hollywood&tax_release-year=2023&wpas=1",
"/account/?ptype=post&tax_category%5B%5D=hollywood&tax_release-year=2022&wpas=1"), ),
SelectFilterOption("Hollywood (2021)", SelectFilterOption(
"/account/?ptype=post&tax_category%5B%5D=hollywood&tax_release-year=2021&wpas=1"), "Hollywood (2022)",
"/account/?ptype=post&tax_category%5B%5D=hollywood&tax_release-year=2022&wpas=1",
),
SelectFilterOption(
"Hollywood (2021)",
"/account/?ptype=post&tax_category%5B%5D=hollywood&tax_release-year=2021&wpas=1",
),
]), ]),
SelectFilter("EnglishSeriesFilter", "Hindi Series", 0, [ SelectFilter("EnglishSeriesFilter", "Hindi Series", 0, [
SelectFilterOption("<select>", ""), SelectFilterOption("<select>", ""),
@@ -319,13 +346,17 @@ class YoMovies extends MProvider {
SelectFilterOption("Hootzy", "/director/hootzy-channel"), SelectFilterOption("Hootzy", "/director/hootzy-channel"),
SelectFilterOption("Balloons", "/director/balloons-originals"), SelectFilterOption("Balloons", "/director/balloons-originals"),
SelectFilterOption( SelectFilterOption(
"Big Movie Zoo", "/director/big-movie-zoo-originals"), "Big Movie Zoo",
"/director/big-movie-zoo-originals",
),
SelectFilterOption("Bambooflix", "/director/bambooflix"), SelectFilterOption("Bambooflix", "/director/bambooflix"),
SelectFilterOption("Piliflix", "/director/piliflix-originals"), SelectFilterOption("Piliflix", "/director/piliflix-originals"),
SelectFilterOption("11upmovies", "/director/11upmovies-originals"), SelectFilterOption("11upmovies", "/director/11upmovies-originals"),
SelectFilterOption("Eightshots", "/director/eightshots-originals"), SelectFilterOption("Eightshots", "/director/eightshots-originals"),
SelectFilterOption( SelectFilterOption(
"I-Entertainment", "/director/i-entertainment-exclusive"), "I-Entertainment",
"/director/i-entertainment-exclusive",
),
SelectFilterOption("Hotprime", "/director/hotprime-originals"), SelectFilterOption("Hotprime", "/director/hotprime-originals"),
SelectFilterOption("BananaPrime", "/director/banana-prime"), SelectFilterOption("BananaPrime", "/director/banana-prime"),
SelectFilterOption("HotHitFilms", "/director/hothitfilms"), SelectFilterOption("HotHitFilms", "/director/hothitfilms"),

View File

@@ -15,8 +15,10 @@ class NimeGami extends MProvider {
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = xpath(res, '//div[@class="wrapper-2-a"]/article/a/@href'); final urls = xpath(res, '//div[@class="wrapper-2-a"]/article/a/@href');
final names = xpath(res, '//div[@class="wrapper-2-a"]/article/a/@title'); final names = xpath(res, '//div[@class="wrapper-2-a"]/article/a/@title');
final images = final images = xpath(
xpath(res, '//div[@class="wrapper-2-a"]/article/a/div/img/@src'); res,
'//div[@class="wrapper-2-a"]/article/a/div/img/@src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -34,10 +36,14 @@ class NimeGami extends MProvider {
(await client.get(Uri.parse("${source.baseUrl}/page/$page"))).body; (await client.get(Uri.parse("${source.baseUrl}/page/$page"))).body;
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = xpath(res, '//div[@class="post-article"]/article/div/a/@href'); final urls = xpath(res, '//div[@class="post-article"]/article/div/a/@href');
final names = final names = xpath(
xpath(res, '//div[@class="post-article"]/article/div/a/@title'); res,
final images = '//div[@class="post-article"]/article/div/a/@title',
xpath(res, '//div[@class="post-article"]/article/div/a/img/@src'); );
final images = xpath(
res,
'//div[@class="post-article"]/article/div/a/img/@src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -51,14 +57,17 @@ class NimeGami extends MProvider {
@override @override
Future<MPages> search(String query, int page, FilterList filterList) async { Future<MPages> search(String query, int page, FilterList filterList) async {
final res = (await client.get( final res =
Uri.parse("${source.baseUrl}/page/$page/?s=$query&post_type=post"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/page/$page/?s=$query&post_type=post"),
)).body;
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = xpath(res, '//div[@class="archive-a"]/article/div/a/@href'); final urls = xpath(res, '//div[@class="archive-a"]/article/div/a/@href');
final names = xpath(res, '//div[@class="archive-a"]/article/h2/a/@title'); final names = xpath(res, '//div[@class="archive-a"]/article/h2/a/@title');
final images = final images = xpath(
xpath(res, '//div[@class="archive-a"]/article/div/a/img/@src'); res,
'//div[@class="archive-a"]/article/div/a/img/@src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -84,21 +93,25 @@ class NimeGami extends MProvider {
anime.author = author.first; anime.author = author.first;
} }
anime.genre = xpath(res, '//tr/td[@class="info_a"]/a/text()'); anime.genre = xpath(res, '//tr/td[@class="info_a"]/a/text()');
final epUrls = xpath(res, '//div[@class="list_eps_stream"]/li/@data') final epUrls =
.reversed xpath(
.toList(); res,
'//div[@class="list_eps_stream"]/li/@data',
).reversed.toList();
final epNums = final epNums =
xpath(res, '//div[@class="list_eps_stream"]/li/@id').reversed.toList(); xpath(res, '//div[@class="list_eps_stream"]/li/@id').reversed.toList();
final names = xpath(res, '//div[@class="list_eps_stream"]/li/text()') final names =
.reversed xpath(
.toList(); res,
'//div[@class="list_eps_stream"]/li/text()',
).reversed.toList();
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
for (var i = 0; i < epUrls.length; i++) { for (var i = 0; i < epUrls.length; i++) {
MChapter episode = MChapter(); MChapter episode = MChapter();
episode.name = names[i]; episode.name = names[i];
episode.url = json.encode({ episode.url = json.encode({
"episodeIndex": int.parse(substringAfterLast(epNums[i], '_')), "episodeIndex": int.parse(substringAfterLast(epNums[i], '_')),
'urls': json.decode(utf8.decode(base64Url.decode(epUrls[i]))) 'urls': json.decode(utf8.decode(base64Url.decode(epUrls[i]))),
}); });
episodesList.add(episode); episodesList.add(episode);
} }
@@ -126,7 +139,8 @@ class NimeGami extends MProvider {
List<MVideo> videos = []; List<MVideo> videos = [];
if (url.contains("video.nimegami.id")) { if (url.contains("video.nimegami.id")) {
final realUrl = utf8.decode( final realUrl = utf8.decode(
base64Url.decode(substringBefore(substringAfter(url, "url="), "&"))); base64Url.decode(substringBefore(substringAfter(url, "url="), "&")),
);
final a = await extractHXFileVideos(realUrl, quality); final a = await extractHXFileVideos(realUrl, quality);
videos.addAll(a); videos.addAll(a);
} else if (url.contains("berkasdrive") || url.contains("drive.nimegami")) { } else if (url.contains("berkasdrive") || url.contains("drive.nimegami")) {
@@ -148,15 +162,19 @@ class NimeGami extends MProvider {
url = url.replaceAll(".co/", ".co/embed-") + ".html"; url = url.replaceAll(".co/", ".co/embed-") + ".html";
} }
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
final script = xpath(res, final script = xpath(
'//script[contains(text(), "eval") and contains(text(), "p,a,c,k,e,d")]/text()'); res,
'//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(
substringAfter(unpackJs(script.first), "sources:[", ""), substringAfter(unpackJs(script.first), "sources:[", ""),
"file\":\"", "file\":\"",
""), "",
'"'); ),
'"',
);
if (videoUrl.isNotEmpty) { if (videoUrl.isNotEmpty) {
return [toVideo(videoUrl, "HXFile - $quality")]; return [toVideo(videoUrl, "HXFile - $quality")];
} }

View File

@@ -13,4 +13,5 @@ Source _nimegami = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/nimegami/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/nimegami/icon.png",
sourceCodeUrl: _nimegamiCodeUrl, sourceCodeUrl: _nimegamiCodeUrl,
version: _nimegamiVersion, version: _nimegamiVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -10,32 +10,35 @@ class OploVerz extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = (await client.get(Uri.parse( final res =
"${source.baseUrl}/anime-list/page/$page/?order=popular"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/anime-list/page/$page/?order=popular"),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client.get( final res =
Uri.parse("${source.baseUrl}/anime-list/page/$page/?order=latest"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/anime-list/page/$page/?order=latest"),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@override @override
Future<MPages> search(String query, int page, FilterList filterList) async { Future<MPages> search(String query, int page, FilterList filterList) async {
final res = (await client.get( final res =
Uri.parse("${source.baseUrl}/anime-list/page/$page/?title=$query"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/anime-list/page/$page/?title=$query"),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"ongoing": 0, "completed": 1} {"ongoing": 0, "completed": 1},
]; ];
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
@@ -47,12 +50,18 @@ class OploVerz extends MProvider {
anime.description = xpath(res, '//*[@class="desc"]/div/text()').first; anime.description = xpath(res, '//*[@class="desc"]/div/text()').first;
anime.genre = xpath(res, '//*[@class="genre-info"]/a/text()'); anime.genre = xpath(res, '//*[@class="genre-info"]/a/text()');
final epUrls = final epUrls = xpath(
xpath(res, '//div[@class="epsleft")]/span[@class="lchx"]/a/@href'); res,
final names = '//div[@class="epsleft")]/span[@class="lchx"]/a/@href',
xpath(res, '//div[@class="epsleft")]/span[@class="lchx"]/a/text()'); );
final dates = final names = xpath(
xpath(res, '//div[@class="epsleft")]/span[@class="date"]/text()'); res,
'//div[@class="epsleft")]/span[@class="lchx"]/a/text()',
);
final dates = xpath(
res,
'//div[@class="epsleft")]/span[@class="date"]/text()',
);
final dateUploads = parseDates(dates, "dd/MM/yyyy", "id"); final dateUploads = parseDates(dates, "dd/MM/yyyy", "id");
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
for (var i = 0; i < epUrls.length; i++) { for (var i = 0; i < epUrls.length; i++) {
@@ -70,28 +79,33 @@ class OploVerz 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(url))).body; final res = (await client.get(Uri.parse(url))).body;
final dataPost = xpath(res, final dataPost =
'//*[@id="server"]/ul/li/div[contains(@id,"player-option")]/@data-post') xpath(
.first; res,
final dataNume = xpath(res, '//*[@id="server"]/ul/li/div[contains(@id,"player-option")]/@data-post',
'//*[@id="server"]/ul/li/div[contains(@id,"player-option")]/@data-nume') ).first;
.first; final dataNume =
final dataType = xpath(res, xpath(
'//*[@id="server"]/ul/li/div[contains(@id,"player-option")]/@data-type') res,
.first; '//*[@id="server"]/ul/li/div[contains(@id,"player-option")]/@data-nume',
).first;
final dataType =
xpath(
res,
'//*[@id="server"]/ul/li/div[contains(@id,"player-option")]/@data-type',
).first;
final ress = (await client.post( final ress =
(await client.post(
Uri.parse("${source.baseUrl}/wp-admin/admin-ajax.php"), Uri.parse("${source.baseUrl}/wp-admin/admin-ajax.php"),
headers: { headers: {"_": "_"},
"_": "_"
},
body: { body: {
"action": "player_ajax", "action": "player_ajax",
"post": dataPost, "post": dataPost,
"nume": dataNume, "nume": dataNume,
"type": dataType "type": dataType,
})) },
.body; )).body;
final playerLink = final playerLink =
xpath(ress, '//iframe[@class="playeriframe"]/@src').first; xpath(ress, '//iframe[@class="playeriframe"]/@src').first;
@@ -127,8 +141,10 @@ class OploVerz extends MProvider {
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = xpath(res, '//div[@class="relat"]/article/div/div/a/@href'); final urls = xpath(res, '//div[@class="relat"]/article/div/div/a/@href');
final names = xpath(res, '//div[@class="relat"]/article/div/div/a/@title'); final names = xpath(res, '//div[@class="relat"]/article/div/div/a/@title');
final images = final images = xpath(
xpath(res, '//div[@class="relat"]/article/div/div/a/div/img/@src'); res,
'//div[@class="relat"]/article/div/div/a/div/img/@src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -138,8 +154,10 @@ class OploVerz extends MProvider {
animeList.add(anime); animeList.add(anime);
} }
final pages = xpath(res, '//div[@class="pagination"]/a/@href'); final pages = xpath(res, '//div[@class="pagination"]/a/@href');
final pageNumberCurrent = xpath(res, final pageNumberCurrent = xpath(
'//div[@class="pagination"]/span[@class="page-numbers current"]/text()'); res,
'//div[@class="pagination"]/span[@class="page-numbers current"]/text()',
);
bool hasNextPage = true; bool hasNextPage = true;
if (pageNumberCurrent.isNotEmpty && pages.isNotEmpty) { if (pageNumberCurrent.isNotEmpty && pages.isNotEmpty) {

View File

@@ -13,4 +13,5 @@ Source _oploverz = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/oploverz/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/oploverz/icon.png",
sourceCodeUrl: _oploverzCodeUrl, sourceCodeUrl: _oploverzCodeUrl,
version: _oploverzVersion, version: _oploverzVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -14,8 +14,9 @@ class OtakuDesu extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = final res =
(await client.get(Uri.parse("$baseUrl/complete-anime/page/$page"))) (await client.get(
.body; Uri.parse("$baseUrl/complete-anime/page/$page"),
)).body;
return parseAnimeList(res); return parseAnimeList(res);
} }
@@ -29,8 +30,9 @@ class OtakuDesu extends MProvider {
@override @override
Future<MPages> search(String query, int page, FilterList filterList) async { Future<MPages> search(String query, int page, FilterList filterList) async {
final res = final res =
(await client.get(Uri.parse("$baseUrl/?s=$query&post_type=anime"))) (await client.get(
.body; Uri.parse("$baseUrl/?s=$query&post_type=anime"),
)).body;
List<MManga> animeList = []; List<MManga> animeList = [];
final images = xpath(res, '//ul[@class="chivsrc"]/li/img/@src'); final images = xpath(res, '//ul[@class="chivsrc"]/li/img/@src');
final names = xpath(res, '//ul[@class="chivsrc"]/li/h2/a/text()'); final names = xpath(res, '//ul[@class="chivsrc"]/li/h2/a/text()');
@@ -49,12 +51,14 @@ class OtakuDesu extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"Ongoing": 0, "Completed": 1} {"Ongoing": 0, "Completed": 1},
]; ];
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
MManga anime = MManga(); MManga anime = MManga();
final status = xpath( final status = xpath(
res, '//*[@class="infozingle"]/p[contains(text(), "Status")]/text()'); res,
'//*[@class="infozingle"]/p[contains(text(), "Status")]/text()',
);
if (status.isNotEmpty) { if (status.isNotEmpty) {
anime.status = parseStatus(status.first.split(':').last, statusList); anime.status = parseStatus(status.first.split(':').last, statusList);
} }
@@ -64,7 +68,9 @@ class OtakuDesu extends MProvider {
} }
final genre = xpath( final genre = xpath(
res, '//*[@class="infozingle"]/p[contains(text(), "Genre")]/text()'); res,
'//*[@class="infozingle"]/p[contains(text(), "Genre")]/text()',
);
if (genre.isNotEmpty) { if (genre.isNotEmpty) {
anime.genre = genre.first.split(':').last.split(','); anime.genre = genre.first.split(':').last.split(',');
} }
@@ -73,7 +79,9 @@ class OtakuDesu extends MProvider {
final names = xpath(res, '//div[@class="episodelist"]/ul/li/span/a/text()'); final names = xpath(res, '//div[@class="episodelist"]/ul/li/span/a/text()');
final dates = xpath( final dates = xpath(
res, '//div[@class="episodelist"]/ul/li/span[@class="zeebr"]/text()'); res,
'//div[@class="episodelist"]/ul/li/span[@class="zeebr"]/text()',
);
final dateUploads = parseDates(dates, "d MMMM,yyyy", "id"); final dateUploads = parseDates(dates, "d MMMM,yyyy", "id");
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
for (var i = 1; i < epUrls.length; i++) { for (var i = 1; i < epUrls.length; i++) {
@@ -93,18 +101,23 @@ class OtakuDesu extends MProvider {
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
final script = final script =
xpath(res, '//script[contains(text(), "{action:")]/text()').first; xpath(res, '//script[contains(text(), "{action:")]/text()').first;
final nonceAction = final nonceAction = substringBefore(
substringBefore(substringAfter(script, "{action:\""), '"'); substringAfter(script, "{action:\""),
'"',
);
final action = substringBefore(substringAfter(script, "action:\""), '"'); final action = substringBefore(substringAfter(script, "action:\""), '"');
final resNonceAction = (await client.post( final resNonceAction =
(await client.post(
Uri.parse("$baseUrl/wp-admin/admin-ajax.php"), Uri.parse("$baseUrl/wp-admin/admin-ajax.php"),
headers: {"_": "_"}, headers: {"_": "_"},
body: {"action": nonceAction})) body: {"action": nonceAction},
.body; )).body;
final nonce = substringBefore(substringAfter(resNonceAction, ":\""), '"'); final nonce = substringBefore(substringAfter(resNonceAction, ":\""), '"');
final mirrorstream = final mirrorstream = xpath(
xpath(res, '//*[@class="mirrorstream"]/ul/li/a/@data-content'); res,
'//*[@class="mirrorstream"]/ul/li/a/@data-content',
);
for (var stream in mirrorstream) { for (var stream in mirrorstream) {
List<MVideo> a = []; List<MVideo> a = [];
final decodedData = json.decode(utf8.decode(base64Url.decode(stream))); final decodedData = json.decode(utf8.decode(base64Url.decode(stream)));
@@ -112,17 +125,12 @@ class OtakuDesu extends MProvider {
final id = decodedData["id"]; final id = decodedData["id"];
final i = decodedData["i"]; final i = decodedData["i"];
final res = (await client final res =
.post(Uri.parse("$baseUrl/wp-admin/admin-ajax.php"), headers: { (await client.post(
"_": "_" Uri.parse("$baseUrl/wp-admin/admin-ajax.php"),
}, body: { headers: {"_": "_"},
"i": i, body: {"i": i, "id": id, "q": q, "nonce": nonce, "action": action},
"id": id, )).body;
"q": q,
"nonce": nonce,
"action": action
}))
.body;
final resJson = json.decode(res); final resJson = json.decode(res);
final html = utf8.decode(base64Url.decode(resJson["data"])); final html = utf8.decode(base64Url.decode(resJson["data"]));
String url = xpath(html, '//iframe/@src').first; String url = xpath(html, '//iframe/@src').first;
@@ -152,8 +160,10 @@ class OtakuDesu extends MProvider {
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
final script = final script =
xpath(res, '//script[contains(text(), "player.src")]/text()').first; xpath(res, '//script[contains(text(), "player.src")]/text()').first;
final videoUrl = final videoUrl = substringBefore(
substringBefore(substringAfter(script, "src: \""), '"'); substringAfter(script, "src: \""),
'"',
);
MVideo video = MVideo(); MVideo video = MVideo();
video video
..url = videoUrl ..url = videoUrl
@@ -196,12 +206,18 @@ class OtakuDesu extends MProvider {
MPages parseAnimeList(String res) { MPages parseAnimeList(String res) {
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = final urls = xpath(
xpath(res, '//div[@class="detpost"]/div[@class="thumb"]/a/@href'); res,
final names = xpath(res, '//div[@class="detpost"]/div[@class="thumb"]/a/@href',
'//div[@class="detpost"]/div[@class="thumb"]/a/div[@class="thumbz"]/h2/text()'); );
final images = xpath(res, final names = xpath(
'//div[@class="detpost"]/div[@class="thumb"]/a/div[@class="thumbz"]/img/@src'); res,
'//div[@class="detpost"]/div[@class="thumb"]/a/div[@class="thumbz"]/h2/text()',
);
final images = xpath(
res,
'//div[@class="detpost"]/div[@class="thumb"]/a/div[@class="thumbz"]/img/@src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -211,7 +227,9 @@ class OtakuDesu extends MProvider {
animeList.add(anime); animeList.add(anime);
} }
final pages = xpath( final pages = xpath(
res, '//div[@class="pagenavix"]/a[@class="next page-numbers"]/@href'); res,
'//div[@class="pagenavix"]/a[@class="next page-numbers"]/@href',
);
return MPages(animeList, pages.isNotEmpty); return MPages(animeList, pages.isNotEmpty);
} }
@@ -224,14 +242,16 @@ class OtakuDesu extends MProvider {
value: "https://otakudesu.cloud", value: "https://otakudesu.cloud",
dialogTitle: "Override BaseUrl", dialogTitle: "Override BaseUrl",
dialogMessage: "", dialogMessage: "",
text: "https://otakudesu.cloud"), text: "https://otakudesu.cloud",
),
ListPreference( ListPreference(
key: "preferred_quality", key: "preferred_quality",
title: "Preferred quality", title: "Preferred quality",
summary: "", summary: "",
valueIndex: 1, valueIndex: 1,
entries: ["1080p", "720p", "480p", "360p"], entries: ["1080p", "720p", "480p", "360p"],
entryValues: ["1080", "720", "480", "360"]) entryValues: ["1080", "720", "480", "360"],
),
]; ];
} }
} }

View File

@@ -13,4 +13,5 @@ Source _otakudesu = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/otakudesu/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/otakudesu/icon.png",
sourceCodeUrl: _otakudesuCodeUrl, sourceCodeUrl: _otakudesuCodeUrl,
version: _otakudesuVersion, version: _otakudesuVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -10,20 +10,27 @@ class AnimeSaturn extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = (await client final res =
.get(Uri.parse("${source.baseUrl}/animeincorso?page=$page"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/animeincorso?page=$page"),
)).body;
List<MManga> animeList = []; List<MManga> animeList = [];
final urls = xpath(res, final urls = xpath(
'//*[@class="sebox"]/div[@class="msebox"]/div[@class="headsebox"]/div[@class="tisebox"]/h2/a/@href'); res,
'//*[@class="sebox"]/div[@class="msebox"]/div[@class="headsebox"]/div[@class="tisebox"]/h2/a/@href',
);
final names = xpath(res, final names = xpath(
'//*[@class="sebox"]/div[@class="msebox"]/div[@class="headsebox"]/div[@class="tisebox"]/h2/a/text()'); res,
'//*[@class="sebox"]/div[@class="msebox"]/div[@class="headsebox"]/div[@class="tisebox"]/h2/a/text()',
);
final images = xpath(res, final images = xpath(
'//*[@class="sebox"]/div[@class="msebox"]/div[@class="bigsebox"]/div/img[@class="attachment-post-thumbnail size-post-thumbnail wp-post-image"]/@src'); res,
'//*[@class="sebox"]/div[@class="msebox"]/div[@class="bigsebox"]/div/img[@class="attachment-post-thumbnail size-post-thumbnail wp-post-image"]/@src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -38,8 +45,9 @@ class AnimeSaturn extends MProvider {
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = final res =
(await client.get(Uri.parse("${source.baseUrl}/newest?page=$page"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/newest?page=$page"),
)).body;
List<MManga> animeList = []; List<MManga> animeList = [];
@@ -47,8 +55,10 @@ class AnimeSaturn extends MProvider {
final names = xpath(res, '//*[@class="card mb-4 shadow-sm"]/a/@title'); final names = xpath(res, '//*[@class="card mb-4 shadow-sm"]/a/@title');
final images = xpath(res, final images = xpath(
'//*[@class="card mb-4 shadow-sm"]/a/img[@class="new-anime"]/@src'); res,
'//*[@class="card mb-4 shadow-sm"]/a/img[@class="new-anime"]/@src',
);
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
MManga anime = MManga(); MManga anime = MManga();
@@ -114,21 +124,29 @@ class AnimeSaturn extends MProvider {
List<String> names = []; List<String> names = [];
List<String> images = []; List<String> images = [];
if (query.isNotEmpty) { if (query.isNotEmpty) {
urls = xpath(res, urls = xpath(
'//*[@class="list-group"]/li[@class="list-group-item bg-dark-as-box-shadow"]/div[@class="item-archivio"]/div[@class="info-archivio"]/h3/a[@class="badge badge-archivio badge-light"]/@href'); res,
'//*[@class="list-group"]/li[@class="list-group-item bg-dark-as-box-shadow"]/div[@class="item-archivio"]/div[@class="info-archivio"]/h3/a[@class="badge badge-archivio badge-light"]/@href',
);
names = xpath(res, names = xpath(
'//*[@class="list-group"]/li[@class="list-group-item bg-dark-as-box-shadow"]/div[@class="item-archivio"]/div[@class="info-archivio"]/h3/a[@class="badge badge-archivio badge-light"]/text()'); res,
'//*[@class="list-group"]/li[@class="list-group-item bg-dark-as-box-shadow"]/div[@class="item-archivio"]/div[@class="info-archivio"]/h3/a[@class="badge badge-archivio badge-light"]/text()',
);
images = xpath(res, images = xpath(
'//*[@class="list-group"]/li[@class="list-group-item bg-dark-as-box-shadow"]/div[@class="item-archivio"]/a/img/@src'); res,
'//*[@class="list-group"]/li[@class="list-group-item bg-dark-as-box-shadow"]/div[@class="item-archivio"]/a/img/@src',
);
} else { } else {
urls = xpath(res, '//*[@class="card mb-4 shadow-sm"]/a/@href'); urls = xpath(res, '//*[@class="card mb-4 shadow-sm"]/a/@href');
names = xpath(res, '//*[@class="card mb-4 shadow-sm"]/a/text()'); names = xpath(res, '//*[@class="card mb-4 shadow-sm"]/a/text()');
images = xpath(res, images = xpath(
'//*[@class="card mb-4 shadow-sm"]/a/img[@class="new-anime"]/@src'); res,
'//*[@class="card mb-4 shadow-sm"]/a/img[@class="new-anime"]/@src',
);
} }
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
@@ -144,20 +162,25 @@ class AnimeSaturn extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"In corso": 0, "Finito": 1} {"In corso": 0, "Finito": 1},
]; ];
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
MManga anime = MManga(); MManga anime = MManga();
final detailsList = xpath(res, final detailsList = xpath(
'//div[@class="container shadow rounded bg-dark-as-box mb-3 p-3 w-100 text-white"]/text()'); res,
'//div[@class="container shadow rounded bg-dark-as-box mb-3 p-3 w-100 text-white"]/text()',
);
if (detailsList.isNotEmpty) { if (detailsList.isNotEmpty) {
final details = detailsList.first; final details = detailsList.first;
anime.status = parseStatus( anime.status = parseStatus(
details.substring( details.substring(
details.indexOf("Stato:") + 6, details.indexOf("Data di uscita:")), details.indexOf("Stato:") + 6,
statusList); details.indexOf("Data di uscita:"),
),
statusList,
);
anime.author = details.substring(7, details.indexOf("Stato:")); anime.author = details.substring(7, details.indexOf("Stato:"));
} }
@@ -174,14 +197,20 @@ class AnimeSaturn extends MProvider {
} }
} }
anime.genre = xpath(res, anime.genre = xpath(
'//*[@class="container shadow rounded bg-dark-as-box mb-3 p-3 w-100"]/a/text()'); res,
'//*[@class="container shadow rounded bg-dark-as-box mb-3 p-3 w-100"]/a/text()',
);
final epUrls = xpath(res, final epUrls = xpath(
'//*[@class="btn-group episodes-button episodi-link-button"]/a/@href'); res,
'//*[@class="btn-group episodes-button episodi-link-button"]/a/@href',
);
final titles = xpath(res, final titles = xpath(
'//*[@class="btn-group episodes-button episodi-link-button"]/a/text()'); res,
'//*[@class="btn-group episodes-button episodi-link-button"]/a/text()',
);
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
for (var i = 0; i < epUrls.length; i++) { for (var i = 0; i < epUrls.length; i++) {
@@ -211,8 +240,10 @@ class AnimeSaturn extends MProvider {
List<MVideo> videos = []; List<MVideo> videos = [];
if (masterUrl.endsWith("playlist.m3u8")) { if (masterUrl.endsWith("playlist.m3u8")) {
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -325,7 +356,8 @@ class AnimeSaturn extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["1080p", "720p", "480p", "360p", "240p", "144p"], entries: ["1080p", "720p", "480p", "360p", "240p", "144p"],
entryValues: ["1080", "720", "480", "360", "240", "144"]), entryValues: ["1080", "720", "480", "360", "240", "144"],
),
]; ];
} }

View File

@@ -13,4 +13,5 @@ Source _animesaturn = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/it/animesaturn/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/it/animesaturn/icon.png",
sourceCodeUrl: _animesaturnCodeUrl, sourceCodeUrl: _animesaturnCodeUrl,
version: _animesaturnVersion, version: _animesaturnVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -14,15 +14,16 @@ class AnimesVision extends MProvider {
@override @override
Map<String, String> get headers => { Map<String, String> get headers => {
"Referer": baseUrl, "Referer": baseUrl,
"Accept-Language": "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7" "Accept-Language": "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7",
}; };
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = (await client.get(Uri.parse(baseUrl), headers: headers)).body; final res = (await client.get(Uri.parse(baseUrl), headers: headers)).body;
final document = parseHtml(res); final document = parseHtml(res);
final elements = final elements = document.select(
document.select("div#anime-trending div.item > a.film-poster"); "div#anime-trending div.item > a.film-poster",
);
List<MManga> animeList = []; List<MManga> animeList = [];
for (var element in elements) { for (var element in elements) {
var anime = MManga(); var anime = MManga();
@@ -37,12 +38,15 @@ class AnimesVision extends MProvider {
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client.get(Uri.parse("$baseUrl/lancamentos?page=$page"), final res =
headers: headers)) (await client.get(
.body; Uri.parse("$baseUrl/lancamentos?page=$page"),
headers: headers,
)).body;
final document = parseHtml(res); final document = parseHtml(res);
final elements = final elements = document.select(
document.select("div.container div.screen-items > div.item"); "div.container div.screen-items > div.item",
);
List<MManga> animeList = []; List<MManga> animeList = [];
for (var element in elements) { for (var element in elements) {
var anime = MManga(); var anime = MManga();
@@ -56,9 +60,10 @@ class AnimesVision extends MProvider {
@override @override
Future<MPages> search(String query, int page, FilterList filterList) async { Future<MPages> search(String query, int page, FilterList filterList) async {
final res = (await client final res =
.get(Uri.parse("$baseUrl/search-anime?nome=$query&page=$page"))) (await client.get(
.body; Uri.parse("$baseUrl/search-anime?nome=$query&page=$page"),
)).body;
final document = parseHtml(res); final document = parseHtml(res);
final elements = document.select("div.film_list-wrap div.film-poster"); final elements = document.select("div.film_list-wrap div.film-poster");
List<MManga> animeList = []; List<MManga> animeList = [];
@@ -76,7 +81,7 @@ class AnimesVision extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final statusList = [ final statusList = [
{"Atualmente sendo exibido": 0, "Fim da exibição": 1} {"Atualmente sendo exibido": 0, "Fim da exibição": 1},
]; ];
MManga anime = MManga(); MManga anime = MManga();
final res = (await client.get(Uri.parse("$baseUrl$url"))).body; final res = (await client.get(Uri.parse("$baseUrl$url"))).body;
@@ -113,8 +118,9 @@ class AnimesVision extends MProvider {
while (hasNextPage(document)) { while (hasNextPage(document)) {
if (episodeList.isNotEmpty) { if (episodeList.isNotEmpty) {
final nextUrl = final nextUrl = nextPageElements(
nextPageElements(document)[0].selectFirst("a").attr("href"); document,
)[0].selectFirst("a").attr("href");
document = parseHtml((await client.get(Uri.parse(nextUrl))).body); document = parseHtml((await client.get(Uri.parse(nextUrl))).body);
} }
for (var element for (var element
@@ -131,13 +137,15 @@ class AnimesVision extends MProvider {
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
final res = (await client.get(Uri.parse("$baseUrl$url"))).body; final res = (await client.get(Uri.parse("$baseUrl$url"))).body;
final document = parseHtml(res); final document = parseHtml(res);
final encodedScript = document final encodedScript =
document
.selectFirst("div.player-frame div#playerglobalapi ~ script") .selectFirst("div.player-frame div#playerglobalapi ~ script")
.text; .text;
final decodedScript = decodeScriptFromString(encodedScript); final decodedScript = decodeScriptFromString(encodedScript);
List<MVideo> videos = []; List<MVideo> videos = [];
for (RegExpMatch match in RegExp(r'"file":"(\S+?)",.*?"label":"(.*?)"') for (RegExpMatch match in RegExp(
.allMatches(decodedScript)) { r'"file":"(\S+?)",.*?"label":"(.*?)"',
).allMatches(decodedScript)) {
final videoUrl = match.group(1)!.replaceAll('\\', ''); final videoUrl = match.group(1)!.replaceAll('\\', '');
final qualityName = match.group(2); final qualityName = match.group(2);
var video = MVideo(); var video = MVideo();
@@ -155,10 +163,14 @@ class AnimesVision extends MProvider {
} }
List<MElement> nextPageElements(MDocument document) { List<MElement> nextPageElements(MDocument document) {
final elements = document final elements =
document
.select("ul.pagination li.page-item") .select("ul.pagination li.page-item")
.where((MElement e) => .where(
e.outerHtml.contains("") && !e.outerHtml.contains("disabled")) (MElement e) =>
e.outerHtml.contains("") &&
!e.outerHtml.contains("disabled"),
)
.toList(); .toList();
return elements; return elements;
} }
@@ -173,7 +185,8 @@ class AnimesVision extends MProvider {
} }
String getInfo(MElement element, String key) { String getInfo(MElement element, String key) {
final divs = element final divs =
element
.select("div.item") .select("div.item")
.where((MElement e) => e.outerHtml.contains(key)) .where((MElement e) => e.outerHtml.contains(key))
.toList(); .toList();
@@ -235,7 +248,8 @@ class AnimesVision extends MProvider {
summary: "", summary: "",
valueIndex: 1, valueIndex: 1,
entries: ["480p", "720p", "1080p", "4K"], entries: ["480p", "720p", "1080p", "4K"],
entryValues: ["1080", "720", "480", "4K"]), entryValues: ["1080", "720", "480", "4K"],
),
]; ];
} }
@@ -251,7 +265,11 @@ class AnimesVision extends MProvider {
} }
String decodeScript( String decodeScript(
String encodedString, String magicStr, int offset, int limit) { String encodedString,
String magicStr,
int offset,
int limit,
) {
RegExp regex = RegExp('\\w'); RegExp regex = RegExp('\\w');
List<String> parts = encodedString.split(magicStr[limit]); List<String> parts = encodedString.split(magicStr[limit]);
List<String> decodedParts = []; List<String> decodedParts = [];
@@ -259,7 +277,9 @@ class AnimesVision extends MProvider {
String replaced = part; String replaced = part;
for (Match match in regex.allMatches(part)) { for (Match match in regex.allMatches(part)) {
replaced = replaced.replaceFirst( replaced = replaced.replaceFirst(
match.group(0)!, magicStr.indexOf(match.group(0)!).toString()); match.group(0)!,
magicStr.indexOf(match.group(0)!).toString(),
);
} }
int charInt = convertToNum(replaced, limit) - offset; int charInt = convertToNum(replaced, limit) - offset;
decodedParts.add(String.fromCharCode(charInt)); decodedParts.add(String.fromCharCode(charInt));

View File

@@ -13,4 +13,5 @@ Source _animesvision = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/pt/animesvision/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/pt/animesvision/icon.png",
sourceCodeUrl: _animesvisionCodeUrl, sourceCodeUrl: _animesvisionCodeUrl,
version: _animesvisionVersion, version: _animesvisionVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -6,8 +6,10 @@ class Filma24 extends MProvider {
MSource source; MSource source;
final Client client = final Client client = Client(
Client(source, json.encode({"useDartHttpClient": true})); source,
json.encode({"useDartHttpClient": true}),
);
@override @override
String get baseUrl => getPreferenceValue(source.id, "pref_domain_new"); String get baseUrl => getPreferenceValue(source.id, "pref_domain_new");
@@ -128,7 +130,8 @@ class Filma24 extends MProvider {
value: "https://www.filma24.band", value: "https://www.filma24.band",
dialogTitle: "Domeni i përdorur aktualisht", dialogTitle: "Domeni i përdorur aktualisht",
dialogMessage: "", dialogMessage: "",
text: "https://www.filma24.band"), text: "https://www.filma24.band",
),
]; ];
} }
@@ -192,22 +195,23 @@ class Filma24 extends MProvider {
} }
Future<List<MVideo>> vidmolyExtractor(String url) async { Future<List<MVideo>> vidmolyExtractor(String url) async {
final headers = { final headers = {'Referer': 'https://vidmoly.to'};
'Referer': 'https://vidmoly.to',
};
List<MVideo> videos = []; List<MVideo> videos = [];
final playListUrlResponse = (await client.get(Uri.parse(url))).body; final playListUrlResponse = (await client.get(Uri.parse(url))).body;
final playlistUrl = final playlistUrl =
RegExp(r'file:"(\S+?)"').firstMatch(playListUrlResponse)?.group(1) ?? RegExp(r'file:"(\S+?)"').firstMatch(playListUrlResponse)?.group(1) ??
""; "";
if (playlistUrl.isEmpty) return []; if (playlistUrl.isEmpty) return [];
final masterPlaylistRes = final masterPlaylistRes = await client.get(
await client.get(Uri.parse(playlistUrl), headers: headers); Uri.parse(playlistUrl),
headers: headers,
);
if (masterPlaylistRes.statusCode == 200) { if (masterPlaylistRes.statusCode == 200) {
for (var it for (var it in substringAfter(
in substringAfter(masterPlaylistRes.body, "#EXT-X-STREAM-INF:") masterPlaylistRes.body,
.split("#EXT-X-STREAM-INF:")) { "#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -234,8 +238,10 @@ class Filma24 extends MProvider {
""; "";
if (playlistUrl.isEmpty) return []; if (playlistUrl.isEmpty) return [];
final masterPlaylistRes = (await client.get(Uri.parse(playlistUrl))).body; final masterPlaylistRes = (await client.get(Uri.parse(playlistUrl))).body;
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:") for (var it in substringAfter(
.split("#EXT-X-STREAM-INF:")) { masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality = final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
@@ -258,8 +264,10 @@ class Filma24 extends MProvider {
return []; return [];
} }
final videoUrl = final videoUrl = substringBefore(
substringBefore(substringAfter(js.first, "sources: [\""), '"'); substringAfter(js.first, "sources: [\""),
'"',
);
MVideo video = MVideo(); MVideo video = MVideo();
video video
..url = videoUrl ..url = videoUrl
@@ -283,8 +291,10 @@ class Filma24 extends MProvider {
mangaList.add(manga); mangaList.add(manga);
} }
return MPages(mangaList, return MPages(
document.selectFirst("div > a.nextpostslink")?.attr("href") != null); mangaList,
document.selectFirst("div > a.nextpostslink")?.attr("href") != null,
);
} }
} }

View File

@@ -13,4 +13,5 @@ Source _filma24 = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/sq/filma24/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/sq/filma24/icon.png",
sourceCodeUrl: _filma24CodeUrl, sourceCodeUrl: _filma24CodeUrl,
version: _filma24Version, version: _filma24Version,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -15,7 +15,9 @@ class DiziWatch extends MProvider {
Map<String, String> get headers => {}; Map<String, String> get headers => {};
Future<MPages> parseMainList(int index) async { Future<MPages> parseMainList(int index) async {
MDocument dom = parseHtml((await client.get(Uri.parse(source.baseUrl))) .body); MDocument dom = parseHtml(
(await client.get(Uri.parse(source.baseUrl))).body,
);
List<MManga> list = []; List<MManga> list = [];
MElement containingElement = dom.select("#list-series-hizala2")[index]; MElement containingElement = dom.select("#list-series-hizala2")[index];
List<MElement> results = containingElement.select("#list-series-main"); List<MElement> results = containingElement.select("#list-series-main");
@@ -59,7 +61,13 @@ class DiziWatch extends MProvider {
genre = filter.values[filter.state].value; genre = filter.values[filter.state].value;
} }
} }
MDocument dom = parseHtml((await client.get(Uri.parse("${source.baseUrl}/anime-arsivi/page/${page}/?orderby=${orderby}&yil=${year}&imdb=${imdb}&isim=${query}&tur=${genre}"))) .body); MDocument dom = parseHtml(
(await client.get(
Uri.parse(
"${source.baseUrl}/anime-arsivi/page/${page}/?orderby=${orderby}&yil=${year}&imdb=${imdb}&isim=${query}&tur=${genre}",
),
)).body,
);
List<MElement> results = dom.select("#list-series"); List<MElement> results = dom.select("#list-series");
List<MManga> list = []; List<MManga> list = [];
for (MElement result in results) { for (MElement result in results) {
@@ -73,7 +81,9 @@ class DiziWatch extends MProvider {
} }
MElement paginateLinksDiv = dom.selectFirst("div.paginate-links"); MElement paginateLinksDiv = dom.selectFirst("div.paginate-links");
int lastPage = int.parse(paginateLinksDiv.selectFirst("a.next").previousElementSibling.text ?? "1"); int lastPage = int.parse(
paginateLinksDiv.selectFirst("a.next").previousElementSibling.text ?? "1",
);
return MPages(list, lastPage > page); return MPages(list, lastPage > page);
} }
@@ -98,7 +108,10 @@ class DiziWatch extends MProvider {
for (MElement result in results) { for (MElement result in results) {
MElement a = result.select("a")[1]; MElement a = result.select("a")[1];
MChapter chapter = new MChapter(); MChapter chapter = new MChapter();
chapter.name = result.selectFirst(".baslik").text + " | " + result.selectFirst("#bolum-ismi").text; chapter.name =
result.selectFirst(".baslik").text +
" | " +
result.selectFirst("#bolum-ismi").text;
chapter.url = a.getHref; chapter.url = a.getHref;
chapters.add(chapter); chapters.add(chapter);
} }
@@ -111,7 +124,14 @@ class DiziWatch extends MProvider {
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
MDocument dom = parseHtml((await client.get(Uri.parse(url))).body); MDocument dom = parseHtml((await client.get(Uri.parse(url))).body);
String id = dom.selectFirst("#takip_et_izledim_Calis").attr("data-ilanid"); String id = dom.selectFirst("#takip_et_izledim_Calis").attr("data-ilanid");
var json = json.decode((await client.get(Uri.parse("${source.baseUrl}/wp-admin/admin-ajax.php?action=playlist&pid=${id}"))).body)[0]; var json =
json.decode(
(await client.get(
Uri.parse(
"${source.baseUrl}/wp-admin/admin-ajax.php?action=playlist&pid=${id}",
),
)).body,
)[0];
var sources = json["sources"]; var sources = json["sources"];
List<MVideo> videos = []; List<MVideo> videos = [];
for (var source in sources) { for (var source in sources) {
@@ -124,7 +144,11 @@ class DiziWatch extends MProvider {
} }
String quality = getPreferenceValue(source.id, "preferred_quality"); String quality = getPreferenceValue(source.id, "preferred_quality");
videos.sort((MVideo a, MVideo b) => (b.quality.contains(quality) ? 1 : 0) - (a.quality.contains(quality) ? 1 : 0)); videos.sort(
(MVideo a, MVideo b) =>
(b.quality.contains(quality) ? 1 : 0) -
(a.quality.contains(quality) ? 1 : 0),
);
return videos; return videos;
} }
@@ -136,7 +160,7 @@ class DiziWatch extends MProvider {
SelectFilter("Sort", "Sırala", 0, [ SelectFilter("Sort", "Sırala", 0, [
SelectFilterOption("IMDb Puanına Göre", "meta_value"), SelectFilterOption("IMDb Puanına Göre", "meta_value"),
SelectFilterOption("Alfabetik", "name"), SelectFilterOption("Alfabetik", "name"),
SelectFilterOption("Eklenme Tarihine Göre", "ID") SelectFilterOption("Eklenme Tarihine Göre", "ID"),
]), ]),
TextFilter("Year", "Yapım Yılı"), TextFilter("Year", "Yapım Yılı"),
SelectFilter("Genre", "Tür", 0, [ SelectFilter("Genre", "Tür", 0, [
@@ -178,10 +202,13 @@ class DiziWatch extends MProvider {
SelectFilterOption("Tarihi", "tarihi"), SelectFilterOption("Tarihi", "tarihi"),
SelectFilterOption("Uzay", "uzay"), SelectFilterOption("Uzay", "uzay"),
SelectFilterOption("Vampir", "vampir"), SelectFilterOption("Vampir", "vampir"),
SelectFilterOption("Yaşamdan Kesitler", "yasam") SelectFilterOption("Yaşamdan Kesitler", "yasam"),
]), ]),
SelectFilter("MinIMDBRating", "Min. IMBD Puanı", 0, [ SelectFilter("MinIMDBRating", "Min. IMBD Puanı", 0, [
SelectFilterOption("1", "0"), // value 1 looks like buggy so use 0 it wont make any difference. SelectFilterOption(
"1",
"0",
), // value 1 looks like buggy so use 0 it wont make any difference.
SelectFilterOption("2", "2"), SelectFilterOption("2", "2"),
SelectFilterOption("3", "3"), SelectFilterOption("3", "3"),
SelectFilterOption("4", "4"), SelectFilterOption("4", "4"),
@@ -189,8 +216,8 @@ class DiziWatch extends MProvider {
SelectFilterOption("6", "6"), SelectFilterOption("6", "6"),
SelectFilterOption("7", "7"), SelectFilterOption("7", "7"),
SelectFilterOption("8", "8"), SelectFilterOption("8", "8"),
SelectFilterOption("9", "9") SelectFilterOption("9", "9"),
]) ]),
]; ];
} }
@@ -203,7 +230,8 @@ class DiziWatch extends MProvider {
summary: "", summary: "",
valueIndex: 0, valueIndex: 0,
entries: ["1080p", "480p"], // I only saw 1080p and 480p in diziWatch. entries: ["1080p", "480p"], // I only saw 1080p and 480p in diziWatch.
entryValues: ["1080", "480"]) entryValues: ["1080", "480"],
),
]; ];
} }
} }

View File

@@ -13,4 +13,5 @@ Source _diziwatchSource = Source(
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/tr/diziwatch/icon.png", "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/tr/diziwatch/icon.png",
sourceCodeUrl: _diziwatchSourceCodeUrl, sourceCodeUrl: _diziwatchSourceCodeUrl,
version: _diziwatchVersion, version: _diziwatchVersion,
itemType: ItemType.anime); itemType: ItemType.anime,
);

View File

@@ -12,5 +12,5 @@ List<Source> dartMangasourceList = [
...mmrcmsSourcesList, ...mmrcmsSourcesList,
mangahereSource, mangahereSource,
...nepnepSourcesList, ...nepnepSourcesList,
...mangaboxSourcesList ...mangaboxSourcesList,
]; ];

View File

@@ -10,18 +10,20 @@ class Madara extends MProvider {
@override @override
Future<MPages> getPopular(int page) async { Future<MPages> getPopular(int page) async {
final res = (await client.get( final res =
Uri.parse("${source.baseUrl}/manga/page/$page/?m_orderby=views"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/manga/page/$page/?m_orderby=views"),
)).body;
final document = parseHtml(res); final document = parseHtml(res);
return mangaFromElements(document.select("div.page-item-detail")); return mangaFromElements(document.select("div.page-item-detail"));
} }
@override @override
Future<MPages> getLatestUpdates(int page) async { Future<MPages> getLatestUpdates(int page) async {
final res = (await client.get( final res =
Uri.parse("${source.baseUrl}/manga/page/$page/?m_orderby=latest"))) (await client.get(
.body; Uri.parse("${source.baseUrl}/manga/page/$page/?m_orderby=latest"),
)).body;
final document = parseHtml(res); final document = parseHtml(res);
return mangaFromElements(document.select("div.page-item-detail")); return mangaFromElements(document.select("div.page-item-detail"));
} }
@@ -95,7 +97,10 @@ class Madara extends MProvider {
var chd = element.selectFirst("span.chapter-release-date"); var chd = element.selectFirst("span.chapter-release-date");
if (chd != null && chd.text.isNotEmpty) { if (chd != null && chd.text.isNotEmpty) {
var dates = parseDates( var dates = parseDates(
[chd.text], source.dateFormat, source.dateFormatLocale); [chd.text],
source.dateFormat,
source.dateFormatLocale,
);
chapter.dateUpload = dates[0]; chapter.dateUpload = dates[0];
} else { } else {
chapter.dateUpload = chapter.dateUpload =
@@ -153,7 +158,7 @@ class Madara extends MProvider {
"En espera": 2, "En espera": 2,
"Canceled": 3, "Canceled": 3,
"Cancelado": 3, "Cancelado": 3,
} },
]; ];
MManga manga = MManga(); MManga manga = MManga();
String res = ""; String res = "";
@@ -161,19 +166,23 @@ class Madara extends MProvider {
final document = parseHtml(res); final document = parseHtml(res);
manga.author = document.selectFirst("div.author-content > a")?.text ?? ""; manga.author = document.selectFirst("div.author-content > a")?.text ?? "";
manga.description = document manga.description =
document
.selectFirst( .selectFirst(
"div.description-summary div.summary__content, div.summary_content div.post-content_item > h5 + div, div.summary_content div.manga-excerpt, div.sinopsis div.contenedor, .description-summary > p") "div.description-summary div.summary__content, div.summary_content div.post-content_item > h5 + div, div.summary_content div.manga-excerpt, div.sinopsis div.contenedor, .description-summary > p",
)
?.text ?? ?.text ??
""; "";
final imageElement = document.selectFirst("div.summary_image img"); final imageElement = document.selectFirst("div.summary_image img");
manga.imageUrl = imageElement?.attr("data-src") ?? manga.imageUrl =
imageElement?.attr("data-src") ??
imageElement?.attr("data-lazy-src") ?? imageElement?.attr("data-lazy-src") ??
imageElement?.attr("srcset") ?? imageElement?.attr("srcset") ??
imageElement?.getSrc; imageElement?.getSrc;
final id = document final id =
document
.selectFirst("div[id^=manga-chapters-holder]") .selectFirst("div[id^=manga-chapters-holder]")
?.attr("data-id") ?? ?.attr("data-id") ??
""; "";
@@ -193,11 +202,14 @@ class Madara extends MProvider {
final oldXhrChaptersRequest = await client.post( final oldXhrChaptersRequest = await client.post(
Uri.parse("${baseUrl}wp-admin/admin-ajax.php"), Uri.parse("${baseUrl}wp-admin/admin-ajax.php"),
headers: headers, headers: headers,
body: {"action": "manga_get_chapters", "manga": mangaId}); body: {"action": "manga_get_chapters", "manga": mangaId},
);
if (oldXhrChaptersRequest.statusCode == 400) { if (oldXhrChaptersRequest.statusCode == 400) {
res = (await client.post(Uri.parse("${url}ajax/chapters"), res =
headers: headers)) (await client.post(
.body; Uri.parse("${url}ajax/chapters"),
headers: headers,
)).body;
} else { } else {
res = oldXhrChaptersRequest.body; res = oldXhrChaptersRequest.body;
} }
@@ -205,9 +217,11 @@ class Madara extends MProvider {
MDocument chapDoc = parseHtml(res); MDocument chapDoc = parseHtml(res);
manga.chapters = getChapters(chapDoc); manga.chapters = getChapters(chapDoc);
if (manga.chapters.isEmpty) { if (manga.chapters.isEmpty) {
res = (await client.post(Uri.parse("${url}ajax/chapters"), res =
headers: headers)) (await client.post(
.body; Uri.parse("${url}ajax/chapters"),
headers: headers,
)).body;
chapDoc = parseHtml(res); chapDoc = parseHtml(res);
manga.chapters = getChapters(chapDoc); manga.chapters = getChapters(chapDoc);
} }
@@ -221,13 +235,15 @@ class Madara extends MProvider {
final document = parseHtml(res.body); final document = parseHtml(res.body);
final pageElements = document.select( final pageElements = document.select(
"div.page-break, li.blocks-gallery-item, .reading-content .text-left:not(:has(.blocks-gallery-item)) img"); "div.page-break, li.blocks-gallery-item, .reading-content .text-left:not(:has(.blocks-gallery-item)) img",
);
List<String> imgs = []; List<String> imgs = [];
for (var element in pageElements) { for (var element in pageElements) {
try { try {
final imgElement = element.selectFirst("img"); final imgElement = element.selectFirst("img");
final img = imgElement.attr("src") ?? final img =
imgElement.attr("src") ??
imgElement.attr("data-src") ?? imgElement.attr("data-src") ??
imgElement.attr("data-lazy-src") ?? imgElement.attr("data-lazy-src") ??
imgElement.attr("srcset"); imgElement.attr("srcset");
@@ -261,7 +277,8 @@ class Madara extends MProvider {
for (var i = 0; i < elements.length; i++) { for (var i = 0; i < elements.length; i++) {
final postTitle = elements[i].selectFirst("div.post-title a"); final postTitle = elements[i].selectFirst("div.post-title a");
final imageElement = elements[i].selectFirst("img"); final imageElement = elements[i].selectFirst("img");
final image = imageElement?.attr("data-src") ?? final image =
imageElement?.attr("data-src") ??
imageElement?.attr("data-lazy-src") ?? imageElement?.attr("data-lazy-src") ??
imageElement?.attr("srcset") ?? imageElement?.attr("srcset") ??
imageElement?.getSrc ?? imageElement?.getSrc ??
@@ -301,7 +318,7 @@ class Madara extends MProvider {
SelectFilterOption("All", ""), SelectFilterOption("All", ""),
SelectFilterOption("None", "0"), SelectFilterOption("None", "0"),
SelectFilterOption("Only", "1"), SelectFilterOption("Only", "1"),
]) ]),
]; ];
} }

View File

@@ -190,7 +190,8 @@ const madaraSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/madara.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/madara.dart";
List<Source> get madaraSourcesList => _madaraSourcesList; List<Source> get madaraSourcesList => _madaraSourcesList;
List<Source> _madaraSourcesList = [ List<Source> _madaraSourcesList =
[
//1st Kiss-Manga (unoriginal) (EN) //1st Kiss-Manga (unoriginal) (EN)
firstkissdashmangaSource, firstkissdashmangaSource,
//AQUA Scans (EN) //AQUA Scans (EN)
@@ -570,8 +571,11 @@ List<Source> _madaraSourcesList = [
//Webtoon Hatti (TR) //Webtoon Hatti (TR)
webtoonhattiSource, webtoonhattiSource,
] ]
.map((e) => e .map(
(e) =>
e
..itemType = ItemType.manga ..itemType = ItemType.manga
..sourceCodeUrl = madaraSourceCodeUrl ..sourceCodeUrl = madaraSourceCodeUrl
..version = madaraVersion) ..version = madaraVersion,
)
.toList(); .toList();

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "pt-BR", lang: "pt-BR",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/akumanotenshi/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/akumanotenshi/icon.png",
dateFormat: "dd/MM/yyyy", dateFormat: "dd/MM/yyyy",
dateFormatLocale: "pt-br", dateFormatLocale: "pt-br",
); );

View File

@@ -7,7 +7,8 @@ Source _alonescanlatorSource = Source(
lang: "pt-br", lang: "pt-br",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/alonescanlator/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/alonescanlator/icon.png",
dateFormat: "dd/MM/yyyy", dateFormat: "dd/MM/yyyy",
dateFormatLocale:"pt-br" dateFormatLocale: "pt-br",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "tr", lang: "tr",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/anikiga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/anikiga/icon.png",
dateFormat: "d MMMMM yyyy", dateFormat: "d MMMMM yyyy",
dateFormatLocale: "tr", dateFormatLocale: "tr",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "tr", lang: "tr",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/araznovel/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/araznovel/icon.png",
dateFormat: "d MMMM yyyy", dateFormat: "d MMMM yyyy",
dateFormatLocale: "en", dateFormatLocale: "en",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "pt-BR", lang: "pt-BR",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/arthurscan/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/arthurscan/icon.png",
dateFormat: "MMMMM dd, yyyy", dateFormat: "MMMMM dd, yyyy",
dateFormatLocale: "pt-br", dateFormatLocale: "pt-br",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "fr", lang: "fr",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/astralmanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/astralmanga/icon.png",
dateFormat: "dd/mm/yyyy", dateFormat: "dd/mm/yyyy",
dateFormatLocale: "fr", dateFormatLocale: "fr",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "en", lang: "en",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/asurascansus/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/asurascansus/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "en_us", dateFormatLocale: "en_us",
); );

View File

@@ -7,7 +7,8 @@ Source _atikrostSource = Source(
lang: "tr", lang: "tr",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/atikrost/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/atikrost/icon.png",
dateFormat: "d MMMM yyyy", dateFormat: "d MMMM yyyy",
dateFormatLocale:"tr" dateFormatLocale: "tr",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "es", lang: "es",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/barmanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/barmanga/icon.png",
dateFormat: "MM/dd/yyyy", dateFormat: "MM/dd/yyyy",
dateFormatLocale: "es", dateFormatLocale: "es",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "ru", lang: "ru",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/bestmanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/bestmanga/icon.png",
dateFormat: "dd.MM.yyyy", dateFormat: "dd.MM.yyyy",
dateFormatLocale: "ru", dateFormatLocale: "ru",
); );

View File

@@ -7,7 +7,8 @@ Source _bokugentranslationSource = Source(
lang: "es", lang: "es",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/bokugentranslation/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/bokugentranslation/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale:"es" dateFormatLocale: "es",
); );

View File

@@ -7,7 +7,8 @@ Source _borutoexplorerSource = Source(
lang: "pt-br", lang: "pt-br",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/borutoexplorer/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/borutoexplorer/icon.png",
dateFormat: "dd 'de' MMMMM 'de' yyyy", dateFormat: "dd 'de' MMMMM 'de' yyyy",
dateFormatLocale:"pt-br" dateFormatLocale: "pt-br",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "en", lang: "en",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/chibimanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/chibimanga/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "en_us", dateFormatLocale: "en_us",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "tr", lang: "tr",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/clovermanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/clovermanga/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "tr", dateFormatLocale: "tr",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "es", lang: "es",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/cocorip/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/cocorip/icon.png",
dateFormat: "dd/MM/yyyy", dateFormat: "dd/MM/yyyy",
dateFormatLocale: "es", dateFormatLocale: "es",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "en", lang: "en",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/coffeemanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/coffeemanga/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "en_us", dateFormatLocale: "en_us",
); );

View File

@@ -7,7 +7,8 @@ Source _crystalcomicsSource = Source(
lang: "pt-br", lang: "pt-br",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/crystalcomics/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/crystalcomics/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale:"pt-br" dateFormatLocale: "pt-br",
); );

View File

@@ -7,7 +7,8 @@ Source _daprobSource = Source(
lang: "es", lang: "es",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/daprob/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/daprob/icon.png",
dateFormat: "dd/MM/yyy", dateFormat: "dd/MM/yyy",
dateFormatLocale:"en" dateFormatLocale: "en",
); );

View File

@@ -7,7 +7,8 @@ Source _demanhuasSource = Source(
lang: "es", lang: "es",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/demanhuas/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/demanhuas/icon.png",
dateFormat: "MMMM d, yyyy", dateFormat: "MMMM d, yyyy",
dateFormatLocale:"es" dateFormatLocale: "es",
); );

View File

@@ -7,7 +7,8 @@ Source _diamondfansubSource = Source(
lang: "tr", lang: "tr",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/diamondfansub/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/diamondfansub/icon.png",
dateFormat: "d MMMM", dateFormat: "d MMMM",
dateFormatLocale:"tr-tr" dateFormatLocale: "tr-tr",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "th", lang: "th",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/doodmanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/doodmanga/icon.png",
dateFormat: "dd MMMMM yyyy", dateFormat: "dd MMMMM yyyy",
dateFormatLocale: "th", dateFormatLocale: "th",
); );

View File

@@ -7,7 +7,8 @@ Source _dragonteaSource = Source(
lang: "en", lang: "en",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/dragontea/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/dragontea/icon.png",
dateFormat: "MM/dd/yyyy", dateFormat: "MM/dd/yyyy",
dateFormatLocale:"en_us" dateFormatLocale: "en_us",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "en", lang: "en",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/elitemanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/elitemanga/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "en_us", dateFormatLocale: "en_us",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "es", lang: "es",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/emperorscan/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/emperorscan/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "es", dateFormatLocale: "es",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "tr", lang: "tr",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/evascans/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/evascans/icon.png",
dateFormat: "MMM d, yyy", dateFormat: "MMM d, yyy",
dateFormatLocale: "tr", dateFormatLocale: "tr",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "en", lang: "en",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/factmanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/factmanga/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "en_us", dateFormatLocale: "en_us",
); );

View File

@@ -8,7 +8,6 @@ import '../../../../../../model/source.dart';
lang: "ar", lang: "ar",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/falconmanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/falconmanga/icon.png",
); );

View File

@@ -7,7 +7,8 @@ Source _fayscansSource = Source(
lang: "pt-br", lang: "pt-br",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/fayscans/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/fayscans/icon.png",
dateFormat: "dd/MM/yyyy", dateFormat: "dd/MM/yyyy",
dateFormatLocale:"pt-br" dateFormatLocale: "pt-br",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "en", lang: "en",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/firstkissdashmanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/firstkissdashmanga/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "en_us", dateFormatLocale: "en_us",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "en", lang: "en",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/freemangatop/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/freemangatop/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "en_us", dateFormatLocale: "en_us",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "fr", lang: "fr",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/frscan/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/frscan/icon.png",
dateFormat: "MMMM d, yyyy", dateFormat: "MMMM d, yyyy",
dateFormatLocale: "fr", dateFormatLocale: "fr",
); );

View File

@@ -7,7 +7,8 @@ Source _galinhasamuraiscanSource = Source(
lang: "pt-br", lang: "pt-br",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/galinhasamuraiscan/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/galinhasamuraiscan/icon.png",
dateFormat: "dd/MM/yyyy", dateFormat: "dd/MM/yyyy",
dateFormatLocale:"pt-br" dateFormatLocale: "pt-br",
); );

View File

@@ -7,7 +7,8 @@ Source _garciamangaSource = Source(
lang: "tr", lang: "tr",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/garciamanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/garciamanga/icon.png",
dateFormat: "MMMM d, yyyy", dateFormat: "MMMM d, yyyy",
dateFormatLocale:"tr" dateFormatLocale: "tr",
); );

View File

@@ -7,7 +7,8 @@ Source _gatemangaSource = Source(
lang: "ar", lang: "ar",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/gatemanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/gatemanga/icon.png",
dateFormat: "d MMMM، yyyy", dateFormat: "d MMMM، yyyy",
dateFormatLocale:"ar" dateFormatLocale: "ar",
); );

View File

@@ -7,7 +7,8 @@ Source _globalblogingSource = Source(
lang: "en", lang: "en",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/globalbloging/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/globalbloging/icon.png",
dateFormat: "dd MMMM yyyy", dateFormat: "dd MMMM yyyy",
dateFormatLocale:"en_us" dateFormatLocale: "en_us",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "tr", lang: "tr",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/glorymanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/glorymanga/icon.png",
dateFormat: "dd/MM/yyy", dateFormat: "dd/MM/yyy",
dateFormatLocale: "tr", dateFormatLocale: "tr",
); );

View File

@@ -7,7 +7,8 @@ Source _gmangasiteSource = Source(
lang: "ar", lang: "ar",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/gmangasite/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/gmangasite/icon.png",
dateFormat: "MMMM dd، yyyy", dateFormat: "MMMM dd، yyyy",
dateFormatLocale:"ar" dateFormatLocale: "ar",
); );

View File

@@ -7,7 +7,8 @@ Source _grabberzoneSource = Source(
lang: "all", lang: "all",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/grabberzone/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/grabberzone/icon.png",
dateFormat: "dd.MM.yyyy", dateFormat: "dd.MM.yyyy",
dateFormatLocale:"en" dateFormatLocale: "en",
); );

View File

@@ -7,7 +7,8 @@ Source _guncelmangaSource = Source(
lang: "tr", lang: "tr",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/guncelmanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/guncelmanga/icon.png",
dateFormat: "d MMMM yyyy", dateFormat: "d MMMM yyyy",
dateFormatLocale:"tr" dateFormatLocale: "tr",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "en", lang: "en",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/harimanga/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/harimanga/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "en_us", dateFormatLocale: "en_us",
); );

View File

@@ -7,7 +7,8 @@ Source _herenscanSource = Source(
lang: "es", lang: "es",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/herenscan/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/herenscan/icon.png",
dateFormat: "d 'de' MMM 'de' yyy", dateFormat: "d 'de' MMM 'de' yyy",
dateFormatLocale:"es" dateFormatLocale: "es",
); );

View File

@@ -7,7 +7,8 @@ Source _hikariganaiSource = Source(
lang: "pt-br", lang: "pt-br",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/hikariganai/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/hikariganai/icon.png",
dateFormat: "d 'de' MMMM 'de' yyyy", dateFormat: "d 'de' MMMM 'de' yyyy",
dateFormatLocale:"pt-br" dateFormatLocale: "pt-br",
); );

View File

@@ -7,7 +7,8 @@ Source _housemangasSource = Source(
lang: "es", lang: "es",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/housemangas/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/housemangas/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale:"es" dateFormatLocale: "es",
); );

View File

@@ -7,7 +7,8 @@ Source _hwagoSource = Source(
lang: "id", lang: "id",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/hwago/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/hwago/icon.png",
dateFormat: "d MMMM yyyy", dateFormat: "d MMMM yyyy",
dateFormatLocale:"en" dateFormatLocale: "en",
); );

View File

@@ -8,7 +8,8 @@ import '../../../../../../model/source.dart';
lang: "en", lang: "en",
typeSource: "madara", typeSource: "madara",
iconUrl:"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/immortalupdates/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/multisrc/madara/src/immortalupdates/icon.png",
dateFormat: "MMMM dd, yyyy", dateFormat: "MMMM dd, yyyy",
dateFormatLocale: "en_us", dateFormatLocale: "en_us",
); );

View File

@@ -7,7 +7,8 @@ Source _imperiodabritanniaSource = Source(
lang: "pt-br", lang: "pt-br",
isNsfw: false, isNsfw: false,
typeSource: "madara", typeSource: "madara",
iconUrl: "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/imperiodabritannia/icon.png", iconUrl:
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/dart/manga/multisrc/madara/src/imperiodabritannia/icon.png",
dateFormat: "dd 'de' MMMMM 'de' yyyy", dateFormat: "dd 'de' MMMMM 'de' yyyy",
dateFormatLocale:"pt-br" dateFormatLocale: "pt-br",
); );

Some files were not shown because too many files have changed in this diff Show More