diff --git a/README.md b/README.md
index 4b0efb75..1d0ed0b8 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ This repository contains the available extension catalogues for the Mangayomi ap
## How to add the extensions
-Click on one of the buttons below to add the corresponding repository/repositories:
+Click on one of the buttons below to add the corresponding repository/repositories (Manga & novels only):
diff --git a/dart/anime/anime_source_list.dart b/dart/anime/anime_source_list.dart
deleted file mode 100644
index 7ab0bc58..00000000
--- a/dart/anime/anime_source_list.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-import '../../model/source.dart';
-import 'multisrc/datalifeengine/sources.dart';
-import 'multisrc/dopeflix/sources.dart';
-import 'multisrc/zorotheme/sources.dart';
-import 'src/all/animeworldindia/sources.dart';
-import 'src/all/nyaa/source.dart';
-import 'src/ar/okanime/source.dart';
-import 'src/de/animetoast/source.dart';
-import 'src/en/animepahe/source.dart';
-import 'src/en/gogoanime/source.dart';
-import 'src/en/kisskh/source.dart';
-import 'src/en/nineanimetv/source.dart';
-import 'src/en/vumeto/source.dart';
-import 'src/es/animeonlineninja/source.dart';
-import 'src/fr/animesama/source.dart';
-import 'src/fr/anizone/source.dart';
-import 'src/hi/yomovies/source.dart';
-import 'src/en/uhdmovies/source.dart';
-import 'src/fr/animesultra/source.dart';
-import 'src/fr/franime/source.dart';
-import 'src/fr/otakufr/source.dart';
-import 'src/id/nimegami/source.dart';
-import 'src/id/oploverz/source.dart';
-import 'src/id/otakudesu/source.dart';
-import 'src/it/animesaturn/source.dart';
-import 'src/pt/animesvision/source.dart';
-import 'src/sq/filma24/source.dart';
-import 'src/tr/diziwatch/source.dart';
-import 'src/en/donghuastream/source.dart';
-
-List dartAnimesourceList = [
- gogoanimeSource,
- franimeSource,
- otakufr,
- animesultraSource,
- ...zorothemeSourcesList,
- okanimeSource,
- otakudesu,
- nimegami,
- oploverz,
- ...dopeflixSourcesList,
- animesaturn,
- uhdmoviesSource,
- ...datalifeengineSourcesList,
- filma24,
- yomoviesSource,
- animesamaSource,
- nineanimetv,
- ...animeworldindiaSourcesList,
- nyaaSource,
- animepaheSource,
- animetoast,
- animesvision,
- diziwatchSource,
- aniZoneSource,
- animeonlineninjaSource,
- kisskhSource,
- vumetoSource,
- donghuastreamSource,
-];
diff --git a/dart/anime/multisrc/datalifeengine/datalifeengine.dart b/dart/anime/multisrc/datalifeengine/datalifeengine.dart
deleted file mode 100644
index 0989ed20..00000000
--- a/dart/anime/multisrc/datalifeengine/datalifeengine.dart
+++ /dev/null
@@ -1,457 +0,0 @@
-import 'dart:convert';
-import 'package:mangayomi/bridge_lib.dart';
-
-class DataLifeEngine extends MProvider {
- DataLifeEngine({required this.source});
-
- MSource source;
-
- final Client client = Client();
-
- @override
- bool get supportsLatest => false;
-
- @override
- String get baseUrl => getPreferenceValue(source.id, "overrideBaseUrl");
-
- @override
- Future getPopular(int page) async {
- final res =
- (await client.get(
- Uri.parse("$baseUrl${getPath(source)}page/$page"),
- )).body;
- return animeFromElement(res);
- }
-
- @override
- Future getLatestUpdates(int page) async {
- return MPages([], false);
- }
-
- @override
- Future search(String query, int page, FilterList filterList) async {
- final filters = filterList.filters;
- String res = "";
- if (query.isNotEmpty) {
- if (query.length < 4)
- throw "La recherche est suspendue! La chaîne de recherche est vide ou contient moins de 4 caractères.";
- final headers = {
- "Host": Uri.parse(baseUrl).host,
- "Origin": baseUrl,
- "Referer": "$baseUrl/",
- };
- final cleanQuery = query.replaceAll(" ", "+");
- if (page == 1) {
- res =
- (await client.post(
- Uri.parse(
- "$baseUrl?do=search&subaction=search&story=$cleanQuery",
- ),
- headers: headers,
- )).body;
- } else {
- res =
- (await client.post(
- Uri.parse(
- "$baseUrl?do=search&subaction=search&search_start=$page&full_search=0&result_from=11&story=$cleanQuery",
- ),
- headers: headers,
- )).body;
- }
- } else {
- String url = "";
- for (var filter in filters) {
- if (filter.type == "CategoriesFilter") {
- if (filter.state != 0) {
- url = "$baseUrl${filter.values[filter.state].value}page/$page/";
- }
- } else if (filter.type == "GenresFilter") {
- if (filter.state != 0) {
- url = "$baseUrl${filter.values[filter.state].value}page/$page/";
- }
- }
- }
- res = (await client.get(Uri.parse(url))).body;
- }
-
- return animeFromElement(res);
- }
-
- @override
- Future getDetail(String url) async {
- String res =
- (await client.get(
- Uri.parse("$baseUrl${getUrlWithoutDomain(url)}"),
- )).body;
- MManga anime = MManga();
- final description = xpath(res, '//span[@itemprop="description"]/text()');
- anime.description = description.isNotEmpty ? description.first : "";
- anime.genre = xpath(res, '//span[@itemprop="genre"]/a/text()');
-
- List? episodesList = [];
-
- if (source.name == "French Anime") {
- final epsData = xpath(res, '//div[@class="eps"]/text()');
- for (var epData in epsData.first.split('\n')) {
- final data = epData.split('!');
- MChapter ep = MChapter();
- ep.name = "Episode ${data.first}";
- ep.url = data.last;
- episodesList.add(ep);
- }
- } else {
- final doc = parseHtml(res);
- final elements =
- doc
- .select(".hostsblock div:has(a)")
- .where(
- (MElement e) => e.outerHtml.contains("loadVideo('https://"),
- )
- .toList();
- if (elements.isNotEmpty) {
- for (var element in elements) {
- element = element as MElement;
- MChapter ep = MChapter();
- ep.name = element.className
- .replaceAll("ep", "Episode ")
- .replaceAll("vs", " VOSTFR")
- .replaceAll("vf", " VF");
- ep.url = element
- .select("a")
- .map(
- (MElement e) => substringBefore(
- substringAfter(e.attr('onclick'), "loadVideo('"),
- "')",
- ),
- )
- .toList()
- .join(",")
- .replaceAll("/vd.php?u=", "");
- ep.scanlator = element.className.contains('vf') ? 'VF' : 'VOSTFR';
- episodesList.add(ep);
- }
- } else {
- MChapter ep = MChapter();
- ep.name = "Film";
- ep.url = doc
- .select("a")
- .where((MElement e) => e.outerHtml.contains("loadVideo('https://"))
- .map(
- (MElement e) => substringBefore(
- substringAfter(e.attr('onclick'), "loadVideo('"),
- "')",
- ),
- )
- .toList()
- .join(",")
- .replaceAll("/vd.php?u=", "");
- episodesList.add(ep);
- }
- }
-
- anime.chapters = episodesList.reversed.toList();
- return anime;
- }
-
- @override
- Future> getVideoList(String url) async {
- List videos = [];
- final sUrls = url.split(',');
- for (var sUrl in sUrls) {
- List a = [];
- if (sUrl.contains("dood") || sUrl.contains("d000")) {
- a = await doodExtractor(sUrl, "DoodStream");
- } else if ([
- "streamhide",
- "guccihide",
- "streamvid",
- "dhtpre",
- ].any((a) => sUrl.contains(a))) {
- a = await streamHideExtractor(sUrl);
- } else if (sUrl.contains("uqload")) {
- a = await uqloadExtractor(sUrl);
- } else if (sUrl.contains("upstream")) {
- a = await upstreamExtractor(sUrl);
- } else if (sUrl.contains("sibnet")) {
- a = await sibnetExtractor(sUrl);
- } else if (sUrl.contains("ok.ru")) {
- a = await okruExtractor(sUrl);
- } else if (sUrl.contains("vidmoly")) {
- a = await vidmolyExtractor(sUrl);
- } else if (sUrl.contains("streamtape")) {
- a = await streamTapeExtractor(sUrl, "");
- } else if (sUrl.contains("voe.sx")) {
- a = await voeExtractor(sUrl, "");
- }
- videos.addAll(a);
- }
- return videos;
- }
-
- MPages animeFromElement(String res) {
- final htmls = parseHtml(res).select("div#dle-content > div.mov");
- List animeList = [];
- for (var h in htmls) {
- final html = h.innerHtml;
- final url = xpath(html, '//a/@href').first;
- final name = xpath(html, '//a/text()').first;
- final image = xpath(html, '//div[contains(@class,"mov")]/img/@src').first;
- final season = xpath(html, '//div/span[@class="block-sai"]/text()');
- MManga anime = MManga();
- anime.name =
- "$name ${season.isNotEmpty ? season.first.replaceAll("\n", " ") : ""}";
- anime.imageUrl = "$baseUrl$image";
- anime.link = url;
- animeList.add(anime);
- }
- final hasNextPage = xpath(res, '//span[@class="pnext"]/a/@href').isNotEmpty;
- return MPages(animeList, hasNextPage);
- }
-
- Future> streamHideExtractor(String url) async {
- final res = (await client.get(Uri.parse(url))).body;
- final masterUrl = substringBefore(
- substringAfter(
- substringAfter(substringAfter(unpackJs(res), "sources:"), "file:\""),
- "src:\"",
- ),
- '"',
- );
- final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
- List videos = [];
- for (var it in substringAfter(
- masterPlaylistRes,
- "#EXT-X-STREAM-INF:",
- ).split("#EXT-X-STREAM-INF:")) {
- final quality =
- "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
-
- String videoUrl = substringBefore(substringAfter(it, "\n"), "\n");
-
- if (!videoUrl.startsWith("http")) {
- videoUrl =
- "${masterUrl.split("/").sublist(0, masterUrl.split("/").length - 1).join("/")}/$videoUrl";
- }
-
- MVideo video = MVideo();
- video
- ..url = videoUrl
- ..originalUrl = videoUrl
- ..quality = "StreamHideVid - $quality";
- videos.add(video);
- }
- return videos;
- }
-
- Future> upstreamExtractor(String url) async {
- final res = (await client.get(Uri.parse(url))).body;
- final js = xpath(res, '//script[contains(text(), "m3u8")]/text()');
- if (js.isEmpty) {
- return [];
- }
- final masterUrl = substringBefore(
- substringAfter(unpackJs(js.first), "{file:\""),
- "\"}",
- );
- final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
- List videos = [];
- for (var it in substringAfter(
- masterPlaylistRes,
- "#EXT-X-STREAM-INF:",
- ).split("#EXT-X-STREAM-INF:")) {
- final quality =
- "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
-
- String videoUrl = substringBefore(substringAfter(it, "\n"), "\n");
-
- if (!videoUrl.startsWith("http")) {
- videoUrl =
- "${masterUrl.split("/").sublist(0, masterUrl.split("/").length - 1).join("/")}/$videoUrl";
- }
-
- MVideo video = MVideo();
- video
- ..url = videoUrl
- ..originalUrl = videoUrl
- ..quality = "Upstream - $quality";
- videos.add(video);
- }
- return videos;
- }
-
- Future> uqloadExtractor(String url) async {
- final res = (await client.get(Uri.parse(url))).body;
- final js = xpath(res, '//script[contains(text(), "sources:")]/text()');
- if (js.isEmpty) {
- return [];
- }
-
- final videoUrl = substringBefore(
- substringAfter(js.first, "sources: [\""),
- '"',
- );
- MVideo video = MVideo();
- video
- ..url = videoUrl
- ..originalUrl = videoUrl
- ..quality = "Uqload"
- ..headers = {"Referer": "${Uri.parse(url).origin}/"};
- return [video];
- }
-
- Future> vidmolyExtractor(String url) async {
- final headers = {'Referer': 'https://vidmoly.to'};
- List videos = [];
- final playListUrlResponse = (await client.get(Uri.parse(url))).body;
- final playlistUrl =
- RegExp(r'file:"(\S+?)"').firstMatch(playListUrlResponse)?.group(1) ??
- "";
- if (playlistUrl.isEmpty) return [];
- final masterPlaylistRes = await client.get(
- Uri.parse(playlistUrl),
- headers: headers,
- );
-
- if (masterPlaylistRes.statusCode == 200) {
- for (var it in substringAfter(
- masterPlaylistRes.body,
- "#EXT-X-STREAM-INF:",
- ).split("#EXT-X-STREAM-INF:")) {
- final quality =
- "${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
-
- String videoUrl = substringBefore(substringAfter(it, "\n"), "\n");
-
- MVideo video = MVideo();
- video
- ..url = videoUrl
- ..originalUrl = videoUrl
- ..quality = "Vidmoly $quality"
- ..headers = headers;
- videos.add(video);
- }
- }
-
- return videos;
- }
-
- String getPath() {
- if (source.name == "French Anime") return "/animes-vostfr/";
- return "/serie-en-streaming/";
- }
-
- @override
- List getSourcePreferences() {
- return [
- if (source.name == "Wiflix")
- EditTextPreference(
- key: "overrideBaseUrl",
- title: "Changer l'url de base",
- summary: "",
- value: "https://wiflix-hd.vip",
- dialogTitle: "Changer l'url de base",
- dialogMessage: "",
- text: "https://wiflix-hd.vip",
- ),
- if (source.name == "French Anime")
- EditTextPreference(
- key: "overrideBaseUrl",
- title: "Changer l'url de base",
- summary: "",
- value: "https://french-anime.com",
- dialogTitle: "Changer l'url de base",
- dialogMessage: "",
- text: "https://french-anime.com",
- ),
- ];
- }
-
- @override
- List getFilterList() {
- return [
- HeaderFilter("La recherche de texte ignore les filtres"),
- if (source.name == "French Anime")
- SelectFilter("CategoriesFilter", "Catégories", 0, [
- SelectFilterOption("", ""),
- SelectFilterOption("Action", "/genre/action/"),
- SelectFilterOption("Aventure", "/genre/aventure/"),
- SelectFilterOption("Arts martiaux", "/genre/arts-martiaux/"),
- SelectFilterOption("Combat", "/genre/combat/"),
- SelectFilterOption("Comédie", "/genre/comedie/"),
- SelectFilterOption("Drame", "/genre/drame/"),
- SelectFilterOption("Epouvante", "/genre/epouvante/"),
- SelectFilterOption("Fantastique", "/genre/fantastique/"),
- SelectFilterOption("Fantasy", "/genre/fantasy/"),
- SelectFilterOption("Mystère", "/genre/mystere/"),
- SelectFilterOption("Romance", "/genre/romance/"),
- SelectFilterOption("Shonen", "/genre/shonen/"),
- SelectFilterOption("Surnaturel", "/genre/surnaturel/"),
- SelectFilterOption("Sci-Fi", "/genre/sci-fi/"),
- SelectFilterOption("School life", "/genre/school-life/"),
- SelectFilterOption("Ninja", "/genre/ninja/"),
- SelectFilterOption("Seinen", "/genre/seinen/"),
- SelectFilterOption("Horreur", "/genre/horreur/"),
- SelectFilterOption("Tranche de vie", "/genre/tranchedevie/"),
- SelectFilterOption("Psychologique", "/genre/psychologique/"),
- ]),
- if (source.name == "French Anime")
- SelectFilter("GenresFilter", "Genres", 0, [
- SelectFilterOption("", ""),
- SelectFilterOption("Animes VF", "/animes-vf/"),
- SelectFilterOption("Animes VOSTFR", "/animes-vostfr/"),
- SelectFilterOption("Films VF et VOSTFR", "/films-vf-vostfr/"),
- ]),
- if (source.name == "Wiflix")
- SelectFilter("CategoriesFilter", "Catégories", 0, [
- SelectFilterOption("", ""),
- SelectFilterOption("Séries", "/serie-en-streaming/"),
- SelectFilterOption("Films", "/film-en-streaming/"),
- ]),
- if (source.name == "Wiflix")
- SelectFilter("GenresFilter", "Genres", 0, [
- SelectFilterOption("", ""),
- SelectFilterOption("Action", "/film-en-streaming/action/"),
- SelectFilterOption("Animation", "/film-en-streaming/animation/"),
- SelectFilterOption(
- "Arts Martiaux",
- "/film-en-streaming/arts-martiaux/",
- ),
- SelectFilterOption("Aventure", "/film-en-streaming/aventure/"),
- SelectFilterOption("Biopic", "/film-en-streaming/biopic/"),
- SelectFilterOption("Comédie", "/film-en-streaming/comedie/"),
- SelectFilterOption(
- "Comédie Dramatique",
- "/film-en-streaming/comedie-dramatique/",
- ),
- SelectFilterOption(
- "Épouvante Horreur",
- "/film-en-streaming/horreur/",
- ),
- SelectFilterOption("Drame", "/film-en-streaming/drame/"),
- SelectFilterOption(
- "Documentaire",
- "/film-en-streaming/documentaire/",
- ),
- SelectFilterOption("Espionnage", "/film-en-streaming/espionnage/"),
- SelectFilterOption("Famille", "/film-en-streaming/famille/"),
- SelectFilterOption("Fantastique", "/film-en-streaming/fantastique/"),
- SelectFilterOption("Guerre", "/film-en-streaming/guerre/"),
- SelectFilterOption("Historique", "/film-en-streaming/historique/"),
- SelectFilterOption("Musical", "/film-en-streaming/musical/"),
- SelectFilterOption("Policier", "/film-en-streaming/policier/"),
- SelectFilterOption("Romance", "/film-en-streaming/romance/"),
- SelectFilterOption(
- "Science-Fiction",
- "/film-en-streaming/science-fiction/",
- ),
- SelectFilterOption("Spectacles", "/film-en-streaming/spectacles/"),
- SelectFilterOption("Thriller", "/film-en-streaming/thriller/"),
- SelectFilterOption("Western", "/film-en-streaming/western/"),
- ]),
- ];
- }
-}
-
-DataLifeEngine main(MSource source) {
- return DataLifeEngine(source: source);
-}
diff --git a/dart/anime/multisrc/datalifeengine/sources.dart b/dart/anime/multisrc/datalifeengine/sources.dart
deleted file mode 100644
index 9d2403ed..00000000
--- a/dart/anime/multisrc/datalifeengine/sources.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-import '../../../../model/source.dart';
-import 'src/frenchanime/frenchanime.dart';
-import 'src/wiflix/wiflix.dart';
-
-const _datalifeengineVersion = "0.0.65";
-const _datalifeengineSourceCodeUrl =
- "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/multisrc/datalifeengine/datalifeengine.dart";
-
-List get datalifeengineSourcesList => _datalifeengineSourcesList;
-List _datalifeengineSourcesList =
- [
- //French Anime (FR)
- frenchanimeSource,
- //Wiflix (FR)
- wiflixSource,
- ]
- .map(
- (e) =>
- e
- ..sourceCodeUrl = _datalifeengineSourceCodeUrl
- ..version = _datalifeengineVersion,
- )
- .toList();
diff --git a/dart/anime/multisrc/datalifeengine/src/frenchanime/frenchanime.dart b/dart/anime/multisrc/datalifeengine/src/frenchanime/frenchanime.dart
deleted file mode 100644
index 719dcece..00000000
--- a/dart/anime/multisrc/datalifeengine/src/frenchanime/frenchanime.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-import '../../../../../../model/source.dart';
-
-Source get frenchanimeSource => _frenchanimeSource;
-
-Source _frenchanimeSource = Source(
- name: "French Anime",
- baseUrl: "https://french-anime.com",
- lang: "fr",
- typeSource: "datalifeengine",
- itemType: ItemType.anime,
- iconUrl:
- "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/multisrc/datalifeengine/src/frenchanime/icon.png",
-);
diff --git a/dart/anime/multisrc/datalifeengine/src/frenchanime/icon.png b/dart/anime/multisrc/datalifeengine/src/frenchanime/icon.png
deleted file mode 100644
index 62591a8e..00000000
Binary files a/dart/anime/multisrc/datalifeengine/src/frenchanime/icon.png and /dev/null differ
diff --git a/dart/anime/multisrc/datalifeengine/src/wiflix/icon.png b/dart/anime/multisrc/datalifeengine/src/wiflix/icon.png
deleted file mode 100644
index 3317e744..00000000
Binary files a/dart/anime/multisrc/datalifeengine/src/wiflix/icon.png and /dev/null differ
diff --git a/dart/anime/multisrc/datalifeengine/src/wiflix/wiflix.dart b/dart/anime/multisrc/datalifeengine/src/wiflix/wiflix.dart
deleted file mode 100644
index c4682ee4..00000000
--- a/dart/anime/multisrc/datalifeengine/src/wiflix/wiflix.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-import '../../../../../../model/source.dart';
-
-Source get wiflixSource => _wiflixSource;
-
-Source _wiflixSource = Source(
- name: "Wiflix",
- baseUrl: "https://wiflix-hd.vip",
- lang: "fr",
- typeSource: "datalifeengine",
- itemType: ItemType.anime,
- iconUrl:
- "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/multisrc/datalifeengine/src/wiflix/icon.png",
-);
diff --git a/dart/anime/multisrc/dopeflix/dopeflix.dart b/dart/anime/multisrc/dopeflix/dopeflix.dart
deleted file mode 100644
index 112259d8..00000000
--- a/dart/anime/multisrc/dopeflix/dopeflix.dart
+++ /dev/null
@@ -1,577 +0,0 @@
-import 'package:mangayomi/bridge_lib.dart';
-import 'dart:convert';
-
-class DopeFlix extends MProvider {
- DopeFlix({required this.source});
-
- MSource source;
-
- final Client client = Client();
-
- @override
- String get baseUrl => getPreferenceValue(source.id, "preferred_domain");
-
- @override
- Future getPopular(int page) async {
- final res =
- (await client.get(
- Uri.parse(
- "$baseUrl/${getPreferenceValue(source.id, "preferred_popular_page")}?page=$page",
- ),
- )).body;
- return parseAnimeList(res);
- }
-
- @override
- Future getLatestUpdates(int page) async {
- final res = (await client.get(Uri.parse("$baseUrl/home"))).body;
- List animeList = [];
- final path =
- '//section[contains(text(),"${getPreferenceValue(source.id, "preferred_latest_page")}")]/div/div[@class="film_list-wrap"]/div[@class="flw-item"]/div[@class="film-poster"]';
- final urls = xpath(res, '$path/a/@href');
- final names = xpath(res, '$path/a/@title');
- final images = xpath(res, '$path/img/@data-src');
-
- for (var i = 0; i < names.length; i++) {
- MManga anime = MManga();
- anime.name = names[i];
- anime.imageUrl = images[i];
- anime.link = urls[i];
- animeList.add(anime);
- }
- return MPages(animeList, false);
- }
-
- @override
- Future search(String query, int page, FilterList filterList) async {
- final filters = filterList.filters;
- String url = "$baseUrl";
-
- if (query.isNotEmpty) {
- url += "/search/${query.replaceAll(" ", "-")}?page=$page";
- } else {
- url += "/filter/?page=$page";
- for (var filter in filters) {
- if (filter.type == "TypeFilter") {
- final type = filter.values[filter.state].value;
- url += "${ll(url)}type=$type";
- } else if (filter.type == "QualityFilter") {
- final quality = filter.values[filter.state].value;
- url += "${ll(url)}quality=$quality";
- } else if (filter.type == "ReleaseYearFilter") {
- final year = filter.values[filter.state].value;
- url += "${ll(url)}release_year=$year";
- } else if (filter.type == "GenresFilter") {
- final genre = (filter.state as List).where((e) => e.state).toList();
- if (genre.isNotEmpty) {
- url += "${ll(url)}genre=";
- for (var st in genre) {
- url += "${st.value}-";
- }
- }
- } else if (filter.type == "CountriesFilter") {
- final country = (filter.state as List).where((e) => e.state).toList();
- if (country.isNotEmpty) {
- url += "${ll(url)}country=";
- for (var st in country) {
- url += "${st.value}-";
- }
- }
- }
- }
- }
-
- final res = (await client.get(Uri.parse(url))).body;
- return parseAnimeList(res);
- }
-
- @override
- Future getDetail(String url) async {
- url = getUrlWithoutDomain(url);
- final res = (await client.get(Uri.parse("$baseUrl$url"))).body;
- MManga anime = MManga();
- final description = xpath(res, '//div[@class="description"]/text()');
- if (description.isNotEmpty) {
- anime.description = description.first.replaceAll("Overview:", "");
- }
- final author = xpath(res, '//div[contains(text(),"Production")]/a/text()');
- if (author.isNotEmpty) {
- anime.author = author.first;
- }
- anime.genre = xpath(res, '//div[contains(text(),"Genre")]/a/text()');
- List episodesList = [];
- final id = xpath(res, '//div[@class="detail_page-watch"]/@data-id').first;
- final dataType =
- xpath(res, '//div[@class="detail_page-watch"]/@data-type').first;
- if (dataType == "1") {
- MChapter episode = MChapter();
- episode.name = "Movie";
- episode.url = "$baseUrl/ajax/movie/episodes/$id";
- episodesList.add(episode);
- } else {
- final resS =
- (await client.get(Uri.parse("$baseUrl/ajax/v2/tv/seasons/$id"))).body;
-
- final seasonIds = xpath(
- resS,
- '//a[@class="dropdown-item ss-item"]/@data-id',
- );
- final seasonNames = xpath(
- resS,
- '//a[@class="dropdown-item ss-item"]/text()',
- );
- for (int i = 0; i < seasonIds.length; i++) {
- final seasonId = seasonIds[i];
- final seasonName = seasonNames[i];
-
- final html =
- (await client.get(
- Uri.parse("$baseUrl/ajax/v2/season/episodes/$seasonId"),
- )).body;
-
- final epsHtmls = parseHtml(html).select("div.eps-item");
-
- for (var epH in epsHtmls) {
- final epHtml = epH.outerHtml;
- final episodeId =
- xpath(
- epHtml,
- '//div[contains(@class,"eps-item")]/@data-id',
- ).first;
- final epNum =
- xpath(epHtml, '//div[@class="episode-number"]/text()').first;
- final epName = xpath(epHtml, '//h3[@class="film-name"]/text()').first;
- MChapter episode = MChapter();
- episode.name = "$seasonName $epNum $epName";
- episode.url = "$baseUrl/ajax/v2/episode/servers/$episodeId";
- episodesList.add(episode);
- }
- }
- }
- anime.chapters = episodesList.reversed.toList();
- return anime;
- }
-
- @override
- Future> getVideoList(String url) async {
- url = getUrlWithoutDomain(url);
- final res = (await client.get(Uri.parse("$baseUrl/$url"))).body;
-
- final vidsHtmls = parseHtml(res).select("ul.fss-list a.btn-play");
-
- List videos = [];
- for (var vidH in vidsHtmls) {
- final vidHtml = vidH.outerHtml;
- final id = xpath(vidHtml, '//a/@data-id').first;
- final name = xpath(vidHtml, '//span/text()').first;
- final resSource =
- (await client.get(Uri.parse("$baseUrl/ajax/sources/$id"))).body;
-
- final vidUrl = substringBefore(
- substringAfter(resSource, "\"link\":\""),
- "\"",
- );
- List a = [];
- String masterUrl = "";
- String type = "";
- if (name.contains("DoodStream")) {
- a = await doodExtractor(vidUrl, "DoodStream");
- } else if (["Vidcloud", "UpCloud"].contains(name)) {
- final id = substringBefore(substringAfter(vidUrl, "/embed-4/"), "?");
- final serverUrl = substringBefore(vidUrl, "/embed");
-
- final resServer =
- (await client.get(
- Uri.parse("$serverUrl/ajax/embed-4/getSources?id=$id"),
- headers: {"X-Requested-With": "XMLHttpRequest"},
- )).body;
- final encrypted = getMapValue(resServer, "encrypted");
-
- String videoResJson = "";
- if (encrypted == "true") {
- final ciphered = getMapValue(resServer, "sources");
-
- List> indexPairs = await generateIndexPairs();
-
- var password = '';
- String ciphertext = ciphered;
- int index = 0;
- for (List item in json.decode(json.encode(indexPairs))) {
- int start = item.first + index;
- int end = start + item.last;
- String passSubstr = ciphered.substring(start, end);
- password += passSubstr;
- ciphertext = ciphertext.replaceFirst(passSubstr, "");
- index += item.last;
- }
- videoResJson = decryptAESCryptoJS(ciphertext, password);
- masterUrl =
- ((json.decode(videoResJson) as List