mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 10:51:17 +00:00
Merge pull request #6 from kodjodevf/add-source-preference
Add source preference
This commit is contained in:
@@ -6,18 +6,21 @@ class DopeFlix extends MProvider {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> getPopular(MSource source, int page) async {
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
final data = {"url": "${source.baseUrl}/movie?page=$page"};
|
final data = {
|
||||||
|
"url":
|
||||||
|
"${preferenceBaseUrl(source.id)}/${getPreferenceValue(source.id, "preferred_popular_page")}?page=$page"
|
||||||
|
};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
return parseAnimeList(res);
|
return parseAnimeList(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
||||||
final data = {"url": "${source.baseUrl}/home"};
|
final data = {"url": "${preferenceBaseUrl(source.id)}/home"};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
List<MManga> animeList = [];
|
List<MManga> animeList = [];
|
||||||
final path =
|
final path =
|
||||||
'//section[contains(text(),"Latest Movies")]/div/div[@class="film_list-wrap"]/div[@class="flw-item"]/div[@class="film-poster"]';
|
'//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 urls = xpath(res, '$path/a/@href');
|
||||||
final names = xpath(res, '$path/a/@title');
|
final names = xpath(res, '$path/a/@title');
|
||||||
final images = xpath(res, '$path/img/@data-src');
|
final images = xpath(res, '$path/img/@data-src');
|
||||||
@@ -36,7 +39,7 @@ class DopeFlix extends MProvider {
|
|||||||
Future<MPages> search(
|
Future<MPages> search(
|
||||||
MSource source, String query, int page, FilterList filterList) async {
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
final filters = filterList.filters;
|
final filters = filterList.filters;
|
||||||
String url = "${source.baseUrl}";
|
String url = "${preferenceBaseUrl(source.id)}";
|
||||||
|
|
||||||
if (query.isNotEmpty) {
|
if (query.isNotEmpty) {
|
||||||
url += "/search/${query.replaceAll(" ", "-")}?page=$page";
|
url += "/search/${query.replaceAll(" ", "-")}?page=$page";
|
||||||
@@ -79,7 +82,7 @@ class DopeFlix extends MProvider {
|
|||||||
@override
|
@override
|
||||||
Future<MManga> getDetail(MSource source, String url) async {
|
Future<MManga> getDetail(MSource source, String url) async {
|
||||||
url = Uri.parse(url).path;
|
url = Uri.parse(url).path;
|
||||||
final data = {"url": "${source.baseUrl}$url"};
|
final data = {"url": "${preferenceBaseUrl(source.id)}$url"};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
MManga anime = MManga();
|
MManga anime = MManga();
|
||||||
final description = xpath(res, '//div[@class="description"]/text()');
|
final description = xpath(res, '//div[@class="description"]/text()');
|
||||||
@@ -98,10 +101,12 @@ class DopeFlix extends MProvider {
|
|||||||
if (dataType == "1") {
|
if (dataType == "1") {
|
||||||
MChapter episode = MChapter();
|
MChapter episode = MChapter();
|
||||||
episode.name = "Movie";
|
episode.name = "Movie";
|
||||||
episode.url = "${source.baseUrl}/ajax/movie/episodes/$id";
|
episode.url = "${preferenceBaseUrl(source.id)}/ajax/movie/episodes/$id";
|
||||||
episodesList.add(episode);
|
episodesList.add(episode);
|
||||||
} else {
|
} else {
|
||||||
final dataS = {"url": "${source.baseUrl}/ajax/v2/tv/seasons/$id"};
|
final dataS = {
|
||||||
|
"url": "${preferenceBaseUrl(source.id)}/ajax/v2/tv/seasons/$id"
|
||||||
|
};
|
||||||
final resS = await http('GET', json.encode(dataS));
|
final resS = await http('GET', json.encode(dataS));
|
||||||
|
|
||||||
final seasonIds =
|
final seasonIds =
|
||||||
@@ -112,7 +117,8 @@ class DopeFlix extends MProvider {
|
|||||||
final seasonId = seasonIds[i];
|
final seasonId = seasonIds[i];
|
||||||
final seasonName = seasonNames[i];
|
final seasonName = seasonNames[i];
|
||||||
final dataE = {
|
final dataE = {
|
||||||
"url": "${source.baseUrl}/ajax/v2/season/episodes/$seasonId"
|
"url":
|
||||||
|
"${preferenceBaseUrl(source.id)}/ajax/v2/season/episodes/$seasonId"
|
||||||
};
|
};
|
||||||
final html = await http('GET', json.encode(dataE));
|
final html = await http('GET', json.encode(dataE));
|
||||||
final epsHtml = querySelectorAll(html,
|
final epsHtml = querySelectorAll(html,
|
||||||
@@ -120,7 +126,8 @@ class DopeFlix extends MProvider {
|
|||||||
typeElement: 2,
|
typeElement: 2,
|
||||||
attributes: "",
|
attributes: "",
|
||||||
typeRegExp: 0);
|
typeRegExp: 0);
|
||||||
print("${source.baseUrl}/ajax/v2/season/episodes/$seasonId");
|
print(
|
||||||
|
"${preferenceBaseUrl(source.id)}/ajax/v2/season/episodes/$seasonId");
|
||||||
for (var epHtml in epsHtml) {
|
for (var epHtml in epsHtml) {
|
||||||
final episodeId =
|
final episodeId =
|
||||||
xpath(epHtml, '//div[contains(@class,"eps-item")]/@data-id')
|
xpath(epHtml, '//div[contains(@class,"eps-item")]/@data-id')
|
||||||
@@ -130,7 +137,8 @@ class DopeFlix extends MProvider {
|
|||||||
final epName = xpath(epHtml, '//h3[@class="film-name"]/text()').first;
|
final epName = xpath(epHtml, '//h3[@class="film-name"]/text()').first;
|
||||||
MChapter episode = MChapter();
|
MChapter episode = MChapter();
|
||||||
episode.name = "$seasonName $epNum $epName";
|
episode.name = "$seasonName $epNum $epName";
|
||||||
episode.url = "${source.baseUrl}/ajax/v2/episode/servers/$episodeId";
|
episode.url =
|
||||||
|
"${preferenceBaseUrl(source.id)}/ajax/v2/episode/servers/$episodeId";
|
||||||
episodesList.add(episode);
|
episodesList.add(episode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,8 +150,8 @@ class DopeFlix extends MProvider {
|
|||||||
@override
|
@override
|
||||||
Future<List<MVideo>> getVideoList(MSource source, String url) async {
|
Future<List<MVideo>> getVideoList(MSource source, String url) async {
|
||||||
url = Uri.parse(url).path;
|
url = Uri.parse(url).path;
|
||||||
final res =
|
final res = await http(
|
||||||
await http('GET', json.encode({"url": "${source.baseUrl}/$url"}));
|
'GET', json.encode({"url": "${preferenceBaseUrl(source.id)}/$url"}));
|
||||||
final vidsHtml = querySelectorAll(res,
|
final vidsHtml = querySelectorAll(res,
|
||||||
selector: "ul.fss-list a.btn-play",
|
selector: "ul.fss-list a.btn-play",
|
||||||
typeElement: 2,
|
typeElement: 2,
|
||||||
@@ -154,7 +162,9 @@ class DopeFlix extends MProvider {
|
|||||||
final id = xpath(vidHtml, '//a/@data-id').first;
|
final id = xpath(vidHtml, '//a/@data-id').first;
|
||||||
final name = xpath(vidHtml, '//span/text()').first;
|
final name = xpath(vidHtml, '//span/text()').first;
|
||||||
final resSource = await http(
|
final resSource = await http(
|
||||||
'GET', json.encode({"url": "${source.baseUrl}/ajax/sources/$id"}));
|
'GET',
|
||||||
|
json.encode(
|
||||||
|
{"url": "${preferenceBaseUrl(source.id)}/ajax/sources/$id"}));
|
||||||
final vidUrl =
|
final vidUrl =
|
||||||
substringBefore(substringAfter(resSource, "\"link\":\""), "\"");
|
substringBefore(substringAfter(resSource, "\"link\":\""), "\"");
|
||||||
List<MVideo> a = [];
|
List<MVideo> a = [];
|
||||||
@@ -212,6 +222,7 @@ class DopeFlix extends MProvider {
|
|||||||
subtitles.add(subtitle);
|
subtitles.add(subtitle);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
subtitles = sortSubs(subtitles, source.id);
|
||||||
if (type == "hls") {
|
if (type == "hls") {
|
||||||
final masterPlaylistRes =
|
final masterPlaylistRes =
|
||||||
await http('GET', json.encode({"url": masterUrl}));
|
await http('GET', json.encode({"url": masterUrl}));
|
||||||
@@ -248,7 +259,7 @@ class DopeFlix extends MProvider {
|
|||||||
videos.addAll(a);
|
videos.addAll(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
return videos;
|
return sortVideos(videos, source.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<List<int>>> generateIndexPairs() async {
|
Future<List<List<int>>> generateIndexPairs() async {
|
||||||
@@ -261,8 +272,8 @@ class DopeFlix extends MProvider {
|
|||||||
script = script.substring(0, script.lastIndexOf(','));
|
script = script.substring(0, script.lastIndexOf(','));
|
||||||
final list = script
|
final list = script
|
||||||
.split(",")
|
.split(",")
|
||||||
.map((e) {
|
.map((String e) {
|
||||||
String value = substringAfter((e as String), "=");
|
String value = substringAfter(e, "=");
|
||||||
if (value.contains("0x")) {
|
if (value.contains("0x")) {
|
||||||
return int.parse(substringAfter(value, "0x"), radix: 16);
|
return int.parse(substringAfter(value, "0x"), radix: 16);
|
||||||
} else {
|
} else {
|
||||||
@@ -273,7 +284,7 @@ class DopeFlix extends MProvider {
|
|||||||
.skip(1)
|
.skip(1)
|
||||||
.toList();
|
.toList();
|
||||||
return chunked(list, 2)
|
return chunked(list, 2)
|
||||||
.map((list) => (list as List<int>).reversed.toList())
|
.map((List<int> list) => list.reversed.toList())
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +321,7 @@ class DopeFlix extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
SelectFilter("TypeFilter", "Type", 0, [
|
SelectFilter("TypeFilter", "Type", 0, [
|
||||||
SelectFilterOption("All", "all"),
|
SelectFilterOption("All", "all"),
|
||||||
@@ -405,6 +416,128 @@ class DopeFlix extends MProvider {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
|
return [
|
||||||
|
if (source.name == "DopeBox")
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_domain",
|
||||||
|
title: "Preferred domain",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["dopebox.to", "dopebox.se"],
|
||||||
|
entryValues: ["https://dopebox.to", "https://dopebox.se"]),
|
||||||
|
if (source.name == "SFlix")
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_domain",
|
||||||
|
title: "Preferred domain",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["sflix.to", "sflix.se"],
|
||||||
|
entryValues: ["https://sflix.to", "https://sflix.se"]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_quality",
|
||||||
|
title: "Preferred Quality",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["1080p", "720p", "480p", "360p"],
|
||||||
|
entryValues: ["1080p", "720p", "480p", "360p"]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_subLang",
|
||||||
|
title: "Preferred sub language",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 1,
|
||||||
|
entries: [
|
||||||
|
"Arabic",
|
||||||
|
"English",
|
||||||
|
"French",
|
||||||
|
"German",
|
||||||
|
"Hungarian",
|
||||||
|
"Italian",
|
||||||
|
"Japanese",
|
||||||
|
"Portuguese",
|
||||||
|
"Romanian",
|
||||||
|
"Russian",
|
||||||
|
"Spanish"
|
||||||
|
],
|
||||||
|
entryValues: [
|
||||||
|
"Arabic",
|
||||||
|
"English",
|
||||||
|
"French",
|
||||||
|
"German",
|
||||||
|
"Hungarian",
|
||||||
|
"Italian",
|
||||||
|
"Japanese",
|
||||||
|
"Portuguese",
|
||||||
|
"Romanian",
|
||||||
|
"Russian",
|
||||||
|
"Spanish"
|
||||||
|
]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_latest_page",
|
||||||
|
title: "Preferred latest page",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["Movies", "TV Shows"],
|
||||||
|
entryValues: ["Latest Movies", "Latest TV Shows"]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_popular_page",
|
||||||
|
title: "Preferred popular page",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["Movies", "TV Shows"],
|
||||||
|
entryValues: ["movie", "tv-show"]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MVideo> sortVideos(List<MVideo> videos, int sourceId) {
|
||||||
|
String quality = getPreferenceValue(sourceId, "preferred_quality");
|
||||||
|
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int qualityMatchA = 0;
|
||||||
|
if (a.quality.contains(quality)) {
|
||||||
|
qualityMatchA = 1;
|
||||||
|
}
|
||||||
|
int qualityMatchB = 0;
|
||||||
|
if (b.quality.contains(quality)) {
|
||||||
|
qualityMatchB = 1;
|
||||||
|
}
|
||||||
|
if (qualityMatchA != qualityMatchB) {
|
||||||
|
return qualityMatchB - qualityMatchA;
|
||||||
|
}
|
||||||
|
|
||||||
|
final regex = RegExp(r'(\d+)p');
|
||||||
|
final matchA = regex.firstMatch(a.quality);
|
||||||
|
final matchB = regex.firstMatch(b.quality);
|
||||||
|
final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0;
|
||||||
|
final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0;
|
||||||
|
return qualityNumB - qualityNumA;
|
||||||
|
});
|
||||||
|
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MTrack> sortSubs(List<MTrack> subs, int sourceId) {
|
||||||
|
String lang = getPreferenceValue(sourceId, "preferred_subLang");
|
||||||
|
|
||||||
|
subs.sort((MTrack a, MTrack b) {
|
||||||
|
int langMatchA = 0;
|
||||||
|
if (a.label.toLowerCase().contains(lang.toLowerCase())) {
|
||||||
|
langMatchA = 1;
|
||||||
|
}
|
||||||
|
int langMatchB = 0;
|
||||||
|
if (b.label.toLowerCase().contains(lang.toLowerCase())) {
|
||||||
|
langMatchB = 1;
|
||||||
|
}
|
||||||
|
return langMatchB - langMatchA;
|
||||||
|
});
|
||||||
|
return subs;
|
||||||
|
}
|
||||||
|
|
||||||
|
String preferenceBaseUrl(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "preferred_domain");
|
||||||
|
}
|
||||||
|
|
||||||
String ll(String url) {
|
String ll(String url) {
|
||||||
if (url.contains("?")) {
|
if (url.contains("?")) {
|
||||||
return "&";
|
return "&";
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import '../../../model/source.dart';
|
import '../../../model/source.dart';
|
||||||
import '../../../utils/utils.dart';
|
import '../../../utils/utils.dart';
|
||||||
|
|
||||||
const dopeflixVersion = "0.0.15";
|
const dopeflixVersion = "0.0.2";
|
||||||
const dopeflixSourceCodeUrl =
|
const dopeflixSourceCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/multisrc/dopeflix/dopeflix-v$dopeflixVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/multisrc/dopeflix/dopeflix-v$dopeflixVersion.dart";
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import '../../../model/source.dart';
|
import '../../../model/source.dart';
|
||||||
import '../../../utils/utils.dart';
|
import '../../../utils/utils.dart';
|
||||||
|
|
||||||
const zorothemeVersion = "0.0.5";
|
const zorothemeVersion = "0.0.55";
|
||||||
const zorothemeSourceCodeUrl =
|
const zorothemeSourceCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/multisrc/zorotheme/zorotheme-v$zorothemeVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/multisrc/zorotheme/zorotheme-v$zorothemeVersion.dart";
|
||||||
|
|
||||||
|
|||||||
@@ -223,7 +223,8 @@ class ZoroTheme extends MProvider {
|
|||||||
typeRegExp: 0);
|
typeRegExp: 0);
|
||||||
|
|
||||||
List<MVideo> videos = [];
|
List<MVideo> videos = [];
|
||||||
|
final hosterSelection = preferenceHosterSelection(source.id);
|
||||||
|
final typeSelection = preferenceTypeSelection(source.id);
|
||||||
for (var i = 0; i < names.length; i++) {
|
for (var i = 0; i < names.length; i++) {
|
||||||
final name = names[i];
|
final name = names[i];
|
||||||
final id = ids[i];
|
final id = ids[i];
|
||||||
@@ -236,19 +237,22 @@ class ZoroTheme extends MProvider {
|
|||||||
|
|
||||||
final resE = await http('GET', json.encode(datasE));
|
final resE = await http('GET', json.encode(datasE));
|
||||||
String epUrl = substringBefore(substringAfter(resE, "\"link\":\""), "\"");
|
String epUrl = substringBefore(substringAfter(resE, "\"link\":\""), "\"");
|
||||||
print(epUrl);
|
|
||||||
List<MVideo> a = [];
|
List<MVideo> a = [];
|
||||||
if (name.contains("Vidstreaming")) {
|
|
||||||
a = await rapidCloudExtractor(epUrl, "Vidstreaming - $subDub");
|
if (hosterSelection.contains(name) && typeSelection.contains(subDub)) {
|
||||||
} else if (name.contains("Vidcloud")) {
|
if (name.contains("Vidstreaming")) {
|
||||||
a = await rapidCloudExtractor(epUrl, "Vidcloud - $subDub");
|
a = await rapidCloudExtractor(epUrl, "Vidstreaming - $subDub");
|
||||||
} else if (name.contains("StreamTape")) {
|
} else if (name.contains("Vidcloud")) {
|
||||||
a = await streamTapeExtractor(epUrl, "StreamTape - $subDub");
|
a = await rapidCloudExtractor(epUrl, "Vidcloud - $subDub");
|
||||||
|
} else if (name.contains("StreamTape")) {
|
||||||
|
a = await streamTapeExtractor(epUrl, "StreamTape - $subDub");
|
||||||
|
}
|
||||||
|
videos.addAll(a);
|
||||||
}
|
}
|
||||||
videos.addAll(a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return videos;
|
return sortVideos(videos, source.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
MPages animeElementM(String res) {
|
MPages animeElementM(String res) {
|
||||||
@@ -288,7 +292,7 @@ class ZoroTheme extends MProvider {
|
|||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
SelectFilter("TypeFilter", "Type", 0, [
|
SelectFilter("TypeFilter", "Type", 0, [
|
||||||
SelectFilterOption("All", ""),
|
SelectFilterOption("All", ""),
|
||||||
@@ -421,6 +425,98 @@ class ZoroTheme extends MProvider {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
|
return [
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_quality",
|
||||||
|
title: "Preferred Quality",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 1,
|
||||||
|
entries: ["1080p", "720p", "480p", "360p"],
|
||||||
|
entryValues: ["1080", "720", "480", "360"]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_server",
|
||||||
|
title: "Preferred server",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["Vidstreaming", "VidCloud", "StreamTape"],
|
||||||
|
entryValues: ["Vidstreaming", "VidCloud", "StreamTape"]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_type",
|
||||||
|
title: "Preferred Type",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["Sub", "Dub"],
|
||||||
|
entryValues: ["sub", "dub"]),
|
||||||
|
MultiSelectListPreference(
|
||||||
|
key: "hoster_selection",
|
||||||
|
title: "Enable/Disable Hosts",
|
||||||
|
summary: "",
|
||||||
|
entries: ["Vidstreaming", "VidCloud", "StreamTape"],
|
||||||
|
entryValues: ["Vidstreaming", "Vidcloud", "StreamTape"],
|
||||||
|
values: ["Vidstreaming", "Vidcloud", "StreamTape"]),
|
||||||
|
MultiSelectListPreference(
|
||||||
|
key: "type_selection",
|
||||||
|
title: "Enable/Disable Types",
|
||||||
|
summary: "",
|
||||||
|
entries: ["Sub", "Dub"],
|
||||||
|
entryValues: ["sub", "dub"],
|
||||||
|
values: ["sub", "dub"]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MVideo> sortVideos(List<MVideo> videos, int sourceId) {
|
||||||
|
String quality = getPreferenceValue(sourceId, "preferred_quality");
|
||||||
|
String server = getPreferenceValue(sourceId, "preferred_server");
|
||||||
|
String type = getPreferenceValue(sourceId, "preferred_type");
|
||||||
|
videos = videos
|
||||||
|
.where(
|
||||||
|
(MVideo e) => e.quality.toLowerCase().contains(type.toLowerCase()))
|
||||||
|
.toList();
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int qualityMatchA = 0;
|
||||||
|
if (a.quality.contains(quality)) {
|
||||||
|
qualityMatchA = 1;
|
||||||
|
}
|
||||||
|
int qualityMatchB = 0;
|
||||||
|
if (b.quality.contains(quality)) {
|
||||||
|
qualityMatchB = 1;
|
||||||
|
}
|
||||||
|
if (qualityMatchA != qualityMatchB) {
|
||||||
|
return qualityMatchB - qualityMatchA;
|
||||||
|
}
|
||||||
|
|
||||||
|
final regex = RegExp(r'(\d+)p');
|
||||||
|
final matchA = regex.firstMatch(a.quality);
|
||||||
|
final matchB = regex.firstMatch(b.quality);
|
||||||
|
final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0;
|
||||||
|
final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0;
|
||||||
|
return qualityNumB - qualityNumA;
|
||||||
|
});
|
||||||
|
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int serverMatchA = 0;
|
||||||
|
if (a.quality.toLowerCase().contains(server.toLowerCase())) {
|
||||||
|
serverMatchA = 1;
|
||||||
|
}
|
||||||
|
int serverMatchB = 0;
|
||||||
|
if (b.quality.toLowerCase().contains(server.toLowerCase())) {
|
||||||
|
serverMatchB = 1;
|
||||||
|
}
|
||||||
|
return serverMatchB - serverMatchA;
|
||||||
|
});
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> preferenceHosterSelection(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "hoster_selection");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> preferenceTypeSelection(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "type_selection");
|
||||||
|
}
|
||||||
|
|
||||||
String ll(String url) {
|
String ll(String url) {
|
||||||
if (url.contains("?")) {
|
if (url.contains("?")) {
|
||||||
return "&";
|
return "&";
|
||||||
@@ -14,6 +14,7 @@ import 'src/fr/otakufr/source.dart';
|
|||||||
import 'src/id/nimegami/source.dart';
|
import 'src/id/nimegami/source.dart';
|
||||||
import 'src/id/oploverz/source.dart';
|
import 'src/id/oploverz/source.dart';
|
||||||
import 'src/id/otakudesu/source.dart';
|
import 'src/id/otakudesu/source.dart';
|
||||||
|
import 'src/it/source.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
List<Source> _sourcesList = [
|
List<Source> _sourcesList = [
|
||||||
@@ -28,7 +29,8 @@ void main() {
|
|||||||
nimegami,
|
nimegami,
|
||||||
oploverz,
|
oploverz,
|
||||||
aniwave,
|
aniwave,
|
||||||
...dopeflixSourcesList
|
...dopeflixSourcesList,
|
||||||
|
animesaturn
|
||||||
];
|
];
|
||||||
final List<Map<String, dynamic>> jsonList =
|
final List<Map<String, dynamic>> jsonList =
|
||||||
_sourcesList.map((source) => source.toJson()).toList();
|
_sourcesList.map((source) => source.toJson()).toList();
|
||||||
|
|||||||
@@ -10,12 +10,11 @@ class OkAnime extends MProvider {
|
|||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
List<MManga> animeList = [];
|
List<MManga> animeList = [];
|
||||||
final urls = xpath(res,
|
String path =
|
||||||
'//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")]';
|
||||||
final names = xpath(res,
|
final urls = xpath(res, '$path/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/text()');
|
final names = xpath(res, '$path/div[@class="anime-title")]/h4/a/text()');
|
||||||
final images = xpath(res,
|
final images = xpath(res, '$path/div[@class="anime-image")]/img/@src');
|
||||||
'//div[@class="section" and contains(text(),"افضل انميات")]/div[@class="section-content"]/div/div/div[contains(@class,"anime-card")]/div[@class="anime-image")]/img/@src');
|
|
||||||
|
|
||||||
for (var i = 0; i < names.length; i++) {
|
for (var i = 0; i < names.length; i++) {
|
||||||
MManga anime = MManga();
|
MManga anime = MManga();
|
||||||
@@ -33,12 +32,10 @@ class OkAnime extends MProvider {
|
|||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
List<MManga> animeList = [];
|
List<MManga> animeList = [];
|
||||||
final urls = xpath(res,
|
String path = '//*[contains(@class,"anime-card")]';
|
||||||
'//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/@href');
|
final urls = xpath(res, '$path/div[@class="anime-title")]/h4/a/@href');
|
||||||
final names = xpath(res,
|
final names = xpath(res, '$path/div[@class="anime-title")]/h4/a/text()');
|
||||||
'//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/text()');
|
final images = xpath(res, '$path/div[@class="episode-image")]/img/@src');
|
||||||
final images = xpath(res,
|
|
||||||
'//*[contains(@class,"anime-card")]/div[@class="episode-image")]/img/@src');
|
|
||||||
|
|
||||||
for (var i = 0; i < names.length; i++) {
|
for (var i = 0; i < names.length; i++) {
|
||||||
MManga anime = MManga();
|
MManga anime = MManga();
|
||||||
@@ -63,12 +60,10 @@ class OkAnime extends MProvider {
|
|||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
List<MManga> animeList = [];
|
List<MManga> animeList = [];
|
||||||
final urls = xpath(res,
|
String path = '//*[contains(@class,"anime-card")]';
|
||||||
'//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/@href');
|
final urls = xpath(res, '$path/div[@class="anime-title")]/h4/a/@href');
|
||||||
final names = xpath(res,
|
final names = xpath(res, '$path/div[@class="anime-title")]/h4/a/text()');
|
||||||
'//*[contains(@class,"anime-card")]/div[@class="anime-title")]/h4/a/text()');
|
final images = xpath(res, '$path/div[@class="anime-image")]/img/@src');
|
||||||
final images = xpath(res,
|
|
||||||
'//*[contains(@class,"anime-card")]/div[@class="anime-image")]/img/@src');
|
|
||||||
|
|
||||||
for (var i = 0; i < names.length; i++) {
|
for (var i = 0; i < names.length; i++) {
|
||||||
MManga anime = MManga();
|
MManga anime = MManga();
|
||||||
@@ -125,29 +120,81 @@ class OkAnime extends MProvider {
|
|||||||
|
|
||||||
final urls = xpath(res, '//*[@id="streamlinks"]/a/@data-src');
|
final urls = xpath(res, '//*[@id="streamlinks"]/a/@data-src');
|
||||||
final qualities = xpath(res, '//*[@id="streamlinks"]/a/span/text()');
|
final qualities = xpath(res, '//*[@id="streamlinks"]/a/span/text()');
|
||||||
|
final hosterSelection = preferenceHosterSelection(source.id);
|
||||||
List<MVideo> 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<MVideo> a = [];
|
List<MVideo> a = [];
|
||||||
|
|
||||||
if (url.contains("https://doo")) {
|
if (url.contains("https://doo") && hosterSelection.contains("Dood")) {
|
||||||
a = await doodExtractor(url, "DoodStream - $quality");
|
a = await doodExtractor(url, "DoodStream - $quality");
|
||||||
} else if (url.contains("mp4upload")) {
|
} else if (url.contains("mp4upload") &&
|
||||||
|
hosterSelection.contains("Mp4upload")) {
|
||||||
a = await mp4UploadExtractor(url, null, "", "");
|
a = await mp4UploadExtractor(url, null, "", "");
|
||||||
} else if (url.contains("ok.ru")) {
|
} else if (url.contains("ok.ru") && hosterSelection.contains("Okru")) {
|
||||||
a = await okruExtractor(url);
|
a = await okruExtractor(url);
|
||||||
} else if (url.contains("voe.sx")) {
|
} else if (url.contains("voe.sx") && hosterSelection.contains("Voe")) {
|
||||||
a = await voeExtractor(url, "VoeSX $quality");
|
a = await voeExtractor(url, "VoeSX $quality");
|
||||||
} else if (containsVidBom(url)) {
|
} else if (containsVidBom(url) && hosterSelection.contains("VidBom")) {
|
||||||
a = await vidBomExtractor(url);
|
a = await vidBomExtractor(url);
|
||||||
}
|
}
|
||||||
videos.addAll(a);
|
videos.addAll(a);
|
||||||
}
|
}
|
||||||
|
return sortVideos(videos, source.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
|
return [
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_quality",
|
||||||
|
title: "Preferred Quality",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 1,
|
||||||
|
entries: ["1080p", "720p", "480p", "360p"],
|
||||||
|
entryValues: ["1080", "720", "480", "360"]),
|
||||||
|
MultiSelectListPreference(
|
||||||
|
key: "hoster_selection",
|
||||||
|
title: "Enable/Disable Hosts",
|
||||||
|
summary: "",
|
||||||
|
entries: ["Dood", "Voe", "Mp4upload", "VidBom", "Okru"],
|
||||||
|
entryValues: ["Dood", "Voe", "Mp4upload", "VidBom", "Okru"],
|
||||||
|
values: ["Dood", "Voe", "Mp4upload", "VidBom", "Okru"]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MVideo> sortVideos(List<MVideo> videos, int sourceId) {
|
||||||
|
String quality = getPreferenceValue(sourceId, "preferred_quality");
|
||||||
|
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int qualityMatchA = 0;
|
||||||
|
if (a.quality.contains(quality)) {
|
||||||
|
qualityMatchA = 1;
|
||||||
|
}
|
||||||
|
int qualityMatchB = 0;
|
||||||
|
if (b.quality.contains(quality)) {
|
||||||
|
qualityMatchB = 1;
|
||||||
|
}
|
||||||
|
if (qualityMatchA != qualityMatchB) {
|
||||||
|
return qualityMatchB - qualityMatchA;
|
||||||
|
}
|
||||||
|
|
||||||
|
final regex = RegExp(r'(\d+)p');
|
||||||
|
final matchA = regex.firstMatch(a.quality);
|
||||||
|
final matchB = regex.firstMatch(b.quality);
|
||||||
|
final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0;
|
||||||
|
final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0;
|
||||||
|
return qualityNumB - qualityNumA;
|
||||||
|
});
|
||||||
|
|
||||||
return videos;
|
return videos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> preferenceHosterSelection(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "hoster_selection");
|
||||||
|
}
|
||||||
|
|
||||||
String getQuality(String quality) {
|
String getQuality(String quality) {
|
||||||
quality = quality.replaceAll(" ", "");
|
quality = quality.replaceAll(" ", "");
|
||||||
if (quality == "HD") {
|
if (quality == "HD") {
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ class Aniwave extends MProvider {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> getPopular(MSource source, int page) async {
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
final data = {"url": "${source.baseUrl}/filter?sort=trending&page=$page"};
|
final data = {
|
||||||
|
"url": "${preferenceBaseUrl(source.id)}/filter?sort=trending&page=$page"
|
||||||
|
};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
return parseAnimeList(res);
|
return parseAnimeList(res);
|
||||||
}
|
}
|
||||||
@@ -14,7 +16,8 @@ class Aniwave extends MProvider {
|
|||||||
@override
|
@override
|
||||||
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
||||||
final data = {
|
final data = {
|
||||||
"url": "${source.baseUrl}/filter?sort=recently_updated&page=$page"
|
"url":
|
||||||
|
"${preferenceBaseUrl(source.id)}/filter?sort=recently_updated&page=$page"
|
||||||
};
|
};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
return parseAnimeList(res);
|
return parseAnimeList(res);
|
||||||
@@ -24,7 +27,7 @@ class Aniwave extends MProvider {
|
|||||||
Future<MPages> search(
|
Future<MPages> search(
|
||||||
MSource source, String query, int page, FilterList filterList) async {
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
final filters = filterList.filters;
|
final filters = filterList.filters;
|
||||||
String url = "${source.baseUrl}/filter?keyword=$query";
|
String url = "${preferenceBaseUrl(source.id)}/filter?keyword=$query";
|
||||||
|
|
||||||
for (var filter in filters) {
|
for (var filter in filters) {
|
||||||
if (filter.type == "OrderFilter") {
|
if (filter.type == "OrderFilter") {
|
||||||
@@ -98,7 +101,7 @@ class Aniwave extends MProvider {
|
|||||||
final statusList = [
|
final statusList = [
|
||||||
{"Releasing": 0, "Completed": 1}
|
{"Releasing": 0, "Completed": 1}
|
||||||
];
|
];
|
||||||
final data = {"url": "${source.baseUrl}${url}"};
|
final data = {"url": "${preferenceBaseUrl(source.id)}${url}"};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
MManga anime = MManga();
|
MManga anime = MManga();
|
||||||
final status = xpath(res, '//div[contains(text(),"Status")]/span/text()');
|
final status = xpath(res, '//div[contains(text(),"Status")]/span/text()');
|
||||||
@@ -124,7 +127,9 @@ class Aniwave extends MProvider {
|
|||||||
.first;
|
.first;
|
||||||
final encrypt = vrfEncrypt(id);
|
final encrypt = vrfEncrypt(id);
|
||||||
final vrf = "vrf=${Uri.encodeComponent(encrypt)}";
|
final vrf = "vrf=${Uri.encodeComponent(encrypt)}";
|
||||||
final dataEp = {"url": "${source.baseUrl}/ajax/episode/list/$id?$vrf"};
|
final dataEp = {
|
||||||
|
"url": "${preferenceBaseUrl(source.id)}/ajax/episode/list/$id?$vrf"
|
||||||
|
};
|
||||||
final resEp = await http('GET', json.encode(dataEp));
|
final resEp = await http('GET', json.encode(dataEp));
|
||||||
final html = json.decode(resEp)["result"];
|
final html = json.decode(resEp)["result"];
|
||||||
List<MChapter>? episodesList = [];
|
List<MChapter>? episodesList = [];
|
||||||
@@ -172,8 +177,11 @@ class Aniwave extends MProvider {
|
|||||||
final ids = substringBefore(url, "&");
|
final ids = substringBefore(url, "&");
|
||||||
final encrypt = vrfEncrypt(ids);
|
final encrypt = vrfEncrypt(ids);
|
||||||
final vrf = "vrf=${Uri.encodeComponent(encrypt)}";
|
final vrf = "vrf=${Uri.encodeComponent(encrypt)}";
|
||||||
final res = await http('GET',
|
final res = await http(
|
||||||
json.encode({"url": "${source.baseUrl}/ajax/server/list/$ids?$vrf"}));
|
'GET',
|
||||||
|
json.encode({
|
||||||
|
"url": "${preferenceBaseUrl(source.id)}/ajax/server/list/$ids?$vrf"
|
||||||
|
}));
|
||||||
final html = json.decode(res)["result"];
|
final html = json.decode(res)["result"];
|
||||||
final vidsHtml = querySelectorAll(html,
|
final vidsHtml = querySelectorAll(html,
|
||||||
selector: "div.servers > div",
|
selector: "div.servers > div",
|
||||||
@@ -191,25 +199,34 @@ class Aniwave extends MProvider {
|
|||||||
final vrf = "vrf=${Uri.encodeComponent(encrypt)}";
|
final vrf = "vrf=${Uri.encodeComponent(encrypt)}";
|
||||||
final res = await http(
|
final res = await http(
|
||||||
'GET',
|
'GET',
|
||||||
json.encode(
|
json.encode({
|
||||||
{"url": "${source.baseUrl}/ajax/server/$serverId?$vrf"}));
|
"url":
|
||||||
|
"${preferenceBaseUrl(source.id)}/ajax/server/$serverId?$vrf"
|
||||||
|
}));
|
||||||
final status = json.decode(res)["status"];
|
final status = json.decode(res)["status"];
|
||||||
if (status == 200) {
|
if (status == 200) {
|
||||||
List<MVideo> a = [];
|
List<MVideo> a = [];
|
||||||
final url = vrfDecrypt(json.decode(res)["result"]["url"]);
|
final url = vrfDecrypt(json.decode(res)["result"]["url"]);
|
||||||
if (url.contains("mp4upload")) {
|
final hosterSelection = preferenceHosterSelection(source.id);
|
||||||
a = await mp4UploadExtractor(url, null, "", type);
|
final typeSelection = preferenceTypeSelection(source.id);
|
||||||
} else if (url.contains("streamtape")) {
|
if (typeSelection.contains(type.toLowerCase())) {
|
||||||
a = await streamTapeExtractor(url, "StreamTape - $type");
|
if (url.contains("mp4upload") &&
|
||||||
} else if (url.contains("filemoon")) {
|
hosterSelection.contains("mp4upload")) {
|
||||||
a = await filemoonExtractor(url, "", type);
|
a = await mp4UploadExtractor(url, null, "", type);
|
||||||
|
} else if (url.contains("streamtape") &&
|
||||||
|
hosterSelection.contains("streamtape")) {
|
||||||
|
a = await streamTapeExtractor(url, "StreamTape - $type");
|
||||||
|
} else if (url.contains("filemoon") &&
|
||||||
|
hosterSelection.contains("filemoon")) {
|
||||||
|
a = await filemoonExtractor(url, "", type);
|
||||||
|
}
|
||||||
|
videos.addAll(a);
|
||||||
}
|
}
|
||||||
videos.addAll(a);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return videos;
|
return sortVideos(videos, source.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
MPages parseAnimeList(String res) {
|
MPages parseAnimeList(String res) {
|
||||||
@@ -295,7 +312,7 @@ class Aniwave extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
SelectFilter("OrderFilter", "Sort order", 0, [
|
SelectFilter("OrderFilter", "Sort order", 0, [
|
||||||
SelectFilterOption("Most relevance", "most_relevance"),
|
SelectFilterOption("Most relevance", "most_relevance"),
|
||||||
@@ -427,6 +444,147 @@ class Aniwave extends MProvider {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
|
return [
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_domain",
|
||||||
|
title: "Preferred domain",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: [
|
||||||
|
"aniwave.to",
|
||||||
|
"aniwave.bz",
|
||||||
|
"aniwave.ws"
|
||||||
|
],
|
||||||
|
entryValues: [
|
||||||
|
"https://aniwave.to",
|
||||||
|
"https://aniwave.bz",
|
||||||
|
"https://aniwave.ws"
|
||||||
|
]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_quality",
|
||||||
|
title: "Preferred Quality",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["1080p", "720p", "480p", "360p"],
|
||||||
|
entryValues: ["1080", "720", "480", "360"]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_language",
|
||||||
|
title: "Preferred Type",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["Sub", "Softsub", "Dub"],
|
||||||
|
entryValues: ["Sub", "Softsub", "Dub"]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_server",
|
||||||
|
title: "Preferred server",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: [
|
||||||
|
"VidPlay",
|
||||||
|
"MyCloud",
|
||||||
|
"Filemoon",
|
||||||
|
"StreamTape",
|
||||||
|
"Mp4Upload"
|
||||||
|
],
|
||||||
|
entryValues: [
|
||||||
|
"vidplay",
|
||||||
|
"mycloud",
|
||||||
|
"filemoon",
|
||||||
|
"streamtape",
|
||||||
|
"mp4upload"
|
||||||
|
]),
|
||||||
|
MultiSelectListPreference(
|
||||||
|
key: "hoster_selection",
|
||||||
|
title: "Enable/Disable Hosts",
|
||||||
|
summary: "",
|
||||||
|
entries: [
|
||||||
|
"VidPlay",
|
||||||
|
"MyCloud",
|
||||||
|
"Filemoon",
|
||||||
|
"StreamTape",
|
||||||
|
"Mp4Upload"
|
||||||
|
],
|
||||||
|
entryValues: [
|
||||||
|
"vidplay",
|
||||||
|
"mycloud",
|
||||||
|
"filemoon",
|
||||||
|
"streamtape",
|
||||||
|
"mp4upload"
|
||||||
|
],
|
||||||
|
values: [
|
||||||
|
"vidplay",
|
||||||
|
"mycloud",
|
||||||
|
"filemoon",
|
||||||
|
"streamtape",
|
||||||
|
"mp4upload"
|
||||||
|
]),
|
||||||
|
MultiSelectListPreference(
|
||||||
|
key: "type_selection",
|
||||||
|
title: "Enable/Disable Type",
|
||||||
|
summary: "",
|
||||||
|
entries: ["Sub", "Softsub", "Dub"],
|
||||||
|
entryValues: ["sub", "softsub", "dub"],
|
||||||
|
values: ["sub", "softsub", "dub"]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
String preferenceBaseUrl(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "preferred_domain");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> preferenceHosterSelection(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "hoster_selection");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> preferenceTypeSelection(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "type_selection");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MVideo> sortVideos(List<MVideo> videos, int sourceId) {
|
||||||
|
String quality = getPreferenceValue(sourceId, "preferred_quality");
|
||||||
|
String server = getPreferenceValue(sourceId, "preferred_server");
|
||||||
|
String lang = getPreferenceValue(sourceId, "preferred_language");
|
||||||
|
videos = videos
|
||||||
|
.where(
|
||||||
|
(MVideo e) => e.quality.toLowerCase().contains(lang.toLowerCase()))
|
||||||
|
.toList();
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int qualityMatchA = 0;
|
||||||
|
if (a.quality.contains(quality)) {
|
||||||
|
qualityMatchA = 1;
|
||||||
|
}
|
||||||
|
int qualityMatchB = 0;
|
||||||
|
if (b.quality.contains(quality)) {
|
||||||
|
qualityMatchB = 1;
|
||||||
|
}
|
||||||
|
if (qualityMatchA != qualityMatchB) {
|
||||||
|
return qualityMatchB - qualityMatchA;
|
||||||
|
}
|
||||||
|
|
||||||
|
final regex = RegExp(r'(\d+)p');
|
||||||
|
final matchA = regex.firstMatch(a.quality);
|
||||||
|
final matchB = regex.firstMatch(b.quality);
|
||||||
|
final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0;
|
||||||
|
final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0;
|
||||||
|
return qualityNumB - qualityNumA;
|
||||||
|
});
|
||||||
|
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int serverMatchA = 0;
|
||||||
|
if (a.quality.toLowerCase().contains(server.toLowerCase())) {
|
||||||
|
serverMatchA = 1;
|
||||||
|
}
|
||||||
|
int serverMatchB = 0;
|
||||||
|
if (b.quality.toLowerCase().contains(server.toLowerCase())) {
|
||||||
|
serverMatchB = 1;
|
||||||
|
}
|
||||||
|
return serverMatchB - serverMatchA;
|
||||||
|
});
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
|
||||||
String ll(String url) {
|
String ll(String url) {
|
||||||
if (url.contains("?")) {
|
if (url.contains("?")) {
|
||||||
return "&";
|
return "&";
|
||||||
@@ -435,14 +593,6 @@ class Aniwave extends MProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> getMirrorPref() {
|
|
||||||
return {
|
|
||||||
"aniwave.to": "https://aniwave.to",
|
|
||||||
"aniwave.bz": "https://aniwave.bz",
|
|
||||||
"aniwave.ws": "https://aniwave.ws",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Aniwave main() {
|
Aniwave main() {
|
||||||
return Aniwave();
|
return Aniwave();
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
|
|||||||
import '../../../../utils/utils.dart';
|
import '../../../../utils/utils.dart';
|
||||||
|
|
||||||
Source get aniwave => _aniwave;
|
Source get aniwave => _aniwave;
|
||||||
const aniwaveVersion = "0.0.15";
|
const aniwaveVersion = "0.0.2";
|
||||||
const aniwaveCodeUrl =
|
const aniwaveCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/aniwave/aniwave-v$aniwaveVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/aniwave/aniwave-v$aniwaveVersion.dart";
|
||||||
Source _aniwave = Source(
|
Source _aniwave = Source(
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ class GogoAnime extends MProvider {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> getPopular(MSource source, int page) async {
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
final data = {"url": "${source.baseUrl}/popular.html?page=$page"};
|
final data = {
|
||||||
|
"url": "${preferenceBaseUrl(source.id)}/popular.html?page=$page"
|
||||||
|
};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
List<MManga> animeList = [];
|
List<MManga> animeList = [];
|
||||||
@@ -130,14 +132,15 @@ class GogoAnime extends MProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (genre.isNotEmpty) {
|
if (genre.isNotEmpty) {
|
||||||
url = "${source.baseUrl}/genre/$genre?page=$page";
|
url = "${preferenceBaseUrl(source.id)}/genre/$genre?page=$page";
|
||||||
} else if (recent.isNotEmpty) {
|
} else if (recent.isNotEmpty) {
|
||||||
url =
|
url =
|
||||||
"https://ajax.gogo-load.com/ajax/page-recent-release.html?page=$page&type=$recent";
|
"https://ajax.gogo-load.com/ajax/page-recent-release.html?page=$page&type=$recent";
|
||||||
} else if (season.isNotEmpty) {
|
} else if (season.isNotEmpty) {
|
||||||
url = "${source.baseUrl}/$season?page=$page";
|
url = "${preferenceBaseUrl(source.id)}/$season?page=$page";
|
||||||
} else {
|
} else {
|
||||||
url = "${source.baseUrl}/filter.html?keyword=$query$filterStr&page=$page";
|
url =
|
||||||
|
"${preferenceBaseUrl(source.id)}/filter.html?keyword=$query$filterStr&page=$page";
|
||||||
}
|
}
|
||||||
|
|
||||||
final data = {"url": url};
|
final data = {"url": url};
|
||||||
@@ -167,7 +170,7 @@ class GogoAnime extends MProvider {
|
|||||||
"Completed": 1,
|
"Completed": 1,
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
final data = {"url": "${source.baseUrl}$url"};
|
final data = {"url": "${preferenceBaseUrl(source.id)}$url"};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
MManga anime = MManga();
|
MManga anime = MManga();
|
||||||
final status = xpath(
|
final status = xpath(
|
||||||
@@ -213,7 +216,7 @@ class GogoAnime extends MProvider {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<MVideo>> getVideoList(MSource source, String url) async {
|
Future<List<MVideo>> getVideoList(MSource source, String url) async {
|
||||||
final datas = {"url": "${source.baseUrl}$url"};
|
final datas = {"url": "${preferenceBaseUrl(source.id)}$url"};
|
||||||
|
|
||||||
final res = await http('GET', json.encode(datas));
|
final res = await http('GET', json.encode(datas));
|
||||||
final serverUrls =
|
final serverUrls =
|
||||||
@@ -221,31 +224,34 @@ class GogoAnime extends MProvider {
|
|||||||
final serverNames =
|
final serverNames =
|
||||||
xpath(res, '//*[@class="anime_muti_link"]/ul/li/@class');
|
xpath(res, '//*[@class="anime_muti_link"]/ul/li/@class');
|
||||||
List<MVideo> videos = [];
|
List<MVideo> videos = [];
|
||||||
|
final hosterSelection = preferenceHosterSelection(source.id);
|
||||||
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<MVideo> a = [];
|
List<MVideo> a = [];
|
||||||
if (name.contains("anime")) {
|
if (hosterSelection.contains(name)) {
|
||||||
a = await gogoCdnExtractor(url);
|
if (name.contains("anime")) {
|
||||||
} else if (name.contains("vidcdn")) {
|
a = await gogoCdnExtractor(url);
|
||||||
a = await gogoCdnExtractor(url);
|
} else if (name.contains("vidcdn")) {
|
||||||
} else if (name.contains("doodstream")) {
|
a = await gogoCdnExtractor(url);
|
||||||
a = await doodExtractor(url);
|
} else if (name.contains("doodstream")) {
|
||||||
} else if (name.contains("mp4upload")) {
|
a = await doodExtractor(url);
|
||||||
a = await mp4UploadExtractor(url, null, "", "");
|
} else if (name.contains("mp4upload")) {
|
||||||
} else if (name.contains("filelions")) {
|
a = await mp4UploadExtractor(url, null, "", "");
|
||||||
a = await streamWishExtractor(url, "FileLions");
|
} else if (name.contains("filelions")) {
|
||||||
} else if (name.contains("streamwish")) {
|
a = await streamWishExtractor(url, "FileLions");
|
||||||
a = await streamWishExtractor(url, "StreamWish");
|
} else if (name.contains("streamwish")) {
|
||||||
|
a = await streamWishExtractor(url, "StreamWish");
|
||||||
|
}
|
||||||
|
videos.addAll(a);
|
||||||
}
|
}
|
||||||
videos.addAll(a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return videos;
|
return sortVideos(videos, source.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
HeaderFilter("Advanced search"),
|
HeaderFilter("Advanced search"),
|
||||||
GroupFilter("GenreFilter", "Genre", [
|
GroupFilter("GenreFilter", "Genre", [
|
||||||
@@ -1025,6 +1031,124 @@ class GogoAnime extends MProvider {
|
|||||||
]),
|
]),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
|
return [
|
||||||
|
EditTextPreference(
|
||||||
|
key: "override_baseurl_v${source.id}",
|
||||||
|
title: "Override BaseUrl",
|
||||||
|
summary:
|
||||||
|
"For temporary uses. Updating the extension will erase this setting.",
|
||||||
|
value: "https://gogoanime3.net",
|
||||||
|
dialogTitle: "Override BaseUrl",
|
||||||
|
dialogMessage: "Default: https://gogoanime3.net",
|
||||||
|
text: "https://gogoanime3.net"),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_quality",
|
||||||
|
title: "Preferred quality",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["1080p", "720p", "480p", "360p"],
|
||||||
|
entryValues: ["1080", "720", "480", "360"]),
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_server",
|
||||||
|
title: "Preferred server",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: [
|
||||||
|
"Gogostream",
|
||||||
|
"Vidstreaming",
|
||||||
|
"Doodstream",
|
||||||
|
"StreamWish",
|
||||||
|
"Mp4upload",
|
||||||
|
"FileLions"
|
||||||
|
],
|
||||||
|
entryValues: [
|
||||||
|
"Gogostream",
|
||||||
|
"Vidstreaming",
|
||||||
|
"Doodstream",
|
||||||
|
"StreamWish",
|
||||||
|
"Mp4upload",
|
||||||
|
"FileLions"
|
||||||
|
]),
|
||||||
|
MultiSelectListPreference(
|
||||||
|
key: "hoster_selection",
|
||||||
|
title: "Enable/Disable Hosts",
|
||||||
|
summary: "",
|
||||||
|
entries: [
|
||||||
|
"Gogostream",
|
||||||
|
"Vidstreaming",
|
||||||
|
"Doodstream",
|
||||||
|
"StreamWish",
|
||||||
|
"Mp4upload",
|
||||||
|
"FileLions"
|
||||||
|
],
|
||||||
|
entryValues: [
|
||||||
|
"vidcdn",
|
||||||
|
"anime",
|
||||||
|
"doodstream",
|
||||||
|
"streamwish",
|
||||||
|
"mp4upload",
|
||||||
|
"filelions"
|
||||||
|
],
|
||||||
|
values: [
|
||||||
|
"vidcdn",
|
||||||
|
"anime",
|
||||||
|
"doodstream",
|
||||||
|
"streamwish",
|
||||||
|
"mp4upload",
|
||||||
|
"filelions"
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
String preferenceBaseUrl(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "override_baseurl_v$sourceId");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> preferenceHosterSelection(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "hoster_selection");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MVideo> sortVideos(List<MVideo> videos, int sourceId) {
|
||||||
|
String quality = getPreferenceValue(sourceId, "preferred_quality");
|
||||||
|
String server = getPreferenceValue(sourceId, "preferred_server");
|
||||||
|
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int qualityMatchA = 0;
|
||||||
|
if (a.quality.contains(quality)) {
|
||||||
|
qualityMatchA = 1;
|
||||||
|
}
|
||||||
|
int qualityMatchB = 0;
|
||||||
|
if (b.quality.contains(quality)) {
|
||||||
|
qualityMatchB = 1;
|
||||||
|
}
|
||||||
|
if (qualityMatchA != qualityMatchB) {
|
||||||
|
return qualityMatchB - qualityMatchA;
|
||||||
|
}
|
||||||
|
|
||||||
|
final regex = RegExp(r'(\d+)p');
|
||||||
|
final matchA = regex.firstMatch(a.quality);
|
||||||
|
final matchB = regex.firstMatch(b.quality);
|
||||||
|
final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0;
|
||||||
|
final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0;
|
||||||
|
return qualityNumB - qualityNumA;
|
||||||
|
});
|
||||||
|
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int serverMatchA = 0;
|
||||||
|
if (a.quality.contains(server)) {
|
||||||
|
serverMatchA = 1;
|
||||||
|
}
|
||||||
|
int serverMatchB = 0;
|
||||||
|
if (b.quality.contains(server)) {
|
||||||
|
serverMatchB = 1;
|
||||||
|
}
|
||||||
|
return serverMatchB - serverMatchA;
|
||||||
|
});
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GogoAnime main() {
|
GogoAnime main() {
|
||||||
@@ -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.4";
|
const gogoanimeVersion = "0.0.5";
|
||||||
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(
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ class FrAnime extends MProvider {
|
|||||||
} else if (language == "vf" && hasVf) {
|
} else if (language == "vf" && hasVf) {
|
||||||
players = vfPlayers;
|
players = vfPlayers;
|
||||||
}
|
}
|
||||||
|
print(players);
|
||||||
List<MVideo> 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";
|
||||||
@@ -155,8 +156,6 @@ class FrAnime extends MProvider {
|
|||||||
..url = playerUrl
|
..url = playerUrl
|
||||||
..originalUrl = playerUrl
|
..originalUrl = playerUrl
|
||||||
..quality = "FRAnime (Vido)");
|
..quality = "FRAnime (Vido)");
|
||||||
} else if (playerName.contains("myvi")) {
|
|
||||||
a = await myTvExtractor(playerUrl);
|
|
||||||
} else if (playerName.contains("sendvid")) {
|
} else if (playerName.contains("sendvid")) {
|
||||||
a = await sendVidExtractor(
|
a = await sendVidExtractor(
|
||||||
playerUrl, json.encode({"Referer": "https://franime.fr/"}), "");
|
playerUrl, json.encode({"Referer": "https://franime.fr/"}), "");
|
||||||
@@ -191,7 +190,7 @@ class FrAnime extends MProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final titleO = animeJson["titleO"];
|
String titleO = animeJson["titleO"];
|
||||||
final title = animeJson["title"];
|
final title = animeJson["title"];
|
||||||
final genre = animeJson["themes"];
|
final genre = animeJson["themes"];
|
||||||
final description = animeJson["description"];
|
final description = animeJson["description"];
|
||||||
@@ -228,7 +227,7 @@ class FrAnime extends MProvider {
|
|||||||
anime.name = seasonTitle;
|
anime.name = seasonTitle;
|
||||||
anime.imageUrl = imageUrl;
|
anime.imageUrl = imageUrl;
|
||||||
anime.link =
|
anime.link =
|
||||||
"/anime/${regExp(titleO, "[^A-Za-z0-9 ]", "", 0, 0).replaceAll(" ", "-").toLowerCase()}?lang=$lang&s=$ind";
|
"/anime/${titleO.replaceAll(RegExp("[^A-Za-z0-9 ]"), "").replaceAll(" ", "-").toLowerCase()}?lang=$lang&s=$ind";
|
||||||
|
|
||||||
animeList.add(anime);
|
animeList.add(anime);
|
||||||
}
|
}
|
||||||
@@ -276,7 +275,7 @@ class FrAnime extends MProvider {
|
|||||||
vfListName.add(vf["lecteurs"].isNotEmpty);
|
vfListName.add(vf["lecteurs"].isNotEmpty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final titleO = animeJson["titleO"];
|
String titleO = animeJson["titleO"];
|
||||||
final title = animeJson["title"];
|
final title = animeJson["title"];
|
||||||
final genre = animeJson["themes"];
|
final genre = animeJson["themes"];
|
||||||
final description = animeJson["description"];
|
final description = animeJson["description"];
|
||||||
@@ -314,7 +313,7 @@ class FrAnime extends MProvider {
|
|||||||
anime.name = seasonTitle;
|
anime.name = seasonTitle;
|
||||||
anime.imageUrl = imageUrl;
|
anime.imageUrl = imageUrl;
|
||||||
anime.link =
|
anime.link =
|
||||||
"/anime/${regExp(titleO, "[^A-Za-z0-9 ]", "", 0, 0).replaceAll(" ", "-").toLowerCase()}?lang=$lang&s=$ind";
|
"/anime/${titleO.replaceAll(RegExp("[^A-Za-z0-9 ]"), "").replaceAll(" ", "-").toLowerCase()}?lang=$lang&s=$ind";
|
||||||
|
|
||||||
animeList.add(anime);
|
animeList.add(anime);
|
||||||
}
|
}
|
||||||
@@ -335,12 +334,11 @@ class FrAnime extends MProvider {
|
|||||||
|
|
||||||
String databaseAnimeByTitleO(String res, String titleO) {
|
String databaseAnimeByTitleO(String res, String titleO) {
|
||||||
print(titleO);
|
print(titleO);
|
||||||
final datas = json.decode(res) as List;
|
final datas = json.decode(res) as List<Map<String, dynamic>>;
|
||||||
for (var data in datas) {
|
for (var data in datas) {
|
||||||
if (regExp(data["titleO"], "[^A-Za-z0-9 ]", "", 0, 0)
|
String title =
|
||||||
.replaceAll(" ", "-")
|
(data["titleO"] as String).replaceAll(RegExp("[^A-Za-z0-9 ]"), "");
|
||||||
.toLowerCase() ==
|
if (title.replaceAll(" ", "-").toLowerCase() == "${titleO}") {
|
||||||
"${titleO}") {
|
|
||||||
return json.encode(data);
|
return json.encode(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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.4";
|
const franimeVersion = "0.0.45";
|
||||||
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(
|
||||||
|
|||||||
@@ -1,197 +0,0 @@
|
|||||||
import 'package:mangayomi/bridge_lib.dart';
|
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
class OtakuFr extends MProvider {
|
|
||||||
OtakuFr();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<MPages> getPopular(MSource source, int page) async {
|
|
||||||
final data = {
|
|
||||||
"url": "${source.baseUrl}/toute-la-liste-affiches/page/$page/?q=."
|
|
||||||
};
|
|
||||||
final res = await http('GET', json.encode(data));
|
|
||||||
|
|
||||||
List<MManga> animeList = [];
|
|
||||||
final urls =
|
|
||||||
xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href');
|
|
||||||
final names =
|
|
||||||
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@title');
|
|
||||||
final images =
|
|
||||||
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@src');
|
|
||||||
|
|
||||||
for (var i = 0; i < names.length; i++) {
|
|
||||||
MManga anime = MManga();
|
|
||||||
anime.name = names[i];
|
|
||||||
anime.imageUrl = images[i];
|
|
||||||
anime.link = urls[i];
|
|
||||||
animeList.add(anime);
|
|
||||||
}
|
|
||||||
final nextPage = xpath(res, '//a[@class="next page-link"]/@href');
|
|
||||||
return MPages(animeList, nextPage.isNotEmpty);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
|
||||||
final data = {"url": "${source.baseUrl}/page/$page/"};
|
|
||||||
final res = await http('GET', json.encode(data));
|
|
||||||
|
|
||||||
List<MManga> animeList = [];
|
|
||||||
final urls = xpath(res, '//*[@class="episode"]/div/a/@href');
|
|
||||||
final namess = xpath(res, '//*[@class="episode"]/div/a/text()');
|
|
||||||
List<String> names = [];
|
|
||||||
for (var name in namess) {
|
|
||||||
names.add(regExp(
|
|
||||||
name,
|
|
||||||
r'(?<=\bS\d\s*|)\d{2}\s*(?=\b(Vostfr|vostfr|VF|Vf|vf|\(VF\)|\(vf\)|\(Vf\)|\(Vostfr\)\b))?',
|
|
||||||
'',
|
|
||||||
0,
|
|
||||||
0)
|
|
||||||
.replaceAll(' vostfr', '')
|
|
||||||
.replaceAll(' Vostfr', '')
|
|
||||||
.replaceAll(' VF', '')
|
|
||||||
.replaceAll(' Vf', '')
|
|
||||||
.replaceAll(' vf', '')
|
|
||||||
.replaceAll(' (VF)', '')
|
|
||||||
.replaceAll(' (vf)', '')
|
|
||||||
.replaceAll(' (vf)', '')
|
|
||||||
.replaceAll(' (Vf)', '')
|
|
||||||
.replaceAll(' (Vostfr)', ''));
|
|
||||||
}
|
|
||||||
final images = xpath(res, '//*[@class="episode"]/div/figure/a/img/@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);
|
|
||||||
}
|
|
||||||
final nextPage = xpath(res, '//a[@class="next page-link"]/@href');
|
|
||||||
return MPages(animeList, nextPage.isNotEmpty);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<MPages> search(
|
|
||||||
MSource source, String query, int page, FilterList filterList) async {
|
|
||||||
final data = {
|
|
||||||
"url": "${source.baseUrl}/toute-la-liste-affiches/page/$page/?q=$query"
|
|
||||||
};
|
|
||||||
final res = await http('GET', json.encode(data));
|
|
||||||
|
|
||||||
List<MManga> animeList = [];
|
|
||||||
final urls =
|
|
||||||
xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href');
|
|
||||||
final names =
|
|
||||||
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@title');
|
|
||||||
final images =
|
|
||||||
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@src');
|
|
||||||
|
|
||||||
for (var i = 0; i < names.length; i++) {
|
|
||||||
MManga anime = MManga();
|
|
||||||
anime.name = names[i];
|
|
||||||
anime.imageUrl = images[i];
|
|
||||||
anime.link = urls[i];
|
|
||||||
animeList.add(anime);
|
|
||||||
}
|
|
||||||
final nextPage = xpath(res, '//a[@class="next page-link"]/@href');
|
|
||||||
return MPages(animeList, nextPage.isNotEmpty);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<MManga> getDetail(MSource source, String url) async {
|
|
||||||
final statusList = [
|
|
||||||
{
|
|
||||||
"En cours": 0,
|
|
||||||
"Terminé": 1,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
final data = {"url": url};
|
|
||||||
String res = await http('GET', json.encode(data));
|
|
||||||
MManga anime = MManga();
|
|
||||||
final originalUrl = xpath(res,
|
|
||||||
'//*[@class="breadcrumb"]/li[@class="breadcrumb-item"][2]/a/@href')
|
|
||||||
.first;
|
|
||||||
if (originalUrl.isNotEmpty) {
|
|
||||||
final newData = {"url": originalUrl};
|
|
||||||
res = await http('GET', json.encode(newData));
|
|
||||||
}
|
|
||||||
|
|
||||||
anime.description = xpath(res, '//*[@class="episode fz-sm synop"]/p/text()')
|
|
||||||
.first
|
|
||||||
.replaceAll("Synopsis:", "");
|
|
||||||
final status = xpath(res,
|
|
||||||
'//*[@class="list-unstyled"]/li[contains(text(),"Statut")]/text()')
|
|
||||||
.first
|
|
||||||
.replaceAll("Statut: ", "");
|
|
||||||
anime.status = parseStatus(status, statusList);
|
|
||||||
anime.genre = xpath(res,
|
|
||||||
'//*[@class="list-unstyled"]/li[contains(text(),"Genre")]/ul/li/a/text()');
|
|
||||||
|
|
||||||
final epUrls = xpath(res, '//*[@class="list-episodes list-group"]/a/@href');
|
|
||||||
final dates =
|
|
||||||
xpath(res, '//*[@class="list-episodes list-group"]/a/span/text()');
|
|
||||||
final names = xpath(res, '//*[@class="list-episodes list-group"]/a/text()');
|
|
||||||
List<String> episodes = [];
|
|
||||||
|
|
||||||
for (var i = 0; i < names.length; i++) {
|
|
||||||
final date = dates[i];
|
|
||||||
final name = names[i];
|
|
||||||
episodes.add(
|
|
||||||
"Episode ${regExp(name.replaceAll(date, ""), r".* (\d*) [VvfF]{1,1}", '', 1, 1)}");
|
|
||||||
}
|
|
||||||
final dateUploads = parseDates(dates, "dd MMMM yyyy", "fr");
|
|
||||||
|
|
||||||
List<MChapter>? episodesList = [];
|
|
||||||
for (var i = 0; i < episodes.length; i++) {
|
|
||||||
MChapter episode = MChapter();
|
|
||||||
episode.name = episodes[i];
|
|
||||||
episode.url = epUrls[i];
|
|
||||||
episode.dateUpload = dateUploads[i];
|
|
||||||
episodesList.add(episode);
|
|
||||||
}
|
|
||||||
|
|
||||||
anime.chapters = episodesList;
|
|
||||||
return anime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<MVideo>> getVideoList(MSource source, String url) async {
|
|
||||||
final res = await http('GET', json.encode({"url": url}));
|
|
||||||
|
|
||||||
final servers = xpath(res, '//*[@id="nav-tabContent"]/div/iframe/@src');
|
|
||||||
List<MVideo> videos = [];
|
|
||||||
for (var url in servers) {
|
|
||||||
final datasServer = {
|
|
||||||
"url": fixUrl(url),
|
|
||||||
"headers": {"X-Requested-With": "XMLHttpRequest"}
|
|
||||||
};
|
|
||||||
|
|
||||||
final resServer = await http('GET', json.encode(datasServer));
|
|
||||||
final serverUrl =
|
|
||||||
fixUrl(regExp(resServer, r"data-url='([^']+)'", '', 1, 1));
|
|
||||||
List<MVideo> a = [];
|
|
||||||
if (serverUrl.contains("https://streamwish")) {
|
|
||||||
a = await streamWishExtractor(serverUrl, "StreamWish");
|
|
||||||
} else if (serverUrl.contains("sibnet")) {
|
|
||||||
a = await sibnetExtractor(serverUrl);
|
|
||||||
} else if (serverUrl.contains("https://doo")) {
|
|
||||||
a = await doodExtractor(serverUrl);
|
|
||||||
} else if (serverUrl.contains("https://voe.sx")) {
|
|
||||||
a = await voeExtractor(serverUrl, null);
|
|
||||||
} else if (serverUrl.contains("https://ok.ru")) {
|
|
||||||
a = await okruExtractor(serverUrl);
|
|
||||||
}
|
|
||||||
videos.addAll(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
return videos;
|
|
||||||
}
|
|
||||||
|
|
||||||
String fixUrl(String url) {
|
|
||||||
return regExp(url, r"^(?:(?:https?:)?//|www\.)", 'https://', 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OtakuFr main() {
|
|
||||||
return OtakuFr();
|
|
||||||
}
|
|
||||||
448
anime/src/fr/otakufr/otakufr-v0.0.45.dart
Normal file
448
anime/src/fr/otakufr/otakufr-v0.0.45.dart
Normal file
@@ -0,0 +1,448 @@
|
|||||||
|
import 'package:mangayomi/bridge_lib.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class OtakuFr extends MProvider {
|
||||||
|
OtakuFr();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
|
final data = {
|
||||||
|
"url": "${source.baseUrl}/toute-la-liste-affiches/page/$page/?q=."
|
||||||
|
};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
|
List<MManga> animeList = [];
|
||||||
|
final urls =
|
||||||
|
xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href');
|
||||||
|
final names =
|
||||||
|
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@title');
|
||||||
|
final images =
|
||||||
|
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@src');
|
||||||
|
|
||||||
|
for (var i = 0; i < names.length; i++) {
|
||||||
|
MManga anime = MManga();
|
||||||
|
anime.name = names[i];
|
||||||
|
anime.imageUrl = images[i];
|
||||||
|
anime.link = urls[i];
|
||||||
|
animeList.add(anime);
|
||||||
|
}
|
||||||
|
final nextPage = xpath(res, '//a[@class="next page-link"]/@href');
|
||||||
|
return MPages(animeList, nextPage.isNotEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
||||||
|
final data = {"url": "${source.baseUrl}/page/$page/"};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
|
List<MManga> animeList = [];
|
||||||
|
final urls = xpath(res, '//*[@class="episode"]/div/a/@href');
|
||||||
|
final namess = xpath(res, '//*[@class="episode"]/div/a/text()');
|
||||||
|
List<String> names = [];
|
||||||
|
for (var name in namess) {
|
||||||
|
names.add(regExp(
|
||||||
|
name,
|
||||||
|
r'(?<=\bS\d\s*|)\d{2}\s*(?=\b(Vostfr|vostfr|VF|Vf|vf|\(VF\)|\(vf\)|\(Vf\)|\(Vostfr\)\b))?',
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
.replaceAll(' vostfr', '')
|
||||||
|
.replaceAll(' Vostfr', '')
|
||||||
|
.replaceAll(' VF', '')
|
||||||
|
.replaceAll(' Vf', '')
|
||||||
|
.replaceAll(' vf', '')
|
||||||
|
.replaceAll(' (VF)', '')
|
||||||
|
.replaceAll(' (vf)', '')
|
||||||
|
.replaceAll(' (vf)', '')
|
||||||
|
.replaceAll(' (Vf)', '')
|
||||||
|
.replaceAll(' (Vostfr)', ''));
|
||||||
|
}
|
||||||
|
final images = xpath(res, '//*[@class="episode"]/div/figure/a/img/@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);
|
||||||
|
}
|
||||||
|
final nextPage = xpath(res, '//a[@class="next page-link"]/@href');
|
||||||
|
return MPages(animeList, nextPage.isNotEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> search(
|
||||||
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
|
final filters = filterList.filters;
|
||||||
|
String url = "";
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
url = "${source.baseUrl}/toute-la-liste-affiches/page/$page/?q=$query";
|
||||||
|
} else {
|
||||||
|
for (var filter in filters) {
|
||||||
|
if (filter.type == "GenreFilter") {
|
||||||
|
if (filter.state != 0) {
|
||||||
|
url =
|
||||||
|
"${source.baseUrl}/${filter.values[filter.state].value}page/$page";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "SubPageFilter") {
|
||||||
|
if (url.isEmpty) {
|
||||||
|
if (filter.state != 0) {
|
||||||
|
url =
|
||||||
|
"${source.baseUrl}/${filter.values[filter.state].value}page/$page";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final data = {"url": url};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
|
List<MManga> animeList = [];
|
||||||
|
final urls =
|
||||||
|
xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href');
|
||||||
|
final names =
|
||||||
|
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@title');
|
||||||
|
final images =
|
||||||
|
xpath(res, '//*[@class="list"]/article/div/div/figure/a/img/@src');
|
||||||
|
|
||||||
|
for (var i = 0; i < names.length; i++) {
|
||||||
|
MManga anime = MManga();
|
||||||
|
anime.name = names[i];
|
||||||
|
anime.imageUrl = images[i];
|
||||||
|
anime.link = urls[i];
|
||||||
|
animeList.add(anime);
|
||||||
|
}
|
||||||
|
final nextPage = xpath(res, '//a[@class="next page-link"]/@href');
|
||||||
|
return MPages(animeList, nextPage.isNotEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MManga> getDetail(MSource source, String url) async {
|
||||||
|
final statusList = [
|
||||||
|
{"En cours": 0, "Terminé": 1}
|
||||||
|
];
|
||||||
|
final data = {"url": url};
|
||||||
|
String res = await http('GET', json.encode(data));
|
||||||
|
MManga anime = MManga();
|
||||||
|
final originalUrl = xpath(res,
|
||||||
|
'//*[@class="breadcrumb"]/li[@class="breadcrumb-item"][2]/a/@href');
|
||||||
|
if (originalUrl.isNotEmpty) {
|
||||||
|
final newData = {"url": originalUrl.first};
|
||||||
|
res = await http('GET', json.encode(newData));
|
||||||
|
}
|
||||||
|
final description =
|
||||||
|
xpath(res, '//*[@class="episode fz-sm synop"]/p/text()');
|
||||||
|
if (description.isNotEmpty) {
|
||||||
|
anime.description = description.first.replaceAll("Synopsis:", "");
|
||||||
|
}
|
||||||
|
final status = xpath(res,
|
||||||
|
'//*[@class="list-unstyled"]/li[contains(text(),"Statut")]/text()');
|
||||||
|
if (status.isNotEmpty) {
|
||||||
|
anime.status =
|
||||||
|
parseStatus(status.first.replaceAll("Statut: ", ""), statusList);
|
||||||
|
}
|
||||||
|
|
||||||
|
anime.genre = xpath(res,
|
||||||
|
'//*[@class="list-unstyled"]/li[contains(text(),"Genre")]/ul/li/a/text()');
|
||||||
|
|
||||||
|
final epUrls = xpath(res, '//*[@class="list-episodes list-group"]/a/@href');
|
||||||
|
final dates =
|
||||||
|
xpath(res, '//*[@class="list-episodes list-group"]/a/span/text()');
|
||||||
|
final names = xpath(res, '//*[@class="list-episodes list-group"]/a/text()');
|
||||||
|
List<String> episodes = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < names.length; i++) {
|
||||||
|
final date = dates[i];
|
||||||
|
final name = names[i];
|
||||||
|
episodes.add(
|
||||||
|
"Episode ${regExp(name.replaceAll(date, ""), r".* (\d*) [VvfF]{1,1}", '', 1, 1)}");
|
||||||
|
}
|
||||||
|
final dateUploads = parseDates(dates, "dd MMMM yyyy", "fr");
|
||||||
|
|
||||||
|
List<MChapter>? episodesList = [];
|
||||||
|
for (var i = 0; i < episodes.length; i++) {
|
||||||
|
MChapter episode = MChapter();
|
||||||
|
episode.name = episodes[i];
|
||||||
|
episode.url = epUrls[i];
|
||||||
|
episode.dateUpload = dateUploads[i];
|
||||||
|
episodesList.add(episode);
|
||||||
|
}
|
||||||
|
|
||||||
|
anime.chapters = episodesList;
|
||||||
|
return anime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<MVideo>> getVideoList(MSource source, String url) async {
|
||||||
|
final res = await http('GET', json.encode({"url": url}));
|
||||||
|
|
||||||
|
final servers = xpath(res, '//*[@id="nav-tabContent"]/div/iframe/@src');
|
||||||
|
List<MVideo> videos = [];
|
||||||
|
final hosterSelection = preferenceHosterSelection(source.id);
|
||||||
|
for (var url in servers) {
|
||||||
|
final datasServer = {
|
||||||
|
"url": fixUrl(url),
|
||||||
|
"headers": {"X-Requested-With": "XMLHttpRequest"}
|
||||||
|
};
|
||||||
|
|
||||||
|
final resServer = await http('GET', json.encode(datasServer));
|
||||||
|
final serverUrl =
|
||||||
|
fixUrl(regExp(resServer, r"data-url='([^']+)'", '', 1, 1));
|
||||||
|
List<MVideo> a = [];
|
||||||
|
if (serverUrl.contains("https://streamwish") &&
|
||||||
|
hosterSelection.contains("Streamwish")) {
|
||||||
|
a = await streamWishExtractor(serverUrl, "StreamWish");
|
||||||
|
} else if (serverUrl.contains("sibnet") &&
|
||||||
|
hosterSelection.contains("Sibnet")) {
|
||||||
|
a = await sibnetExtractor(serverUrl);
|
||||||
|
} else if (serverUrl.contains("https://doo") &&
|
||||||
|
hosterSelection.contains("Doodstream")) {
|
||||||
|
a = await doodExtractor(serverUrl);
|
||||||
|
} else if (serverUrl.contains("https://voe.sx") &&
|
||||||
|
hosterSelection.contains("Voe")) {
|
||||||
|
a = await voeExtractor(serverUrl, null);
|
||||||
|
} else if (serverUrl.contains("https://ok.ru") &&
|
||||||
|
hosterSelection.contains("Okru")) {
|
||||||
|
a = await okruExtractor(serverUrl);
|
||||||
|
} else if (serverUrl.contains("vadbam") &&
|
||||||
|
hosterSelection.contains("Vidbm")) {
|
||||||
|
a = await vidbmExtractor(serverUrl);
|
||||||
|
} else if (serverUrl.contains("upstream") &&
|
||||||
|
hosterSelection.contains("Upstream")) {
|
||||||
|
a = await upstreamExtractor(serverUrl);
|
||||||
|
} else if (serverUrl.contains("sendvid") &&
|
||||||
|
hosterSelection.contains("Sendvid")) {
|
||||||
|
a = await sendVidExtractor(serverUrl, null, "");
|
||||||
|
}
|
||||||
|
videos.addAll(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
|
||||||
|
String fixUrl(String url) {
|
||||||
|
return regExp(url, r"^(?:(?:https?:)?//|www\.)", 'https://', 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getFilterList(MSource source) {
|
||||||
|
return [
|
||||||
|
HeaderFilter("La recherche de texte ignore les filtres"),
|
||||||
|
SelectFilter("GenreFilter", "Genre", 0, [
|
||||||
|
SelectFilterOption("<Selectionner>", ""),
|
||||||
|
SelectFilterOption("Action", "/genre/action/"),
|
||||||
|
SelectFilterOption("Aventure", "/genre/aventure/"),
|
||||||
|
SelectFilterOption("Comedie", "/genre/comedie/"),
|
||||||
|
SelectFilterOption("Crime", "/genre/crime/"),
|
||||||
|
SelectFilterOption("Démons", "/genre/demons/"),
|
||||||
|
SelectFilterOption("Drame", "/genre/drame/"),
|
||||||
|
SelectFilterOption("Ecchi", "/genre/ecchi/"),
|
||||||
|
SelectFilterOption("Espace", "/genre/espace/"),
|
||||||
|
SelectFilterOption("Fantastique", "/genre/fantastique/"),
|
||||||
|
SelectFilterOption("Gore", "/genre/gore/"),
|
||||||
|
SelectFilterOption("Harem", "/genre/harem/"),
|
||||||
|
SelectFilterOption("Historique", "/genre/historique/"),
|
||||||
|
SelectFilterOption("Horreur", "/genre/horreur/"),
|
||||||
|
SelectFilterOption("Isekai", "/genre/isekai/"),
|
||||||
|
SelectFilterOption("Jeux", "/genre/jeu/"),
|
||||||
|
SelectFilterOption("L'école", "/genre/lecole/"),
|
||||||
|
SelectFilterOption("Magical girls", "/genre/magical-girls/"),
|
||||||
|
SelectFilterOption("Magie", "/genre/magie/"),
|
||||||
|
SelectFilterOption("Martial Arts", "/genre/martial-arts/"),
|
||||||
|
SelectFilterOption("Mecha", "/genre/mecha/"),
|
||||||
|
SelectFilterOption("Militaire", "/genre/militaire/"),
|
||||||
|
SelectFilterOption("Musique", "/genre/musique/"),
|
||||||
|
SelectFilterOption("Mysterieux", "/genre/mysterieux/"),
|
||||||
|
SelectFilterOption("Parodie", "/genre/Parodie/"),
|
||||||
|
SelectFilterOption("Police", "/genre/police/"),
|
||||||
|
SelectFilterOption("Psychologique", "/genre/psychologique/"),
|
||||||
|
SelectFilterOption("Romance", "/genre/romance/"),
|
||||||
|
SelectFilterOption("Samurai", "/genre/samurai/"),
|
||||||
|
SelectFilterOption("Sci-Fi", "/genre/sci-fi/"),
|
||||||
|
SelectFilterOption("Seinen", "/genre/seinen/"),
|
||||||
|
SelectFilterOption("Shoujo", "/genre/shoujo/"),
|
||||||
|
SelectFilterOption("Shoujo Ai", "/genre/shoujo-ai/"),
|
||||||
|
SelectFilterOption("Shounen", "/genre/shounen/"),
|
||||||
|
SelectFilterOption("Shounen Ai", "/genre/shounen-ai/"),
|
||||||
|
SelectFilterOption("Sport", "/genre/sport/"),
|
||||||
|
SelectFilterOption("Super Power", "/genre/super-power/"),
|
||||||
|
SelectFilterOption("Surnaturel", "/genre/surnaturel/"),
|
||||||
|
SelectFilterOption("Suspense", "/genre/suspense/"),
|
||||||
|
SelectFilterOption("Thriller", "/genre/thriller/"),
|
||||||
|
SelectFilterOption("Tranche de vie", "/genre/tranche-de-vie/"),
|
||||||
|
SelectFilterOption("Vampire", "/genre/vampire/")
|
||||||
|
]),
|
||||||
|
SelectFilter("SubPageFilter", "Sous page", 0, [
|
||||||
|
SelectFilterOption("<Selectionner>", ""),
|
||||||
|
SelectFilterOption("Terminé", "/termine/"),
|
||||||
|
SelectFilterOption("Film", "/film/"),
|
||||||
|
])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
|
return [
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_quality",
|
||||||
|
title: "Preferred Quality",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 1,
|
||||||
|
entries: ["1080p", "720p", "480p", "360p"],
|
||||||
|
entryValues: ["1080", "720", "480", "360"]),
|
||||||
|
MultiSelectListPreference(
|
||||||
|
key: "hoster_selection",
|
||||||
|
title: "Enable/Disable Hosts",
|
||||||
|
summary: "",
|
||||||
|
entries: [
|
||||||
|
"Streamwish",
|
||||||
|
"Doodstream",
|
||||||
|
"Sendvid",
|
||||||
|
"Vidbm",
|
||||||
|
"Okru",
|
||||||
|
"Voe",
|
||||||
|
"Sibnet",
|
||||||
|
"Upstream"
|
||||||
|
],
|
||||||
|
entryValues: [
|
||||||
|
"Streamwish",
|
||||||
|
"Doodstream",
|
||||||
|
"Sendvid",
|
||||||
|
"Vidbm",
|
||||||
|
"Okru",
|
||||||
|
"Voe",
|
||||||
|
"Sibnet",
|
||||||
|
"Upstream"
|
||||||
|
],
|
||||||
|
values: [
|
||||||
|
"Streamwish",
|
||||||
|
"Doodstream",
|
||||||
|
"Sendvid",
|
||||||
|
"Vidbm",
|
||||||
|
"Okru",
|
||||||
|
"Voe",
|
||||||
|
"Sibnet",
|
||||||
|
"Upstream"
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MVideo> sortVideos(List<MVideo> videos, int sourceId) {
|
||||||
|
String quality = getPreferenceValue(sourceId, "preferred_quality");
|
||||||
|
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int qualityMatchA = 0;
|
||||||
|
if (a.quality.contains(quality)) {
|
||||||
|
qualityMatchA = 1;
|
||||||
|
}
|
||||||
|
int qualityMatchB = 0;
|
||||||
|
if (b.quality.contains(quality)) {
|
||||||
|
qualityMatchB = 1;
|
||||||
|
}
|
||||||
|
if (qualityMatchA != qualityMatchB) {
|
||||||
|
return qualityMatchB - qualityMatchA;
|
||||||
|
}
|
||||||
|
|
||||||
|
final regex = RegExp(r'(\d+)p');
|
||||||
|
final matchA = regex.firstMatch(a.quality);
|
||||||
|
final matchB = regex.firstMatch(b.quality);
|
||||||
|
final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0;
|
||||||
|
final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0;
|
||||||
|
return qualityNumB - qualityNumA;
|
||||||
|
});
|
||||||
|
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> preferenceHosterSelection(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "hoster_selection");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<MVideo>> upstreamExtractor(String url) async {
|
||||||
|
final res = await http('GET', json.encode({"url": url}));
|
||||||
|
final js = xpath(res, '//script[contains(text(), "m3u8")]/text()');
|
||||||
|
if (js.isEmpty) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
final masterUrl =
|
||||||
|
substringBefore(substringAfter(evalJs(js.first), "{file:\""), "\"}");
|
||||||
|
final masterPlaylistRes =
|
||||||
|
await http('GET', json.encode({"url": masterUrl}));
|
||||||
|
List<MVideo> 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<List<MVideo>> vidbmExtractor(String url) async {
|
||||||
|
final res = await http('GET', json.encode({"url": url}));
|
||||||
|
final js = xpath(res,
|
||||||
|
'//script[contains(text(), "m3u8") or contains(text(), "mp4")]/text()');
|
||||||
|
if (js.isEmpty) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
final masterUrl = substringBefore(substringAfter(js.first, "source"), "\"");
|
||||||
|
final quality = substringBefore(
|
||||||
|
substringAfter(
|
||||||
|
substringBefore(
|
||||||
|
substringAfter(substringAfter(js.first, "source"), "file"),
|
||||||
|
"]"),
|
||||||
|
"label:\""),
|
||||||
|
"\"");
|
||||||
|
List<MVideo> videos = [];
|
||||||
|
if (masterUrl.contains("m3u8")) {
|
||||||
|
final masterPlaylistRes =
|
||||||
|
await http('GET', json.encode({"url": masterUrl}));
|
||||||
|
|
||||||
|
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:")
|
||||||
|
.split("#EXT-X-STREAM-INF:")) {
|
||||||
|
final quality =
|
||||||
|
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
|
||||||
|
|
||||||
|
String videoUrl = substringBefore(substringAfter(it, "\n"), "\n");
|
||||||
|
|
||||||
|
if (!videoUrl.startsWith("http")) {
|
||||||
|
videoUrl =
|
||||||
|
"${masterUrl.split("/").sublist(0, masterUrl.split("/").length - 1).join("/")}/$videoUrl";
|
||||||
|
}
|
||||||
|
|
||||||
|
MVideo video = MVideo();
|
||||||
|
video
|
||||||
|
..url = videoUrl
|
||||||
|
..originalUrl = videoUrl
|
||||||
|
..quality = "Vidbm - $quality";
|
||||||
|
videos.add(video);
|
||||||
|
}
|
||||||
|
return videos;
|
||||||
|
} else {
|
||||||
|
MVideo video = MVideo();
|
||||||
|
video
|
||||||
|
..url = masterUrl
|
||||||
|
..originalUrl = masterUrl
|
||||||
|
..quality = "Vidbm - $quality";
|
||||||
|
videos.add(video);
|
||||||
|
}
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OtakuFr main() {
|
||||||
|
return OtakuFr();
|
||||||
|
}
|
||||||
@@ -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.4";
|
const otakufrVersion = "0.0.45";
|
||||||
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(
|
||||||
|
|||||||
@@ -98,12 +98,11 @@ class OploVerz extends MProvider {
|
|||||||
xpath(ress, '//iframe[@class="playeriframe"]/@src').first;
|
xpath(ress, '//iframe[@class="playeriframe"]/@src').first;
|
||||||
final resPlayer = await http('GET', json.encode({"url": playerLink}));
|
final resPlayer = await http('GET', json.encode({"url": playerLink}));
|
||||||
var resJson = substringBefore(substringAfter(resPlayer, "= "), "<");
|
var resJson = substringBefore(substringAfter(resPlayer, "= "), "<");
|
||||||
var streams =
|
var streams = json.decode(resJson)["streams"] as List<Map<String, dynamic>>;
|
||||||
json.decode(getMapValue(resJson, "streams", encode: true)) as List;
|
|
||||||
List<MVideo> videos = [];
|
List<MVideo> videos = [];
|
||||||
for (var stream in streams) {
|
for (var stream in streams) {
|
||||||
final videoUrl = getMapValue(stream, "play_url");
|
String videoUrl = stream["play_url"];
|
||||||
final quality = getQuality(getMapValue(stream, "format_id"));
|
final quality = getQuality(stream["format_id"]);
|
||||||
|
|
||||||
MVideo video = MVideo();
|
MVideo video = MVideo();
|
||||||
video
|
video
|
||||||
@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
|
|||||||
import '../../../../utils/utils.dart';
|
import '../../../../utils/utils.dart';
|
||||||
|
|
||||||
Source get oploverz => _oploverz;
|
Source get oploverz => _oploverz;
|
||||||
const oploverzVersion = "0.0.15";
|
const oploverzVersion = "0.0.2";
|
||||||
const oploverzCodeUrl =
|
const oploverzCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/id/oploverz/oploverz-v$oploverzVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/id/oploverz/oploverz-v$oploverzVersion.dart";
|
||||||
Source _oploverz = Source(
|
Source _oploverz = Source(
|
||||||
|
|||||||
360
anime/src/it/animesaturn-v0.0.1.dart
Normal file
360
anime/src/it/animesaturn-v0.0.1.dart
Normal file
@@ -0,0 +1,360 @@
|
|||||||
|
import 'package:mangayomi/bridge_lib.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class AnimeSaturn extends MProvider {
|
||||||
|
AnimeSaturn();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
|
final data = {"url": "${source.baseUrl}/animeincorso?page=$page"};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
|
List<MManga> animeList = [];
|
||||||
|
|
||||||
|
final urls = xpath(res,
|
||||||
|
'//*[@class="sebox"]/div[@class="msebox"]/div[@class="headsebox"]/div[@class="tisebox"]/h2/a/@href');
|
||||||
|
|
||||||
|
final names = xpath(res,
|
||||||
|
'//*[@class="sebox"]/div[@class="msebox"]/div[@class="headsebox"]/div[@class="tisebox"]/h2/a/text()');
|
||||||
|
|
||||||
|
final images = xpath(res,
|
||||||
|
'//*[@class="sebox"]/div[@class="msebox"]/div[@class="bigsebox"]/div/img[@class="attachment-post-thumbnail size-post-thumbnail wp-post-image"]/@src');
|
||||||
|
|
||||||
|
for (var i = 0; i < names.length; i++) {
|
||||||
|
MManga anime = MManga();
|
||||||
|
anime.name = formatTitle(names[i]);
|
||||||
|
anime.imageUrl = images[i];
|
||||||
|
anime.link = urls[i];
|
||||||
|
animeList.add(anime);
|
||||||
|
}
|
||||||
|
return MPages(animeList, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
||||||
|
final data = {"url": "${source.baseUrl}/newest?page=$page"};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
|
List<MManga> animeList = [];
|
||||||
|
|
||||||
|
final urls = xpath(res, '//*[@class="card mb-4 shadow-sm"]/a/@href');
|
||||||
|
|
||||||
|
final names = xpath(res, '///*[@class="card mb-4 shadow-sm"]/a/@title');
|
||||||
|
|
||||||
|
final images = xpath(res,
|
||||||
|
'//*[@class="card mb-4 shadow-sm"]/a/img[@class="new-anime"]/@src');
|
||||||
|
|
||||||
|
for (var i = 0; i < names.length; i++) {
|
||||||
|
MManga anime = MManga();
|
||||||
|
anime.name = formatTitle(names[i]);
|
||||||
|
anime.imageUrl = images[i];
|
||||||
|
anime.link = urls[i];
|
||||||
|
animeList.add(anime);
|
||||||
|
}
|
||||||
|
return MPages(animeList, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> search(
|
||||||
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
|
final filters = filterList.filters;
|
||||||
|
String url = "";
|
||||||
|
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
url = "${source.baseUrl}/animelist?search=$query";
|
||||||
|
} else {
|
||||||
|
url = "${source.baseUrl}/filter?";
|
||||||
|
int variantgenre = 0;
|
||||||
|
int variantstate = 0;
|
||||||
|
int variantyear = 0;
|
||||||
|
for (var filter in filters) {
|
||||||
|
if (filter.type == "GenreFilter") {
|
||||||
|
final genre = (filter.state as List).where((e) => e.state).toList();
|
||||||
|
if (genre.isNotEmpty) {
|
||||||
|
for (var st in genre) {
|
||||||
|
url += "&categories%5B${variantgenre}%5D=${st.value}";
|
||||||
|
variantgenre++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (filter.type == "YearList") {
|
||||||
|
final years = (filter.state as List).where((e) => e.state).toList();
|
||||||
|
if (years.isNotEmpty) {
|
||||||
|
for (var st in years) {
|
||||||
|
url += "&years%5B${variantyear}%5D=${st.value}";
|
||||||
|
variantyear++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (filter.type == "StateList") {
|
||||||
|
final states = (filter.state as List).where((e) => e.state).toList();
|
||||||
|
if (states.isNotEmpty) {
|
||||||
|
for (var st in states) {
|
||||||
|
url += "&states%5B${variantstate}%5D=${st.value}";
|
||||||
|
variantstate++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (filter.type == "LangList") {
|
||||||
|
final lang = filter.values[filter.state].value;
|
||||||
|
if (lang.isNotEmpty) {
|
||||||
|
url += "&language%5B0%5D=$lang";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
url += "&page=$page";
|
||||||
|
}
|
||||||
|
final data = {"url": url};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
|
List<MManga> animeList = [];
|
||||||
|
List<String> urls = [];
|
||||||
|
List<String> names = [];
|
||||||
|
List<String> images = [];
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
urls = xpath(res,
|
||||||
|
'//*[@class="list-group"]/li[@class="list-group-item bg-dark-as-box-shadow"]/div[@class="item-archivio"]/div[@class="info-archivio"]/h3/a[@class="badge badge-archivio badge-light"]/@href');
|
||||||
|
|
||||||
|
names = xpath(res,
|
||||||
|
'//*[@class="list-group"]/li[@class="list-group-item bg-dark-as-box-shadow"]/div[@class="item-archivio"]/div[@class="info-archivio"]/h3/a[@class="badge badge-archivio badge-light"]/text()');
|
||||||
|
|
||||||
|
images = xpath(res,
|
||||||
|
'//*[@class="list-group"]/li[@class="list-group-item bg-dark-as-box-shadow"]/div[@class="item-archivio"]/a/img/@src');
|
||||||
|
} else {
|
||||||
|
urls = xpath(res, '//*[@class="card mb-4 shadow-sm"]/a/@href');
|
||||||
|
|
||||||
|
names = xpath(res, '//*[@class="card mb-4 shadow-sm"]/a/text()');
|
||||||
|
|
||||||
|
images = xpath(res,
|
||||||
|
'//*[@class="card mb-4 shadow-sm"]/a/img[@class="new-anime"]/@src');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < names.length; i++) {
|
||||||
|
MManga anime = MManga();
|
||||||
|
anime.name = formatTitle(names[i]);
|
||||||
|
anime.imageUrl = images[i];
|
||||||
|
anime.link = urls[i];
|
||||||
|
animeList.add(anime);
|
||||||
|
}
|
||||||
|
return MPages(animeList, query.isEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MManga> getDetail(MSource source, String url) async {
|
||||||
|
final statusList = [
|
||||||
|
{"In corso": 0, "Finito": 1}
|
||||||
|
];
|
||||||
|
final data = {"url": url};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
MManga anime = MManga();
|
||||||
|
final details = xpath(res,
|
||||||
|
'//div[@class="container shadow rounded bg-dark-as-box mb-3 p-3 w-100 text-white"]/text()')
|
||||||
|
.first;
|
||||||
|
|
||||||
|
anime.status = parseStatus(
|
||||||
|
details.substring(
|
||||||
|
details.indexOf("Stato:") + 6, details.indexOf("Data di uscita:")),
|
||||||
|
statusList);
|
||||||
|
anime.author = details.substring(7, details.indexOf("Stato:"));
|
||||||
|
final description = xpath(res, '//*[@id="shown-trama"]/text()');
|
||||||
|
final descriptionFull = xpath(res, '//*[@id="full-trama"]/text()');
|
||||||
|
if (description.isNotEmpty) {
|
||||||
|
anime.description = description.first;
|
||||||
|
} else {
|
||||||
|
anime.description = "";
|
||||||
|
}
|
||||||
|
if (descriptionFull.isNotEmpty) {
|
||||||
|
if (descriptionFull.first.length > anime.description.length) {
|
||||||
|
anime.description = descriptionFull.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
anime.genre = xpath(res,
|
||||||
|
'//*[@class="container shadow rounded bg-dark-as-box mb-3 p-3 w-100"]/a/text()');
|
||||||
|
|
||||||
|
final epUrls = xpath(res,
|
||||||
|
'//*[@class="btn-group episodes-button episodi-link-button"]/a/@href');
|
||||||
|
|
||||||
|
final titles = xpath(res,
|
||||||
|
'//*[@class="btn-group episodes-button episodi-link-button"]/a/text()');
|
||||||
|
|
||||||
|
List<MChapter>? episodesList = [];
|
||||||
|
for (var i = 0; i < epUrls.length; i++) {
|
||||||
|
MChapter episode = MChapter();
|
||||||
|
episode.name = titles[i];
|
||||||
|
episode.url = epUrls[i];
|
||||||
|
episodesList.add(episode);
|
||||||
|
}
|
||||||
|
|
||||||
|
anime.chapters = episodesList.reversed.toList();
|
||||||
|
return anime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<MVideo>> getVideoList(MSource source, String url) async {
|
||||||
|
final res = await http('GET', json.encode({"url": url}));
|
||||||
|
|
||||||
|
final urlVid = xpath(res, '//a[contains(@href,"/watch")]/@href').first;
|
||||||
|
final resVid = await http('GET', json.encode({"url": urlVid}));
|
||||||
|
String masterUrl = "";
|
||||||
|
if (resVid.contains("jwplayer(")) {
|
||||||
|
masterUrl = substringBefore(substringAfter(resVid, "file: \""), "\"");
|
||||||
|
} else {
|
||||||
|
masterUrl = querySelectorAll(resVid,
|
||||||
|
selector: "source",
|
||||||
|
typeElement: 3,
|
||||||
|
attributes: "src",
|
||||||
|
typeRegExp: 0)
|
||||||
|
.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MVideo> videos = [];
|
||||||
|
if (masterUrl.endsWith("playlist.m3u8")) {
|
||||||
|
final masterPlaylistRes =
|
||||||
|
await http('GET', json.encode({"url": masterUrl}));
|
||||||
|
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-STREAM-INF:")
|
||||||
|
.split("#EXT-X-STREAM-INF:")) {
|
||||||
|
final quality =
|
||||||
|
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
|
||||||
|
|
||||||
|
String videoUrl = substringBefore(substringAfter(it, "\n"), "\n");
|
||||||
|
|
||||||
|
if (!videoUrl.startsWith("http")) {
|
||||||
|
videoUrl =
|
||||||
|
"${masterUrl.split("/").sublist(0, masterUrl.split("/").length - 1).join("/")}/$videoUrl";
|
||||||
|
}
|
||||||
|
|
||||||
|
MVideo video = MVideo();
|
||||||
|
video
|
||||||
|
..url = videoUrl
|
||||||
|
..originalUrl = videoUrl
|
||||||
|
..quality = quality;
|
||||||
|
videos.add(video);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MVideo video = MVideo();
|
||||||
|
video
|
||||||
|
..url = masterUrl
|
||||||
|
..originalUrl = masterUrl
|
||||||
|
..quality = "Qualità predefinita";
|
||||||
|
videos.add(video);
|
||||||
|
}
|
||||||
|
return sortVideos(videos, source.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatTitle(String titlestring) {
|
||||||
|
return titlestring
|
||||||
|
.replaceAll("(ITA) ITA", "Dub ITA")
|
||||||
|
.replaceAll("(ITA)", "Dub ITA")
|
||||||
|
.replaceAll("Sub ITA", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getFilterList(MSource source) {
|
||||||
|
return [
|
||||||
|
HeaderFilter("Ricerca per titolo ignora i filtri e viceversa"),
|
||||||
|
GroupFilter("GenreFilter", "Generi", [
|
||||||
|
CheckBoxFilter("Arti Marziali", "Arti Marziali"),
|
||||||
|
CheckBoxFilter("Avventura", "Avventura"),
|
||||||
|
CheckBoxFilter("Azione", "Azione"),
|
||||||
|
CheckBoxFilter("Bambini", "Bambini"),
|
||||||
|
CheckBoxFilter("Commedia", "Commedia"),
|
||||||
|
CheckBoxFilter("Demenziale", "Demenziale"),
|
||||||
|
CheckBoxFilter("Demoni", "Demoni"),
|
||||||
|
CheckBoxFilter("Drammatico", "Drammatico"),
|
||||||
|
CheckBoxFilter("Ecchi", "Ecchi"),
|
||||||
|
CheckBoxFilter("Fantasy", "Fantasy"),
|
||||||
|
CheckBoxFilter("Gioco", "Gioco"),
|
||||||
|
CheckBoxFilter("Harem", "Harem"),
|
||||||
|
CheckBoxFilter("Hentai", "Hentai"),
|
||||||
|
CheckBoxFilter("Horror", "Horror"),
|
||||||
|
CheckBoxFilter("Josei", "Josei"),
|
||||||
|
CheckBoxFilter("Magia", "Magia"),
|
||||||
|
CheckBoxFilter("Mecha", "Mecha"),
|
||||||
|
CheckBoxFilter("Militari", "Militari"),
|
||||||
|
CheckBoxFilter("Mistero", "Mistero"),
|
||||||
|
CheckBoxFilter("Musicale", "Musicale"),
|
||||||
|
CheckBoxFilter("Parodia", "Parodia"),
|
||||||
|
CheckBoxFilter("Polizia", "Polizia"),
|
||||||
|
CheckBoxFilter("Psicologico", "Psicologico"),
|
||||||
|
CheckBoxFilter("Romantico", "Romantico"),
|
||||||
|
CheckBoxFilter("Samurai", "Samurai"),
|
||||||
|
CheckBoxFilter("Sci-Fi", "Sci-Fi"),
|
||||||
|
CheckBoxFilter("Scolastico", "Scolastico"),
|
||||||
|
CheckBoxFilter("Seinen", "Seinen"),
|
||||||
|
CheckBoxFilter("Sentimentale", "Sentimentale"),
|
||||||
|
CheckBoxFilter("Shoujo Ai", "Shoujo Ai"),
|
||||||
|
CheckBoxFilter("Shoujo", "Shoujo"),
|
||||||
|
CheckBoxFilter("Shounen Ai", "Shounen Ai"),
|
||||||
|
CheckBoxFilter("Shounen", "Shounen"),
|
||||||
|
CheckBoxFilter("Slice of Life", "Slice of Life"),
|
||||||
|
CheckBoxFilter("Soprannaturale", "Soprannaturale"),
|
||||||
|
CheckBoxFilter("Spazio", "Spazio"),
|
||||||
|
CheckBoxFilter("Sport", "Sport"),
|
||||||
|
CheckBoxFilter("Storico", "Storico"),
|
||||||
|
CheckBoxFilter("Superpoteri", "Superpoteri"),
|
||||||
|
CheckBoxFilter("Thriller", "Thriller"),
|
||||||
|
CheckBoxFilter("Vampiri", "Vampiri"),
|
||||||
|
CheckBoxFilter("Veicoli", "Veicoli"),
|
||||||
|
CheckBoxFilter("Yaoi", "Yaoi"),
|
||||||
|
CheckBoxFilter("Yuri", "Yuri"),
|
||||||
|
]),
|
||||||
|
GroupFilter("YearList", "Anno di Uscita", [
|
||||||
|
for (var i = 1969; i < 2022; i++)
|
||||||
|
CheckBoxFilter(i.toString(), i.toString()),
|
||||||
|
]),
|
||||||
|
GroupFilter("StateList", "Stato", [
|
||||||
|
CheckBoxFilter("In corso", "0"),
|
||||||
|
CheckBoxFilter("Finito", "1"),
|
||||||
|
CheckBoxFilter("Non rilasciato", "2"),
|
||||||
|
CheckBoxFilter("Droppato", "3"),
|
||||||
|
]),
|
||||||
|
SelectFilter("LangList", "Lingua", 0, [
|
||||||
|
SelectFilterOption("", ""),
|
||||||
|
SelectFilterOption("Subbato", "0"),
|
||||||
|
SelectFilterOption("Doppiato", "1"),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
|
return [
|
||||||
|
ListPreference(
|
||||||
|
key: "preferred_quality",
|
||||||
|
title: "Qualità preferita",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["1080p", "720p", "480p", "360p", "240p", "144p"],
|
||||||
|
entryValues: ["1080", "720", "480", "360", "240", "144"]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MVideo> sortVideos(List<MVideo> videos, int sourceId) {
|
||||||
|
String quality = getPreferenceValue(sourceId, "preferred_quality");
|
||||||
|
|
||||||
|
videos.sort((MVideo a, MVideo b) {
|
||||||
|
int qualityMatchA = 0;
|
||||||
|
if (a.quality.contains(quality)) {
|
||||||
|
qualityMatchA = 1;
|
||||||
|
}
|
||||||
|
int qualityMatchB = 0;
|
||||||
|
if (b.quality.contains(quality)) {
|
||||||
|
qualityMatchB = 1;
|
||||||
|
}
|
||||||
|
if (qualityMatchA != qualityMatchB) {
|
||||||
|
return qualityMatchB - qualityMatchA;
|
||||||
|
}
|
||||||
|
|
||||||
|
final regex = RegExp(r'(\d+)p');
|
||||||
|
final matchA = regex.firstMatch(a.quality);
|
||||||
|
final matchB = regex.firstMatch(b.quality);
|
||||||
|
final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0;
|
||||||
|
final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0;
|
||||||
|
return qualityNumB - qualityNumA;
|
||||||
|
});
|
||||||
|
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimeSaturn main() {
|
||||||
|
return AnimeSaturn();
|
||||||
|
}
|
||||||
16
anime/src/it/source.dart
Normal file
16
anime/src/it/source.dart
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import '../../../model/source.dart';
|
||||||
|
import '../../../utils/utils.dart';
|
||||||
|
|
||||||
|
Source get animesaturn => _animesaturn;
|
||||||
|
const animesaturnVersion = "0.0.1";
|
||||||
|
const animesaturnCodeUrl =
|
||||||
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/it/animesaturn/animesaturn-v$animesaturnVersion.dart";
|
||||||
|
Source _animesaturn = Source(
|
||||||
|
name: "AnimeSaturn",
|
||||||
|
baseUrl: "https://www.animesaturn.tv",
|
||||||
|
lang: "it",
|
||||||
|
typeSource: "single",
|
||||||
|
iconUrl: getIconUrl("animesaturn", "it"),
|
||||||
|
sourceCodeUrl: animesaturnCodeUrl,
|
||||||
|
version: animesaturnVersion,
|
||||||
|
isManga: false);
|
||||||
BIN
icons/mangayomi-it-animesaturn.png
Normal file
BIN
icons/mangayomi-it-animesaturn.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
@@ -356,7 +356,7 @@ class Madara extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
TextFilter("AuthorFilter", "Author"),
|
TextFilter("AuthorFilter", "Author"),
|
||||||
TextFilter("ArtistFilter", "Artist"),
|
TextFilter("ArtistFilter", "Artist"),
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ class MangaReader extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
SeparatorFilter(),
|
SeparatorFilter(),
|
||||||
TextFilter("AuthorFilter", "Author"),
|
TextFilter("AuthorFilter", "Author"),
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ class MMRCMS extends MProvider {
|
|||||||
return pagesUrl;
|
return pagesUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
HeaderFilter("NOTE: Ignored if using text search!"),
|
HeaderFilter("NOTE: Ignored if using text search!"),
|
||||||
SeparatorFilter(),
|
SeparatorFilter(),
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ class NepNep extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
TextFilter("YearFilter", "Years"),
|
TextFilter("YearFilter", "Years"),
|
||||||
TextFilter("AuthorFilter", "Author"),
|
TextFilter("AuthorFilter", "Author"),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class Batoto extends MProvider {
|
|||||||
@override
|
@override
|
||||||
Future<MPages> getPopular(MSource source, int page) async {
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
final url =
|
final url =
|
||||||
"${source.baseUrl}/browse?${lang(source.lang)}&sort=views_a&page=$page";
|
"${preferenceMirror(source.id)}/browse?${lang(source.lang)}&sort=views_a&page=$page";
|
||||||
final data = {"url": url};
|
final data = {"url": url};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
return mangaElementM(res, source);
|
return mangaElementM(res, source);
|
||||||
@@ -16,7 +16,7 @@ class Batoto extends MProvider {
|
|||||||
@override
|
@override
|
||||||
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
||||||
final url =
|
final url =
|
||||||
"${source.baseUrl}/browse?${lang(source.lang)}&sort=update&page=$page";
|
"${preferenceMirror(source.id)}/browse?${lang(source.lang)}&sort=update&page=$page";
|
||||||
final data = {"url": url};
|
final data = {"url": url};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
return mangaElementM(res, source);
|
return mangaElementM(res, source);
|
||||||
@@ -30,7 +30,7 @@ class Batoto extends MProvider {
|
|||||||
String min = "";
|
String min = "";
|
||||||
String max = "";
|
String max = "";
|
||||||
if (query.isNotEmpty) {
|
if (query.isNotEmpty) {
|
||||||
url = "${source.baseUrl}/search?word=$query&page=$page";
|
url = "${preferenceMirror(source.id)}/search?word=$query&page=$page";
|
||||||
for (var filter in filters) {
|
for (var filter in filters) {
|
||||||
if (filter.type == "LetterFilter") {
|
if (filter.type == "LetterFilter") {
|
||||||
if (filter.state == 1) {
|
if (filter.state == 1) {
|
||||||
@@ -39,7 +39,7 @@ class Batoto extends MProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
url = "${source.baseUrl}/browse";
|
url = "${preferenceMirror(source.id)}/browse";
|
||||||
for (var filter in filters) {
|
for (var filter in filters) {
|
||||||
if (filter.type == "LangGroupFilter") {
|
if (filter.type == "LangGroupFilter") {
|
||||||
final langs = (filter.state as List).where((e) => e.state).toList();
|
final langs = (filter.state as List).where((e) => e.state).toList();
|
||||||
@@ -111,7 +111,7 @@ class Batoto extends MProvider {
|
|||||||
{"Ongoing": 0, "Completed": 1, "Cancelled": 3, "Hiatus": 2}
|
{"Ongoing": 0, "Completed": 1, "Cancelled": 3, "Hiatus": 2}
|
||||||
];
|
];
|
||||||
|
|
||||||
final data = {"url": "${source.baseUrl}$url"};
|
final data = {"url": "${preferenceMirror(source.id)}$url"};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
MManga manga = MManga();
|
MManga manga = MManga();
|
||||||
final workStatus = xpath(res,
|
final workStatus = xpath(res,
|
||||||
@@ -171,7 +171,7 @@ class Batoto extends MProvider {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<String>> getPageList(MSource source, String url) async {
|
Future<List<String>> getPageList(MSource source, String url) async {
|
||||||
final datas = {"url": "${source.baseUrl}$url"};
|
final datas = {"url": "${preferenceMirror(source.id)}$url"};
|
||||||
final res = await http('GET', json.encode(datas));
|
final res = await http('GET', json.encode(datas));
|
||||||
|
|
||||||
final script = xpath(res,
|
final script = xpath(res,
|
||||||
@@ -273,7 +273,7 @@ class Batoto extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
SelectFilter("LetterFilter", "Letter matching mode (Slow)", 0, [
|
SelectFilter("LetterFilter", "Letter matching mode (Slow)", 0, [
|
||||||
SelectFilterOption("Disabled", "disabled"),
|
SelectFilterOption("Disabled", "disabled"),
|
||||||
@@ -1663,36 +1663,51 @@ class Batoto extends MProvider {
|
|||||||
SeparatorFilter(),
|
SeparatorFilter(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> getMirrorPref() {
|
@override
|
||||||
return {
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
"bato.to": "https://bato.to",
|
return [
|
||||||
"batocomic.com": "https://batocomic.com",
|
ListPreference(
|
||||||
"batocomic.net": "https://batocomic.net",
|
key: "mirror",
|
||||||
"batocomic.org": "https://batocomic.org",
|
title: "Mirror",
|
||||||
"batotoo.com": "https://batotoo.com",
|
summary: "",
|
||||||
"batotwo.com": "https://batotwo.com",
|
valueIndex: 0,
|
||||||
"battwo.com": "https://battwo.com",
|
entries: mirrorEntries,
|
||||||
"comiko.net": "https://comiko.net",
|
entryValues: mirrorEntries.map((e) => "https://$e").toList()),
|
||||||
"comiko.org": "https://comiko.org",
|
];
|
||||||
"mangatoto.com": "https://mangatoto.com",
|
}
|
||||||
"mangatoto.net": "https://mangatoto.net",
|
|
||||||
"mangatoto.org": "https://mangatoto.org",
|
List<String> mirrorEntries = [
|
||||||
"readtoto.com": "https://readtoto.com",
|
"bato.to",
|
||||||
"readtoto.net": "https://readtoto.net",
|
"batocomic.com",
|
||||||
"readtoto.org": "https://readtoto.org",
|
"batocomic.net",
|
||||||
"dto.to": "https://dto.to",
|
"batocomic.org",
|
||||||
"hto.to": "https://hto.to",
|
"batotoo.com",
|
||||||
"mto.to": "https://mto.to",
|
"batotwo.com",
|
||||||
"wto.to": "https://wto.to",
|
"battwo.com",
|
||||||
"xbato.com": "https://xbato.com",
|
"comiko.net",
|
||||||
"xbato.net": "https://xbato.net",
|
"comiko.org",
|
||||||
"xbato.org": "https://xbato.org",
|
"mangatoto.com",
|
||||||
"zbato.com": "https://zbato.com",
|
"mangatoto.net",
|
||||||
"zbato.net": "https://zbato.net",
|
"mangatoto.org",
|
||||||
"zbato.org": "https://zbato.org",
|
"readtoto.com",
|
||||||
};
|
"readtoto.net",
|
||||||
|
"readtoto.org",
|
||||||
|
"dto.to",
|
||||||
|
"hto.to",
|
||||||
|
"mto.to",
|
||||||
|
"wto.to",
|
||||||
|
"xbato.com",
|
||||||
|
"xbato.net",
|
||||||
|
"xbato.org",
|
||||||
|
"zbato.com",
|
||||||
|
"zbato.net",
|
||||||
|
"zbato.org",
|
||||||
|
];
|
||||||
|
|
||||||
|
String preferenceMirror(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "mirror");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Batoto main() {
|
Batoto main() {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import '../../../../model/source.dart';
|
import '../../../../model/source.dart';
|
||||||
import '../../../../utils/utils.dart';
|
import '../../../../utils/utils.dart';
|
||||||
|
|
||||||
const batotoVersion = "0.0.4";
|
const batotoVersion = "0.0.45";
|
||||||
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";
|
||||||
|
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ class ComickFun extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
HeaderFilter("The filter is ignored when using text search."),
|
HeaderFilter("The filter is ignored when using text search."),
|
||||||
GroupFilter("GenreFilter", "Genre", [
|
GroupFilter("GenreFilter", "Genre", [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class MangaDex extends MProvider {
|
|||||||
Future<MPages> getPopular(MSource source, int page) async {
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
page = (20 * (page - 1));
|
page = (20 * (page - 1));
|
||||||
final url =
|
final url =
|
||||||
"https://api.mangadex.org/manga?limit=20&offset=$page&availableTranslatedLanguage[]=${source.lang}&includes[]=cover_art${getMDXContentRating()}&order[followedCount]=desc";
|
"https://api.mangadex.org/manga?limit=20&offset=$page&availableTranslatedLanguage[]=${source.lang}&includes[]=cover_art${preferenceContentRating(source.id)}${preferenceOriginalLanguages(source.id)}&order[followedCount]=desc";
|
||||||
final datas = {"url": url};
|
final datas = {"url": url};
|
||||||
final res = await http('GET', json.encode(datas));
|
final res = await http('GET', json.encode(datas));
|
||||||
return mangaRes(res, source);
|
return mangaRes(res, source);
|
||||||
@@ -24,12 +24,12 @@ class MangaDex extends MProvider {
|
|||||||
final mangaIds =
|
final mangaIds =
|
||||||
jsonPathToString(ress, r'$.data[*].relationships[*].id', '.--')
|
jsonPathToString(ress, r'$.data[*].relationships[*].id', '.--')
|
||||||
.split('.--');
|
.split('.--');
|
||||||
String mangaIdss = "".toString();
|
String mangaIdss = "";
|
||||||
for (var id in mangaIds) {
|
for (var id in mangaIds) {
|
||||||
mangaIdss += "&ids[]=$id";
|
mangaIdss += "&ids[]=$id";
|
||||||
}
|
}
|
||||||
final newUrl =
|
final newUrl =
|
||||||
"https://api.mangadex.org/manga?includes[]=cover_art&limit=${mangaIds.length}${getMDXContentRating()}$mangaIdss";
|
"https://api.mangadex.org/manga?includes[]=cover_art&limit=${mangaIds.length}${preferenceContentRating(source.id)}${preferenceOriginalLanguages(source.id)}$mangaIdss";
|
||||||
final res = await http('GET', json.encode({"url": newUrl}));
|
final res = await http('GET', json.encode({"url": newUrl}));
|
||||||
return mangaRes(res, source);
|
return mangaRes(res, source);
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@ class MangaDex extends MProvider {
|
|||||||
final mangaId = url.split('/').last;
|
final mangaId = url.split('/').last;
|
||||||
|
|
||||||
final paginatedChapterList =
|
final paginatedChapterList =
|
||||||
await paginatedChapterListRequest(mangaId, 0, source.lang);
|
await paginatedChapterListRequest(mangaId, 0, source.lang, source.id);
|
||||||
final chapterList =
|
final chapterList =
|
||||||
jsonPathToString(paginatedChapterList, r'$.data[*]', '_.').split('_.');
|
jsonPathToString(paginatedChapterList, r'$.data[*]', '_.').split('_.');
|
||||||
int limit =
|
int limit =
|
||||||
@@ -206,8 +206,8 @@ class MangaDex extends MProvider {
|
|||||||
var hasMoreResults = (limit + offset) < total;
|
var hasMoreResults = (limit + offset) < total;
|
||||||
while (hasMoreResults) {
|
while (hasMoreResults) {
|
||||||
offset += limit;
|
offset += limit;
|
||||||
var newRequest =
|
var newRequest = await paginatedChapterListRequest(
|
||||||
await paginatedChapterListRequest(mangaId, offset, source.lang);
|
mangaId, offset, source.lang, source.id);
|
||||||
int total = int.parse(jsonPathToString(newRequest, r'$.total', ''));
|
int total = int.parse(jsonPathToString(newRequest, r'$.total', ''));
|
||||||
final chapterList =
|
final chapterList =
|
||||||
jsonPathToString(paginatedChapterList, r'$.data[*]', '_.')
|
jsonPathToString(paginatedChapterList, r'$.data[*]', '_.')
|
||||||
@@ -244,7 +244,7 @@ class MangaDex extends MProvider {
|
|||||||
for (var e in resJson) {
|
for (var e in resJson) {
|
||||||
MManga manga = MManga();
|
MManga manga = MManga();
|
||||||
manga.name = findTitle(json.encode(e), source.lang);
|
manga.name = findTitle(json.encode(e), source.lang);
|
||||||
manga.imageUrl = getCover(json.encode(e));
|
manga.imageUrl = getCover(json.encode(e), source.id);
|
||||||
manga.link = "/manga/${getMapValue(json.encode(e), "id")}";
|
manga.link = "/manga/${getMapValue(json.encode(e), "id")}";
|
||||||
mangaList.add(manga);
|
mangaList.add(manga);
|
||||||
}
|
}
|
||||||
@@ -253,28 +253,28 @@ class MangaDex extends MProvider {
|
|||||||
|
|
||||||
List<MChapter> getChapters(int length, String paginatedChapterListA) {
|
List<MChapter> getChapters(int length, String paginatedChapterListA) {
|
||||||
List<MChapter> chaptersList = [];
|
List<MChapter> chaptersList = [];
|
||||||
String paginatedChapterList = paginatedChapterListA.toString();
|
String paginatedChapterList = paginatedChapterListA;
|
||||||
final dataList = jsonPathToList(paginatedChapterList, r'$.data[*]', 0);
|
final dataList = jsonPathToList(paginatedChapterList, r'$.data[*]', 0);
|
||||||
for (var res in dataList) {
|
for (var res in dataList) {
|
||||||
String scan = "".toString();
|
String scan = "";
|
||||||
final groups = jsonPathToList(res,
|
final groups = jsonPathToList(res,
|
||||||
r'$.relationships[?@.id!="00e03853-1b96-4f41-9542-c71b8692033b"]', 0);
|
r'$.relationships[?@.id!="00e03853-1b96-4f41-9542-c71b8692033b"]', 0);
|
||||||
String chapName = "".toString();
|
String chapName = "";
|
||||||
for (var element in groups) {
|
for (var element in groups) {
|
||||||
final data = getMapValue(element, "attributes", encode: true);
|
final data = getMapValue(element, "attributes", encode: true);
|
||||||
if (data.isNotEmpty) {
|
if (data.isNotEmpty) {
|
||||||
final name = getMapValue(data, "name");
|
final name = getMapValue(data, "name");
|
||||||
scan += "$name".toString();
|
scan += "$name";
|
||||||
final username = getMapValue(data, "username");
|
final username = getMapValue(data, "username");
|
||||||
if (username.isNotEmpty) {
|
if (username.isNotEmpty) {
|
||||||
if (scan.isEmpty) {
|
if (scan.isEmpty) {
|
||||||
scan += "Uploaded by $username".toString();
|
scan += "Uploaded by $username";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scan.isEmpty) {
|
if (scan.isEmpty) {
|
||||||
scan = "No Group".toString();
|
scan = "No Group";
|
||||||
}
|
}
|
||||||
final dataRes = getMapValue(res, "attributes", encode: true);
|
final dataRes = getMapValue(res, "attributes", encode: true);
|
||||||
if (dataRes.isNotEmpty) {
|
if (dataRes.isNotEmpty) {
|
||||||
@@ -282,26 +282,26 @@ class MangaDex extends MProvider {
|
|||||||
final volume = getMapValue(data, "volume");
|
final volume = getMapValue(data, "volume");
|
||||||
if (volume.isNotEmpty) {
|
if (volume.isNotEmpty) {
|
||||||
if (volume != "null") {
|
if (volume != "null") {
|
||||||
chapName = "Vol.$volume ".toString();
|
chapName = "Vol.$volume ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final chapter = getMapValue(data, "chapter");
|
final chapter = getMapValue(data, "chapter");
|
||||||
if (chapter.isNotEmpty) {
|
if (chapter.isNotEmpty) {
|
||||||
if (chapter != "null") {
|
if (chapter != "null") {
|
||||||
chapName += "Ch.$chapter ".toString();
|
chapName += "Ch.$chapter ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final title = getMapValue(data, "title");
|
final title = getMapValue(data, "title");
|
||||||
if (title.isNotEmpty) {
|
if (title.isNotEmpty) {
|
||||||
if (title != "null") {
|
if (title != "null") {
|
||||||
if (chapName.isNotEmpty) {
|
if (chapName.isNotEmpty) {
|
||||||
chapName += "- ".toString();
|
chapName += "- ";
|
||||||
}
|
}
|
||||||
chapName += "$title".toString();
|
chapName += "$title";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chapName.isEmpty) {
|
if (chapName.isEmpty) {
|
||||||
chapName += "Oneshot".toString();
|
chapName += "Oneshot";
|
||||||
}
|
}
|
||||||
final date = getMapValue(data, "publishAt");
|
final date = getMapValue(data, "publishAt");
|
||||||
final id = getMapValue(res, "id");
|
final id = getMapValue(res, "id");
|
||||||
@@ -319,19 +319,13 @@ class MangaDex extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<String> paginatedChapterListRequest(
|
Future<String> paginatedChapterListRequest(
|
||||||
String mangaId, int offset, String lang) async {
|
String mangaId, int offset, String lang, int sourceId) 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${preferenceContentRating(sourceId)}';
|
||||||
final res = await http('GET', json.encode({"url": url}));
|
final res = await http('GET', json.encode({"url": url}));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getMDXContentRating() {
|
|
||||||
String ctnRating =
|
|
||||||
"&contentRating[]=suggestive&contentRating[]=safe&contentRating[]=erotica&contentRating[]=pornographic";
|
|
||||||
return ctnRating;
|
|
||||||
}
|
|
||||||
|
|
||||||
String findTitle(String dataRes, String lang) {
|
String findTitle(String dataRes, String lang) {
|
||||||
final attributes = getMapValue(dataRes, "attributes", encode: true);
|
final attributes = getMapValue(dataRes, "attributes", encode: true);
|
||||||
final altTitlesJ =
|
final altTitlesJ =
|
||||||
@@ -349,7 +343,8 @@ class MangaDex extends MProvider {
|
|||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getCover(String dataRes) {
|
String getCover(String dataRes, int sourceId) {
|
||||||
|
final coverQuality = getPreferenceValue(sourceId, "cover_quality");
|
||||||
final relationships = json
|
final relationships = json
|
||||||
.decode(getMapValue(dataRes, "relationships", encode: true)) as List;
|
.decode(getMapValue(dataRes, "relationships", encode: true)) as List;
|
||||||
String coverFileName = "".toString();
|
String coverFileName = "".toString();
|
||||||
@@ -360,7 +355,7 @@ class MangaDex extends MProvider {
|
|||||||
final attributes =
|
final attributes =
|
||||||
getMapValue(json.encode(a), "attributes", encode: true);
|
getMapValue(json.encode(a), "attributes", encode: true);
|
||||||
coverFileName =
|
coverFileName =
|
||||||
"https://uploads.mangadex.org/covers/${getMapValue(dataRes, "id")}/${getMapValue(attributes, "fileName")}";
|
"https://uploads.mangadex.org/covers/${getMapValue(dataRes, "id")}/${getMapValue(attributes, "fileName")}$coverQuality";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,7 +363,7 @@ class MangaDex extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
CheckBoxFilter(
|
CheckBoxFilter(
|
||||||
"Has available chapters", "", "HasAvailableChaptersFilter"),
|
"Has available chapters", "", "HasAvailableChaptersFilter"),
|
||||||
@@ -510,6 +505,83 @@ class MangaDex extends MProvider {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
|
return [
|
||||||
|
ListPreference(
|
||||||
|
key: "cover_quality",
|
||||||
|
title: "Cover quality",
|
||||||
|
summary: "",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: ["Original", "Medium", "Low"],
|
||||||
|
entryValues: ["", ".512.jpg", ".256.jpg"]),
|
||||||
|
MultiSelectListPreference(
|
||||||
|
key: "content_rating",
|
||||||
|
title: "Default content rating",
|
||||||
|
summary: "Show content with the selected rating by default",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: [
|
||||||
|
"safe",
|
||||||
|
"suggestive",
|
||||||
|
"erotica",
|
||||||
|
"pornographic"
|
||||||
|
],
|
||||||
|
entryValues: [
|
||||||
|
"contentRating[]=safe",
|
||||||
|
"contentRating[]=suggestive",
|
||||||
|
"contentRating[]=erotica",
|
||||||
|
"contentRating[]=pornographic"
|
||||||
|
],
|
||||||
|
values: [
|
||||||
|
"contentRating[]=safe",
|
||||||
|
"contentRating[]=suggestive"
|
||||||
|
]),
|
||||||
|
MultiSelectListPreference(
|
||||||
|
key: "original_languages",
|
||||||
|
title: "Filter original languages",
|
||||||
|
summary:
|
||||||
|
"Only show content that was originaly published in the selected languages in both latest and browse",
|
||||||
|
valueIndex: 0,
|
||||||
|
entries: [
|
||||||
|
"Japanese",
|
||||||
|
"Chinese",
|
||||||
|
"Korean"
|
||||||
|
],
|
||||||
|
entryValues: [
|
||||||
|
"originalLanguage[]=ja",
|
||||||
|
"originalLanguage[]=zh&originalLanguage[]=zh-hk",
|
||||||
|
"originalLanguage[]=ko"
|
||||||
|
],
|
||||||
|
values: []),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
String preferenceContentRating(int sourceId) {
|
||||||
|
final contentRating =
|
||||||
|
getPreferenceValue(sourceId, "content_rating") as List<String>;
|
||||||
|
String contentRatingStr = "";
|
||||||
|
if (contentRating.isNotEmpty) {
|
||||||
|
contentRatingStr = "&";
|
||||||
|
for (var ctn in contentRating) {
|
||||||
|
contentRatingStr += "&$ctn";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return contentRatingStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
String preferenceOriginalLanguages(int sourceId) {
|
||||||
|
final originalLanguages =
|
||||||
|
getPreferenceValue(sourceId, "original_languages") as List<String>;
|
||||||
|
String originalLanguagesStr = "";
|
||||||
|
if (originalLanguages.isNotEmpty) {
|
||||||
|
originalLanguagesStr = "&";
|
||||||
|
for (var language in originalLanguages) {
|
||||||
|
originalLanguagesStr += "&$language";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return originalLanguagesStr;
|
||||||
|
}
|
||||||
|
|
||||||
String ll(String url) {
|
String ll(String url) {
|
||||||
if (url.contains("?")) {
|
if (url.contains("?")) {
|
||||||
return "&";
|
return "&";
|
||||||
@@ -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.45";
|
const mangadexVersion = "0.0.5";
|
||||||
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");
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ class MangaHere extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> getFilterList() {
|
List<dynamic> getFilterList(MSource source) {
|
||||||
return [
|
return [
|
||||||
SelectFilter("TypeList", "Type", 1, [
|
SelectFilter("TypeList", "Type", 1, [
|
||||||
SelectFilterOption("American Manga", "5"),
|
SelectFilterOption("American Manga", "5"),
|
||||||
|
|||||||
@@ -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.1.1"});
|
this.appMinVerReq = "0.1.2"});
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user