Merge pull request #1 from kodjodevf/Refactor

Refactor
This commit is contained in:
Moustapha Kodjo Amadou
2023-10-25 19:26:35 +01:00
committed by GitHub
41 changed files with 1153 additions and 1499 deletions

View File

@@ -5,20 +5,16 @@ import '../model/source.dart';
import 'src/ar/okanime/source.dart'; import 'src/ar/okanime/source.dart';
import 'src/en/aniwatch/sources.dart'; import 'src/en/aniwatch/sources.dart';
import 'src/en/gogoanime/source.dart'; import 'src/en/gogoanime/source.dart';
// import 'src/en/wcostream/source.dart';
import 'src/en/kisskh/source.dart'; import 'src/en/kisskh/source.dart';
import 'src/fr/animesultra/source.dart'; import 'src/fr/animesultra/source.dart';
import 'src/fr/franime/source.dart'; import 'src/fr/franime/source.dart';
import 'src/fr/otakufr/source.dart'; import 'src/fr/otakufr/source.dart';
import 'src/fr/universanime/source.dart';
void main() { void main() {
List<Source> _sourcesList = [ List<Source> _sourcesList = [
gogoanimeSource, gogoanimeSource,
franimeSource, franimeSource,
universanimeSource,
otakufr, otakufr,
// wcostreamSource,
animesultraSource, animesultraSource,
...aniwatchSourcesList, ...aniwatchSourcesList,
kisskhSource, kisskhSource,

View File

@@ -1,12 +1,13 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
getPopularAnime(MangaModel anime) async { getPopularAnime(MManga anime) async {
final data = {"url": "https://www.okanime.xyz"}; final data = {"url": "https://www.okanime.xyz"};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath(res, anime.urls = MBridge.xpath(res,
'//div[@class="section" and contains(text(),"افضل انميات")]/div[@class="section-content"]/div/div/div[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/@href'); '//div[@class="section" and contains(text(),"افضل انميات")]/div[@class="section-content"]/div/div/div[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/@href');
@@ -19,15 +20,16 @@ getPopularAnime(MangaModel anime) async {
return anime; return anime;
} }
getAnimeDetail(MangaModel anime) async { getAnimeDetail(MManga anime) async {
final statusList = [ final statusList = [
{"يعرض الان": 0, "مكتمل": 1} {"يعرض الان": 0, "مكتمل": 1}
]; ];
final data = {"url": anime.link}; final data = {"url": anime.link};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
final status = MBridge.xpath(res, final status = MBridge.xpath(res,
'//*[@class="full-list-info" and contains(text(),"حالة الأنمي")]/small/a/text()'); '//*[@class="full-list-info" and contains(text(),"حالة الأنمي")]/small/a/text()');
@@ -52,14 +54,15 @@ getAnimeDetail(MangaModel anime) async {
return anime; return anime;
} }
getLatestUpdatesAnime(MangaModel anime) async { getLatestUpdatesAnime(MManga anime) async {
final data = { final data = {
"url": "https://www.okanime.xyz/espisode-list?page=${anime.page}" "url": "https://www.okanime.xyz/espisode-list?page=${anime.page}"
}; };
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath(res, anime.urls = MBridge.xpath(res,
'//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/@href'); '//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/@href');
@@ -78,16 +81,17 @@ getLatestUpdatesAnime(MangaModel anime) async {
return anime; return anime;
} }
searchAnime(MangaModel anime) async { searchAnime(MManga anime) async {
String url = "https://www.okanime.xyz/search/?s=${anime.query}"; String url = "https://www.okanime.xyz/search/?s=${anime.query}";
if (anime.page > 1) { if (anime.page > 1) {
url += "&page=${anime.page}"; url += "&page=${anime.page}";
} }
final data = {"url": url}; final data = {"url": url};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath(res, anime.urls = MBridge.xpath(res,
'//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/@href'); '//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/@href');
@@ -106,21 +110,22 @@ searchAnime(MangaModel anime) async {
return anime; return anime;
} }
getVideoList(MangaModel anime) async { getVideoList(MManga anime) async {
final datas = {"url": anime.link}; final datas = {"url": anime.link};
final res = await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (response.hasError) {
return []; return response;
} }
String res = response.body;
final urls = MBridge.xpath(res, '//*[@id="streamlinks"]/a/@data-src'); final urls = MBridge.xpath(res, '//*[@id="streamlinks"]/a/@data-src');
final qualities = MBridge.xpath(res, '//*[@id="streamlinks"]/a/span/text()'); final qualities = MBridge.xpath(res, '//*[@id="streamlinks"]/a/span/text()');
List<VideoModel> videos = []; List<MVideo> videos = [];
for (var i = 0; i < urls.length; i++) { for (var i = 0; i < urls.length; i++) {
final url = urls[i]; final url = urls[i];
final quality = getQuality(qualities[i]); final quality = getQuality(qualities[i]);
List<VideoModel> a = []; List<MVideo> a = [];
if (url.contains("https://doo")) { if (url.contains("https://doo")) {
a = await MBridge.doodExtractor(url, "DoodStream - $quality"); a = await MBridge.doodExtractor(url, "DoodStream - $quality");

View File

@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
Source get okanimeSource => _okanimeSource; Source get okanimeSource => _okanimeSource;
const okanimeVersion = "0.0.1"; const okanimeVersion = "0.0.2";
const okanimeSourceCodeUrl = const okanimeSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/ar/okanime/okanime-v$okanimeVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/ar/okanime/okanime-v$okanimeVersion.dart";
Source _okanimeSource = Source( Source _okanimeSource = Source(
@@ -13,5 +13,4 @@ Source _okanimeSource = Source(
iconUrl: getIconUrl("okanime", "ar"), iconUrl: getIconUrl("okanime", "ar"),
sourceCodeUrl: okanimeSourceCodeUrl, sourceCodeUrl: okanimeSourceCodeUrl,
version: okanimeVersion, version: okanimeVersion,
appMinVerReq: "0.0.48",
isManga: false); isManga: false);

View File

@@ -1,26 +1,25 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
getPopularAnime(MangaModel anime) async { getPopularAnime(MManga anime) async {
final data = {"url": "${anime.baseUrl}/most-popular?page=${anime.page}"}; final data = {"url": "${anime.baseUrl}/most-popular?page=${anime.page}"};
final res = await MBridge.http('GET', json.encode(data)); final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (res.hasError) {
return anime; return res;
} }
return animeElementM(res.body, anime);
return animeElementM(res, anime);
} }
getLatestUpdatesAnime(MangaModel anime) async { getLatestUpdatesAnime(MManga anime) async {
final data = {"url": "${anime.baseUrl}/top-airing?page=${anime.page}"}; final data = {"url": "${anime.baseUrl}/top-airing?page=${anime.page}"};
final res = await MBridge.http('GET', json.encode(data)); final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (res.hasError) {
return anime; return res;
} }
return animeElementM(res, anime); return animeElementM(res.body, anime);
} }
getAnimeDetail(MangaModel anime) async { getAnimeDetail(MManga anime) async {
final statusList = [ final statusList = [
{ {
"Currently Airing": 0, "Currently Airing": 0,
@@ -29,11 +28,11 @@ getAnimeDetail(MangaModel anime) async {
]; ];
final url = "${anime.baseUrl}${anime.link}"; final url = "${anime.baseUrl}${anime.link}";
final data = {"url": url, "headers": null}; final data = {"url": url, "headers": null};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
final status = MBridge.xpath(res, final status = MBridge.xpath(res,
'//*[@class="anisc-info"]/div[contains(text(),"Status:")]/span[2]/text()') '//*[@class="anisc-info"]/div[contains(text(),"Status:")]/span[2]/text()')
.first; .first;
@@ -75,7 +74,7 @@ getAnimeDetail(MangaModel anime) async {
}; };
final resEp = await MBridge.http('GET', json.encode(dataEp)); final resEp = await MBridge.http('GET', json.encode(dataEp));
final html = json.decode(resEp)["html"]; final html = json.decode(resEp.body)["html"];
final epUrls = MBridge.querySelectorAll(html, final epUrls = MBridge.querySelectorAll(html,
selector: "a.ep-item", typeElement: 3, attributes: "href", typeRegExp: 0); selector: "a.ep-item", typeElement: 3, attributes: "href", typeRegExp: 0);
@@ -107,18 +106,18 @@ getAnimeDetail(MangaModel anime) async {
return anime; return anime;
} }
searchAnime(MangaModel anime) async { searchAnime(MManga anime) async {
final data = { final data = {
"url": "${anime.baseUrl}/search?keyword=${anime.query}&page=${anime.page}" "url": "${anime.baseUrl}/search?keyword=${anime.query}&page=${anime.page}"
}; };
final res = await MBridge.http('GET', json.encode(data)); final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (res.hasError) {
return anime; return res;
} }
return animeElementM(res, anime); return animeElementM(res.body, anime);
} }
getVideoList(MangaModel anime) async { getVideoList(MManga anime) async {
final id = MBridge.substringAfterLast(anime.link, '?ep='); final id = MBridge.substringAfterLast(anime.link, '?ep=');
final datas = { final datas = {
"url": "url":
@@ -129,10 +128,10 @@ getVideoList(MangaModel anime) async {
final res = await MBridge.http('GET', json.encode(datas)); final res = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (res.hasError) {
return []; return res;
} }
final html = json.decode(res)["html"]; final html = json.decode(res.body)["html"];
final names = MBridge.querySelectorAll(html, final names = MBridge.querySelectorAll(html,
selector: "div.server-item", selector: "div.server-item",
@@ -152,7 +151,7 @@ getVideoList(MangaModel anime) async {
attributes: "data-type", attributes: "data-type",
typeRegExp: 0); typeRegExp: 0);
List<VideoModel> videos = []; List<MVideo> videos = [];
for (var i = 0; i < names.length; i++) { for (var i = 0; i < names.length; i++) {
final name = names[i]; final name = names[i];
@@ -166,9 +165,9 @@ getVideoList(MangaModel anime) async {
final resE = await MBridge.http('GET', json.encode(datasE)); final resE = await MBridge.http('GET', json.encode(datasE));
String url = MBridge.substringBefore( String url = MBridge.substringBefore(
MBridge.substringAfter(resE, "\"link\":\""), "\""); MBridge.substringAfter(resE.body, "\"link\":\""), "\"");
print(url); print(url);
List<VideoModel> a = []; List<MVideo> a = [];
if (name.contains("Vidstreaming")) { if (name.contains("Vidstreaming")) {
a = await MBridge.rapidCloudExtractor(url, "Vidstreaming - $subDub"); a = await MBridge.rapidCloudExtractor(url, "Vidstreaming - $subDub");
videos.addAll(a); videos.addAll(a);
@@ -184,7 +183,7 @@ getVideoList(MangaModel anime) async {
return videos; return videos;
} }
MangaModel animeElementM(String res, MangaModel anime) async { MManga animeElementM(String res, MManga anime) async {
if (res.isEmpty) { if (res.isEmpty) {
return anime; return anime;
} }

View File

@@ -1,7 +1,7 @@
import '../../../../model/source.dart'; import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
const aniwatchVersion = "0.0.21"; const aniwatchVersion = "0.0.3";
const aniwatchSourceCodeUrl = const aniwatchSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/aniwatch/aniwatch-v$aniwatchVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/aniwatch/aniwatch-v$aniwatchVersion.dart";
@@ -15,7 +15,6 @@ List<Source> _aniwatchSourcesList = [
iconUrl: getIconUrl("aniwatch", "en"), iconUrl: getIconUrl("aniwatch", "en"),
version: aniwatchVersion, version: aniwatchVersion,
isManga: false, isManga: false,
appMinVerReq: "0.0.45",
sourceCodeUrl: aniwatchSourceCodeUrl), sourceCodeUrl: aniwatchSourceCodeUrl),
Source( Source(
name: "Kaido.to", name: "Kaido.to",
@@ -25,6 +24,5 @@ List<Source> _aniwatchSourcesList = [
iconUrl: getIconUrl("kaido", "en"), iconUrl: getIconUrl("kaido", "en"),
version: aniwatchVersion, version: aniwatchVersion,
isManga: false, isManga: false,
appMinVerReq: "0.0.45",
sourceCodeUrl: aniwatchSourceCodeUrl), sourceCodeUrl: aniwatchSourceCodeUrl),
]; ];

View File

@@ -1,32 +1,30 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
getPopularAnime(MangaModel anime) async { getPopularAnime(MManga anime) async {
final data = {"url": "${anime.baseUrl}/popular.html?page=${anime.page}"}; final data = {"url": "${anime.baseUrl}/popular.html?page=${anime.page}"};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath(res, '//*[@class="img"]/a/@href'); anime.urls = MBridge.xpath(res, '//*[@class="img"]/a/@href');
anime.names = MBridge.xpath(res, '//*[@class="img"]/a/@title'); anime.names = MBridge.xpath(res, '//*[@class="img"]/a/@title');
anime.images = MBridge.xpath(res, '//*[@class="img"]/a/img/@src'); anime.images = MBridge.xpath(res, '//*[@class="img"]/a/img/@src');
return anime; return anime;
} }
getLatestUpdatesAnime(MangaModel anime) async { getLatestUpdatesAnime(MManga anime) async {
final url = final url =
"https://ajax.gogo-load.com/ajax/page-recent-release-ongoing.html?page=${anime.page}&type=1"; "https://ajax.gogo-load.com/ajax/page-recent-release-ongoing.html?page=${anime.page}&type=1";
final data = {"url": url}; final data = {"url": url};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath( anime.urls = MBridge.xpath(
res, '//*[@class="added_series_body popular"]/ul/li/a[1]/@href'); res, '//*[@class="added_series_body popular"]/ul/li/a[1]/@href');
anime.names = MBridge.xpath( anime.names = MBridge.xpath(
res, '//*[//*[@class="added_series_body popular"]/ul/li/a[1]/@title'); res, '//*[//*[@class="added_series_body popular"]/ul/li/a[1]/@title');
List<String> images = []; List<String> images = [];
@@ -41,7 +39,7 @@ getLatestUpdatesAnime(MangaModel anime) async {
return anime; return anime;
} }
getAnimeDetail(MangaModel anime) async { getAnimeDetail(MManga anime) async {
final statusList = [ final statusList = [
{ {
"Ongoing": 0, "Ongoing": 0,
@@ -50,21 +48,20 @@ getAnimeDetail(MangaModel anime) async {
]; ];
final data = {"url": "${anime.baseUrl}${anime.link}"}; final data = {"url": "${anime.baseUrl}${anime.link}"};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
final status = MBridge.xpath( final status = MBridge.xpath(
res, '//*[@class="anime_info_body_bg"]/p[@class="type"][5]/text()') res, '//*[@class="anime_info_body_bg"]/p[@class="type"][5]/text()')
.first .first
.replaceAll("Status: ", ""); .replaceAll("Status: ", "");
anime.description = MBridge.xpath( anime.description = MBridge.xpath(
res, '//*[@class="anime_info_body_bg"]/p[@class="type"][2]/text()') res, '//*[@class="anime_info_body_bg"]/p[@class="type"][2]/text()')
.first .first
.replaceAll("Plot Summary: ", ""); .replaceAll("Plot Summary: ", "");
anime.status = MBridge.parseStatus(status, statusList); anime.status = MBridge.parseStatus(status, statusList);
anime.genre = MBridge.xpath( anime.genre = MBridge.xpath(
res, '//*[@class="anime_info_body_bg"]/p[@class="type"][3]/text()') res, '//*[@class="anime_info_body_bg"]/p[@class="type"][3]/text()')
@@ -76,7 +73,11 @@ getAnimeDetail(MangaModel anime) async {
final urlEp = final urlEp =
"https://ajax.gogo-load.com/ajax/load-list-episode?ep_start=0&ep_end=4000&id=$id"; "https://ajax.gogo-load.com/ajax/load-list-episode?ep_start=0&ep_end=4000&id=$id";
final dataEp = {"url": urlEp}; final dataEp = {"url": urlEp};
final resEp = await MBridge.http('GET', json.encode(dataEp)); final responseresEp = await MBridge.http('GET', json.encode(dataEp));
if (responseresEp.hasError) {
return response;
}
String resEp = responseresEp.body;
anime.urls = MBridge.xpath(resEp, '//*[@id="episode_related"]/li/a/@href'); anime.urls = MBridge.xpath(resEp, '//*[@id="episode_related"]/li/a/@href');
final names = MBridge.xpath( final names = MBridge.xpath(
resEp, '//*[@id="episode_related"]/li/a/div[@class="name"]/text()'); resEp, '//*[@id="episode_related"]/li/a/div[@class="name"]/text()');
@@ -91,26 +92,26 @@ getAnimeDetail(MangaModel anime) async {
return anime; return anime;
} }
getVideoList(MangaModel anime) async { getVideoList(MManga anime) async {
final datas = {"url": "${anime.baseUrl}${anime.link}"}; final datas = {"url": "${anime.baseUrl}${anime.link}"};
final res = await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (response.hasError) {
return []; return response;
} }
String res = response.body;
final serverUrls = final serverUrls =
MBridge.xpath(res, '//*[@class="anime_muti_link"]/ul/li/a/@data-video'); MBridge.xpath(res, '//*[@class="anime_muti_link"]/ul/li/a/@data-video');
final classNames = final classNames =
MBridge.xpath(res, '//*[@class="anime_muti_link"]/ul/li/@class'); MBridge.xpath(res, '//*[@class="anime_muti_link"]/ul/li/@class');
print(serverUrls); List<MVideo> videos = [];
List<VideoModel> videos = [];
for (var i = 0; i < classNames.length; i++) { for (var i = 0; i < classNames.length; i++) {
final name = classNames[i]; final name = classNames[i];
final url = serverUrls[i]; final url = serverUrls[i];
print(url); print(url);
List<VideoModel> a = []; List<MVideo> a = [];
if (name.contains("anime")) { if (name.contains("anime")) {
a = await MBridge.gogoCdnExtractor(url); a = await MBridge.gogoCdnExtractor(url);
} else if (name.contains("vidcdn")) { } else if (name.contains("vidcdn")) {
@@ -131,18 +132,17 @@ getVideoList(MangaModel anime) async {
return videos; return videos;
} }
searchAnime(MangaModel anime) async { searchAnime(MManga anime) async {
final url = final url =
"${anime.baseUrl}/search.html?keyword=${anime.query}&page=${anime.page}"; "${anime.baseUrl}/search.html?keyword=${anime.query}&page=${anime.page}";
final data = {"url": url}; final data = {"url": url};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath(res, '//*[@class="img"]/a/@href'); anime.urls = MBridge.xpath(res, '//*[@class="img"]/a/@href');
anime.names = MBridge.xpath(res, '//*[@class="img"]/a/@title'); anime.names = MBridge.xpath(res, '//*[@class="img"]/a/@title');
anime.images = MBridge.xpath(res, '//*[@class="img"]/a/img/@src'); anime.images = MBridge.xpath(res, '//*[@class="img"]/a/img/@src');
return anime; return anime;
} }

View File

@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
Source get gogoanimeSource => _gogoanimeSource; Source get gogoanimeSource => _gogoanimeSource;
const gogoanimeVersion = "0.0.2"; const gogoanimeVersion = "0.0.3";
const gogoanimeSourceCodeUrl = const gogoanimeSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/gogoanime/gogoanime-v$gogoanimeVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/gogoanime/gogoanime-v$gogoanimeVersion.dart";
Source _gogoanimeSource = Source( Source _gogoanimeSource = Source(

View File

@@ -1,15 +1,16 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
getPopularAnime(MangaModel anime) async { getPopularAnime(MManga anime) async {
final data = { final data = {
"url": "url":
"${anime.baseUrl}/api/DramaList/List?page=${anime.page}&type=0&sub=0&country=0&status=0&order=1&pageSize=40" "${anime.baseUrl}/api/DramaList/List?page=${anime.page}&type=0&sub=0&country=0&status=0&order=1&pageSize=40"
}; };
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
final jsonRes = json.decode(res); final jsonRes = json.decode(res);
final datas = jsonRes["data"] as List; final datas = jsonRes["data"] as List;
anime.names = datas.map((e) => e["title"]).toList(); anime.names = datas.map((e) => e["title"]).toList();
@@ -24,15 +25,16 @@ getPopularAnime(MangaModel anime) async {
return anime; return anime;
} }
getLatestUpdatesAnime(MangaModel anime) async { getLatestUpdatesAnime(MManga anime) async {
final data = { final data = {
"url": "url":
"${anime.baseUrl}/api/DramaList/List?page=${anime.page}&type=0&sub=0&country=0&status=0&order=12&pageSize=40" "${anime.baseUrl}/api/DramaList/List?page=${anime.page}&type=0&sub=0&country=0&status=0&order=12&pageSize=40"
}; };
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
final jsonRes = json.decode(res); final jsonRes = json.decode(res);
final datas = jsonRes["data"] as List; final datas = jsonRes["data"] as List;
anime.names = datas.map((e) => e["title"]).toList(); anime.names = datas.map((e) => e["title"]).toList();
@@ -48,7 +50,7 @@ getLatestUpdatesAnime(MangaModel anime) async {
return anime; return anime;
} }
getAnimeDetail(MangaModel anime) async { getAnimeDetail(MManga anime) async {
final statusList = [ final statusList = [
{ {
"Ongoing": 0, "Ongoing": 0,
@@ -57,10 +59,11 @@ getAnimeDetail(MangaModel anime) async {
]; ];
final data = {"url": anime.link}; final data = {"url": anime.link};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
final jsonRes = json.decode(res); final jsonRes = json.decode(res);
final status = jsonRes["status"] ?? ""; final status = jsonRes["status"] ?? "";
print(status); print(status);
@@ -72,10 +75,10 @@ getAnimeDetail(MangaModel anime) async {
final episodesCount = jsonRes["episodesCount"] as int; final episodesCount = jsonRes["episodesCount"] as int;
List<String> episodesNames = []; List<String> episodesNames = [];
List<String> episodesUrls = []; List<String> episodesUrls = [];
bool containsAnime = type.contains("Anime") as bool; final containsAnime = type.contains("Anime") as bool;
bool containsTVSeries = type.contains("TVSeries") as bool; final containsTVSeries = type.contains("TVSeries") as bool;
bool containsHollywood = type.contains("Hollywood") as bool; final containsHollywood = type.contains("Hollywood") as bool;
bool containsMovie = type.contains("Movie") as bool; final containsMovie = type.contains("Movie") as bool;
for (var a in episodes) { for (var a in episodes) {
String number = (a["number"] as double).toString().replaceAll(".0", ""); String number = (a["number"] as double).toString().replaceAll(".0", "");
final id = a["id"]; final id = a["id"];
@@ -96,28 +99,29 @@ getAnimeDetail(MangaModel anime) async {
return anime; return anime;
} }
getVideoList(MangaModel anime) async { getVideoList(MManga anime) async {
final datas = {"url": anime.link}; final datas = {"url": anime.link};
final res = await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (response.hasError) {
return []; return response;
} }
String res = response.body;
final id = MBridge.substringAfter( final id = MBridge.substringAfter(
MBridge.substringBefore(anime.link, ".png"), "Episode/"); MBridge.substringBefore(anime.link, ".png"), "Episode/");
final jsonRes = json.decode(res); final jsonRes = json.decode(res);
final subRes = await MBridge.http( final subRes = await MBridge.http(
'GET', json.encode({"url": "${anime.baseUrl}/api/Sub/$id"})); 'GET', json.encode({"url": "${anime.baseUrl}/api/Sub/$id"}));
var jsonSubRes = json.decode(subRes); var jsonSubRes = json.decode(subRes.body);
List<TrackModel> subtitles = []; List<MTrack> subtitles = [];
for (var sub in jsonSubRes) { for (var sub in jsonSubRes) {
try { try {
final subUrl = sub["src"]; final subUrl = sub["src"];
final label = sub["label"]; final label = sub["label"];
TrackModel subtitle = TrackModel(); MTrack subtitle = MTrack();
subtitle subtitle
..label = label ..label = label
..file = subUrl; ..file = subUrl;
@@ -126,7 +130,7 @@ getVideoList(MangaModel anime) async {
} }
final videoUrl = jsonRes["Video"]; final videoUrl = jsonRes["Video"];
VideoModel video = VideoModel(); MVideo video = MVideo();
video video
..url = videoUrl ..url = videoUrl
..originalUrl = videoUrl ..originalUrl = videoUrl
@@ -139,20 +143,18 @@ getVideoList(MangaModel anime) async {
return [video]; return [video];
} }
searchAnime(MangaModel anime) async { searchAnime(MManga anime) async {
final data = { final data = {
"url": "${anime.baseUrl}/api/DramaList/Search?q=${anime.query}&type=0" "url": "${anime.baseUrl}/api/DramaList/Search?q=${anime.query}&type=0"
}; };
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
var jsonRes = json.decode(res) as List; var jsonRes = json.decode(res) as List;
anime.names = jsonRes.map((e) => e["title"]).toList(); anime.names = jsonRes.map((e) => e["title"]).toList();
anime.images = jsonRes.map((e) => e["thumbnail"] ?? "").toList(); anime.images = jsonRes.map((e) => e["thumbnail"] ?? "").toList();
anime.urls = jsonRes anime.urls = jsonRes
.map((e) => "${anime.baseUrl}/api/DramaList/Drama/${e["id"]}?isq=false") .map((e) => "${anime.baseUrl}/api/DramaList/Drama/${e["id"]}?isq=false")
.toList(); .toList();

View File

@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
Source get kisskhSource => _kisskhSource; Source get kisskhSource => _kisskhSource;
const kisskhVersion = "0.0.1"; const kisskhVersion = "0.0.2";
const kisskhSourceCodeUrl = const kisskhSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/kisskh/kisskh-v$kisskhVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/kisskh/kisskh-v$kisskhVersion.dart";
Source _kisskhSource = Source( Source _kisskhSource = Source(
@@ -13,5 +13,4 @@ Source _kisskhSource = Source(
iconUrl: getIconUrl("kisskh", "en"), iconUrl: getIconUrl("kisskh", "en"),
sourceCodeUrl: kisskhSourceCodeUrl, sourceCodeUrl: kisskhSourceCodeUrl,
version: kisskhVersion, version: kisskhVersion,
appMinVerReq: "0.0.48",
isManga: false); isManga: false);

View File

@@ -1,17 +0,0 @@
import '../../../../model/source.dart';
import '../../../../utils/utils.dart';
Source get wcostreamSource => _wcostreamSource;
const wcostreamVersion = "0.0.11";
const wcostreamSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/wcostream/wcostream-v$wcostreamVersion.dart";
Source _wcostreamSource = Source(
name: "WCOStream",
baseUrl: "https://www.wcostream.org",
lang: "en",
typeSource: "single",
iconUrl: getIconUrl("wcostream", "en"),
sourceCodeUrl: wcostreamSourceCodeUrl,
version: wcostreamVersion,
isManga: false,
isFullData: false);

View File

@@ -1,223 +0,0 @@
import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart';
getPopularAnime(MangaModel anime) async {
return await getLatestUpdatesAnime(anime);
}
Future<MangaModel> getLatestUpdatesAnime(MangaModel anime) async {
final data = {
"url": anime.baseUrl,
"headers": {"referer": "https://wcostream.org/"},
"sourceId": anime.sourceId
};
final res = await MBridge.http(json.encode(data), 0);
if (res.isEmpty) {
return anime;
}
final urlss = MBridge.xpath(
res,
'//*[@id="content"]/div/div[contains(text(),"Recent Releases")]/div/ul/li/div[@class="img"]/a/img/@alt',
'._')
.split('._');
List<String> urls = [];
for (var url in MBridge.listParse(urlss, 0)) {
urls.add(
"/anime/${MBridge.regExp(url, "[^A-Za-z0-9 ]", "", 0, 0).replaceAll(" ", "-").toLowerCase()}/");
}
anime.urls = urls;
final imagess = MBridge.xpath(
res,
'//*[@id="content"]/div/div[contains(text(),"Recent Releases")]/div/ul/li/div[@class="img"]/a/img/@src',
'._')
.split('._');
List<String> images = [];
for (var image in MBridge.listParse(imagess, 0)) {
images.add(fixUrl(image));
}
anime.images = images;
final namess = MBridge.xpath(
res,
'//*[@id="content"]/div/div[contains(text(),"Recent Releases")]/div/ul/li/div[@class="recent-release-episodes"]/a/text()',
'._')
.split('._');
List<String> names = [];
for (var name in MBridge.listParse(namess, 0)) {
names.add(MBridge.subString(name, ' Episode', 0));
}
anime.names = names;
anime.hasNextPage = false;
return anime;
}
String fixUrl(String url) {
return MBridge.regExp(url, r"^(?:(?:https?:)?//|www\.)", 'https://', 0, 0);
}
getAnimeDetail(MangaModel anime) async {
final url = '${anime.baseUrl}${anime.link}';
print(url);
final data = {
"url": url,
"headers": {"referer": "https://wcostream.org/"}
};
final res = await MBridge.http(json.encode(data), 0);
if (res.isEmpty) {
return anime;
}
anime.status = 5;
anime.description = MBridge.xpath(
res,
'//*[@class="katcont"]/div/p[contains(text(),"Plot Summary:")]/text()',
'')
.replaceAll('Plot Summary: ', '');
anime.genre = MBridge.xpath(
res, '//*[@id="cat-genre"]/div[@class="wcobtn"]/a/text()', '._')
.split('._');
anime.urls = MBridge.xpath(
res,
'//*[@id="catlist-listview" and @class^="cat-listview"]/ul/li/a/@href',
'._')
.split('._');
anime.names = MBridge.xpath(
res,
'//*[@id="catlist-listview" and @class^="cat-listview"]/ul/li/a/text()',
'._')
.split('._');
anime.chaptersDateUploads = [];
return anime;
}
searchAnime(MangaModel anime) async {
final data = {
"url": "${anime.baseUrl}/search",
"fields": {'catara': anime.query.replaceAll(" ", "+"), 'konuara': 'series'},
"headers": {"Referer": "${anime.baseUrl}/"},
"sourceId": anime.sourceId
};
final res = await MBridge.httpMultiparFormData(json.encode(data), 1);
if (res.isEmpty) {
return anime;
}
anime.urls = MBridge.xpath(
res,
'//*[@id="blog"]/div[@class="cerceve"]/div[@class="iccerceve"]/a/@href',
'._')
.split('._');
anime.names = MBridge.xpath(
res,
'//*[@id="blog"]/div[@class="cerceve"]/div[@class="iccerceve"]/a/@title',
'._')
.split('._');
anime.images = MBridge.xpath(
res,
'//*[@id="blog"]/div[@class="cerceve"]/div[@class="iccerceve"]/a/img/@src',
'._')
.split('._');
anime.hasNextPage = false;
return anime;
}
getVideoList(MangaModel anime) async {
final datas = {
"url": anime.link,
"headers": null,
"sourceId": anime.sourceId
};
final res = await MBridge.http(json.encode(datas), 0);
if (res.isEmpty) {
return [];
}
final script = MBridge.xpath(
res, '//script[contains(text(), "decodeURIComponent")]/text()', "");
final stringList = MBridge.jsonDecodeToList(
"[${MBridge.subString(MBridge.subString(script, '[', 2), ']', 0)}]", 0);
final shiftNumber = MBridge.intParse(
MBridge.subString(MBridge.subString(script, '- ', 1), ')', 0));
print(shiftNumber - 1);
List<String> iframeStuff = [];
for (var i = 0; i < stringList.length; i++) {
final decoded = MBridge.bAse64(MBridge.listParse(stringList, 0)[i], 0);
final intValue =
MBridge.intParse(MBridge.regExp(decoded, r"""\D""", '', 0, 0));
iframeStuff
.add(MBridge.stringParse("${intValue - shiftNumber}".toString(), 1));
}
final iframeUrl =
MBridge.xpath(MBridge.listParse(iframeStuff, 6)[0], '//iframe/@src', "");
final iframeHeaders = {
'Accept':
'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Connection': 'keep-alive',
'Host': MBridge.listParse(iframeUrl.split('/'), 0)[2],
'Referer': '${anime.baseUrl}/',
'Sec-Fetch-Dest': 'iframe',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'cross-site',
'Upgrade-Insecure-Requests': '1',
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63',
};
final datasIframe = {"url": iframeUrl, "headers": iframeHeaders};
final resIframe = await MBridge.http(json.encode(datasIframe), 0);
final getVideoLinkScript = MBridge.xpath(
resIframe, '//script[contains(text(), "getJSON")]/text()', "");
final getVideoLinkUrl = MBridge.subString(
MBridge.subString(getVideoLinkScript, "getJSON(\"", 2), "\"", 0);
final getVideoHeaders = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Host': MBridge.listParse(iframeUrl.split('/'), 0)[2],
'Referer': iframeUrl,
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63',
'X-Requested-With': 'XMLHttpRequest',
};
final datasVideoLink = {
"url":
'https://${MBridge.listParse(iframeUrl.split('/'), 0)[2]}$getVideoLinkUrl',
"headers": getVideoHeaders
};
final resVideoLink = await MBridge.http(json.encode(datasVideoLink), 0);
final server = MBridge.getMapValue(resVideoLink, "server", 0);
final enc = MBridge.getMapValue(resVideoLink, "enc", 0);
final hd = MBridge.getMapValue(resVideoLink, "hd", 0);
final fhd = MBridge.getMapValue(resVideoLink, "fhd", 0);
final videoUrl = "$server/getvid?evid=$enc";
final videoHeaders = {
'Accept':
'video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5',
'Host': MBridge.listParse(videoUrl.split('/'), 0)[2],
'Referer': MBridge.listParse(iframeUrl.split('/'), 0)[2],
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63',
};
List<VideoModel> videos = [];
videos.add(MBridge.toVideo(
videoUrl, "Video 480p", videoUrl, json.encode(videoHeaders)));
if (hd.isEmpty) {
} else {
final hdVideoUrl = "$server/getvid?evid=$hd";
videos.add(MBridge.toVideo(
hdVideoUrl, "Video 720p", hdVideoUrl, json.encode(videoHeaders)));
}
if (fhd.isEmpty) {
} else {
final fhdVideoUrl = "$server/getvid?evid=$fhd";
videos.add(MBridge.toVideo(
fhdVideoUrl, "Video 1080p", fhdVideoUrl, json.encode(videoHeaders)));
}
return videos;
}

View File

@@ -1,60 +1,58 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
getPopularAnime(MangaModel anime) async { getPopularAnime(MManga anime) async {
final data = {"url": "${anime.baseUrl}/"}; final data = {"url": "${anime.baseUrl}/"};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath(res, anime.urls = MBridge.xpath(res,
'//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/@href'); '//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/@href');
anime.names = MBridge.xpath(res, anime.names = MBridge.xpath(res,
'//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/img/@title'); '//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/img/@title');
anime.images = MBridge.xpath(res, anime.images = MBridge.xpath(res,
'//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/img/@data-src'); '//*[contains(@class,"swiper-slide item-qtip")]/div[@class="item"]/a/img/@data-src');
anime.hasNextPage = false; anime.hasNextPage = false;
return anime; return anime;
} }
getLatestUpdatesAnime(MangaModel anime) async { getLatestUpdatesAnime(MManga anime) async {
final data = {"url": "${anime.baseUrl}/"}; final data = {"url": "${anime.baseUrl}/"};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath(res, anime.urls = MBridge.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/@href');
anime.names = MBridge.xpath(res, anime.names = MBridge.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/@title'); '//*[@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');
anime.images = MBridge.xpath(res, anime.images = MBridge.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'); '//*[@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');
anime.hasNextPage = false; anime.hasNextPage = false;
return anime; return anime;
} }
searchAnime(MangaModel anime) async { searchAnime(MManga anime) async {
final url = final url =
"${anime.baseUrl}/?story=${anime.query}&do=search&subaction=search"; "${anime.baseUrl}/?story=${anime.query}&do=search&subaction=search";
final data = {"url": url}; final data = {"url": url};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath(res, '//*[@class="film-poster"]/a/@href'); anime.urls = MBridge.xpath(res, '//*[@class="film-poster"]/a/@href');
anime.names = MBridge.xpath(res, '//*[@class="film-poster"]/a/@title'); anime.names = MBridge.xpath(res, '//*[@class="film-poster"]/a/@title');
anime.images = MBridge.xpath(res, '//*[@class="film-poster"]/img/@data-src'); anime.images = MBridge.xpath(res, '//*[@class="film-poster"]/img/@data-src');
anime.hasNextPage = false; anime.hasNextPage = false;
return anime; return anime;
} }
getAnimeDetail(MangaModel anime) async { getAnimeDetail(MManga anime) async {
final statusList = [ final statusList = [
{ {
"En cours": 0, "En cours": 0,
@@ -63,20 +61,18 @@ getAnimeDetail(MangaModel anime) async {
]; ];
final url = anime.link; final url = anime.link;
final data = {"url": url}; final data = {"url": url};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.description = anime.description =
MBridge.xpath(res, '//*[@class="film-description m-hide"]/text()').first; MBridge.xpath(res, '//*[@class="film-description m-hide"]/text()').first;
final status = MBridge.xpath(res, final status = MBridge.xpath(res,
'//*[@class="item item-title" and contains(text(),"Status:")]/span[2]/text()') '//*[@class="item item-title" and contains(text(),"Status:")]/span[2]/text()')
.first; .first;
anime.status = MBridge.parseStatus(status, statusList); anime.status = MBridge.parseStatus(status, statusList);
anime.genre = MBridge.xpath(res, anime.genre = MBridge.xpath(res,
'//*[@class="item item-list" and contains(text(),"Genres:")]/a/text()'); '//*[@class="item item-list" and contains(text(),"Genres:")]/a/text()');
anime.author = MBridge.xpath(res, anime.author = MBridge.xpath(res,
@@ -88,7 +84,6 @@ getAnimeDetail(MangaModel anime) async {
anime.urls = MBridge.xpath(resEpWebview, '//*[@class="ss-list"]/a/@href') anime.urls = MBridge.xpath(resEpWebview, '//*[@class="ss-list"]/a/@href')
.reversed .reversed
.toList(); .toList();
anime.names = MBridge.xpath(resEpWebview, anime.names = MBridge.xpath(resEpWebview,
'//*[@class="ss-list"]/a/div[@class="ssli-detail"]/div/text()') '//*[@class="ss-list"]/a/div[@class="ssli-detail"]/div/text()')
.reversed .reversed
@@ -97,7 +92,7 @@ getAnimeDetail(MangaModel anime) async {
return anime; return anime;
} }
getVideoList(MangaModel anime) async { getVideoList(MManga anime) async {
final resWebview = await MBridge.getHtmlViaWebview( final resWebview = await MBridge.getHtmlViaWebview(
anime.link, '//*[@class="ps__-list"]/div/@data-server-id'); anime.link, '//*[@class="ps__-list"]/div/@data-server-id');
@@ -112,13 +107,12 @@ getVideoList(MangaModel anime) async {
.first; .first;
serverUrls.add(serversUrls); serverUrls.add(serversUrls);
} }
List<MVideo> videos = [];
List<VideoModel> videos = [];
for (var i = 0; i < serverNames.length; i++) { for (var i = 0; i < serverNames.length; i++) {
final name = serverNames[i]; final name = serverNames[i];
final url = serverUrls[i]; final url = serverUrls[i];
List<VideoModel> a = []; List<MVideo> a = [];
if (name.contains("Sendvid")) { if (name.contains("Sendvid")) {
a = await MBridge.sendVidExtractor( a = await MBridge.sendVidExtractor(
url.replaceAll("https:////", "https://"), url.replaceAll("https:////", "https://"),

View File

@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
Source get animesultraSource => _animesultraSource; Source get animesultraSource => _animesultraSource;
const animesultraVersion = "0.0.2"; const animesultraVersion = "0.0.3";
const animesultraSourceCodeUrl = const animesultraSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/fr/animesultra/animesultra-v$animesultraVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/fr/animesultra/animesultra-v$animesultraVersion.dart";
Source _animesultraSource = Source( Source _animesultraSource = Source(

View File

@@ -1,34 +1,34 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
Future<String> dataBase(int sourceId) async { Future<MHttpResponse> dataBase(int sourceId) async {
final data = { final data = {
"url": "https://api.franime.fr/api/animes/", "url": "https://api.franime.fr/api/animes/",
"headers": {"Referer": "https://franime.fr/"} "headers": {"Referer": "https://franime.fr/"}
}; };
final res = await MBridge.http('GET', json.encode(data));
return res; return await MBridge.http('GET', json.encode(data));
} }
getPopularAnime(MangaModel anime) async { getPopularAnime(MManga anime) async {
final data = { final data = {
"url": "https://api.franime.fr/api/animes/", "url": "https://api.franime.fr/api/animes/",
"headers": {"Referer": "https://franime.fr/"} "headers": {"Referer": "https://franime.fr/"}
}; };
final res = await MBridge.http('GET', json.encode(data)); final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (res.hasError) {
return anime; return res;
} }
List<MangaModel> animeList = animeResList(res); List<MManga> animeList = animeResList(res.body);
return animeList; return animeList;
} }
List<MangaModel> animeResList(String res) { List<MManga> animeResList(String res) {
final statusList = [ final statusList = [
{"EN COURS": 0, "TERMINÉ": 1} {"EN COURS": 0, "TERMINÉ": 1}
]; ];
List<MangaModel> animeList = []; List<MManga> animeList = [];
var jsonResList = json.decode(res); var jsonResList = json.decode(res);
@@ -56,7 +56,7 @@ List<MangaModel> animeResList(String res) {
bool hasVf = vfListName.contains(true); bool hasVf = vfListName.contains(true);
if (hasVostfr || hasVf) { if (hasVostfr || hasVf) {
for (int i = 0; i < seasons.length; i++) { for (int i = 0; i < seasons.length; i++) {
MangaModel anime = MangaModel(); MManga anime = MManga();
int ind = i + 1; int ind = i + 1;
anime.genre = genre; anime.genre = genre;
anime.description = description; anime.description = description;
@@ -106,7 +106,7 @@ String databaseAnimeByTitleO(String res, String titleO) {
return ""; return "";
} }
getAnimeDetail(MangaModel anime) async { getAnimeDetail(MManga anime) async {
String language = "vo".toString(); String language = "vo".toString();
if (anime.link.contains("lang=")) { if (anime.link.contains("lang=")) {
language = MBridge.substringBefore( language = MBridge.substringBefore(
@@ -115,10 +115,10 @@ getAnimeDetail(MangaModel anime) async {
String stem = String stem =
MBridge.substringBefore(MBridge.substringAfterLast(anime.link, "/"), "?"); MBridge.substringBefore(MBridge.substringAfterLast(anime.link, "/"), "?");
final res = await dataBase(anime.sourceId); final res = await dataBase(anime.sourceId);
if (res.isEmpty) { if (res.hasError) {
return anime; return res;
} }
final animeByTitleOJson = databaseAnimeByTitleO(res, stem); final animeByTitleOJson = databaseAnimeByTitleO(res.body, stem);
if (animeByTitleOJson.isEmpty) { if (animeByTitleOJson.isEmpty) {
return anime; return anime;
} }
@@ -165,37 +165,37 @@ getAnimeDetail(MangaModel anime) async {
return anime; return anime;
} }
getLatestUpdatesAnime(MangaModel anime) async { getLatestUpdatesAnime(MManga anime) async {
final res = await dataBase(anime.sourceId); final res = await dataBase(anime.sourceId);
if (res.isEmpty) { if (res.hasError) {
return anime; return res;
} }
List list = json.decode(res); List list = json.decode(res.body);
List reversedList = list.reversed.toList(); List reversedList = list.reversed.toList();
List<MangaModel> animeList = animeResList(json.encode(reversedList)); List<MManga> animeList = animeResList(json.encode(reversedList));
return animeList; return animeList;
} }
searchAnime(MangaModel anime) async { searchAnime(MManga anime) async {
final res = await dataBase(anime.sourceId); final res = await dataBase(anime.sourceId);
if (res.isEmpty) { if (res.hasError) {
return anime; return res;
} }
List<MangaModel> animeList = animeSeachFetch(res, anime.query); List<MManga> animeList = animeSeachFetch(res.body, anime.query);
return animeList; return animeList;
} }
List<MangaModel> animeSeachFetch(String res, query) { List<MManga> animeSeachFetch(String res, query) {
final statusList = [ final statusList = [
{"EN COURS": 0, "TERMINÉ": 1} {"EN COURS": 0, "TERMINÉ": 1}
]; ];
List<MangaModel> animeList = []; List<MManga> animeList = [];
final jsonResList = json.decode(res); final jsonResList = json.decode(res);
for (var animeJson in jsonResList) { for (var animeJson in jsonResList) {
MangaModel anime = MangaModel(); MManga anime = MManga();
final titleO = MBridge.getMapValue(json.encode(animeJson), "titleO"); final titleO = MBridge.getMapValue(json.encode(animeJson), "titleO");
final titleAlt = final titleAlt =
@@ -250,7 +250,7 @@ List<MangaModel> animeSeachFetch(String res, query) {
bool hasVf = vfListName.contains(true); bool hasVf = vfListName.contains(true);
if (hasVostfr || hasVf) { if (hasVostfr || hasVf) {
for (int i = 0; i < seasons.length; i++) { for (int i = 0; i < seasons.length; i++) {
MangaModel anime = MangaModel(); MManga anime = MManga();
int ind = i + 1; int ind = i + 1;
anime.genre = genre; anime.genre = genre;
anime.description = description; anime.description = description;
@@ -287,7 +287,7 @@ List<MangaModel> animeSeachFetch(String res, query) {
return animeList; return animeList;
} }
getVideoList(MangaModel anime) async { getVideoList(MManga anime) async {
String language = "vo".toString(); String language = "vo".toString();
String videoBaseUrl = "https://api.franime.fr/api/anime".toString(); String videoBaseUrl = "https://api.franime.fr/api/anime".toString();
if (anime.link.contains("lang=")) { if (anime.link.contains("lang=")) {
@@ -298,10 +298,10 @@ getVideoList(MangaModel anime) async {
String stem = String stem =
MBridge.substringBefore(MBridge.substringAfterLast(anime.link, "/"), "?"); MBridge.substringBefore(MBridge.substringAfterLast(anime.link, "/"), "?");
final res = await dataBase(anime.sourceId); final res = await dataBase(anime.sourceId);
if (res.isEmpty) { if (res.hasError) {
return anime; return res;
} }
final animeByTitleOJson = databaseAnimeByTitleO(res, stem); final animeByTitleOJson = databaseAnimeByTitleO(res.body, stem);
if (animeByTitleOJson.isEmpty) { if (animeByTitleOJson.isEmpty) {
return anime; return anime;
} }
@@ -346,20 +346,24 @@ getVideoList(MangaModel anime) async {
} else if (language == "vf" && hasVf) { } else if (language == "vf" && hasVf) {
players = vfPlayers; players = vfPlayers;
} }
List<VideoModel> videos = []; List<MVideo> videos = [];
for (var i = 0; i < players.length; i++) { for (var i = 0; i < players.length; i++) {
String apiUrl = "$videoBaseUrl/$language/$i"; String apiUrl = "$videoBaseUrl/$language/$i";
String playerName = players[i]; String playerName = players[i];
VideoModel video = VideoModel(); MVideo video = MVideo();
final data = { final data = {
"url": apiUrl, "url": apiUrl,
"headers": {"Referer": "https://franime.fr/"}, "headers": {"Referer": "https://franime.fr/"},
"sourceId": anime.sourceId "sourceId": anime.sourceId
}; };
final playerUrl = await MBridge.http('GET', json.encode(data)); final requestPlayerUrl = await MBridge.http('GET', json.encode(data));
List<VideoModel> a = []; if (requestPlayerUrl.hasError) {
return requestPlayerUrl;
}
String playerUrl = requestPlayerUrl.body;
List<MVideo> a = [];
if (playerName.contains("franime_myvi")) { if (playerName.contains("franime_myvi")) {
videos.add(video videos.add(video
..url = playerUrl ..url = playerUrl

View File

@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
Source get franimeSource => _franimeSource; Source get franimeSource => _franimeSource;
const franimeVersion = "0.0.22"; const franimeVersion = "0.0.3";
const franimeSourceCodeUrl = const franimeSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/fr/franime/franime-v$franimeVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/fr/franime/franime-v$franimeVersion.dart";
Source _franimeSource = Source( Source _franimeSource = Source(

View File

@@ -1,18 +1,17 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
getPopularAnime(MangaModel anime) async { getPopularAnime(MManga anime) async {
final data = { final data = {
"url": "${anime.baseUrl}/toute-la-liste-affiches/page/${anime.page}/?q=." "url": "${anime.baseUrl}/toute-la-liste-affiches/page/${anime.page}/?q=."
}; };
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = anime.urls =
MBridge.xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href'); MBridge.xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href');
anime.names = MBridge.xpath( anime.names = MBridge.xpath(
res, '//*[@class="list"]/article/div/div/figure/a/img/@title'); res, '//*[@class="list"]/article/div/div/figure/a/img/@title');
anime.images = MBridge.xpath( anime.images = MBridge.xpath(
@@ -26,13 +25,13 @@ getPopularAnime(MangaModel anime) async {
return anime; return anime;
} }
getLatestUpdatesAnime(MangaModel anime) async { getLatestUpdatesAnime(MManga anime) async {
final data = {"url": "${anime.baseUrl}/page/${anime.page}/"}; final data = {"url": "${anime.baseUrl}/page/${anime.page}/"};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = MBridge.xpath(res, '//*[@class="episode"]/div/a/@href'); anime.urls = MBridge.xpath(res, '//*[@class="episode"]/div/a/@href');
final namess = MBridge.xpath(res, '//*[@class="episode"]/div/a/text()'); final namess = MBridge.xpath(res, '//*[@class="episode"]/div/a/text()');
List<String> names = []; List<String> names = [];
@@ -66,7 +65,7 @@ getLatestUpdatesAnime(MangaModel anime) async {
return anime; return anime;
} }
getAnimeDetail(MangaModel anime) async { getAnimeDetail(MManga anime) async {
final statusList = [ final statusList = [
{ {
"En cours": 0, "En cours": 0,
@@ -75,17 +74,22 @@ getAnimeDetail(MangaModel anime) async {
]; ];
final url = anime.link; final url = anime.link;
final data = {"url": url}; final data = {"url": url};
String res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
final originalUrl = MBridge.xpath(res, final originalUrl = MBridge.xpath(res,
'//*[@class="breadcrumb"]/li[@class="breadcrumb-item"][2]/a/@href') '//*[@class="breadcrumb"]/li[@class="breadcrumb-item"][2]/a/@href')
.first; .first;
if (originalUrl.isNotEmpty) { if (originalUrl.isNotEmpty) {
final newData = {"url": originalUrl}; final newData = {"url": originalUrl};
res = await MBridge.http('GET', json.encode(newData)); final newResponse = await MBridge.http('GET', json.encode(newData));
if (newResponse.hasError) {
return newResponse;
}
res = newResponse.body;
if (res.isEmpty) { if (res.isEmpty) {
return anime; return anime;
} }
@@ -122,15 +126,16 @@ getAnimeDetail(MangaModel anime) async {
return anime; return anime;
} }
searchAnime(MangaModel anime) async { searchAnime(MManga anime) async {
final data = { final data = {
"url": "url":
"${anime.baseUrl}/toute-la-liste-affiches/page/${anime.page}/?q=${anime.query}" "${anime.baseUrl}/toute-la-liste-affiches/page/${anime.page}/?q=${anime.query}"
}; };
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return anime; return response;
} }
String res = response.body;
anime.urls = anime.urls =
MBridge.xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href'); MBridge.xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href');
@@ -148,27 +153,29 @@ searchAnime(MangaModel anime) async {
return anime; return anime;
} }
getVideoList(MangaModel anime) async { getVideoList(MManga anime) async {
final datas = {"url": anime.link}; final datas = {"url": anime.link};
final res = await MBridge.http('GET', json.encode(datas)); final res = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (res.hasError) {
return []; return res;
} }
final servers = final servers =
MBridge.xpath(res, '//*[@id="nav-tabContent"]/div/iframe/@src'); MBridge.xpath(res.body, '//*[@id="nav-tabContent"]/div/iframe/@src');
List<VideoModel> videos = []; List<MVideo> videos = [];
for (var url in servers) { for (var url in servers) {
final datasServer = { final datasServer = {
"url": fixUrl(url), "url": fixUrl(url),
"headers": {"X-Requested-With": "XMLHttpRequest"} "headers": {"X-Requested-With": "XMLHttpRequest"}
}; };
final resServer = await MBridge.http('GET', json.encode(datasServer)); final responseResServer =
await MBridge.http('GET', json.encode(datasServer));
String resServer = responseResServer.body;
final serverUrl = final serverUrl =
fixUrl(MBridge.regExp(resServer, r"data-url='([^']+)'", '', 1, 1)); fixUrl(MBridge.regExp(resServer, r"data-url='([^']+)'", '', 1, 1));
List<VideoModel> a = []; List<MVideo> a = [];
if (serverUrl.contains("https://streamwish")) { if (serverUrl.contains("https://streamwish")) {
a = await MBridge.streamWishExtractor(serverUrl, "StreamWish"); a = await MBridge.streamWishExtractor(serverUrl, "StreamWish");
} else if (serverUrl.contains("sibnet")) { } else if (serverUrl.contains("sibnet")) {

View File

@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
Source get otakufr => _otakufr; Source get otakufr => _otakufr;
const otakufrVersion = "0.0.2"; const otakufrVersion = "0.0.3";
const otakufrCodeUrl = const otakufrCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/fr/otakufr/otakufr-v$otakufrVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/fr/otakufr/otakufr-v$otakufrVersion.dart";
Source _otakufr = Source( Source _otakufr = Source(

View File

@@ -1,17 +0,0 @@
import '../../../../model/source.dart';
import '../../../../utils/utils.dart';
Source get universanimeSource => _universanimeSource;
const universanimeVersion = "0.0.2";
const universanimeSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/fr/universanime/universanime-v$universanimeVersion.dart";
Source _universanimeSource = Source(
name: "UniversAnime",
baseUrl: "https://www.universanime.club",
lang: "fr",
typeSource: "single",
iconUrl: getIconUrl("universanime", "fr"),
sourceCodeUrl: universanimeSourceCodeUrl,
version: universanimeVersion,
isManga: false,
isFullData: true);

View File

@@ -1,125 +0,0 @@
import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart';
getVideoList(MangaModel anime) async {
final datas = {"url": anime.link};
final res = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) {
return [];
}
final serverUrls =
MBridge.xpath(res, '//*[@class="entry-content"]/div/div/iframe/@src');
List<VideoModel> videos = [];
for (var i = 0; i < serverUrls.length; i++) {
final url = serverUrls[i];
print(url);
List<VideoModel> a = [];
if (url.startsWith("https://filemoon.")) {
a = await MBridge.filemoonExtractor(url, "");
} else if (url.startsWith("https://doodstream.")) {
a = await MBridge.doodExtractor(url);
} else if (url.startsWith("https://streamtape.")) {
a = await MBridge.streamTapeExtractor(url);
} else if (url.contains("streamsb")) {}
for (var vi in a) {
videos.add(vi);
}
}
return videos;
}
Future<MangaModel> getLatestUpdatesAnime(MangaModel anime) async {
final data = {"url": "${anime.baseUrl}/page/${anime.page}/"};
final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) {
return anime;
}
anime.urls = MBridge.xpath(
res, '//*[@class="recent-posts"]/li/div[@class="post-thumb"]/a/@href');
anime.names = MBridge.xpath(
res, '//*[@class="recent-posts"]/li/div[@class="post-thumb"]/a/@title');
anime.images = [];
return anime;
}
getAnimeDetail(MangaModel anime) async {
final url = anime.link;
final data = {"url": url};
final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) {
return anime;
}
anime.description = MBridge.xpath(res,
'//*[@class="entry-content"]/p[contains(text(),"Synopsis")]/text()')
.first;
anime.status = 5;
final urls = MBridge.xpath(res,
'//*[@class="entry-content"]/ul[@class="lcp_catlist" and contains(@id,"lcp_instance_")]/li/a/@href');
final names = MBridge.xpath(res,
'//*[@class="entry-content"]/ul[@class="lcp_catlist" and contains(@id,"lcp_instance_")]/li/a/text()');
if (urls.isEmpty && names.isEmpty) {
anime.urls = [anime.link];
anime.names = ["Film"];
} else {
anime.urls = urls;
anime.names = names;
}
anime.chaptersDateUploads = [];
return anime;
}
getPopularAnime(MangaModel anime) async {
return await getLatestUpdatesAnime(anime);
}
searchAnime(MangaModel anime) async {
final data = {"url": "${anime.baseUrl}/liste-des-animes-2/"};
final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) {
return anime;
}
final dataMovies = {"url": "${anime.baseUrl}/films-mangas/"};
final resMovies = await MBridge.http('GET', json.encode(dataMovies));
List<String> urlsS = [];
List<String> namesS = [];
final urls = MBridge.xpath(res,
'//*[@class="lcp_catlist" and contains(@id,"lcp_instance_")]/li/a/@href');
final names = MBridge.xpath(res,
'//*[@class="lcp_catlist" and contains(@id,"lcp_instance_")]/li/a/text()');
final urlsMovies = MBridge.xpath(resMovies,
'//*[@class="recent-posts"]/li/div[@class="post-thumb"]/a/@href');
final namesMovies = MBridge.xpath(resMovies,
'//*[@class="recent-posts"]/li/div[@class="post-thumb"]/a/@title');
for (var i = 0; i < names.length; i++) {
final name = names[i];
if (name.toLowerCase().contains(anime.query)) {
final url = urls[i];
urlsS.add(url);
namesS.add(name);
}
}
for (var i = 0; i < namesMovies.length; i++) {
final name = namesMovies[i];
if (name.toLowerCase().contains(anime.query)) {
final url = urlsMovies[i];
urlsS.add(url);
namesS.add(name);
}
}
anime.urls = urlsS;
anime.names = namesS;
anime.images = [];
return anime;
}

File diff suppressed because one or more lines are too long

View File

@@ -1,47 +1,30 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
searchManga(MangaModel manga) async { searchManga(MManga manga) async {
final headers = getHeader(manga.baseUrl); final headers = getHeader(manga.baseUrl);
MHttpResponse response = MHttpResponse();
String res = "".toString();
if (!useNewQueryEndpoint(manga.source)) { if (!useNewQueryEndpoint(manga.source)) {
final url = "${manga.apiUrl}/series/search"; final url = "${manga.apiUrl}/series/search";
final body = {"term": manga.query}; final body = {"term": manga.query};
final data = {"url": url, "headers": headers, "body": body}; final data = {"url": url, "headers": headers, "body": body};
res = await MBridge.http('POST', json.encode(data)); response = await MBridge.http('POST', json.encode(data));
if (res.isEmpty) {
return manga;
}
} else { } else {
final newEndpointUrl = "${manga.apiUrl}/query"; final newEndpointUrl =
final newEndpointBody = { "${manga.apiUrl}/query/?page=${manga.page}&query_string=${manga.query}&series_status=All&order=desc&orderBy=total_views&perPage=12&tags_ids=[]&series_type=Comic";
"query_string": manga.query,
"series_status": "All",
"page": manga.page,
"order": "desc",
"order_by": "total_views",
"perPage": "12",
"tags_ids": "[]",
"series_type": "Comic"
};
final newEndpointData = {
"url": newEndpointUrl,
"headers": headers,
"newEndpointBody": newEndpointBody
};
res = await MBridge.http('GET', json.encode(newEndpointData));
if (res.isEmpty) {
return manga;
}
}
return mangaModelRes(res, manga); final newEndpointData = {"url": newEndpointUrl, "headers": headers};
response = await MBridge.http('GET', json.encode(newEndpointData));
}
if (response.hasError) {
return response;
}
return mMangaRes(response, manga);
} }
getPopularManga(MangaModel manga) async { getPopularManga(MManga manga) async {
final headers = getHeader(manga.baseUrl); final headers = getHeader(manga.baseUrl);
String res = "".toString(); MHttpResponse response = MHttpResponse();
if (!useNewQueryEndpoint(manga.source)) { if (!useNewQueryEndpoint(manga.source)) {
final url = "${manga.apiUrl}/series/querysearch"; final url = "${manga.apiUrl}/series/querysearch";
print(url); print(url);
@@ -59,38 +42,24 @@ getPopularManga(MangaModel manga) async {
"sourceId": manga.sourceId, "sourceId": manga.sourceId,
"body": body "body": body
}; };
response = await MBridge.http('POST', json.encode(data));
res = await MBridge.http('POST', json.encode(data));
} else { } else {
final newEndpointUrl = "${manga.apiUrl}/query"; final newEndpointUrl =
final newEndpointBody = { "${manga.apiUrl}/query/?page=${manga.page}&query_string=&series_status=All&order=desc&orderBy=total_views&perPage=12&tags_ids=[]&series_type=Comic";
"query_string": "",
"series_status": "All",
"page": manga.page,
"order": "desc",
"order_by": "total_views",
"perPage": "12",
"tags_ids": "[]",
"series_type": "Comic"
};
final newEndpointData = { final newEndpointData = {
"url": newEndpointUrl, "url": newEndpointUrl,
"headers": headers, "headers": headers,
"sourceId": manga.sourceId, "sourceId": manga.sourceId
"body": newEndpointBody
}; };
print("sssssssssssssssssssss"); response = await MBridge.http('GET', json.encode(newEndpointData));
res = await MBridge.http('GET', json.encode(newEndpointData));
} }
if (res.isEmpty) { return mMangaRes(response, manga);
return manga;
}
return mangaModelRes(res, manga);
} }
getLatestUpdatesManga(MangaModel manga) async { getLatestUpdatesManga(MManga manga) async {
final headers = getHeader(manga.baseUrl); final headers = getHeader(manga.baseUrl);
String res = "".toString(); MHttpResponse response = MHttpResponse();
if (!useNewQueryEndpoint(manga.source)) { if (!useNewQueryEndpoint(manga.source)) {
final url = "${manga.apiUrl}/series/querysearch"; final url = "${manga.apiUrl}/series/querysearch";
final body = { final body = {
@@ -106,45 +75,28 @@ getLatestUpdatesManga(MangaModel manga) async {
"sourceId": manga.sourceId, "sourceId": manga.sourceId,
"body": body "body": body
}; };
res = await MBridge.http('POST', json.encode(data)); response = await MBridge.http('POST', json.encode(data));
} else { } else {
final newEndpointUrl = "${manga.apiUrl}/query"; final newEndpointUrl =
final newEndpointBody = { "${manga.apiUrl}/query/?page=${manga.page}&query_string=&series_status=All&order=desc&orderBy=latest&perPage=12&tags_ids=[]&series_type=Comic";
"query_string": "",
"series_status": "All", final newEndpointData = {"url": newEndpointUrl, "headers": headers};
"page": manga.page, response = await MBridge.http('GET', json.encode(newEndpointData));
"order": "desc",
"order_by": "latest",
"perPage": "12",
"tags_ids": "[]",
"series_type": "Comic"
};
final newEndpointData = {
"url": newEndpointUrl,
"headers": headers,
"sourceId": manga.sourceId,
"body": newEndpointBody
};
res = await MBridge.http('GET', json.encode(newEndpointData));
print(res);
} }
if (res.isEmpty) { return mMangaRes(response, manga);
return manga;
}
return mangaModelRes(res, manga);
} }
getMangaDetail(MangaModel manga) async { getMangaDetail(MManga manga) async {
String currentSlug = MBridge.substringAfterLast(manga.link, "/"); String currentSlug = MBridge.substringAfterLast(manga.link, "/");
final headers = getHeader(manga.baseUrl); final headers = getHeader(manga.baseUrl);
final url = "${manga.apiUrl}/series/$currentSlug"; final url = "${manga.apiUrl}/series/$currentSlug";
final data = {"url": url, "headers": headers}; final data = {"url": url, "headers": headers};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
print(res); String res = response.body;
manga.author = MBridge.getMapValue(res, "author"); manga.author = MBridge.getMapValue(res, "author");
manga.description = MBridge.getMapValue(res, "description"); manga.description = MBridge.getMapValue(res, "description");
@@ -193,19 +145,25 @@ getMangaDetail(MangaModel manga) async {
return manga; return manga;
} }
getChapterUrl(MangaModel manga) async { getChapterPages(MManga manga) async {
String res = "".toString(); MHttpResponse response = MHttpResponse();
final headers = getHeader(manga.baseUrl); final headers = getHeader(manga.baseUrl);
String res = "".toString();
if (!useslugStrategy(manga.source)) { if (!useslugStrategy(manga.source)) {
String chapterId = MBridge.substringAfter(manga.link, '#'); String chapterId = MBridge.substringAfter(manga.link, '#');
final url = "${manga.apiUrl}/series/chapter/$chapterId"; final url = "${manga.apiUrl}/series/chapter/$chapterId";
final data = {"url": url, "headers": headers}; final data = {"url": url, "headers": headers};
res = await MBridge.http('GET', json.encode(data)); response = await MBridge.http('GET', json.encode(data));
res = response.body;
} else { } else {
final url = "${manga.baseUrl}${manga.link}"; final url = "${manga.baseUrl}${manga.link}";
final data = {"url": url, "headers": headers}; final data = {"url": url, "headers": headers};
res = await MBridge.http('GET', json.encode(data)); response = await MBridge.http('GET', json.encode(data));
if (response.hasError) {
return response;
}
res = response.body;
List<String> pageUrls = []; List<String> pageUrls = [];
var imagesRes = MBridge.querySelectorAll(res, var imagesRes = MBridge.querySelectorAll(res,
selector: "div.min-h-screen > div.container > p.items-center", selector: "div.min-h-screen > div.container > p.items-center",
@@ -218,9 +176,8 @@ getChapterUrl(MangaModel manga) async {
return pageUrls.where((e) => e.isNotEmpty).toList(); return pageUrls.where((e) => e.isNotEmpty).toList();
} }
if (response.hasError) {
if (res.isEmpty) { return response;
return [];
} }
final pages = MBridge.jsonPathToList(res, r"$.content.images[*]", 0); final pages = MBridge.jsonPathToList(res, r"$.content.images[*]", 0);
List<String> pageUrls = []; List<String> pageUrls = [];
@@ -255,11 +212,11 @@ bool useslugStrategy(String sourceName) {
return sources.contains(sourceName); return sources.contains(sourceName);
} }
MangaModel mangaModelRes(String res, MangaModel manga) { MManga mMangaRes(MHttpResponse response, MManga manga) {
String res = response.body;
List<String> names = []; List<String> names = [];
List<String> urls = []; List<String> urls = [];
List<String> images = []; List<String> images = [];
if (res.startsWith("{")) { if (res.startsWith("{")) {
for (var a in json.decode(res)["data"]) { for (var a in json.decode(res)["data"]) {
String thumbnail = a["thumbnail"]; String thumbnail = a["thumbnail"];
@@ -269,7 +226,7 @@ MangaModel mangaModelRes(String res, MangaModel manga) {
images.add("${manga.apiUrl}/cover/$thumbnail"); images.add("${manga.apiUrl}/cover/$thumbnail");
} }
names.add(a["title"]); names.add(a["title"]);
final seriesSlug = MBridge.regExp(a["series_slug"], "-\\d+", "", 0, 0); final seriesSlug = a["series_slug"];
urls.add("/series/$seriesSlug"); urls.add("/series/$seriesSlug");
} }
} else { } else {
@@ -281,9 +238,10 @@ MangaModel mangaModelRes(String res, MangaModel manga) {
images.add("${manga.apiUrl}/cover/$thumbnail"); images.add("${manga.apiUrl}/cover/$thumbnail");
} }
names.add(a["title"]); names.add(a["title"]);
final seriesSlug = MBridge.regExp(a["series_slug"], "-\\d+", "", 0, 0); final seriesSlug = a["series_slug"];
urls.add("/series/$seriesSlug"); urls.add("/series/$seriesSlug");
} }
manga.hasNextPage = false;
} }
manga.urls = urls; manga.urls = urls;

View File

@@ -1,7 +1,7 @@
import '../../../model/source.dart'; import '../../../model/source.dart';
import '../../../utils/utils.dart'; import '../../../utils/utils.dart';
const heancmsVersion = "0.0.21"; const heancmsVersion = "0.0.3";
const heancmsSourceCodeUrl = const heancmsSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/heancms/heancms-v$heancmsVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/heancms/heancms-v$heancmsVersion.dart";
const defaultDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; const defaultDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ";

View File

@@ -1,13 +1,14 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
getPopularManga(MangaModel manga) async { getPopularManga(MManga manga) async {
final url = "${manga.baseUrl}/manga/page/${manga.page}/?m_orderby=views"; final url = "${manga.baseUrl}/manga/page/${manga.page}/?m_orderby=views";
final data = {"url": url, "sourceId": manga.sourceId}; final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.urls = MBridge.xpath(res, '//*[@class^="post-title"]/h3/a/@href'); manga.urls = MBridge.xpath(res, '//*[@class^="post-title"]/h3/a/@href');
var images = MBridge.xpath(res, '//*[@id^="manga-item"]/a/img/@data-src'); var images = MBridge.xpath(res, '//*[@id^="manga-item"]/a/img/@data-src');
if (images.isEmpty) { if (images.isEmpty) {
@@ -25,7 +26,7 @@ getPopularManga(MangaModel manga) async {
return manga; return manga;
} }
getMangaDetail(MangaModel manga) async { getMangaDetail(MManga manga) async {
final statusList = [ final statusList = [
{ {
"OnGoing": 0, "OnGoing": 0,
@@ -70,12 +71,13 @@ getMangaDetail(MangaModel manga) async {
"Cancelado": 3, "Cancelado": 3,
} }
]; ];
MHttpResponse response = MHttpResponse();
final datas = {"url": manga.link, "sourceId": manga.sourceId}; final datas = {"url": manga.link, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(datas)); response = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.author = MBridge.querySelectorAll(res, manga.author = MBridge.querySelectorAll(res,
selector: "div.author-content > a", selector: "div.author-content > a",
typeElement: 0, typeElement: 0,
@@ -126,21 +128,23 @@ getMangaDetail(MangaModel manga) async {
"${baseUrl}wp-admin/admin-ajax.php?action=manga_get_chapters&manga=$mangaId"; "${baseUrl}wp-admin/admin-ajax.php?action=manga_get_chapters&manga=$mangaId";
final datasP = {"url": url, "headers": headers, "sourceId": manga.sourceId}; final datasP = {"url": url, "headers": headers, "sourceId": manga.sourceId};
String resP = await MBridge.http('POST', json.encode(datasP)); response = await MBridge.http('POST', json.encode(datasP));
if (resP == "400") { if (response.statusCode != 200) {
final urlP = "${manga.link}ajax/chapters"; final urlP = "${manga.link}ajax/chapters";
final datasP = { final datasP = {
"url": urlP, "url": urlP,
"headers": headers, "headers": headers,
"sourceId": manga.sourceId "sourceId": manga.sourceId
}; };
resP = await MBridge.http('POST', json.encode(datasP)); response = await MBridge.http('POST', json.encode(datasP));
} }
String resP = response.body;
manga.urls = MBridge.xpath(resP, "//li/a/@href"); manga.urls = MBridge.xpath(resP, "//li/a/@href");
var chaptersNames = MBridge.xpath(resP, "//li/a/text()"); var chaptersNames = MBridge.xpath(resP, "//li/a/text()");
var dateF = MBridge.xpath(resP, "//li/span/i/text()"); var dateF = MBridge.xpath(resP, "//li/span/i/text()");
if (MBridge.xpath(resP, "//li/a/text()", "").isEmpty) { if (dateF.isEmpty) {
final resWebview = await MBridge.getHtmlViaWebview(manga.link, final resWebview = await MBridge.getHtmlViaWebview(manga.link,
"//*[@id='manga-chapters-holder']/div[2]/div/ul/li/a/@href"); "//*[@id='manga-chapters-holder']/div[2]/div/ul/li/a/@href");
manga.urls = MBridge.xpath(resWebview, manga.urls = MBridge.xpath(resWebview,
@@ -174,12 +178,13 @@ getMangaDetail(MangaModel manga) async {
return manga; return manga;
} }
getChapterUrl(MangaModel manga) async { getChapterPages(MManga manga) async {
final datas = {"url": manga.link, "sourceId": manga.sourceId}; final datas = {"url": manga.link, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (response.hasError) {
return []; return response;
} }
String res = response.body;
final pagesSelectorRes = MBridge.querySelectorAll(res, final pagesSelectorRes = MBridge.querySelectorAll(res,
selector: selector:
"div.page-break, li.blocks-gallery-item, .reading-content, .text-left img", "div.page-break, li.blocks-gallery-item, .reading-content, .text-left img",
@@ -222,13 +227,14 @@ getChapterUrl(MangaModel manga) async {
return pageUrls; return pageUrls;
} }
getLatestUpdatesManga(MangaModel manga) async { getLatestUpdatesManga(MManga manga) async {
final url = "${manga.baseUrl}/manga/page/${manga.page}/?m_orderby=latest"; final url = "${manga.baseUrl}/manga/page/${manga.page}/?m_orderby=latest";
final datas = {"url": url, "sourceId": manga.sourceId}; final datas = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.urls = MBridge.xpath(res, '//*[@class^="post-title"]/h3/a/@href'); manga.urls = MBridge.xpath(res, '//*[@class^="post-title"]/h3/a/@href');
var images = MBridge.xpath(res, '//*[@id^="manga-item"]/a/img/@data-src'); var images = MBridge.xpath(res, '//*[@id^="manga-item"]/a/img/@data-src');
if (images.isEmpty) { if (images.isEmpty) {
@@ -245,13 +251,14 @@ getLatestUpdatesManga(MangaModel manga) async {
return manga; return manga;
} }
searchManga(MangaModel manga) async { searchManga(MManga manga) async {
final urll = "${manga.baseUrl}/?s=${manga.query}&post_type=wp-manga"; final urll = "${manga.baseUrl}/?s=${manga.query}&post_type=wp-manga";
final datas = {"url": urll, "sourceId": manga.sourceId}; final datas = {"url": urll, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.urls = manga.urls =
MBridge.xpath(res, '//*[@class^="tab-thumb c-image-hover"]/a/@href'); MBridge.xpath(res, '//*[@class^="tab-thumb c-image-hover"]/a/@href');
var images = MBridge.xpath( var images = MBridge.xpath(

View File

@@ -1,7 +1,7 @@
import '../../../model/source.dart'; import '../../../model/source.dart';
import '../../../utils/utils.dart'; import '../../../utils/utils.dart';
const madaraVersion = "0.0.2"; const madaraVersion = "0.0.3";
const madaraSourceCodeUrl = const madaraSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/madara/madara-v$madaraVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/madara/madara-v$madaraVersion.dart";
const defaultDateFormat = "MMMM dd, yyyy"; const defaultDateFormat = "MMMM dd, yyyy";

View File

@@ -1,33 +1,43 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
getPopularManga(MangaModel manga) async { getPopularManga(MManga manga) async {
final url = "${manga.baseUrl}${getMangaUrlDirectory(manga.source)}/?page=${manga.page}&order=popular"; final url =
"${manga.baseUrl}${getMangaUrlDirectory(manga.source)}/?page=${manga.page}&order=popular";
final data = {"url": url, "sourceId": manga.sourceId}; final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
manga.urls = MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@href'); String res = response.body;
manga.names = MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@title'); manga.urls =
manga.images = MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/div[1]/img/@src'); MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@href');
manga.names =
MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@title');
manga.images = MBridge.xpath(
res, '//*[ @class="imgu" or @class="bsx"]/a/div[1]/img/@src');
return manga; return manga;
} }
getLatestUpdatesManga(MangaModel manga) async { getLatestUpdatesManga(MManga manga) async {
final url = "${manga.baseUrl}${getMangaUrlDirectory(manga.source)}/?page=${manga.page}&order=update"; final url =
"${manga.baseUrl}${getMangaUrlDirectory(manga.source)}/?page=${manga.page}&order=update";
final data = {"url": url, "sourceId": manga.sourceId}; final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
manga.urls = MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@href'); String res = response.body;
manga.names = MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@title'); manga.urls =
manga.images = MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/div[1]/img/@src'); MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@href');
manga.names =
MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@title');
manga.images = MBridge.xpath(
res, '//*[ @class="imgu" or @class="bsx"]/a/div[1]/img/@src');
return manga; return manga;
} }
getMangaDetail(MangaModel manga) async { getMangaDetail(MManga manga) async {
final statusList = [ final statusList = [
{ {
"مستمرة": 0, "مستمرة": 0,
@@ -81,11 +91,11 @@ getMangaDetail(MangaModel manga) async {
]; ];
final datas = {"url": manga.link, "sourceId": manga.sourceId}; final datas = {"url": manga.link, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
if (response.hasError) {
if (res.isEmpty) { return response;
return manga;
} }
String res = response.body;
manga.author = MBridge.xpath( manga.author = MBridge.xpath(
res, res,
'//*[@class="imptdt" and contains(text(), "Author") or @class="infotable" and contains(text(), "Author") or @class="infotable" and contains(text(), "Auteur") or @class="fmed" and contains(text(), "Auteur") or @class="infotable" and contains(text(), "Autor")]/text()', '//*[@class="imptdt" and contains(text(), "Author") or @class="infotable" and contains(text(), "Author") or @class="infotable" and contains(text(), "Auteur") or @class="fmed" and contains(text(), "Auteur") or @class="infotable" and contains(text(), "Autor")]/text()',
@@ -97,7 +107,10 @@ getMangaDetail(MangaModel manga) async {
.replaceAll("[Add, ]", ""); .replaceAll("[Add, ]", "");
manga.description = MBridge.querySelectorAll(res, manga.description = MBridge.querySelectorAll(res,
selector: ".desc, .entry-content[itemprop=description]", typeElement: 0, attributes: "", typeRegExp: 0) selector: ".desc, .entry-content[itemprop=description]",
typeElement: 0,
attributes: "",
typeRegExp: 0)
.first; .first;
final status = MBridge.xpath( final status = MBridge.xpath(
@@ -111,7 +124,8 @@ getMangaDetail(MangaModel manga) async {
manga.status = MBridge.parseStatus(status, statusList); manga.status = MBridge.parseStatus(status, statusList);
manga.genre = MBridge.xpath(res, '//*[@class="gnr" or @class="mgen" or @class="seriestugenre" ]/a/text()'); manga.genre = MBridge.xpath(res,
'//*[@class="gnr" or @class="mgen" or @class="seriestugenre" ]/a/text()');
manga.urls = MBridge.xpath(res, manga.urls = MBridge.xpath(res,
'//*[@class="bxcl" or @class="cl" or @class="chbox" or @class="eph-num" or @id="chapterlist"]/div/a[not(@href="#/chapter-{{number}}")]/@href'); '//*[@class="bxcl" or @class="cl" or @class="chbox" or @class="eph-num" or @id="chapterlist"]/div/a[not(@href="#/chapter-{{number}}")]/@href');
manga.names = MBridge.xpath(res, manga.names = MBridge.xpath(res,
@@ -120,32 +134,37 @@ getMangaDetail(MangaModel manga) async {
final chaptersDateUploads = MBridge.xpath(res, final chaptersDateUploads = MBridge.xpath(res,
'//*[@class="bxcl" or @class="cl" or @class="chbox" or @class="eph-num" or @id="chapterlist"]/div/a/span[@class="chapterdate" and not(text()="{{date}}")]/text()'); '//*[@class="bxcl" or @class="cl" or @class="chbox" or @class="eph-num" or @id="chapterlist"]/div/a/span[@class="chapterdate" and not(text()="{{date}}")]/text()');
manga.chaptersDateUploads = MBridge.listParseDateTime(chaptersDateUploads, manga.dateFormat, manga.dateFormatLocale); manga.chaptersDateUploads = MBridge.listParseDateTime(
chaptersDateUploads, manga.dateFormat, manga.dateFormatLocale);
return manga; return manga;
} }
searchManga(MangaModel manga) async { searchManga(MManga manga) async {
final url = "${manga.baseUrl}${getMangaUrlDirectory(manga.source)}/?&title=${manga.query}&page=${manga.page}"; final url =
"${manga.baseUrl}${getMangaUrlDirectory(manga.source)}/?&title=${manga.query}&page=${manga.page}";
final data = {"url": url, "sourceId": manga.sourceId}; final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
manga.urls = MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@href'); String res = response.body;
manga.names = MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@title'); manga.urls =
manga.images = MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/div[1]/img/@src'); MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@href');
manga.names =
MBridge.xpath(res, '//*[ @class="imgu" or @class="bsx"]/a/@title');
manga.images = MBridge.xpath(
res, '//*[ @class="imgu" or @class="bsx"]/a/div[1]/img/@src');
return manga; return manga;
} }
getChapterUrl(MangaModel manga) async { getChapterPages(MManga manga) async {
final datas = {"url": manga.link, "sourceId": manga.sourceId}; final datas = {"url": manga.link, "sourceId": manga.sourceId};
final response = await MBridge.http('GET', json.encode(datas));
final res = await MBridge.http('GET', json.encode(datas)); if (response.hasError) {
return response;
if (res.isEmpty) {
return [];
} }
String res = response.body;
var pages = []; var pages = [];
List<String> pagesUrl = []; List<String> pagesUrl = [];
pages = MBridge.xpath(res, '//*[@id="readerarea"]/p/img/@src'); pages = MBridge.xpath(res, '//*[@id="readerarea"]/p/img/@src');
@@ -153,7 +172,8 @@ getChapterUrl(MangaModel manga) async {
pages = MBridge.xpath(res, '//*[@id="readerarea"]/img/@src'); pages = MBridge.xpath(res, '//*[@id="readerarea"]/img/@src');
} }
if (pages.isEmpty || pages.length == 1) { if (pages.isEmpty || pages.length == 1) {
final images = MBridge.regExp(res, "\"images\"\\s*:\\s*(\\[.*?])", "", 1, 1); final images =
MBridge.regExp(res, "\"images\"\\s*:\\s*(\\[.*?])", "", 1, 1);
final pages = MBridge.jsonDecodeToList(images, 0); final pages = MBridge.jsonDecodeToList(images, 0);
for (var page in pages) { for (var page in pages) {
pagesUrl.add(page); pagesUrl.add(page);

View File

@@ -1,7 +1,7 @@
import '../../../model/source.dart'; import '../../../model/source.dart';
import '../../../utils/utils.dart'; import '../../../utils/utils.dart';
const mangareaderVersion = "0.0.3"; const mangareaderVersion = "0.0.4";
const mangareaderSourceCodeUrl = const mangareaderSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/mangareader/mangareader-v$mangareaderVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/mangareader/mangareader-v$mangareaderVersion.dart";
const defaultDateFormat = "MMMM dd, yyyy"; const defaultDateFormat = "MMMM dd, yyyy";

View File

@@ -1,13 +1,14 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
searchManga(MangaModel manga) async { searchManga(MManga manga) async {
final url = "${manga.baseUrl}/search?query=${manga.query}"; final url = "${manga.baseUrl}/search?query=${manga.query}";
final data = {"url": url, "sourceId": manga.sourceId}; final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
final jsonList = json.decode(res)["suggestions"]; final jsonList = json.decode(res)["suggestions"];
List<String> urls = []; List<String> urls = [];
List<String> names = []; List<String> names = [];
@@ -26,7 +27,8 @@ searchManga(MangaModel manga) async {
if (manga.source == "Manga-FR") { if (manga.source == "Manga-FR") {
images.add("${manga.baseUrl}/uploads/manga/$data.jpg"); images.add("${manga.baseUrl}/uploads/manga/$data.jpg");
} else { } else {
images.add("${manga.baseUrl}/uploads/manga/$data/cover/cover_250x350.jpg"); images
.add("${manga.baseUrl}/uploads/manga/$data/cover/cover_250x350.jpg");
} }
} }
manga.names = names; manga.names = names;
@@ -35,13 +37,15 @@ searchManga(MangaModel manga) async {
return manga; return manga;
} }
getPopularManga(MangaModel manga) async { getPopularManga(MManga manga) async {
final url = "${manga.baseUrl}/filterList?page=${manga.page}&sortBy=views&asc=false"; final url =
"${manga.baseUrl}/filterList?page=${manga.page}&sortBy=views&asc=false";
final data = {"url": url, "sourceId": manga.sourceId}; final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.urls = MBridge.xpath(res, '//*[ @class="chart-title"]/@href'); manga.urls = MBridge.xpath(res, '//*[ @class="chart-title"]/@href');
manga.names = MBridge.xpath(res, '//*[ @class="chart-title"]/text()'); manga.names = MBridge.xpath(res, '//*[ @class="chart-title"]/text()');
List<String> images = []; List<String> images = [];
@@ -50,14 +54,15 @@ getPopularManga(MangaModel manga) async {
if (manga.source == "Manga-FR") { if (manga.source == "Manga-FR") {
images.add("${manga.baseUrl}/uploads/manga/${slug}.jpg"); images.add("${manga.baseUrl}/uploads/manga/${slug}.jpg");
} else { } else {
images.add("${manga.baseUrl}/uploads/manga/${slug}/cover/cover_250x350.jpg"); images.add(
"${manga.baseUrl}/uploads/manga/${slug}/cover/cover_250x350.jpg");
} }
} }
manga.images = images; manga.images = images;
return manga; return manga;
} }
getMangaDetail(MangaModel manga) async { getMangaDetail(MManga manga) async {
final statusList = [ final statusList = [
{ {
"complete": 1, "complete": 1,
@@ -77,10 +82,11 @@ getMangaDetail(MangaModel manga) async {
]; ];
final datas = {"url": manga.link, "sourceId": manga.sourceId}; final datas = {"url": manga.link, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.author = MBridge.xpath(res, manga.author = MBridge.xpath(res,
'//*[@class="dl-horizontal"]/dt[contains(text(), "Auteur(s)") or contains(text(), "Author(s)") or contains(text(), "Autor(es)") or contains(text(), "Yazar(lar) or contains(text(), "Mangaka(lar)")]//following-sibling::dd[1]/text()') '//*[@class="dl-horizontal"]/dt[contains(text(), "Auteur(s)") or contains(text(), "Author(s)") or contains(text(), "Autor(es)") or contains(text(), "Yazar(lar) or contains(text(), "Mangaka(lar)")]//following-sibling::dd[1]/text()')
.first; .first;
@@ -88,24 +94,29 @@ getMangaDetail(MangaModel manga) async {
'//*[@class="dl-horizontal"]/dt[contains(text(), "Statut") or contains(text(), "Status") or contains(text(), "Estado") or contains(text(), "Durum")]/following-sibling::dd[1]/text()') '//*[@class="dl-horizontal"]/dt[contains(text(), "Statut") or contains(text(), "Status") or contains(text(), "Estado") or contains(text(), "Durum")]/following-sibling::dd[1]/text()')
.first; .first;
manga.status = MBridge.parseStatus(status, statusList); manga.status = MBridge.parseStatus(status, statusList);
manga.description = MBridge.xpath(res, '//*[@class="well" or @class="manga well"]/p/text()').first; manga.description =
MBridge.xpath(res, '//*[@class="well" or @class="manga well"]/p/text()')
.first;
manga.genre = MBridge.xpath(res, manga.genre = MBridge.xpath(res,
'//*[@class="dl-horizontal"]/dt[contains(text(), "Categories") or contains(text(), "Categorias") or contains(text(), "Categorías") or contains(text(), "Catégories") or contains(text(), "Kategoriler" or contains(text(), "Kategorie") or contains(text(), "Kategori") or contains(text(), "Tagi"))]/following-sibling::dd[1]/text()'); '//*[@class="dl-horizontal"]/dt[contains(text(), "Categories") or contains(text(), "Categorias") or contains(text(), "Categorías") or contains(text(), "Catégories") or contains(text(), "Kategoriler" or contains(text(), "Kategorie") or contains(text(), "Kategori") or contains(text(), "Tagi"))]/following-sibling::dd[1]/text()');
manga.names = MBridge.xpath(res, '//*[@class="chapter-title-rtl"]/a/text()'); manga.names = MBridge.xpath(res, '//*[@class="chapter-title-rtl"]/a/text()');
manga.urls = MBridge.xpath(res, '//*[@class="chapter-title-rtl"]/a/@href'); manga.urls = MBridge.xpath(res, '//*[@class="chapter-title-rtl"]/a/@href');
final date = MBridge.xpath(res, '//*[@class="date-chapter-title-rtl"]/text()'); final date =
manga.chaptersDateUploads = MBridge.listParseDateTime(date, "d MMM. yyyy", "en_US"); MBridge.xpath(res, '//*[@class="date-chapter-title-rtl"]/text()');
manga.chaptersDateUploads =
MBridge.listParseDateTime(date, "d MMM. yyyy", "en_US");
return manga; return manga;
} }
getLatestUpdatesManga(MangaModel manga) async { getLatestUpdatesManga(MManga manga) async {
final url = "${manga.baseUrl}/latest-release?page=${manga.page}"; final url = "${manga.baseUrl}/latest-release?page=${manga.page}";
final data = {"url": url, "sourceId": manga.sourceId}; final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.urls = MBridge.xpath(res, '//*[@class="manga-item"]/h3/a/@href'); manga.urls = MBridge.xpath(res, '//*[@class="manga-item"]/h3/a/@href');
manga.names = MBridge.xpath(res, '//*[@class="manga-item"]/h3/a/text()'); manga.names = MBridge.xpath(res, '//*[@class="manga-item"]/h3/a/text()');
List<String> images = []; List<String> images = [];
@@ -114,21 +125,24 @@ getLatestUpdatesManga(MangaModel manga) async {
if (manga.source == "Manga-FR") { if (manga.source == "Manga-FR") {
images.add("${manga.baseUrl}/uploads/manga/${slug}.jpg"); images.add("${manga.baseUrl}/uploads/manga/${slug}.jpg");
} else { } else {
images.add("${manga.baseUrl}/uploads/manga/${slug}/cover/cover_250x350.jpg"); images.add(
"${manga.baseUrl}/uploads/manga/${slug}/cover/cover_250x350.jpg");
} }
} }
manga.images = images; manga.images = images;
return manga; return manga;
} }
getChapterUrl(MangaModel manga) async { getChapterPages(MManga manga) async {
final datas = {"url": manga.link, "sourceId": manga.sourceId}; final datas = {"url": manga.link, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) { if (response.hasError) {
return []; return response;
} }
String res = response.body;
List<String> pagesUrl = []; List<String> pagesUrl = [];
final pages = MBridge.xpath(res, '//*[@id="all"]/img[@class="img-responsive"]/@data-src'); final pages = MBridge.xpath(
res, '//*[@id="all"]/img[@class="img-responsive"]/@data-src');
for (var page in pages) { for (var page in pages) {
if (page.startsWith('//')) { if (page.startsWith('//')) {
pagesUrl.add(page.replaceAll('//', 'https://')); pagesUrl.add(page.replaceAll('//', 'https://'));

View File

@@ -1,7 +1,7 @@
import '../../../model/source.dart'; import '../../../model/source.dart';
import '../../../utils/utils.dart'; import '../../../utils/utils.dart';
const mmrcmsVersion = "0.0.2"; const mmrcmsVersion = "0.0.3";
const mmrcmsSourceCodeUrl = const mmrcmsSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/mmrcms/mmrcms-v$mmrcmsVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/mmrcms/mmrcms-v$mmrcmsVersion.dart";
const defaultDateFormat = "d MMM. yyyy"; const defaultDateFormat = "d MMM. yyyy";

View File

@@ -1,36 +1,39 @@
import 'dart:convert'; import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
getPopularManga(MangaModel manga) async { getPopularManga(MManga manga) async {
final data = {"url": "${manga.baseUrl}/search/"}; final data = {"url": "${manga.baseUrl}/search/"};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
final directory = directoryFromDocument(res); final directory = directoryFromDocument(res);
final resSort = MBridge.sortMapList(json.decode(directory), "vm", 1); final resSort = MBridge.sortMapList(json.decode(directory), "vm", 1);
return parseDirectory(resSort, manga); return parseDirectory(resSort, manga);
} }
getLatestUpdatesManga(MangaModel manga) async { getLatestUpdatesManga(MManga manga) async {
final data = {"url": "${manga.baseUrl}/search/"}; final data = {"url": "${manga.baseUrl}/search/"};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
final directory = directoryFromDocument(res); final directory = directoryFromDocument(res);
final resSort = MBridge.sortMapList(json.decode(directory), "lt", 1); final resSort = MBridge.sortMapList(json.decode(directory), "lt", 1);
return parseDirectory(resSort, manga); return parseDirectory(resSort, manga);
} }
searchManga(MangaModel manga) async { searchManga(MManga manga) async {
final data = {"url": "${manga.baseUrl}/search/"}; final data = {"url": "${manga.baseUrl}/search/"};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
final directory = directoryFromDocument(res); final directory = directoryFromDocument(res);
final resSort = MBridge.sortMapList(json.decode(directory), "lt", 1); final resSort = MBridge.sortMapList(json.decode(directory), "lt", 1);
final datas = json.decode(resSort) as List; final datas = json.decode(resSort) as List;
@@ -45,17 +48,18 @@ searchManga(MangaModel manga) async {
return parseDirectory(json.encode(queryRes), manga); return parseDirectory(json.encode(queryRes), manga);
} }
getMangaDetail(MangaModel manga) async { getMangaDetail(MManga manga) async {
final statusList = [ final statusList = [
{"Ongoing": 0, "Completed": 1, "Cancelled": 3, "Hiatus": 2} {"Ongoing": 0, "Completed": 1, "Cancelled": 3, "Hiatus": 2}
]; ];
final headers = getHeader(manga.baseUrl); final headers = getHeader(manga.baseUrl);
final url = '${manga.baseUrl}/manga/${manga.link}'; final url = '${manga.baseUrl}/manga/${manga.link}';
final data = {"url": url, "headers": headers}; final data = {"url": url, "headers": headers};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.author = MBridge.xpath(res, manga.author = MBridge.xpath(res,
'//li[contains(@class,"list-group-item") and contains(text(),"Author")]/a/text()') '//li[contains(@class,"list-group-item") and contains(text(),"Author")]/a/text()')
.first; .first;
@@ -94,12 +98,17 @@ getMangaDetail(MangaModel manga) async {
return manga; return manga;
} }
getChapterUrl(MangaModel manga) async { getChapterPages(MManga manga) async {
final headers = getHeader(manga.baseUrl); final headers = getHeader(manga.baseUrl);
final url = '${manga.baseUrl}${manga.link}'; final url = '${manga.baseUrl}${manga.link}';
List<String> pages = []; List<String> pages = [];
final data = {"url": url, "headers": headers}; final data = {"url": url, "headers": headers};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
final script = final script =
MBridge.xpath(res, '//script[contains(text(), "MainFunction")]/text()') MBridge.xpath(res, '//script[contains(text(), "MainFunction")]/text()')
.first; .first;
@@ -164,7 +173,7 @@ String directoryFromDocument(String res) {
.replaceAll(";", " "); .replaceAll(";", " ");
} }
MangaModel parseDirectory(String resSort, MangaModel manga) { MManga parseDirectory(String resSort, MManga manga) {
final datas = json.decode(resSort) as List; final datas = json.decode(resSort) as List;
manga.names = datas.map((e) => e["s"]).toList(); manga.names = datas.map((e) => e["s"]).toList();
manga.images = datas manga.images = datas

View File

@@ -1,7 +1,7 @@
import '../../../model/source.dart'; import '../../../model/source.dart';
import '../../../utils/utils.dart'; import '../../../utils/utils.dart';
const nepnepVersion = "0.0.1"; const nepnepVersion = "0.0.2";
const nepnepSourceCodeUrl = const nepnepSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/nepnep/nepnep-v$nepnepVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/nepnep/nepnep-v$nepnepVersion.dart";
const defaultDateFormat = "yyyy-MM-dd HH:mm:ss"; const defaultDateFormat = "yyyy-MM-dd HH:mm:ss";
@@ -18,7 +18,6 @@ List<Source> _nepnepSourcesList = [
dateFormat: defaultDateFormat, dateFormat: defaultDateFormat,
dateFormatLocale: defaultDateFormatLocale, dateFormatLocale: defaultDateFormatLocale,
version: nepnepVersion, version: nepnepVersion,
appMinVerReq: "0.0.5",
sourceCodeUrl: nepnepSourceCodeUrl, sourceCodeUrl: nepnepSourceCodeUrl,
), ),
Source( Source(
@@ -30,7 +29,6 @@ List<Source> _nepnepSourcesList = [
dateFormat: defaultDateFormat, dateFormat: defaultDateFormat,
dateFormatLocale: defaultDateFormatLocale, dateFormatLocale: defaultDateFormatLocale,
version: nepnepVersion, version: nepnepVersion,
appMinVerReq: "0.0.5",
sourceCodeUrl: nepnepSourceCodeUrl, sourceCodeUrl: nepnepSourceCodeUrl,
), ),
]; ];

View File

@@ -1,187 +0,0 @@
import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart';
getPopularManga(MangaModel manga) async {
final url = "${manga.baseUrl}/browse?${lang(manga.lang)}&sort=views_a&page=${manga.page}";
final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data));
return mangaElementM(res, manga);
}
String lang(String lang) {
lang = lang.replaceAll("-", "_");
if (lang == "all") {
return "";
}
return "langs=$lang";
}
getLatestUpdatesManga(MangaModel manga) async {
final url = "${manga.baseUrl}/browse?${lang(manga.lang)}&sort=update&page=${manga.page}";
final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data));
return mangaElementM(res, manga);
}
searchManga(MangaModel manga) async {
final data = {"url": "${manga.baseUrl}/search?word=${manga.query}&page=${manga.page}", "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data));
return mangaElementM(res, manga);
}
getMangaDetail(MangaModel manga) async {
final statusList = [
{
"Ongoing": 0,
"Completed": 1,
"Cancelled": 3,
"Hiatus": 2,
}
];
final url = "${manga.baseUrl}${manga.link}";
final data = {"url": url, "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) {
return manga;
}
final workStatus = MBridge.xpath(
res, '//*[@class="attr-item"]/b[contains(text(),"Original work")]/following-sibling::span[1]/text()')
.first;
manga.status = MBridge.parseStatus(workStatus, statusList);
manga.author =
MBridge.xpath(res, '//*[@class="attr-item"]/b[contains(text(),"Authors")]/following-sibling::span[1]/text()')
.first;
manga.genre =
MBridge.xpath(res, '//*[@class="attr-item"]/b[contains(text(),"Genres")]/following-sibling::span[1]/text()')
.first
.split(",");
manga.description = MBridge.xpath(res, '//*[@class="limit-html"]/text()').first;
List<String> chapsElement =
MBridge.querySelectorAll(res, selector: "div.main div.p-2", typeElement: 2, attributes: "", typeRegExp: 0);
List<String> times = [];
List<String> chapsUrls = [];
List<String> chapsNames = [];
List<String> scanlators = [];
for (var element in chapsElement) {
final urlElement =
MBridge.querySelectorAll(element, selector: "a.chapt", typeElement: 2, attributes: "", typeRegExp: 0).first;
final group = MBridge.xpath(element, '//*[@class="extra"]/a/text()').first;
final name = MBridge.xpath(urlElement, '//a/text()').first;
final url = MBridge.xpath(urlElement, '//a/@href').first;
final time = MBridge.xpath(element, '//*[@class="extra"]/i[@class="ps-3"]/text()').first;
times.add(time);
chapsUrls.add(url);
scanlators.add(group);
chapsNames.add(name.replaceAll("\n ", "").replaceAll(" ", ""));
}
manga.urls = chapsUrls;
manga.names = chapsNames;
manga.chaptersScanlators = scanlators;
manga.chaptersDateUploads = MBridge.listParseDateTime(times, "MMM dd,yyyy", "en");
return manga;
}
getChapterUrl(MangaModel manga) async {
final datas = {"url": "${manga.baseUrl}${manga.link}", "sourceId": manga.sourceId};
final res = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) {
return [];
}
final script = MBridge.xpath(res,
'//script[contains(text(), "imgHttpLis") and contains(text(), "batoWord") and contains(text(), "batoPass")]/text()')
.first;
final imgHttpLisString = MBridge.substringBefore(MBridge.substringAfterLast(script, 'const imgHttpLis ='), ';');
var imgHttpLis = json.decode(imgHttpLisString);
final batoWord = MBridge.substringBefore(MBridge.substringAfterLast(script, 'const batoWord ='), ';');
final batoPass = MBridge.substringBefore(MBridge.substringAfterLast(script, 'const batoPass ='), ';');
final evaluatedPass = MBridge.deobfuscateJsPassword(batoPass);
final imgAccListString = MBridge.decryptAESCryptoJS(batoWord.replaceAll('"', ""), evaluatedPass);
var imgAccList = json.decode(imgAccListString);
List<String> pagesUrl = [];
for (int i = 0; i < imgHttpLis.length; i++) {
String imgUrl = imgHttpLis[i];
String imgAcc = imgAccList[i];
pagesUrl.add("$imgUrl?$imgAcc");
}
return pagesUrl;
}
MangaModel mangaElementM(String res, MangaModel manga) async {
if (res.isEmpty) {
return manga;
}
final lang = manga.lang.replaceAll("-", "_");
var resB =
MBridge.querySelectorAll(res, selector: "div#series-list div.col", typeElement: 2, attributes: "", typeRegExp: 0);
List<String> images = [];
List<String> urls = [];
List<String> names = [];
for (var element in resB) {
if (manga.lang == "all" ||
manga.lang == "en" && element.contains('no-flag') ||
element.contains('data-lang="$lang"')) {
final item =
MBridge.querySelectorAll(element, selector: "a.item-cover", typeElement: 2, attributes: "", typeRegExp: 0)
.first;
final img =
MBridge.querySelectorAll(item, selector: "img", typeElement: 3, attributes: "src", typeRegExp: 0).first;
final url =
MBridge.querySelectorAll(item, selector: "a", typeElement: 3, attributes: "href", typeRegExp: 0).first;
images.add(img);
urls.add(url);
final title =
MBridge.querySelectorAll(element, selector: "a.item-title", typeElement: 0, attributes: "", typeRegExp: 0)
.first;
names.add(title);
}
}
manga.urls = urls;
manga.names = names;
manga.images = images;
final nextPage = MBridge.xpath(res, '//li[@class="page-item disabled"]/a/span[contains(text(),"»")]/text()').first;
if (nextPage.isEmpty) {
manga.hasNextPage = true;
} else {
manga.hasNextPage = false;
}
return manga;
}
Map<String, String> getMirrorPref() {
return {
"bato.to": "https://bato.to",
"batocomic.com": "https://batocomic.com",
"batocomic.net": "https://batocomic.net",
"batocomic.org": "https://batocomic.org",
"batotoo.com": "https://batotoo.com",
"batotwo.com": "https://batotwo.com",
"battwo.com": "https://battwo.com",
"comiko.net": "https://comiko.net",
"comiko.org": "https://comiko.org",
"mangatoto.com": "https://mangatoto.com",
"mangatoto.net": "https://mangatoto.net",
"mangatoto.org": "https://mangatoto.org",
"readtoto.com": "https://readtoto.com",
"readtoto.net": "https://readtoto.net",
"readtoto.org": "https://readtoto.org",
"dto.to": "https://dto.to",
"hto.to": "https://hto.to",
"mto.to": "https://mto.to",
"wto.to": "https://wto.to",
"xbato.com": "https://xbato.com",
"xbato.net": "https://xbato.net",
"xbato.org": "https://xbato.org",
"zbato.com": "https://zbato.com",
"zbato.net": "https://zbato.net",
"zbato.org": "https://zbato.org",
};
}

View File

@@ -0,0 +1,228 @@
import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart';
getPopularManga(MManga manga) async {
final url =
"${manga.baseUrl}/browse?${lang(manga.lang)}&sort=views_a&page=${manga.page}";
final data = {"url": url, "sourceId": manga.sourceId};
final response = await MBridge.http('GET', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
return mangaElementM(res, manga);
}
String lang(String lang) {
lang = lang.replaceAll("-", "_");
if (lang == "all") {
return "";
}
return "langs=$lang";
}
getLatestUpdatesManga(MManga manga) async {
final url =
"${manga.baseUrl}/browse?${lang(manga.lang)}&sort=update&page=${manga.page}";
final data = {"url": url, "sourceId": manga.sourceId};
final response = await MBridge.http('GET', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
return mangaElementM(res, manga);
}
searchManga(MManga manga) async {
final data = {
"url": "${manga.baseUrl}/search?word=${manga.query}&page=${manga.page}",
"sourceId": manga.sourceId
};
final response = await MBridge.http('GET', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
return mangaElementM(res, manga);
}
getMangaDetail(MManga manga) async {
final statusList = [
{
"Ongoing": 0,
"Completed": 1,
"Cancelled": 3,
"Hiatus": 2,
}
];
final url = "${manga.baseUrl}${manga.link}";
final data = {"url": url, "sourceId": manga.sourceId};
final response = await MBridge.http('GET', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
final workStatus = MBridge.xpath(res,
'//*[@class="attr-item"]/b[contains(text(),"Original work")]/following-sibling::span[1]/text()')
.first;
manga.status = MBridge.parseStatus(workStatus, statusList);
manga.author = MBridge.xpath(res,
'//*[@class="attr-item"]/b[contains(text(),"Authors")]/following-sibling::span[1]/text()')
.first;
manga.genre = MBridge.xpath(res,
'//*[@class="attr-item"]/b[contains(text(),"Genres")]/following-sibling::span[1]/text()')
.first
.split(",");
manga.description =
MBridge.xpath(res, '//*[@class="limit-html"]/text()').first;
List<String> chapsElement = MBridge.querySelectorAll(res,
selector: "div.main div.p-2",
typeElement: 2,
attributes: "",
typeRegExp: 0);
List<String> times = [];
List<String> chapsUrls = [];
List<String> chapsNames = [];
List<String> scanlators = [];
for (var element in chapsElement) {
final urlElement = MBridge.querySelectorAll(element,
selector: "a.chapt", typeElement: 2, attributes: "", typeRegExp: 0)
.first;
final group = MBridge.xpath(element, '//*[@class="extra"]/a/text()').first;
final name = MBridge.xpath(urlElement, '//a/text()').first;
final url = MBridge.xpath(urlElement, '//a/@href').first;
final time =
MBridge.xpath(element, '//*[@class="extra"]/i[@class="ps-3"]/text()')
.first;
times.add(time);
chapsUrls.add(url);
scanlators.add(group);
chapsNames.add(name.replaceAll("\n ", "").replaceAll(" ", ""));
}
manga.urls = chapsUrls;
manga.names = chapsNames;
manga.chaptersScanlators = scanlators;
manga.chaptersDateUploads =
MBridge.listParseDateTime(times, "MMM dd,yyyy", "en");
return manga;
}
getChapterPages(MManga manga) async {
final datas = {
"url": "${manga.baseUrl}${manga.link}",
"sourceId": manga.sourceId
};
final response = await MBridge.http('GET', json.encode(datas));
if (response.hasError) {
return response;
}
String res = response.body;
final script = MBridge.xpath(res,
'//script[contains(text(), "imgHttpLis") and contains(text(), "batoWord") and contains(text(), "batoPass")]/text()')
.first;
final imgHttpLisString = MBridge.substringBefore(
MBridge.substringAfterLast(script, 'const imgHttpLis ='), ';');
var imgHttpLis = json.decode(imgHttpLisString);
final batoWord = MBridge.substringBefore(
MBridge.substringAfterLast(script, 'const batoWord ='), ';');
final batoPass = MBridge.substringBefore(
MBridge.substringAfterLast(script, 'const batoPass ='), ';');
final evaluatedPass = MBridge.deobfuscateJsPassword(batoPass);
final imgAccListString =
MBridge.decryptAESCryptoJS(batoWord.replaceAll('"', ""), evaluatedPass);
var imgAccList = json.decode(imgAccListString);
List<String> pagesUrl = [];
for (int i = 0; i < imgHttpLis.length; i++) {
String imgUrl = imgHttpLis[i];
String imgAcc = imgAccList[i];
pagesUrl.add("$imgUrl?$imgAcc");
}
return pagesUrl;
}
MManga mangaElementM(String res, MManga manga) async {
final lang = manga.lang.replaceAll("-", "_");
var resB = MBridge.querySelectorAll(res,
selector: "div#series-list div.col",
typeElement: 2,
attributes: "",
typeRegExp: 0);
List<String> images = [];
List<String> urls = [];
List<String> names = [];
for (var element in resB) {
if (manga.lang == "all" ||
manga.lang == "en" && element.contains('no-flag') ||
element.contains('data-lang="$lang"')) {
final item = MBridge.querySelectorAll(element,
selector: "a.item-cover",
typeElement: 2,
attributes: "",
typeRegExp: 0)
.first;
final img = MBridge.querySelectorAll(item,
selector: "img", typeElement: 3, attributes: "src", typeRegExp: 0)
.first;
final url = MBridge.querySelectorAll(item,
selector: "a", typeElement: 3, attributes: "href", typeRegExp: 0)
.first;
images.add(img);
urls.add(url);
final title = MBridge.querySelectorAll(element,
selector: "a.item-title",
typeElement: 0,
attributes: "",
typeRegExp: 0)
.first;
names.add(title);
}
}
manga.urls = urls;
manga.names = names;
manga.images = images;
final nextPage = MBridge.xpath(res,
'//li[@class="page-item disabled"]/a/span[contains(text(),"»")]/text()');
manga.hasNextPage = true;
return manga;
}
Map<String, String> getMirrorPref() {
return {
"bato.to": "https://bato.to",
"batocomic.com": "https://batocomic.com",
"batocomic.net": "https://batocomic.net",
"batocomic.org": "https://batocomic.org",
"batotoo.com": "https://batotoo.com",
"batotwo.com": "https://batotwo.com",
"battwo.com": "https://battwo.com",
"comiko.net": "https://comiko.net",
"comiko.org": "https://comiko.org",
"mangatoto.com": "https://mangatoto.com",
"mangatoto.net": "https://mangatoto.net",
"mangatoto.org": "https://mangatoto.org",
"readtoto.com": "https://readtoto.com",
"readtoto.net": "https://readtoto.net",
"readtoto.org": "https://readtoto.org",
"dto.to": "https://dto.to",
"hto.to": "https://hto.to",
"mto.to": "https://mto.to",
"wto.to": "https://wto.to",
"xbato.com": "https://xbato.com",
"xbato.net": "https://xbato.net",
"xbato.org": "https://xbato.org",
"zbato.com": "https://zbato.com",
"zbato.net": "https://zbato.net",
"zbato.org": "https://zbato.org",
};
}

View File

@@ -1,7 +1,7 @@
import '../../../../model/source.dart'; import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
const batotoVersion = "0.0.2"; const batotoVersion = "0.0.3";
const batotoSourceCodeUrl = const batotoSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/all/batoto/batoto-v$batotoVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/all/batoto/batoto-v$batotoVersion.dart";
@@ -128,6 +128,5 @@ List<Source> _batotoSourcesList = languages
isNsfw: isNsfw, isNsfw: isNsfw,
dateFormatLocale: "en", dateFormatLocale: "en",
version: batotoVersion, version: batotoVersion,
appMinVerReq: "0.0.43",
sourceCodeUrl: batotoSourceCodeUrl)) sourceCodeUrl: batotoSourceCodeUrl))
.toList(); .toList();

View File

@@ -1,14 +1,15 @@
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
import 'dart:convert'; import 'dart:convert';
getLatestUpdatesManga(MangaModel manga) async { getLatestUpdatesManga(MManga manga) async {
final url = "${manga.apiUrl}/v1.0/search?sort=uploaded&page=${manga.page}&tachiyomi=true"; final url =
"${manga.apiUrl}/v1.0/search?sort=uploaded&page=${manga.page}&tachiyomi=true";
final data = {"url": url, "headers": getHeader(manga.baseUrl)}; final data = {"url": url, "headers": getHeader(manga.baseUrl)};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.names = MBridge.jsonPathToList(res, r'$.title', 0); manga.names = MBridge.jsonPathToList(res, r'$.title', 0);
List<String> ids = MBridge.jsonPathToList(res, r'$.hid', 0); List<String> ids = MBridge.jsonPathToList(res, r'$.hid', 0);
List<String> mangaUrls = []; List<String> mangaUrls = [];
@@ -20,7 +21,7 @@ getLatestUpdatesManga(MangaModel manga) async {
return manga; return manga;
} }
getMangaDetail(MangaModel manga) async { getMangaDetail(MManga manga) async {
final statusList = [ final statusList = [
{ {
"1": 0, "1": 0,
@@ -32,46 +33,70 @@ getMangaDetail(MangaModel manga) async {
final headers = getHeader(manga.baseUrl); final headers = getHeader(manga.baseUrl);
final urll = "${manga.apiUrl}${manga.link.replaceAll("#", '')}?tachiyomi=true"; final urll =
"${manga.apiUrl}${manga.link.replaceAll("#", '')}?tachiyomi=true";
final data = {"url": urll, "headers": headers}; final data = {"url": urll, "headers": headers};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.author = MBridge.jsonPathToString(res, r'$.authors[*].name', ''); manga.author = MBridge.jsonPathToString(res, r'$.authors[*].name', '');
manga.genre = MBridge.jsonPathToString(res, r'$.genres[*].name', "_.").split("_."); manga.genre =
MBridge.jsonPathToString(res, r'$.genres[*].name', "_.").split("_.");
manga.description = MBridge.jsonPathToString(res, r'$..desc', ''); manga.description = MBridge.jsonPathToString(res, r'$..desc', '');
manga.status = MBridge.parseStatus(MBridge.jsonPathToString(res, r'$..comic.status', ''), statusList); manga.status = MBridge.parseStatus(
MBridge.jsonPathToString(res, r'$..comic.status', ''), statusList);
final chapUrlReq = final chapUrlReq =
"${manga.apiUrl}${manga.link.replaceAll("#", '')}chapters?lang=${manga.lang}&tachiyomi=true&page=1"; "${manga.apiUrl}${manga.link.replaceAll("#", '')}chapters?lang=${manga.lang}&tachiyomi=true&page=1";
final dataReq = {"url": chapUrlReq, "headers": headers}; final dataReq = {"url": chapUrlReq, "headers": headers};
final request = await MBridge.http('GET', json.encode(dataReq)); final request = await MBridge.http('GET', json.encode(dataReq));
var total = MBridge.jsonPathToString(request, r'$.total', ''); if (request.hasError) {
return response;
}
var total = MBridge.jsonPathToString(request.body, r'$.total', '');
final chapterLimit = MBridge.intParse("$total"); final chapterLimit = MBridge.intParse("$total");
final newChapUrlReq = final newChapUrlReq =
"${manga.apiUrl}${manga.link.replaceAll("#", '')}chapters?limit=$chapterLimit&lang=${manga.lang}&tachiyomi=true&page=1"; "${manga.apiUrl}${manga.link.replaceAll("#", '')}chapters?limit=$chapterLimit&lang=${manga.lang}&tachiyomi=true&page=1";
final newDataReq = {"url": newChapUrlReq, "headers": headers}; final newDataReq = {"url": newChapUrlReq, "headers": headers};
final newRequest = await MBridge.http('GET', json.encode(newDataReq)); final newRequest = await MBridge.http('GET', json.encode(newDataReq));
if (newRequest.hasError) {
manga.urls = MBridge.jsonPathToString(newRequest, r'$.chapters[*].hid', "_.").split("_."); return response;
final chapDate = MBridge.jsonPathToString(newRequest, r'$.chapters[*].created_at', "_.").split("_."); }
manga.chaptersDateUploads =MBridge.listParseDateTime(chapDate, "yyyy-MM-dd'T'HH:mm:ss'Z'", "en"); manga.urls =
manga.chaptersVolumes = MBridge.jsonPathToString(newRequest, r'$.chapters[*].vol', "_.").split("_."); MBridge.jsonPathToString(newRequest.body, r'$.chapters[*].hid', "_.")
manga.chaptersScanlators = MBridge.jsonPathToString(newRequest, r'$.chapters[*].group_name', "_.").split("_."); .split("_.");
manga.names = MBridge.jsonPathToString(newRequest, r'$.chapters[*].title', "_.").split("_."); final chapDate = MBridge.jsonPathToString(
manga.chaptersChaps = MBridge.jsonPathToString(newRequest, r'$.chapters[*].chap', "_.").split("_."); newRequest.body, r'$.chapters[*].created_at', "_.")
.split("_.");
manga.chaptersDateUploads =
MBridge.listParseDateTime(chapDate, "yyyy-MM-dd'T'HH:mm:ss'Z'", "en");
manga.chaptersVolumes =
MBridge.jsonPathToString(newRequest.body, r'$.chapters[*].vol', "_.")
.split("_.");
manga.chaptersScanlators = MBridge.jsonPathToString(
newRequest.body, r'$.chapters[*].group_name', "_.")
.split("_.");
manga.names =
MBridge.jsonPathToString(newRequest.body, r'$.chapters[*].title', "_.")
.split("_.");
manga.chaptersChaps =
MBridge.jsonPathToString(newRequest.body, r'$.chapters[*].chap', "_.")
.split("_.");
return manga; return manga;
} }
getPopularManga(MangaModel manga) async { getPopularManga(MManga manga) async {
final urll = "${manga.apiUrl}/v1.0/search?sort=follow&page=${manga.page}&tachiyomi=true"; final urll =
"${manga.apiUrl}/v1.0/search?sort=follow&page=${manga.page}&tachiyomi=true";
final data = {"url": urll, "headers": getHeader(manga.baseUrl)}; final data = {"url": urll, "headers": getHeader(manga.baseUrl)};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.names = MBridge.jsonPathToList(res, r'$.title', 0); manga.names = MBridge.jsonPathToList(res, r'$.title', 0);
List<String> ids = MBridge.jsonPathToList(res, r'$.hid', 0); List<String> ids = MBridge.jsonPathToList(res, r'$.hid', 0);
List<String> mangaUrls = []; List<String> mangaUrls = [];
@@ -83,13 +108,14 @@ getPopularManga(MangaModel manga) async {
return manga; return manga;
} }
searchManga(MangaModel manga) async { searchManga(MManga manga) async {
final urll = "${manga.apiUrl}/v1.0/search?q=${manga.query}&tachiyomi=true"; final urll = "${manga.apiUrl}/v1.0/search?q=${manga.query}&tachiyomi=true";
final data = {"url": urll, "headers": getHeader(manga.baseUrl)}; final data = {"url": urll, "headers": getHeader(manga.baseUrl)};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return manga; return response;
} }
String res = response.body;
manga.names = MBridge.jsonPathToList(res, r'$.title', 0); manga.names = MBridge.jsonPathToList(res, r'$.title', 0);
List<String> ids = MBridge.jsonPathToList(res, r'$.hid', 0); List<String> ids = MBridge.jsonPathToList(res, r'$.hid', 0);
List<String> mangaUrls = []; List<String> mangaUrls = [];
@@ -101,20 +127,23 @@ searchManga(MangaModel manga) async {
return manga; return manga;
} }
getChapterUrl(MangaModel manga) async { getChapterPages(MManga manga) async {
final url = "${manga.apiUrl}/chapter/${manga.link}?tachiyomi=true"; final url = "${manga.apiUrl}/chapter/${manga.link}?tachiyomi=true";
final data = {"url": url, "headers": getHeader(url)}; final data = {"url": url, "headers": getHeader(url)};
final res = await MBridge.http('GET', json.encode(data)); final response = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) { if (response.hasError) {
return []; return response;
} }
return MBridge.jsonPathToString(res, r'$.chapter.images[*].url', '_.').split('_.'); String res = response.body;
return MBridge.jsonPathToString(res, r'$.chapter.images[*].url', '_.')
.split('_.');
} }
Map<String, String> getHeader(String url) { Map<String, String> getHeader(String url) {
final headers = { final headers = {
"Referer": "$url/", "Referer": "$url/",
'User-Agent': "Tachiyomi Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0" 'User-Agent':
"Tachiyomi Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0"
}; };
return headers; return headers;
} }

View File

@@ -1,7 +1,7 @@
import '../../../../model/source.dart'; import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
const comickVersion = "0.0.2"; const comickVersion = "0.0.3";
const comickSourceCodeUrl = const comickSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/all/comick/comick-v$comickVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/all/comick/comick-v$comickVersion.dart";

View File

@@ -1,43 +1,204 @@
import 'package:bridge_lib/bridge_lib.dart'; import 'package:bridge_lib/bridge_lib.dart';
import 'dart:convert'; import 'dart:convert';
getPopularManga(MManga manga) async {
int page = (20 * (manga.page - 1));
final url =
"https://api.mangadex.org/manga?limit=20&offset=$page&availableTranslatedLanguage[]=en&includes[]=cover_art${getMDXContentRating()}&order[followedCount]=desc";
final datas = {"url": url};
final response = await MBridge.http('GET', json.encode(datas));
if (response.hasError) {
return response;
}
return parseManga(response.body, manga);
}
getLatestUpdatesManga(MManga manga) async {
int page = (20 * (manga.page - 1));
final urll =
"https://api.mangadex.org/chapter?limit=20&offset=$page&translatedLanguage[]=${manga.lang}&includeFutureUpdates=0&order[publishAt]=desc&includeFuturePublishAt=0&includeEmptyPages=0";
final datas = {"url": urll};
final response = await MBridge.http('GET', json.encode(datas));
if (response.hasError) {
return response;
}
String ress = response.body;
final mangaIds = MBridge.listParse(
MBridge.jsonPathToString(ress, r'$.data[*].relationships[*].id', '.--')
.split('.--'),
3);
String mangaa = "".toString();
for (var id in mangaIds) {
mangaa += "&ids[]=$id";
}
final newUrl =
"https://api.mangadex.org/manga?includes[]=cover_art&limit=${mangaIds.length}${getMDXContentRating()}$mangaa";
final datass = {"url": newUrl};
final res = await MBridge.http('GET', json.encode(datass));
if (res.hasError) {
return res;
}
return parseManga(res.body, manga);
}
searchManga(MManga manga) async {
final url =
"https://api.mangadex.org/manga?includes[]=cover_art&offset=0&limit=20&title=${manga.query}${getMDXContentRating()}&order[followedCount]=desc&availableTranslatedLanguage[]=${manga.lang}";
final datas = {"url": url};
final res = await MBridge.http('GET', json.encode(datas));
if (res.hasError) {
return res;
}
return parseManga(res.body, manga);
}
getMangaDetail(MManga manga) async {
final statusList = [
{
"ongoing": 0,
"completed": 1,
"hiatus": 2,
"cancelled": 3,
}
];
final url =
"https://api.mangadex.org${manga.link}?includes[]=cover_art&includes[]=author&includes[]=artist";
final datas = {"url": url};
final response = await MBridge.http('GET', json.encode(datas));
if (response.hasError) {
return response;
}
String res = response.body;
manga.author = MBridge.jsonPathToString(
res, r'$..data.relationships[*].attributes.name', ', ');
String expressionDescriptionA = r'$..data.attributes.description.en';
String expressionDescription = MBridge.regExp(
r'$..data.attributes.description[a]', r'\[a\]', ".${manga.lang}", 0, 1);
String description = MBridge.jsonPathToString(res, expressionDescription, '');
if (description.isEmpty) {
description = MBridge.jsonPathToString(res, expressionDescriptionA, '');
}
manga.description = description;
List<String> genres = [];
final genre = MBridge.listParse(
MBridge.jsonPathToString(
res, r'$..data.attributes.tags[*].attributes.name.en', '.-')
.split('.-'),
0);
genres = genre;
String contentRating =
MBridge.jsonPathToString(res, r'$..data.attributes.contentRating', '');
if (contentRating == "safe") {
} else {
genres.add(contentRating);
}
String publicationDemographic = MBridge.jsonPathToString(
res, r'$..data.attributes.publicationDemographic', '');
if (publicationDemographic == "null") {
} else {
genres.add(publicationDemographic);
}
manga.genre = genres;
String statusRes =
MBridge.jsonPathToString(res, r'$..data.attributes.status', '');
manga.status = MBridge.parseStatus(statusRes, statusList);
final mangaId = MBridge.listParse(manga.link.split('/'), 2)[0];
final paginatedChapterList =
await paginatedChapterListRequest(mangaId, 0, manga.lang);
final chapterList =
MBridge.jsonPathToString(paginatedChapterList, r'$.data[*]', '_.')
.split('_.');
int limit = MBridge.intParse(
MBridge.jsonPathToString(paginatedChapterList, r'$.limit', ''));
int offset = MBridge.intParse(
MBridge.jsonPathToString(paginatedChapterList, r'$.offset', ''));
int total = MBridge.intParse(
MBridge.jsonPathToString(paginatedChapterList, r'$.total', ''));
List<MManga> chapterListA = [];
List<String> chapNames = [];
List<String> scanlators = [];
List<String> chapterUrl = [];
List<String> chapterDate = [];
final list = getChapters(
manga, MBridge.intParse("${chapterList.length}"), paginatedChapterList);
chapterListA.add(list);
var hasMoreResults = (limit + offset) < total;
while (hasMoreResults) {
offset += limit;
var newRequest =
await paginatedChapterListRequest(mangaId, offset, manga.lang);
int total =
MBridge.intParse(MBridge.jsonPathToString(newRequest, r'$.total', ''));
final chapterList =
MBridge.jsonPathToString(paginatedChapterList, r'$.data[*]', '_.')
.split('_.');
final list = getChapters(
manga, MBridge.intParse("${chapterList.length}"), newRequest);
chapterListA.add(list);
hasMoreResults = (limit + offset) < total;
}
for (var element in chapterListA) {
for (var name in element.names) {
if (name.isNotEmpty) {
chapNames.add(name);
}
}
}
for (var element in chapterListA) {
for (var url in element.urls) {
if (url.isNotEmpty) {
chapterUrl.add(url);
}
}
}
for (var element in chapterListA) {
for (var chapDate in element.chaptersDateUploads) {
if (chapDate.isNotEmpty) {
chapterDate.add(chapDate);
}
}
}
for (var element in chapterListA) {
for (var scanlator in element.chaptersScanlators) {
if (scanlator.isNotEmpty) {
scanlators.add(scanlator);
}
}
}
manga.urls = chapterUrl;
manga.chaptersDateUploads = chapterDate;
manga.chaptersScanlators = scanlators;
manga.names = chapNames;
return manga;
}
getChapterPages(MManga manga) async {
final url = "https://api.mangadex.org/at-home/server/${manga.link}";
final data = {"url": url};
final response = await MBridge.http('GET', json.encode(data));
if (response.hasError) {
return response;
}
final dataRes = json.decode(response.body);
final host = dataRes["baseUrl"];
final hash = dataRes["chapter"]["hash"];
final chapterDatas = dataRes["chapter"]["data"] as List;
return chapterDatas.map((e) => "$host/data/$hash/$e").toList();
}
String getMDXContentRating() { String getMDXContentRating() {
String ctnRating = String ctnRating =
"&contentRating[]=suggestive&contentRating[]=safe&contentRating[]=erotica&contentRating[]=pornographic"; "&contentRating[]=suggestive&contentRating[]=safe&contentRating[]=erotica&contentRating[]=pornographic";
return ctnRating; return ctnRating;
} }
getPopularManga(MangaModel manga) async { MManga getChapters(MManga manga, int length, String paginatedChapterListA) {
int page = (20 * (manga.page - 1));
final url =
"https://api.mangadex.org/manga?limit=20&offset=$page&availableTranslatedLanguage[]=en&includes[]=cover_art${getMDXContentRating()}&order[followedCount]=desc";
final datas = {"url": url, "headers": null};
final res = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) {
return manga;
}
List<String> data = MBridge.listParse(
MBridge.jsonPathToString(res, r'$.data[*]', '_.').split("_."), 0);
List<String> urlList = [];
List<String> titleList = [];
List<String> imageList = [];
for (var i = 0; i < data.length; i++) {
final expressionId =
MBridge.regExp(r'$.data[a].id', r'\[a\]', "[$i]", 0, 1);
final id = MBridge.jsonPathToString(res, expressionId, '_.');
titleList.add(findTitle(res, i, manga.lang));
urlList.add("/manga/$id");
imageList.add(getCover(res, i, id));
}
manga.names = titleList;
manga.urls = urlList;
manga.images = imageList;
return manga;
}
MangaModel getChapters(
MangaModel manga, int length, String paginatedChapterListA) {
String scanlators = "".toString(); String scanlators = "".toString();
String chapNames = "".toString(); String chapNames = "".toString();
String chapDate = "".toString(); String chapDate = "".toString();
@@ -120,289 +281,53 @@ MangaModel getChapters(
return manga; return manga;
} }
getMangaDetail(MangaModel manga) async {
final statusList = [
{
"ongoing": 0,
"completed": 1,
"hiatus": 2,
"cancelled": 3,
}
];
final url =
"https://api.mangadex.org${manga.link}?includes[]=cover_art&includes[]=author&includes[]=artist";
final datas = {"url": url, "headers": null};
final res = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) {
return manga;
}
manga.author = MBridge.jsonPathToString(
res, r'$..data.relationships[*].attributes.name', ', ');
String expressionDescriptionA = r'$..data.attributes.description.en';
String expressionDescription = MBridge.regExp(
r'$..data.attributes.description[a]', r'\[a\]', ".${manga.lang}", 0, 1);
String description = MBridge.jsonPathToString(res, expressionDescription, '');
if (description.isEmpty) {
description = MBridge.jsonPathToString(res, expressionDescriptionA, '');
}
manga.description = description;
List<String> genres = [];
final genre = MBridge.listParse(
MBridge.jsonPathToString(
res, r'$..data.attributes.tags[*].attributes.name.en', '.-')
.split('.-'),
0);
genres = genre;
String contentRating =
MBridge.jsonPathToString(res, r'$..data.attributes.contentRating', '');
if (contentRating == "safe") {
} else {
genres.add(contentRating);
}
String publicationDemographic = MBridge.jsonPathToString(
res, r'$..data.attributes.publicationDemographic', '');
if (publicationDemographic == "null") {
} else {
genres.add(publicationDemographic);
}
manga.genre = genres;
String statusRes =
MBridge.jsonPathToString(res, r'$..data.attributes.status', '');
manga.status = MBridge.parseStatus(statusRes, statusList);
final mangaId = MBridge.listParse(manga.link.split('/'), 2)[0];
final paginatedChapterList =
await paginatedChapterListRequest(mangaId, 0, manga.lang);
final chapterList =
MBridge.jsonPathToString(paginatedChapterList, r'$.data[*]', '_.')
.split('_.');
int limit = MBridge.intParse(
MBridge.jsonPathToString(paginatedChapterList, r'$.limit', ''));
int offset = MBridge.intParse(
MBridge.jsonPathToString(paginatedChapterList, r'$.offset', ''));
int total = MBridge.intParse(
MBridge.jsonPathToString(paginatedChapterList, r'$.total', ''));
List<MangaModel> chapterListA = [];
List<String> chapNames = [];
List<String> scanlators = [];
List<String> chapterUrl = [];
List<String> chapterDate = [];
final list = getChapters(
manga, MBridge.intParse("${chapterList.length}"), paginatedChapterList);
chapterListA.add(list);
var hasMoreResults = (limit + offset) < total;
while (hasMoreResults) {
offset += limit;
var newRequest =
await paginatedChapterListRequest(mangaId, offset, manga.lang);
int total =
MBridge.intParse(MBridge.jsonPathToString(newRequest, r'$.total', ''));
final chapterList =
MBridge.jsonPathToString(paginatedChapterList, r'$.data[*]', '_.')
.split('_.');
final list = getChapters(
manga, MBridge.intParse("${chapterList.length}"), newRequest);
chapterListA.add(list);
hasMoreResults = (limit + offset) < total;
}
for (var element in chapterListA) {
for (var name in element.names) {
if (name.isEmpty) {
} else {
chapNames.add(name);
}
}
}
for (var element in chapterListA) {
for (var url in element.urls) {
if (url.isEmpty) {
} else {
chapterUrl.add(url);
}
}
}
for (var element in chapterListA) {
for (var chapDate in element.chaptersDateUploads) {
if (chapDate.isEmpty) {
} else {
chapterDate.add(chapDate);
}
}
}
for (var element in chapterListA) {
for (var scanlator in element.chaptersScanlators) {
if (scanlator.isEmpty) {
} else {
scanlators.add(scanlator);
}
}
}
manga.urls = chapterUrl;
manga.chaptersDateUploads = chapterDate;
manga.chaptersScanlators = scanlators;
manga.names = chapNames;
return manga;
}
getLatestUpdatesManga(MangaModel manga) async {
int page = (20 * (manga.page - 1));
final urll =
"https://api.mangadex.org/chapter?limit=20&offset=$page&translatedLanguage[]=${manga.lang}&includeFutureUpdates=0&order[publishAt]=desc&includeFuturePublishAt=0&includeEmptyPages=0";
final datas = {"url": urll, "headers": null};
final ress = await MBridge.http('GET', json.encode(datas));
if (ress.isEmpty) {
return manga;
}
final mangaIds = MBridge.listParse(
MBridge.jsonPathToString(ress, r'$.data[*].relationships[*].id', '.--')
.split('.--'),
3);
String mangaa = "".toString();
for (var id in mangaIds) {
mangaa += "&ids[]=$id";
}
final newUrl =
"https://api.mangadex.org/manga?includes[]=cover_art&limit=${mangaIds.length}${getMDXContentRating()}$mangaa";
final datass = {"url": newUrl, "headers": null};
final res = await MBridge.http('GET', json.encode(datass));
List<String> data = MBridge.listParse(
MBridge.jsonPathToString(res, r'$.data[*]', '_.').split("_."), 0);
List<String> urlList = [];
List<String> titleList = [];
List<String> imageList = [];
for (var i = 0; i < data.length; i++) {
final expressionId =
MBridge.regExp(r'$.data[a].id', r'\[a\]', "[$i]", 0, 1);
final id = MBridge.jsonPathToString(res, expressionId, '_.');
titleList.add(findTitle(res, i, manga.lang));
urlList.add("/manga/$id");
imageList.add(getCover(res, i, id));
}
manga.names = titleList;
manga.urls = urlList;
manga.images = imageList;
return manga;
}
searchManga(MangaModel manga) async {
final url =
"https://api.mangadex.org/manga?includes[]=cover_art&offset=0&limit=20&title=${manga.query}${getMDXContentRating()}&order[followedCount]=desc&availableTranslatedLanguage[]=${manga.lang}";
final datas = {"url": url, "headers": null};
final res = await MBridge.http('GET', json.encode(datas));
if (res.isEmpty) {
return manga;
}
List<String> data = MBridge.listParse(
MBridge.jsonPathToString(res, r'$.data[*]', '_.').split("_."), 0);
List<String> urlList = [];
List<String> titleList = [];
List<String> imageList = [];
for (var i = 0; i < data.length; i++) {
final expressionId =
MBridge.regExp(r'$.data[a].id', r'\[a\]', "[$i]", 0, 1);
final id = MBridge.jsonPathToString(res, expressionId, '_.');
titleList.add(findTitle(res, i, manga.lang));
urlList.add("/manga/$id");
imageList.add(getCover(res, i, id));
}
manga.names = titleList;
manga.urls = urlList;
manga.images = imageList;
return manga;
}
getChapterUrl(MangaModel manga) async {
final url = "https://api.mangadex.org/at-home/server/${manga.link}";
final data = {"url": url, "headers": null};
final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) {
return [];
}
final host = MBridge.jsonPathToString(res, r'$.baseUrl', '');
final hash = MBridge.jsonPathToString(res, r'$.chapter.hash', '');
List<String> pageSuffix = [];
List<String> pageUrls = [];
List<String> chapterDatas = MBridge.listParse(
MBridge.jsonPathToString(res, r'$.chapter.data[*]', '.--').split('.--'),
0);
for (var d in chapterDatas) {
pageSuffix.add("/data/$hash/$d");
}
for (var url in pageSuffix) {
pageUrls.add("$host$url");
}
return pageUrls;
}
Future<String> paginatedChapterListRequest( Future<String> paginatedChapterListRequest(
String mangaId, int offset, String lang) async { String mangaId, int offset, String lang) async {
final url = final url =
'https://api.mangadex.org/manga/$mangaId/feed?limit=500&offset=$offset&includes[]=user&includes[]=scanlation_group&order[volume]=desc&order[chapter]=desc&translatedLanguage[]=$lang&includeFuturePublishAt=0&includeEmptyPages=0${getMDXContentRating()}'; 'https://api.mangadex.org/manga/$mangaId/feed?limit=500&offset=$offset&includes[]=user&includes[]=scanlation_group&order[volume]=desc&order[chapter]=desc&translatedLanguage[]=$lang&includeFuturePublishAt=0&includeEmptyPages=0${getMDXContentRating()}';
final datas = {"url": url, "headers": null}; final datas = {"url": url};
return await MBridge.http('GET', json.encode(datas)); final response = await MBridge.http('GET', json.encode(datas));
return response.body;
} }
String findTitle(String dataRes, int mangaIndex, String lang) { String findTitle(Map<String, dynamic> dataRes, String lang) {
String expressionAltTitlesA = MBridge.regExp( final altTitlesJ = dataRes["attributes"]["altTitles"];
r'$.data[a].attributes.altTitles[b]', r'\[a\]', "[$mangaIndex]", 0, 1); final titleJ = dataRes["attributes"]["title"];
String expressionAltTitles = final title = MBridge.getMapValue(json.encode(titleJ), "en");
MBridge.regExp(expressionAltTitlesA, r'\[b\]', "[*].$lang", 0, 1);
String altTitles =
MBridge.jsonPathToString(dataRes, expressionAltTitles, '_.');
if (altTitles.isEmpty) {
expressionAltTitles = MBridge.regExp(
r'$.data[a].attributes.altTitles[?@.en].en',
r'\[a\]',
"[$mangaIndex]",
0,
1);
altTitles = MBridge.jsonPathToString(dataRes, expressionAltTitles, '_.');
}
List<String> dataAltTitles = MBridge.listParse(altTitles.split('_.'), 0);
final expressionTitle = MBridge.regExp(
r'$.data[a].attributes.title.en', r'\[a\]', "[$mangaIndex]", 0, 1);
final title = MBridge.jsonPathToString(dataRes, expressionTitle, '_.');
if (title.isEmpty) { if (title.isEmpty) {
return dataAltTitles[0]; for (var r in altTitlesJ) {
} else { final altTitle = MBridge.getMapValue(json.encode(r), "en");
return title; if (altTitle.isNotEmpty) {
return altTitle;
} }
}
}
return title;
} }
String getCover(String dataRes, int mangaIndex, String mangaId) { String getCover(Map<String, dynamic> dataRes) {
final expressionRelationAll = MBridge.regExp( final relationships = dataRes["relationships"];
r'$.data[a].relationships[*]', r'\[a\]', "[$mangaIndex]", 0, 1);
List<String> relationDatas = MBridge.listParse(
MBridge.jsonPathToString(dataRes, expressionRelationAll, '_.')
.split("_."),
0);
String coverFileName = "".toString(); String coverFileName = "".toString();
for (var j = 0; j < relationDatas.length; j++) { for (var a in relationships) {
final expressionData = MBridge.regExp( final relationType = a["type"];
r'$.data[a].relationships[b]', r'\[a\]', "[$mangaIndex]", 0, 1);
final expressionRelationType =
MBridge.regExp(expressionData, r'\[b\]', "[$j].type", 0, 1);
final relationType =
MBridge.jsonPathToString(dataRes, expressionRelationType, '');
if (relationType == "cover_art") { if (relationType == "cover_art") {
if (coverFileName.isEmpty) { if (coverFileName.isEmpty) {
final expressionRelationCoverFile = MBridge.regExp(
expressionData, r'\[b\]', "[$j].attributes.fileName", 0, 1);
coverFileName = coverFileName =
MBridge.jsonPathToString(dataRes, expressionRelationCoverFile, ''); "https://uploads.mangadex.org/covers/${dataRes["id"]}/${a["attributes"]["fileName"]}";
coverFileName =
"https://uploads.mangadex.org/covers/$mangaId/$coverFileName";
} }
} }
} }
return coverFileName; return coverFileName;
} }
MManga parseManga(String res, MManga manga) {
if (res.isEmpty) {
return manga;
}
final datasRes = json.decode(res);
final resJson = datasRes["data"] as List;
manga.names = resJson.map((e) => findTitle(e, manga.lang)).toList();
manga.urls = resJson.map((e) => "/manga/${e["id"]}").toList();
manga.images = resJson.map((e) => getCover(e)).toList();
return manga;
}

View File

@@ -4,7 +4,7 @@ import '../../../../utils/utils.dart';
const apiUrl = 'https://api.mangadex.org'; const apiUrl = 'https://api.mangadex.org';
const baseUrl = 'https://mangadex.org'; const baseUrl = 'https://mangadex.org';
const isNsfw = true; const isNsfw = true;
const mangadexVersion = "0.0.2"; const mangadexVersion = "0.0.3";
const mangadexSourceCodeUrl = const mangadexSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/all/mangadex/mangadex-v$mangadexVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/all/mangadex/mangadex-v$mangadexVersion.dart";
String _iconUrl = getIconUrl("mangadex", "all"); String _iconUrl = getIconUrl("mangadex", "all");

View File

@@ -1,157 +0,0 @@
import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart';
searchManga(MangaModel manga) async {
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}/search?title=${manga.query}&page=${manga.page}";
final data = {"url": url, "headers": headers};
final res = await MBridge.http('POST', json.encode(data));
if (res.isEmpty) {
return manga;
}
manga.names = MBridge.xpath(res, '//*[contains(@class, "manga-list-4-list")]/li/a/@title');
manga.images =
MBridge.xpath(res, '//*[contains(@class, "manga-list-4-list")]/li/a/img[@class="manga-list-4-cover"]/@src');
manga.urls = MBridge.xpath(res, '//*[contains(@class, "manga-list-4-list")]/li/a/@href');
return manga;
}
getLatestUpdatesManga(MangaModel manga) async {
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}/directory/${manga.page}.htm?latest";
final data = {"url": url, "headers": headers};
final res = await MBridge.http('POST', json.encode(data));
if (res.isEmpty) {
return manga;
}
manga.names = MBridge.xpath(res, '//*[ contains(@class, "manga-list-1-list")]/li/a/@title');
manga.images =
MBridge.xpath(res, '//*[ contains(@class, "manga-list-1-list")]/li/a/img[@class="manga-list-1-cover"]/@src');
manga.urls = MBridge.xpath(res, '//*[ contains(@class, "manga-list-1-list")]/li/a/@href');
return manga;
}
getMangaDetail(MangaModel manga) async {
final statusList = [
{
"Ongoing": 0,
"Completed": 1,
}
];
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}/${manga.link}";
final data = {"url": url, "headers": headers};
final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) {
return manga;
}
manga.author = MBridge.xpath(res, '//*[@class="detail-info-right-say"]/a/text()').first;
manga.description = MBridge.xpath(res, '//*[@class="fullcontent"]/text()').first;
final status = MBridge.xpath(res, '//*[@class="detail-info-right-title-tip"]/text()').first;
manga.status = MBridge.parseStatus(status, statusList);
manga.genre = MBridge.xpath(res, '//*[@class="detail-info-right-tag-list"]/a/text()');
manga.urls = MBridge.xpath(res, '//*[@class="detail-main-list"]/li/a/@href');
manga.names = MBridge.xpath(res, '//*[@class="detail-main-list"]/li/a/div/p[@class="title3"]/text()');
final chapterDates = MBridge.xpath(res, '//*[@class="detail-main-list"]/li/a/div/p[@class="title2"]/text()');
manga.chaptersDateUploads = MBridge.listParseDateTime(chapterDates, manga.dateFormat, manga.dateFormatLocale);
return manga;
}
getPopularManga(MangaModel manga) async {
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}/directory/${manga.page}.htm";
final data = {"url": url, "headers": headers};
final res = await MBridge.http('POST', json.encode(data));
if (res.isEmpty) {
return manga;
}
manga.names = MBridge.xpath(res, '//*[ contains(@class, "manga-list-1-list")]/li/a/@title');
manga.images =
MBridge.xpath(res, '//*[ contains(@class, "manga-list-1-list")]/li/a/img[@class="manga-list-1-cover"]/@src');
manga.urls = MBridge.xpath(res, '//*[ contains(@class, "manga-list-1-list")]/li/a/@href');
return manga;
}
getChapterUrl(MangaModel manga) async {
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}${manga.link}";
final data = {"url": url, "headers": headers};
final res = await MBridge.http('GET', json.encode(data));
if (res.isEmpty) {
return [];
}
final pages = MBridge.xpath(res, "//body/div/div/span/a/text()");
List<String> pageUrls = [];
if (pages.isEmpty) {
final script =
MBridge.xpath(res, "//script[contains(text(),'function(p,a,c,k,e,d)')]/text()").first.replaceAll("eval", "");
String deobfuscatedScript = MBridge.evalJs(script);
int a = deobfuscatedScript.indexOf("newImgs=['") + 10;
int b = deobfuscatedScript.indexOf("'];");
List<String> urls = MBridge.listParse(deobfuscatedScript.substring(a, b).split("','"), 0);
for (var url in urls) {
pageUrls.add("https:$url");
}
} else {
final pagesNumberList = pages;
int pagesNumber = MBridge.intParse(pagesNumberList[pagesNumberList.length - 2]);
int secretKeyScriptLocation = res.indexOf("eval(function(p,a,c,k,e,d)");
int secretKeyScriptEndLocation = res.indexOf("</script>", secretKeyScriptLocation);
String secretKeyScript = res.substring(secretKeyScriptLocation, secretKeyScriptEndLocation).replaceAll("eval", "");
String secretKeyDeobfuscatedScript = MBridge.evalJs(secretKeyScript);
int secretKeyStartLoc = secretKeyDeobfuscatedScript.indexOf("'");
int secretKeyEndLoc = secretKeyDeobfuscatedScript.indexOf(";");
String secretKey = secretKeyDeobfuscatedScript.substring(secretKeyStartLoc, secretKeyEndLoc);
int chapterIdStartLoc = res.indexOf("chapterid");
String chapterId = res.substring(chapterIdStartLoc + 11, res.indexOf(";", chapterIdStartLoc));
String pageBase = url.substring(0, url.lastIndexOf("/"));
for (int i = 1; i <= pagesNumber; i++) {
String pageLink = "$pageBase/chapterfun.ashx?cid=$chapterId&page=$i&key=$secretKey";
String responseText = MBridge.stringParse("", 0);
for (int tr = 1; tr <= 3; tr++) {
if (responseText.isEmpty) {
final headers = {
"Referer": url,
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.9",
"Connection": "keep-alive",
"Host": "www.mangahere.cc",
"X-Requested-With": "XMLHttpRequest"
};
final data = {"url": pageLink, "headers": headers};
final response = await MBridge.http('GET', json.encode(data));
responseText = MBridge.stringParse(response, 0);
if (responseText.isEmpty) {
secretKey = "";
}
}
}
String deobfuscatedScript = MBridge.evalJs(responseText.replaceAll("eval", ""));
int baseLinkStartPos = deobfuscatedScript.indexOf("pix=") + 5;
int baseLinkEndPos = deobfuscatedScript.indexOf(";", baseLinkStartPos) - 1;
String baseLink = deobfuscatedScript.substring(baseLinkStartPos, baseLinkEndPos);
int imageLinkStartPos = deobfuscatedScript.indexOf("pvalue=") + 9;
int imageLinkEndPos = deobfuscatedScript.indexOf("\"", imageLinkStartPos);
String imageLink = deobfuscatedScript.substring(imageLinkStartPos, imageLinkEndPos);
pageUrls.add("https:$baseLink$imageLink");
}
}
return pageUrls;
}
Map<String, String> getHeader(String url) {
final headers = {'Referer': '$url/', "Cookie": "isAdult=1"};
return headers;
}

View File

@@ -0,0 +1,190 @@
import 'dart:convert';
import 'package:bridge_lib/bridge_lib.dart';
searchManga(MManga manga) async {
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}/search?title=${manga.query}&page=${manga.page}";
final data = {"url": url, "headers": headers};
final response = await MBridge.http('POST', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
manga.names = MBridge.xpath(
res, '//*[contains(@class, "manga-list-4-list")]/li/a/@title');
manga.images = MBridge.xpath(res,
'//*[contains(@class, "manga-list-4-list")]/li/a/img[@class="manga-list-4-cover"]/@src');
manga.urls = MBridge.xpath(
res, '//*[contains(@class, "manga-list-4-list")]/li/a/@href');
return manga;
}
getLatestUpdatesManga(MManga manga) async {
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}/directory/${manga.page}.htm?latest";
final data = {"url": url, "headers": headers};
final response = await MBridge.http('POST', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
manga.names = MBridge.xpath(
res, '//*[ contains(@class, "manga-list-1-list")]/li/a/@title');
manga.images = MBridge.xpath(res,
'//*[ contains(@class, "manga-list-1-list")]/li/a/img[@class="manga-list-1-cover"]/@src');
manga.urls = MBridge.xpath(
res, '//*[ contains(@class, "manga-list-1-list")]/li/a/@href');
return manga;
}
getMangaDetail(MManga manga) async {
final statusList = [
{
"Ongoing": 0,
"Completed": 1,
}
];
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}/${manga.link}";
final data = {"url": url, "headers": headers};
final response = await MBridge.http('GET', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
manga.author =
MBridge.xpath(res, '//*[@class="detail-info-right-say"]/a/text()').first;
manga.description =
MBridge.xpath(res, '//*[@class="fullcontent"]/text()').first;
final status =
MBridge.xpath(res, '//*[@class="detail-info-right-title-tip"]/text()')
.first;
manga.status = MBridge.parseStatus(status, statusList);
manga.genre =
MBridge.xpath(res, '//*[@class="detail-info-right-tag-list"]/a/text()');
manga.urls = MBridge.xpath(res, '//*[@class="detail-main-list"]/li/a/@href');
manga.names = MBridge.xpath(
res, '//*[@class="detail-main-list"]/li/a/div/p[@class="title3"]/text()');
final chapterDates = MBridge.xpath(
res, '//*[@class="detail-main-list"]/li/a/div/p[@class="title2"]/text()');
manga.chaptersDateUploads = MBridge.listParseDateTime(
chapterDates, manga.dateFormat, manga.dateFormatLocale);
return manga;
}
getPopularManga(MManga manga) async {
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}/directory/${manga.page}.htm";
final data = {"url": url, "headers": headers};
final response = await MBridge.http('POST', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
manga.names = MBridge.xpath(
res, '//*[ contains(@class, "manga-list-1-list")]/li/a/@title');
manga.images = MBridge.xpath(res,
'//*[ contains(@class, "manga-list-1-list")]/li/a/img[@class="manga-list-1-cover"]/@src');
manga.urls = MBridge.xpath(
res, '//*[ contains(@class, "manga-list-1-list")]/li/a/@href');
return manga;
}
getChapterPages(MManga manga) async {
final headers = getHeader(manga.baseUrl);
final url = "${manga.baseUrl}${manga.link}";
final data = {"url": url, "headers": headers};
final response = await MBridge.http('GET', json.encode(data));
if (response.hasError) {
return response;
}
String res = response.body;
final pages = MBridge.xpath(res, "//body/div/div/span/a/text()");
List<String> pageUrls = [];
if (pages.isEmpty) {
final script = MBridge.xpath(
res, "//script[contains(text(),'function(p,a,c,k,e,d)')]/text()")
.first
.replaceAll("eval", "");
String deobfuscatedScript = MBridge.evalJs(script);
int a = deobfuscatedScript.indexOf("newImgs=['") + 10;
int b = deobfuscatedScript.indexOf("'];");
List<String> urls = deobfuscatedScript.substring(a, b).split("','");
for (var url in urls) {
pageUrls.add("https:$url");
}
} else {
final pagesNumberList = pages;
int pagesNumber =
MBridge.intParse(pagesNumberList[pagesNumberList.length - 2]);
int secretKeyScriptLocation = res.indexOf("eval(function(p,a,c,k,e,d)");
int secretKeyScriptEndLocation =
res.indexOf("</script>", secretKeyScriptLocation);
String secretKeyScript = res
.substring(secretKeyScriptLocation, secretKeyScriptEndLocation)
.replaceAll("eval", "");
String secretKeyDeobfuscatedScript = MBridge.evalJs(secretKeyScript);
int secretKeyStartLoc = secretKeyDeobfuscatedScript.indexOf("'");
int secretKeyEndLoc = secretKeyDeobfuscatedScript.indexOf(";");
String secretKey = secretKeyDeobfuscatedScript.substring(
secretKeyStartLoc, secretKeyEndLoc);
int chapterIdStartLoc = res.indexOf("chapterid");
String chapterId = res.substring(
chapterIdStartLoc + 11, res.indexOf(";", chapterIdStartLoc));
String pageBase = url.substring(0, url.lastIndexOf("/"));
for (int i = 1; i <= pagesNumber; i++) {
String pageLink =
"$pageBase/chapterfun.ashx?cid=$chapterId&page=$i&key=$secretKey";
String responseText = "".toString();
for (int tr = 1; tr <= 3; tr++) {
if (responseText.isEmpty) {
final headers = {
"Referer": url,
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.9",
"Connection": "keep-alive",
"Host": "www.mangahere.cc",
"X-Requested-With": "XMLHttpRequest"
};
final data = {"url": pageLink, "headers": headers};
final ress = await MBridge.http('GET', json.encode(data));
if (ress.hasError) {
return response;
}
responseText = ress.body;
if (responseText.isEmpty) {
secretKey = "";
}
}
}
String deobfuscatedScript =
MBridge.evalJs(responseText.replaceAll("eval", ""));
int baseLinkStartPos = deobfuscatedScript.indexOf("pix=") + 5;
int baseLinkEndPos =
deobfuscatedScript.indexOf(";", baseLinkStartPos) - 1;
String baseLink =
deobfuscatedScript.substring(baseLinkStartPos, baseLinkEndPos);
int imageLinkStartPos = deobfuscatedScript.indexOf("pvalue=") + 9;
int imageLinkEndPos = deobfuscatedScript.indexOf("\"", imageLinkStartPos);
String imageLink =
deobfuscatedScript.substring(imageLinkStartPos, imageLinkEndPos);
pageUrls.add("https:$baseLink$imageLink");
}
}
return pageUrls;
}
Map<String, String> getHeader(String url) {
final headers = {'Referer': '$url/', "Cookie": "isAdult=1"};
return headers;
}

View File

@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
Source get mangahereSource => _mangahereSource; Source get mangahereSource => _mangahereSource;
const mangahereVersion = "0.0.2"; const mangahereVersion = "0.0.3";
const mangahereSourceCodeUrl = const mangahereSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/en/mangahere/mangahere-v$mangahereVersion.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/en/mangahere/mangahere-v$mangahereVersion.dart";
Source _mangahereSource = Source( Source _mangahereSource = Source(

View File

@@ -47,7 +47,7 @@ class Source {
this.version = "", this.version = "",
this.isManga = true, this.isManga = true,
this.isFullData = false, this.isFullData = false,
this.appMinVerReq = "0.0.46"}); this.appMinVerReq = "0.0.6"});
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {