mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-17 12:20:28 +00:00
add filter method
This commit is contained in:
@@ -67,11 +67,53 @@ class Madara extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> search(MSource source, String query, int page) async {
|
Future<MPages> search(
|
||||||
final data = {
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
"url": "${source.baseUrl}/?s=$query&post_type=wp-manga",
|
final filters = filterList.filters;
|
||||||
"sourceId": source.id
|
|
||||||
};
|
String url = "${source.baseUrl}/?s=$query&post_type=wp-manga";
|
||||||
|
|
||||||
|
for (var filter in filters) {
|
||||||
|
if (filter.type == "AuthorFilter") {
|
||||||
|
if (filter.state.isNotEmpty) {
|
||||||
|
url += "${ll(url)}author=${Uri.encodeComponent(filter.state)}";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "ArtistFilter") {
|
||||||
|
if (filter.state.isNotEmpty) {
|
||||||
|
url += "${ll(url)}artist=${Uri.encodeComponent(filter.state)}";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "YearFilter") {
|
||||||
|
if (filter.state.isNotEmpty) {
|
||||||
|
url += "${ll(url)}release=${Uri.encodeComponent(filter.state)}";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "StatusFilter") {
|
||||||
|
final status = (filter.state as List).where((e) => e.state).toList();
|
||||||
|
if (status.isNotEmpty) {
|
||||||
|
for (var st in status) {
|
||||||
|
url += "${ll(url)}status[]=${st.value},";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (filter.type == "OrderByFilter") {
|
||||||
|
if (filter.state != 0) {
|
||||||
|
final order = filter.values[filter.state].value;
|
||||||
|
url += "${ll(url)}m_orderby=$order";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "AdultContentFilter") {
|
||||||
|
final ctn = filter.values[filter.state].value;
|
||||||
|
if (ctn.isNotEmpty) {
|
||||||
|
url += "${ll(url)}adult=$ctn";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "GenreListFilter") {
|
||||||
|
final genres = (filter.state as List).where((e) => e.state).toList();
|
||||||
|
if (genres.isNotEmpty) {
|
||||||
|
for (var genre in genres) {
|
||||||
|
url += "${ll(url)}genre[]=${genre.value},";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final data = {"url": url, "sourceId": source.id};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
List<MManga> mangaList = [];
|
List<MManga> mangaList = [];
|
||||||
@@ -312,6 +354,41 @@ class Madara extends MProvider {
|
|||||||
}
|
}
|
||||||
return pageUrls;
|
return pageUrls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<dynamic> getFilterList() {
|
||||||
|
return [
|
||||||
|
TextFilter("AuthorFilter", "Author"),
|
||||||
|
TextFilter("ArtistFilter", "Artist"),
|
||||||
|
TextFilter("YearFilter", "Year of Released"),
|
||||||
|
GroupFilter("StatusFilter", "Status", [
|
||||||
|
CheckBoxFilter("Completed", "end"),
|
||||||
|
CheckBoxFilter("Ongoing", "on-going"),
|
||||||
|
CheckBoxFilter("Canceled", "canceled"),
|
||||||
|
CheckBoxFilter("On Hold", "on-hold"),
|
||||||
|
]),
|
||||||
|
SelectFilter("OrderByFilter", "Order By", 0, [
|
||||||
|
SelectFilterOption("Relevance", ""),
|
||||||
|
SelectFilterOption("Latest", "latest"),
|
||||||
|
SelectFilterOption("A-Z", "alphabet"),
|
||||||
|
SelectFilterOption("Rating", "rating"),
|
||||||
|
SelectFilterOption("Trending", "trending"),
|
||||||
|
SelectFilterOption("Most Views", "views"),
|
||||||
|
SelectFilterOption("New", "new-manga"),
|
||||||
|
]),
|
||||||
|
SelectFilter("AdultContentFilter", "Adult Content", 0, [
|
||||||
|
SelectFilterOption("All", ""),
|
||||||
|
SelectFilterOption("None", "0"),
|
||||||
|
SelectFilterOption("Only", "1"),
|
||||||
|
])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
String ll(String url) {
|
||||||
|
if (url.contains("?")) {
|
||||||
|
return "&";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Madara main() {
|
Madara main() {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import '../../../model/source.dart';
|
import '../../../model/source.dart';
|
||||||
import '../../../utils/utils.dart';
|
import '../../../utils/utils.dart';
|
||||||
|
|
||||||
const madaraVersion = "0.0.35";
|
const madaraVersion = "0.0.4";
|
||||||
const madaraSourceCodeUrl =
|
const madaraSourceCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/madara/madara-v$madaraVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/madara/madara-v$madaraVersion.dart";
|
||||||
const defaultDateFormat = "MMMM dd, yyyy";
|
const defaultDateFormat = "MMMM dd, yyyy";
|
||||||
|
|||||||
@@ -25,9 +25,49 @@ class MangaReader extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> search(MSource source, String query, int page) async {
|
Future<MPages> search(
|
||||||
final url =
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
|
final filters = filterList.filters;
|
||||||
|
|
||||||
|
String url =
|
||||||
"${source.baseUrl}${getMangaUrlDirectory(source.name)}/?&title=$query&page=$page";
|
"${source.baseUrl}${getMangaUrlDirectory(source.name)}/?&title=$query&page=$page";
|
||||||
|
|
||||||
|
for (var filter in filters) {
|
||||||
|
if (filter.type == "AuthorFilter") {
|
||||||
|
url += "${ll(url)}author=${Uri.encodeComponent(filter.state)}";
|
||||||
|
} else if (filter.type == "YearFilter") {
|
||||||
|
url += "${ll(url)}yearx=${Uri.encodeComponent(filter.state)}";
|
||||||
|
} else if (filter.type == "StatusFilter") {
|
||||||
|
final status = filter.values[filter.state].value;
|
||||||
|
url += "${ll(url)}status=$status";
|
||||||
|
} else if (filter.type == "TypeFilter") {
|
||||||
|
final type = filter.values[filter.state].value;
|
||||||
|
url += "${ll(url)}type=$type";
|
||||||
|
} else if (filter.type == "OrderByFilter") {
|
||||||
|
final order = filter.values[filter.state].value;
|
||||||
|
url += "${ll(url)}order=$order";
|
||||||
|
} else if (filter.type == "GenreListFilter") {
|
||||||
|
final included = (filter.state as List)
|
||||||
|
.where((e) => e.state == 1 ? true : false)
|
||||||
|
.toList();
|
||||||
|
final excluded = (filter.state as List)
|
||||||
|
.where((e) => e.state == 2 ? true : false)
|
||||||
|
.toList();
|
||||||
|
if (included.isNotEmpty) {
|
||||||
|
url += "${ll(url)}genres[]=";
|
||||||
|
for (var val in included) {
|
||||||
|
url += "${val.value},";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (excluded.isNotEmpty) {
|
||||||
|
url += "${ll(url)}genres[]=";
|
||||||
|
for (var val in excluded) {
|
||||||
|
url += "-${val.value},";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final data = {"url": url, "sourceId": source.id};
|
final data = {"url": url, "sourceId": source.id};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
@@ -195,6 +235,47 @@ class MangaReader extends MProvider {
|
|||||||
return MPages(mangaList, true);
|
return MPages(mangaList, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<dynamic> getFilterList() {
|
||||||
|
return [
|
||||||
|
SeparatorFilter(),
|
||||||
|
TextFilter("AuthorFilter", "Author"),
|
||||||
|
TextFilter("YearFilter", "Year"),
|
||||||
|
SelectFilter("StatusFilter", "Status", 0, [
|
||||||
|
SelectFilterOption("All", ""),
|
||||||
|
SelectFilterOption("Ongoing", "ongoing"),
|
||||||
|
SelectFilterOption("Completed", "completed"),
|
||||||
|
SelectFilterOption("Hiatus", "hiatus"),
|
||||||
|
SelectFilterOption("Dropped", "dropped"),
|
||||||
|
]),
|
||||||
|
SelectFilter("TypeFilter", "Type", 0, [
|
||||||
|
SelectFilterOption("All", ""),
|
||||||
|
SelectFilterOption("Manga", "Manga"),
|
||||||
|
SelectFilterOption("Manhwa", "Manhwa"),
|
||||||
|
SelectFilterOption("Manhua", "Manhua"),
|
||||||
|
SelectFilterOption("Comic", "Comic"),
|
||||||
|
]),
|
||||||
|
SelectFilter("OrderByFilter", "Sort By", 0, [
|
||||||
|
SelectFilterOption("Default", ""),
|
||||||
|
SelectFilterOption("A-Z", "title"),
|
||||||
|
SelectFilterOption("Z-A", "titlereverse"),
|
||||||
|
SelectFilterOption("Latest Update", "update"),
|
||||||
|
SelectFilterOption("Latest Added", "latest"),
|
||||||
|
SelectFilterOption("Popular", "popular"),
|
||||||
|
]),
|
||||||
|
HeaderFilter("Genre exclusion is not available for all sources"),
|
||||||
|
GroupFilter("GenreListFilter", "Genre", [
|
||||||
|
TriStateFilter("Press reset to attempt to fetch genres", ""),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
String ll(String url) {
|
||||||
|
if (url.contains("?")) {
|
||||||
|
return "&";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
String getMangaUrlDirectory(String sourceName) {
|
String getMangaUrlDirectory(String sourceName) {
|
||||||
if (sourceName == "Sushi-Scan") {
|
if (sourceName == "Sushi-Scan") {
|
||||||
return "/catalogue";
|
return "/catalogue";
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import '../../../model/source.dart';
|
import '../../../model/source.dart';
|
||||||
import '../../../utils/utils.dart';
|
import '../../../utils/utils.dart';
|
||||||
|
|
||||||
const mangareaderVersion = "0.0.45";
|
const mangareaderVersion = "0.0.5";
|
||||||
const mangareaderSourceCodeUrl =
|
const mangareaderSourceCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/mangareader/mangareader-v$mangareaderVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/mangareader/mangareader-v$mangareaderVersion.dart";
|
||||||
const defaultDateFormat = "MMMM dd, yyyy";
|
const defaultDateFormat = "MMMM dd, yyyy";
|
||||||
|
|||||||
@@ -68,16 +68,45 @@ class MMRCMS extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> search(MSource source, String query, int page) async {
|
Future<MPages> search(
|
||||||
final url = "${source.baseUrl}/search?query=$query";
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
|
final filters = filterList.filters;
|
||||||
|
String url = "";
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
url = "${source.baseUrl}/search?query=$query";
|
||||||
|
} else {
|
||||||
|
url = "${source.baseUrl}/filterList?page=$page";
|
||||||
|
for (var filter in filters) {
|
||||||
|
if (filter.type == "AuthorFilter") {
|
||||||
|
url += "${ll(url)}author=${Uri.encodeComponent(filter.state)}";
|
||||||
|
} else if (filter.type == "SortFilter") {
|
||||||
|
url += "${ll(url)}sortBy=${filter.values[filter.state.index].value}";
|
||||||
|
final asc = filter.state.ascending ? "asc=true" : "asc=false";
|
||||||
|
url += "${ll(url)}$asc";
|
||||||
|
} else if (filter.type == "CategoryFilter") {
|
||||||
|
if (filter.state != 0) {
|
||||||
|
final cat = filter.values[filter.state].value;
|
||||||
|
url += "${ll(url)}cat=$cat";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "BeginsWithFilter") {
|
||||||
|
if (filter.state != 0) {
|
||||||
|
final a = filter.values[filter.state].value;
|
||||||
|
url += "${ll(url)}alpha=$a";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
final data = {"url": url, "sourceId": source.id};
|
final data = {"url": url, "sourceId": source.id};
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
List<MManga> mangaList = [];
|
List<MManga> mangaList = [];
|
||||||
final jsonList = json.decode(res)["suggestions"];
|
|
||||||
List<String> urls = [];
|
List<String> urls = [];
|
||||||
List<String> names = [];
|
List<String> names = [];
|
||||||
List<String> images = [];
|
List<String> images = [];
|
||||||
|
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
final jsonList = json.decode(res)["suggestions"];
|
||||||
for (var da in jsonList) {
|
for (var da in jsonList) {
|
||||||
String value = da["value"];
|
String value = da["value"];
|
||||||
String data = da["data"];
|
String data = da["data"];
|
||||||
@@ -96,6 +125,19 @@ class MMRCMS extends MProvider {
|
|||||||
"${source.baseUrl}/uploads/manga/$data/cover/cover_250x350.jpg");
|
"${source.baseUrl}/uploads/manga/$data/cover/cover_250x350.jpg");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
urls = xpath(res, '//div/div/div/a/@href');
|
||||||
|
names = xpath(res, '//div/div/div/a/text()');
|
||||||
|
for (var url in urls) {
|
||||||
|
String slug = substringAfterLast(url, '/');
|
||||||
|
if (source.name == "Manga-FR") {
|
||||||
|
images.add("${source.baseUrl}/uploads/manga/${slug}.jpg");
|
||||||
|
} else {
|
||||||
|
images.add(
|
||||||
|
"${source.baseUrl}/uploads/manga/${slug}/cover/cover_250x350.jpg");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < names.length; i++) {
|
for (var i = 0; i < names.length; i++) {
|
||||||
MManga manga = MManga();
|
MManga manga = MManga();
|
||||||
@@ -189,6 +231,91 @@ class MMRCMS extends MProvider {
|
|||||||
|
|
||||||
return pagesUrl;
|
return pagesUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<dynamic> getFilterList() {
|
||||||
|
return [
|
||||||
|
HeaderFilter("NOTE: Ignored if using text search!"),
|
||||||
|
SeparatorFilter(),
|
||||||
|
TextFilter("AuthorFilter", "Author"),
|
||||||
|
SelectFilter("CategoryFilter", "Category", 0, [
|
||||||
|
SelectFilterOption("Any", ""),
|
||||||
|
SelectFilterOption("Action", "Action"),
|
||||||
|
SelectFilterOption("Adventure", "Adventure"),
|
||||||
|
SelectFilterOption("Comedy", "Comedy"),
|
||||||
|
SelectFilterOption("Doujinshi", "Doujinshi"),
|
||||||
|
SelectFilterOption("Drama", "Drama"),
|
||||||
|
SelectFilterOption("Ecchi", "Ecchi"),
|
||||||
|
SelectFilterOption("Fantasy", "Fantasy"),
|
||||||
|
SelectFilterOption("Gender Bender", "Gender Bender"),
|
||||||
|
SelectFilterOption("Harem", "Harem"),
|
||||||
|
SelectFilterOption("Historical", "Historical"),
|
||||||
|
SelectFilterOption("Horror", "Horror"),
|
||||||
|
SelectFilterOption("Josei", "Josei"),
|
||||||
|
SelectFilterOption("Martial Arts", "Martial Arts"),
|
||||||
|
SelectFilterOption("Mature", "Mature"),
|
||||||
|
SelectFilterOption("Mecha", "Mecha"),
|
||||||
|
SelectFilterOption("Mystery", "Mystery"),
|
||||||
|
SelectFilterOption("One Shot", "One Shot"),
|
||||||
|
SelectFilterOption("Psychological", "Psychological"),
|
||||||
|
SelectFilterOption("Romance", "Romance"),
|
||||||
|
SelectFilterOption("School Life", "School Life"),
|
||||||
|
SelectFilterOption("Sci-fi", "Sci-fi"),
|
||||||
|
SelectFilterOption("Seinen", "Seinen"),
|
||||||
|
SelectFilterOption("Shoujo", "Shoujo"),
|
||||||
|
SelectFilterOption("Shoujo Ai", "Shoujo Ai"),
|
||||||
|
SelectFilterOption("Shounen", "Shounen"),
|
||||||
|
SelectFilterOption("Shounen Ai", "Shounen Ai"),
|
||||||
|
SelectFilterOption("Slice of Life", "Slice of Life"),
|
||||||
|
SelectFilterOption("Sports", "Sports"),
|
||||||
|
SelectFilterOption("Supernatural", "Supernatural"),
|
||||||
|
SelectFilterOption("Tragedy", "Tragedy"),
|
||||||
|
SelectFilterOption("Yaoi", "Yaoi"),
|
||||||
|
SelectFilterOption("Yuri", "Yuri"),
|
||||||
|
]),
|
||||||
|
SelectFilter("BeginsWithFilter", "Begins with", 0, [
|
||||||
|
SelectFilterOption("Any", ""),
|
||||||
|
SelectFilterOption("#", "#"),
|
||||||
|
SelectFilterOption("A", "A"),
|
||||||
|
SelectFilterOption("B", "B"),
|
||||||
|
SelectFilterOption("C", "C"),
|
||||||
|
SelectFilterOption("D", "D"),
|
||||||
|
SelectFilterOption("E", "E"),
|
||||||
|
SelectFilterOption("F", "F"),
|
||||||
|
SelectFilterOption("G", "G"),
|
||||||
|
SelectFilterOption("H", "H"),
|
||||||
|
SelectFilterOption("I", "I"),
|
||||||
|
SelectFilterOption("J", "J"),
|
||||||
|
SelectFilterOption("K", "K"),
|
||||||
|
SelectFilterOption("L", "L"),
|
||||||
|
SelectFilterOption("M", "M"),
|
||||||
|
SelectFilterOption("N", "N"),
|
||||||
|
SelectFilterOption("O", "O"),
|
||||||
|
SelectFilterOption("P", "P"),
|
||||||
|
SelectFilterOption("Q", "Q"),
|
||||||
|
SelectFilterOption("R", "R"),
|
||||||
|
SelectFilterOption("S", "S"),
|
||||||
|
SelectFilterOption("T", "T"),
|
||||||
|
SelectFilterOption("U", "U"),
|
||||||
|
SelectFilterOption("V", "V"),
|
||||||
|
SelectFilterOption("W", "W"),
|
||||||
|
SelectFilterOption("X", "X"),
|
||||||
|
SelectFilterOption("Y", "Y"),
|
||||||
|
SelectFilterOption("Z", "Z"),
|
||||||
|
]),
|
||||||
|
SortFilter("SortFilter", "Sort", SortState(0, true), [
|
||||||
|
SelectFilterOption("Name", "name"),
|
||||||
|
SelectFilterOption("Popularity", "views"),
|
||||||
|
SelectFilterOption("Last update", "last_release"),
|
||||||
|
])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
String ll(String url) {
|
||||||
|
if (url.contains("?")) {
|
||||||
|
return "&";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MMRCMS main() {
|
MMRCMS main() {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import '../../../model/source.dart';
|
import '../../../model/source.dart';
|
||||||
import '../../../utils/utils.dart';
|
import '../../../utils/utils.dart';
|
||||||
|
|
||||||
const mmrcmsVersion = "0.0.35";
|
const mmrcmsVersion = "0.0.4";
|
||||||
const mmrcmsSourceCodeUrl =
|
const mmrcmsSourceCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/mmrcms/mmrcms-v$mmrcmsVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/mmrcms/mmrcms-v$mmrcmsVersion.dart";
|
||||||
const defaultDateFormat = "d MMM. yyyy";
|
const defaultDateFormat = "d MMM. yyyy";
|
||||||
|
|||||||
@@ -1,182 +0,0 @@
|
|||||||
import 'package:mangayomi/bridge_lib.dart';
|
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
class ComickFun extends MProvider {
|
|
||||||
ComickFun();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<MPages> getPopular(MSource source, int page) async {
|
|
||||||
final url =
|
|
||||||
"${source.apiUrl}/v1.0/search?sort=follow&page=$page&tachiyomi=true";
|
|
||||||
final data = {"url": url, "headers": getHeader(source.baseUrl)};
|
|
||||||
final res = await http('GET', json.encode(data));
|
|
||||||
return mangaRes(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
|
||||||
final url =
|
|
||||||
"${source.apiUrl}/v1.0/search?sort=uploaded&page=$page&tachiyomi=true";
|
|
||||||
final data = {"url": url, "headers": getHeader(source.baseUrl)};
|
|
||||||
final res = await http('GET', json.encode(data));
|
|
||||||
return mangaRes(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<MPages> search(MSource source, String query, int page) async {
|
|
||||||
final url = "${source.apiUrl}/v1.0/search?q=$query&tachiyomi=true";
|
|
||||||
final data = {"url": url, "headers": getHeader(source.baseUrl)};
|
|
||||||
final res = await http('GET', json.encode(data));
|
|
||||||
return mangaRes(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<MManga> getDetail(MSource source, String url) async {
|
|
||||||
final statusList = [
|
|
||||||
{"1": 0, "2": 1, "3": 3, "4": 2}
|
|
||||||
];
|
|
||||||
|
|
||||||
final headers = getHeader(source.baseUrl);
|
|
||||||
|
|
||||||
final urll = "${source.apiUrl}${url.replaceAll("#", '')}?tachiyomi=true";
|
|
||||||
final data = {"url": urll, "headers": headers};
|
|
||||||
final res = await http('GET', json.encode(data));
|
|
||||||
MManga manga = MManga();
|
|
||||||
manga.author = jsonPathToString(res, r'$.authors[*].name', '');
|
|
||||||
manga.genre = jsonPathToString(res, r'$.genres[*].name', "_.").split("_.");
|
|
||||||
manga.description = jsonPathToString(res, r'$..desc', '');
|
|
||||||
manga.status =
|
|
||||||
parseStatus(jsonPathToString(res, r'$..comic.status', ''), statusList);
|
|
||||||
final chapUrlReq =
|
|
||||||
"${source.apiUrl}${url.replaceAll("#", '')}chapters?lang=${source.lang}&tachiyomi=true&page=1";
|
|
||||||
final dataReq = {"url": chapUrlReq, "headers": headers};
|
|
||||||
final request = await http('GET', json.encode(dataReq));
|
|
||||||
var total = jsonPathToString(request, r'$.total', '');
|
|
||||||
final chapterLimit = int.parse(total);
|
|
||||||
final newChapUrlReq =
|
|
||||||
"${source.apiUrl}${url.replaceAll("#", '')}chapters?limit=$chapterLimit&lang=${source.lang}&tachiyomi=true&page=1";
|
|
||||||
|
|
||||||
final newDataReq = {"url": newChapUrlReq, "headers": headers};
|
|
||||||
final newRequest = await http('GET', json.encode(newDataReq));
|
|
||||||
|
|
||||||
final chapsUrls =
|
|
||||||
jsonPathToString(newRequest, r'$.chapters[*].hid', "_.").split("_.");
|
|
||||||
final chapDate =
|
|
||||||
jsonPathToString(newRequest, r'$.chapters[*].created_at', "_.")
|
|
||||||
.split("_.");
|
|
||||||
final chaptersVolumes =
|
|
||||||
jsonPathToString(newRequest, r'$.chapters[*].vol', "_.").split("_.");
|
|
||||||
final chaptersScanlators =
|
|
||||||
jsonPathToString(newRequest, r'$.chapters[*].group_name', "_.")
|
|
||||||
.split("_.");
|
|
||||||
final chapsNames =
|
|
||||||
jsonPathToString(newRequest, r'$.chapters[*].title', "_.").split("_.");
|
|
||||||
final chaptersChaps =
|
|
||||||
jsonPathToString(newRequest, r'$.chapters[*].chap', "_.").split("_.");
|
|
||||||
|
|
||||||
var dateUploads =
|
|
||||||
parseDates(chapDate, source.dateFormat, source.dateFormatLocale);
|
|
||||||
List<MChapter>? chaptersList = [];
|
|
||||||
for (var i = 0; i < chapsNames.length; i++) {
|
|
||||||
String title = "";
|
|
||||||
String scanlator = "";
|
|
||||||
if (chaptersChaps.isNotEmpty && chaptersVolumes.isNotEmpty) {
|
|
||||||
title = beautifyChapterName(
|
|
||||||
chaptersVolumes[i], chaptersChaps[i], chapsNames[i], source.lang);
|
|
||||||
} else {
|
|
||||||
title = chapsNames[i];
|
|
||||||
}
|
|
||||||
if (chaptersScanlators.isNotEmpty) {
|
|
||||||
scanlator = chaptersScanlators[i]
|
|
||||||
.toString()
|
|
||||||
.replaceAll(']', "")
|
|
||||||
.replaceAll("[", "");
|
|
||||||
}
|
|
||||||
MChapter chapter = MChapter();
|
|
||||||
chapter.name = title;
|
|
||||||
chapter.url = chapsUrls[i];
|
|
||||||
chapter.scanlator = scanlator == "null" ? "" : scanlator;
|
|
||||||
chapter.dateUpload = dateUploads[i];
|
|
||||||
chaptersList.add(chapter);
|
|
||||||
}
|
|
||||||
manga.chapters = chaptersList;
|
|
||||||
return manga;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<String>> getPageList(MSource source, String url) async {
|
|
||||||
final urll = "${source.apiUrl}/chapter/$url?tachiyomi=true";
|
|
||||||
final data = {"url": urll, "headers": getHeader(url)};
|
|
||||||
final res = await http('GET', json.encode(data));
|
|
||||||
return jsonPathToString(res, r'$.chapter.images[*].url', '_.').split('_.');
|
|
||||||
}
|
|
||||||
|
|
||||||
MPages mangaRes(String res) async {
|
|
||||||
final names = jsonPathToList(res, r'$.title', 0);
|
|
||||||
List<String> ids = jsonPathToList(res, r'$.hid', 0);
|
|
||||||
List<String> mangaUrls = [];
|
|
||||||
for (var id in ids) {
|
|
||||||
mangaUrls.add("/comic/$id/#");
|
|
||||||
}
|
|
||||||
final urls = mangaUrls;
|
|
||||||
final images = jsonPathToList(res, r'$.cover_url', 0);
|
|
||||||
List<MManga> mangaList = [];
|
|
||||||
for (var i = 0; i < urls.length; i++) {
|
|
||||||
MManga manga = MManga();
|
|
||||||
manga.name = names[i];
|
|
||||||
manga.imageUrl = images[i];
|
|
||||||
manga.link = urls[i];
|
|
||||||
mangaList.add(manga);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MPages(mangaList, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
String beautifyChapterName(
|
|
||||||
String vol, String chap, String title, String lang) {
|
|
||||||
String result = "";
|
|
||||||
|
|
||||||
if (vol != "null" && vol.isNotEmpty) {
|
|
||||||
if (chap != "null" && chap.isEmpty) {
|
|
||||||
result += "Volume $vol ";
|
|
||||||
} else {
|
|
||||||
result += "Vol. $vol ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chap != "null" && chap.isNotEmpty) {
|
|
||||||
if (vol != "null" && vol.isEmpty) {
|
|
||||||
if (lang != "null" && lang == "fr") {
|
|
||||||
result += "Chapitre $chap";
|
|
||||||
} else {
|
|
||||||
result += "Chapter $chap";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result += "Ch. $chap ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (title != "null" && title.isNotEmpty) {
|
|
||||||
if (chap != "null" && chap.isEmpty) {
|
|
||||||
result += title;
|
|
||||||
} else {
|
|
||||||
result += " : $title";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> getHeader(String url) {
|
|
||||||
final headers = {
|
|
||||||
"Referer": "$url/",
|
|
||||||
'User-Agent':
|
|
||||||
"Tachiyomi Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0"
|
|
||||||
};
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComickFun main() {
|
|
||||||
return ComickFun();
|
|
||||||
}
|
|
||||||
647
manga/src/all/comick/comick-v0.0.4.dart
Normal file
647
manga/src/all/comick/comick-v0.0.4.dart
Normal file
@@ -0,0 +1,647 @@
|
|||||||
|
import 'package:mangayomi/bridge_lib.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class ComickFun extends MProvider {
|
||||||
|
ComickFun();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
|
final url =
|
||||||
|
"${source.apiUrl}/v1.0/search?sort=follow&page=$page&tachiyomi=true";
|
||||||
|
final data = {"url": url, "headers": getHeader(source.baseUrl)};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
return mangaRes(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
||||||
|
final url =
|
||||||
|
"${source.apiUrl}/v1.0/search?sort=uploaded&page=$page&tachiyomi=true";
|
||||||
|
final data = {"url": url, "headers": getHeader(source.baseUrl)};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
return mangaRes(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> search(
|
||||||
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
|
final filters = filterList.filters;
|
||||||
|
String url = "";
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
url = "${source.apiUrl}/v1.0/search?q=$query&tachiyomi=true";
|
||||||
|
} else {
|
||||||
|
url = "${source.apiUrl}/v1.0/search";
|
||||||
|
for (var filter in filters) {
|
||||||
|
if (filter.type == "CompletedFilter") {
|
||||||
|
if (filter.state) {
|
||||||
|
url += "${ll(url)}completed=true";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "GenreFilter") {
|
||||||
|
final included = (filter.state as List)
|
||||||
|
.where((e) => e.state == 1 ? true : false)
|
||||||
|
.toList();
|
||||||
|
final excluded = (filter.state as List)
|
||||||
|
.where((e) => e.state == 2 ? true : false)
|
||||||
|
.toList();
|
||||||
|
if (included.isNotEmpty) {
|
||||||
|
for (var val in included) {
|
||||||
|
url += "${ll(url)}genres=${val.value}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (excluded.isNotEmpty) {
|
||||||
|
for (var val in excluded) {
|
||||||
|
url += "${ll(url)}excludes=${val.value}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (filter.type == "DemographicFilter") {
|
||||||
|
final included = (filter.state as List)
|
||||||
|
.where((e) => e.state == 1 ? true : false)
|
||||||
|
.toList();
|
||||||
|
if (included.isNotEmpty) {
|
||||||
|
for (var val in included) {
|
||||||
|
url += "${ll(url)}demographic=${val.value}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (filter.type == "TypeFilter") {
|
||||||
|
final country = (filter.state as List).where((e) => e.state).toList();
|
||||||
|
if (country.isNotEmpty) {
|
||||||
|
for (var coun in country) {
|
||||||
|
url += "${ll(url)}country=${coun.value}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (filter.type == "SortFilter") {
|
||||||
|
url += "${ll(url)}sort=${filter.values[filter.state].value}";
|
||||||
|
} else if (filter.type == "StatusFilter") {
|
||||||
|
url += "${ll(url)}status=${filter.values[filter.state].value}";
|
||||||
|
} else if (filter.type == "CreatedAtFilter") {
|
||||||
|
if (filter.state > 0) {
|
||||||
|
url += "${ll(url)}time=${filter.values[filter.state].value}";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "MinimumFilter") {
|
||||||
|
if (filter.state.isNotEmpty) {
|
||||||
|
url += "${ll(url)}minimum=${filter.state}";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "FromYearFilter") {
|
||||||
|
if (filter.state.isNotEmpty) {
|
||||||
|
url += "${ll(url)}from=${filter.state}";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "ToYearFilter") {
|
||||||
|
if (filter.state.isNotEmpty) {
|
||||||
|
url += "${ll(url)}to=${filter.state}";
|
||||||
|
}
|
||||||
|
} else if (filter.type == "TagFilter") {
|
||||||
|
if (filter.state.isNotEmpty) {
|
||||||
|
final tags = (filter.state as String).split(",");
|
||||||
|
for (var tag in tags) {
|
||||||
|
url += "${ll(url)}tags=$tag";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
url += "${ll(url)}page=$page&tachiyomi=true";
|
||||||
|
}
|
||||||
|
final data = {"url": url, "headers": getHeader(source.baseUrl)};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
return mangaRes(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MManga> getDetail(MSource source, String url) async {
|
||||||
|
final statusList = [
|
||||||
|
{"1": 0, "2": 1, "3": 3, "4": 2}
|
||||||
|
];
|
||||||
|
|
||||||
|
final headers = getHeader(source.baseUrl);
|
||||||
|
|
||||||
|
final urll = "${source.apiUrl}${url.replaceAll("#", '')}?tachiyomi=true";
|
||||||
|
final data = {"url": urll, "headers": headers};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
MManga manga = MManga();
|
||||||
|
manga.author = jsonPathToString(res, r'$.authors[*].name', '');
|
||||||
|
manga.genre = jsonPathToString(res, r'$.genres[*].name', "_.").split("_.");
|
||||||
|
manga.description = jsonPathToString(res, r'$..desc', '');
|
||||||
|
manga.status =
|
||||||
|
parseStatus(jsonPathToString(res, r'$..comic.status', ''), statusList);
|
||||||
|
final chapUrlReq =
|
||||||
|
"${source.apiUrl}${url.replaceAll("#", '')}chapters?lang=${source.lang}&tachiyomi=true&page=1";
|
||||||
|
final dataReq = {"url": chapUrlReq, "headers": headers};
|
||||||
|
final request = await http('GET', json.encode(dataReq));
|
||||||
|
var total = jsonPathToString(request, r'$.total', '');
|
||||||
|
final chapterLimit = int.parse(total);
|
||||||
|
final newChapUrlReq =
|
||||||
|
"${source.apiUrl}${url.replaceAll("#", '')}chapters?limit=$chapterLimit&lang=${source.lang}&tachiyomi=true&page=1";
|
||||||
|
|
||||||
|
final newDataReq = {"url": newChapUrlReq, "headers": headers};
|
||||||
|
final newRequest = await http('GET', json.encode(newDataReq));
|
||||||
|
|
||||||
|
final chapsUrls =
|
||||||
|
jsonPathToString(newRequest, r'$.chapters[*].hid', "_.").split("_.");
|
||||||
|
final chapDate =
|
||||||
|
jsonPathToString(newRequest, r'$.chapters[*].created_at', "_.")
|
||||||
|
.split("_.");
|
||||||
|
final chaptersVolumes =
|
||||||
|
jsonPathToString(newRequest, r'$.chapters[*].vol', "_.").split("_.");
|
||||||
|
final chaptersScanlators =
|
||||||
|
jsonPathToString(newRequest, r'$.chapters[*].group_name', "_.")
|
||||||
|
.split("_.");
|
||||||
|
final chapsNames =
|
||||||
|
jsonPathToString(newRequest, r'$.chapters[*].title', "_.").split("_.");
|
||||||
|
final chaptersChaps =
|
||||||
|
jsonPathToString(newRequest, r'$.chapters[*].chap', "_.").split("_.");
|
||||||
|
|
||||||
|
var dateUploads =
|
||||||
|
parseDates(chapDate, source.dateFormat, source.dateFormatLocale);
|
||||||
|
List<MChapter>? chaptersList = [];
|
||||||
|
for (var i = 0; i < chapsNames.length; i++) {
|
||||||
|
String title = "";
|
||||||
|
String scanlator = "";
|
||||||
|
if (chaptersChaps.isNotEmpty && chaptersVolumes.isNotEmpty) {
|
||||||
|
title = beautifyChapterName(
|
||||||
|
chaptersVolumes[i], chaptersChaps[i], chapsNames[i], source.lang);
|
||||||
|
} else {
|
||||||
|
title = chapsNames[i];
|
||||||
|
}
|
||||||
|
if (chaptersScanlators.isNotEmpty) {
|
||||||
|
scanlator = chaptersScanlators[i]
|
||||||
|
.toString()
|
||||||
|
.replaceAll(']', "")
|
||||||
|
.replaceAll("[", "");
|
||||||
|
}
|
||||||
|
MChapter chapter = MChapter();
|
||||||
|
chapter.name = title;
|
||||||
|
chapter.url = chapsUrls[i];
|
||||||
|
chapter.scanlator = scanlator == "null" ? "" : scanlator;
|
||||||
|
chapter.dateUpload = dateUploads[i];
|
||||||
|
chaptersList.add(chapter);
|
||||||
|
}
|
||||||
|
manga.chapters = chaptersList;
|
||||||
|
return manga;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<String>> getPageList(MSource source, String url) async {
|
||||||
|
final urll = "${source.apiUrl}/chapter/$url?tachiyomi=true";
|
||||||
|
final data = {"url": urll, "headers": getHeader(url)};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
return jsonPathToString(res, r'$.chapter.images[*].url', '_.').split('_.');
|
||||||
|
}
|
||||||
|
|
||||||
|
MPages mangaRes(String res) async {
|
||||||
|
final names = jsonPathToList(res, r'$.title', 0);
|
||||||
|
List<String> ids = jsonPathToList(res, r'$.hid', 0);
|
||||||
|
List<String> mangaUrls = [];
|
||||||
|
for (var id in ids) {
|
||||||
|
mangaUrls.add("/comic/$id/#");
|
||||||
|
}
|
||||||
|
final urls = mangaUrls;
|
||||||
|
final images = jsonPathToList(res, r'$.cover_url', 0);
|
||||||
|
List<MManga> mangaList = [];
|
||||||
|
for (var i = 0; i < urls.length; i++) {
|
||||||
|
MManga manga = MManga();
|
||||||
|
manga.name = names[i];
|
||||||
|
manga.imageUrl = images[i];
|
||||||
|
manga.link = urls[i];
|
||||||
|
mangaList.add(manga);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MPages(mangaList, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
String ll(String url) {
|
||||||
|
if (url.contains("?")) {
|
||||||
|
return "&";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
List<dynamic> getFilterList() {
|
||||||
|
return [
|
||||||
|
HeaderFilter("The filter is ignored when using text search."),
|
||||||
|
GroupFilter("GenreFilter", "Genre", [
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "4-Koma", "value": "4-koma"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Action", "value": "action"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Adaptation", "value": "adaptation"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Adult", "value": "adult"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Adventure", "value": "adventure"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Aliens", "value": "aliens"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Animals", "value": "animals"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Anthology", "value": "anthology"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Award Winning", "value": "award-winning"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Comedy", "value": "comedy"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Cooking", "value": "cooking"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Crime", "value": "crime"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Crossdressing", "value": "crossdressing"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Delinquents", "value": "delinquents"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Demons", "value": "demons"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Doujinshi", "value": "doujinshi"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Drama", "value": "drama"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Ecchi", "value": "ecchi"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Fan Colored", "value": "fan-colored"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Fantasy", "value": "fantasy"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Full Color", "value": "full-color"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Gender Bender", "value": "gender-bender"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Genderswap", "value": "genderswap"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Ghosts", "value": "ghosts"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Gore", "value": "gore"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Gyaru", "value": "gyaru"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Harem", "value": "harem"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Historical", "value": "historical"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Horror", "value": "horror"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Incest", "value": "incest"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Isekai", "value": "isekai"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Loli", "value": "loli"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Long Strip", "value": "long-strip"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Mafia", "value": "mafia"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Magic", "value": "magic"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Magical Girls", "value": "magical-girls"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Martial Arts", "value": "martial-arts"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Mature", "value": "mature"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Mecha", "value": "mecha"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Medical", "value": "medical"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Military", "value": "military"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Monster Girls", "value": "monster-girls"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Monsters", "value": "monsters"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Music", "value": "music"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Mystery", "value": "mystery"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Ninja", "value": "ninja"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Office Workers", "value": "office-workers"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Official Colored", "value": "official-colored"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Oneshot", "value": "oneshot"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Philosophical", "value": "philosophical"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Police", "value": "police"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Post-Apocalyptic", "value": "post-apocalyptic"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Psychological", "value": "psychological"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Reincarnation", "value": "reincarnation"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Reverse Harem", "value": "reverse-harem"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Romance", "value": "romance"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Samurai", "value": "samurai"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "School Life", "value": "school-life"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Sci-Fi", "value": "sci-fi"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Sexual Violence", "value": "sexual-violence"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Shota", "value": "shota"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Shoujo Ai", "value": "shoujo-ai"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Shounen Ai", "value": "shounen-ai"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Slice of Life", "value": "slice-of-life"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Smut", "value": "smut"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Sports", "value": "sports"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Superhero", "value": "superhero"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Supernatural", "value": "supernatural"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Survival", "value": "survival"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Thriller", "value": "thriller"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Time Travel", "value": "time-travel"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Traditional Games", "value": "traditional-games"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Tragedy", "value": "tragedy"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "User Created", "value": "user-created"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Vampires", "value": "vampires"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Video Games", "value": "video-games"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Villainess", "value": "villainess"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Virtual Reality", "value": "virtual-reality"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Web Comic", "value": "web-comic"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Wuxia", "value": "wuxia"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Yaoi", "value": "yaoi"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Yuri", "value": "yuri"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TriState",
|
||||||
|
"filter": {"name": "Zombies", "value": "zombies"}
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
GroupFilter("DemographicFilter", "Demographic", [
|
||||||
|
TriStateFilter("Shounen", "1"),
|
||||||
|
TriStateFilter("Shoujo", "2"),
|
||||||
|
TriStateFilter("Seinen", "3"),
|
||||||
|
TriStateFilter("Josei", "4"),
|
||||||
|
]),
|
||||||
|
GroupFilter("TypeFilter", "Type", [
|
||||||
|
CheckBoxFilter("Manga", "jp"),
|
||||||
|
CheckBoxFilter("Manhwa", "kr"),
|
||||||
|
CheckBoxFilter("Manhua", "cn"),
|
||||||
|
]),
|
||||||
|
SelectFilter("SortFilter", "Sort", 0, [
|
||||||
|
SelectFilterOption("Most popular", "follow"),
|
||||||
|
SelectFilterOption("Most follows", "user_follow_count"),
|
||||||
|
SelectFilterOption("Most views", "view"),
|
||||||
|
SelectFilterOption("High rating", "rating"),
|
||||||
|
SelectFilterOption("Last updated", "uploaded"),
|
||||||
|
SelectFilterOption("Newest", "created_at"),
|
||||||
|
]),
|
||||||
|
SelectFilter("StatusFilter", "Status", 0, [
|
||||||
|
SelectFilterOption("All", "0"),
|
||||||
|
SelectFilterOption("Ongoing", "1"),
|
||||||
|
SelectFilterOption("Completed", "2"),
|
||||||
|
SelectFilterOption("Cancelled", "3"),
|
||||||
|
SelectFilterOption("Hiatus", "4"),
|
||||||
|
]),
|
||||||
|
CheckBoxFilter("Completely Scanlated?", "", "CompletedFilter"),
|
||||||
|
SelectFilter("CreatedAtFilter", "Created at", 0, [
|
||||||
|
SelectFilterOption("", ""),
|
||||||
|
SelectFilterOption("3 days", "3"),
|
||||||
|
SelectFilterOption("7 days", "7"),
|
||||||
|
SelectFilterOption("30 days", "30"),
|
||||||
|
SelectFilterOption("3 months", "90"),
|
||||||
|
SelectFilterOption("6 months", "180"),
|
||||||
|
SelectFilterOption("1 year", "365"),
|
||||||
|
]),
|
||||||
|
TextFilter("MinimumFilter", "Minimum Chapters"),
|
||||||
|
HeaderFilter("From Year, ex: 2010"),
|
||||||
|
TextFilter("FromYearFilter", "From"),
|
||||||
|
HeaderFilter("To Year, ex: 2021"),
|
||||||
|
TextFilter("ToYearFilter", "To"),
|
||||||
|
HeaderFilter("Separate tags with commas"),
|
||||||
|
TextFilter("TagFilter", "Tags")
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
String beautifyChapterName(
|
||||||
|
String vol, String chap, String title, String lang) {
|
||||||
|
String result = "";
|
||||||
|
|
||||||
|
if (vol != "null" && vol.isNotEmpty) {
|
||||||
|
if (chap != "null" && chap.isEmpty) {
|
||||||
|
result += "Volume $vol ";
|
||||||
|
} else {
|
||||||
|
result += "Vol. $vol ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chap != "null" && chap.isNotEmpty) {
|
||||||
|
if (vol != "null" && vol.isEmpty) {
|
||||||
|
if (lang != "null" && lang == "fr") {
|
||||||
|
result += "Chapitre $chap";
|
||||||
|
} else {
|
||||||
|
result += "Chapter $chap";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result += "Ch. $chap ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title != "null" && title.isNotEmpty) {
|
||||||
|
if (chap != "null" && chap.isEmpty) {
|
||||||
|
result += title;
|
||||||
|
} else {
|
||||||
|
result += " : $title";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> getHeader(String url) {
|
||||||
|
final headers = {
|
||||||
|
"Referer": "$url/",
|
||||||
|
'User-Agent':
|
||||||
|
"Tachiyomi Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0"
|
||||||
|
};
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComickFun main() {
|
||||||
|
return ComickFun();
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import '../../../../model/source.dart';
|
import '../../../../model/source.dart';
|
||||||
import '../../../../utils/utils.dart';
|
import '../../../../utils/utils.dart';
|
||||||
|
|
||||||
const comickVersion = "0.0.35";
|
const comickVersion = "0.0.4";
|
||||||
const comickSourceCodeUrl =
|
const comickSourceCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/all/comick/comick-v$comickVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/all/comick/comick-v$comickVersion.dart";
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ class MangaDex extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> search(MSource source, String query, int page) async {
|
Future<MPages> search(
|
||||||
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
final url =
|
final url =
|
||||||
"https://api.mangadex.org/manga?includes[]=cover_art&offset=0&limit=20&title=$query${getMDXContentRating()}&order[followedCount]=desc&availableTranslatedLanguage[]=${source.lang}";
|
"https://api.mangadex.org/manga?includes[]=cover_art&offset=0&limit=20&title=$query${getMDXContentRating()}&order[followedCount]=desc&availableTranslatedLanguage[]=${source.lang}";
|
||||||
|
|
||||||
@@ -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.4";
|
const mangadexVersion = "0.0.45";
|
||||||
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");
|
||||||
|
|||||||
@@ -59,10 +59,55 @@ class MangaHere extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> search(MSource source, String query, int page) async {
|
Future<MPages> search(
|
||||||
|
MSource source, String query, int page, FilterList filterList) async {
|
||||||
final headers = getHeader(source.baseUrl);
|
final headers = getHeader(source.baseUrl);
|
||||||
final url = "${source.baseUrl}/search?title=$query&page=$page";
|
|
||||||
|
|
||||||
|
final filters = filterList.filters;
|
||||||
|
String url = "${source.baseUrl}/search";
|
||||||
|
|
||||||
|
for (var filter in filters) {
|
||||||
|
if (filter.type == "TypeList") {
|
||||||
|
final type = filter.values[filter.state].value;
|
||||||
|
url += "${ll(url)}type=$type";
|
||||||
|
} else if (filter.type == "CompletionList") {
|
||||||
|
final cmp = filter.values[filter.state].value;
|
||||||
|
url += "${ll(url)}st=$cmp";
|
||||||
|
} else if (filter.type == "RatingList") {
|
||||||
|
url += "${ll(url)}rating_method=gt";
|
||||||
|
final rt = filter.values[filter.state].value;
|
||||||
|
url += "${ll(url)}rating=$rt";
|
||||||
|
} else if (filter.type == "GenreList") {
|
||||||
|
final included = (filter.state as List)
|
||||||
|
.where((e) => e.state == 1 ? true : false)
|
||||||
|
.toList();
|
||||||
|
final excluded = (filter.state as List)
|
||||||
|
.where((e) => e.state == 2 ? true : false)
|
||||||
|
.toList();
|
||||||
|
if (included.isNotEmpty) {
|
||||||
|
url += "${ll(url)}genres=";
|
||||||
|
for (var val in included) {
|
||||||
|
url += "${val.value},";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (excluded.isNotEmpty) {
|
||||||
|
url += "${ll(url)}nogenres=";
|
||||||
|
for (var val in excluded) {
|
||||||
|
url += "${val.value},";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (filter.type == "ArtistFilter") {
|
||||||
|
url += "${ll(url)}artist_method=cw";
|
||||||
|
url += "${ll(url)}artist=${Uri.encodeComponent(filter.state)}";
|
||||||
|
} else if (filter.type == "AuthorFilter") {
|
||||||
|
url += "${ll(url)}author_method=cw";
|
||||||
|
url += "${ll(url)}author=${Uri.encodeComponent(filter.state)}";
|
||||||
|
} else if (filter.type == "YearFilter") {
|
||||||
|
url += "${ll(url)}released_method=cw";
|
||||||
|
url += "${ll(url)}released=${Uri.encodeComponent(filter.state)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
url += "${ll(url)}title=$query&page=$page";
|
||||||
final data = {"url": url, "headers": headers};
|
final data = {"url": url, "headers": headers};
|
||||||
final res = await http('POST', json.encode(data));
|
final res = await http('POST', json.encode(data));
|
||||||
|
|
||||||
@@ -205,6 +250,83 @@ class MangaHere extends MProvider {
|
|||||||
|
|
||||||
return pageUrls;
|
return pageUrls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String ll(String url) {
|
||||||
|
if (url.contains("?")) {
|
||||||
|
return "&";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
List<dynamic> getFilterList() {
|
||||||
|
return [
|
||||||
|
SelectFilter("TypeList", "Type", 1, [
|
||||||
|
SelectFilterOption("American Manga", "5"),
|
||||||
|
SelectFilterOption("Any", "0"),
|
||||||
|
SelectFilterOption("Chinese Manhua", "3"),
|
||||||
|
SelectFilterOption("European Manga", "4"),
|
||||||
|
SelectFilterOption("Hong Kong Manga", "6"),
|
||||||
|
SelectFilterOption("Japanese Manga", "1"),
|
||||||
|
SelectFilterOption("Korean Manhwa", "2"),
|
||||||
|
SelectFilterOption("Other Manga", "7"),
|
||||||
|
]),
|
||||||
|
TextFilter("ArtistFilter", "Artist"),
|
||||||
|
TextFilter("AuthorFilter", "Author"),
|
||||||
|
GroupFilter("GenreList", "Genres", [
|
||||||
|
TriStateFilter("Action", "1"),
|
||||||
|
TriStateFilter("Adventure", "2"),
|
||||||
|
TriStateFilter("Comedy", "3"),
|
||||||
|
TriStateFilter("Fantasy", "4"),
|
||||||
|
TriStateFilter("Historical", "5"),
|
||||||
|
TriStateFilter("Horror", "6"),
|
||||||
|
TriStateFilter("Martial Arts", "7"),
|
||||||
|
TriStateFilter("Mystery", "8"),
|
||||||
|
TriStateFilter("Romance", "9"),
|
||||||
|
TriStateFilter("Shounen Ai", "10"),
|
||||||
|
TriStateFilter("Supernatural", "11"),
|
||||||
|
TriStateFilter("Drama", "12"),
|
||||||
|
TriStateFilter("Shounen", "13"),
|
||||||
|
TriStateFilter("School Life", "14"),
|
||||||
|
TriStateFilter("Shoujo", "15"),
|
||||||
|
TriStateFilter("Gender Bender", "16"),
|
||||||
|
TriStateFilter("Josei", "17"),
|
||||||
|
TriStateFilter("Psychological", "18"),
|
||||||
|
TriStateFilter("Seinen", "19"),
|
||||||
|
TriStateFilter("Slice of Life", "20"),
|
||||||
|
TriStateFilter("Sci-fi", "21"),
|
||||||
|
TriStateFilter("Ecchi", "22"),
|
||||||
|
TriStateFilter("Harem", "23"),
|
||||||
|
TriStateFilter("Shoujo Ai", "24"),
|
||||||
|
TriStateFilter("Yuri", "25"),
|
||||||
|
TriStateFilter("Mature", "26"),
|
||||||
|
TriStateFilter("Tragedy", "27"),
|
||||||
|
TriStateFilter("Yaoi", "28"),
|
||||||
|
TriStateFilter("Doujinshi", "29"),
|
||||||
|
TriStateFilter("Sports", "30"),
|
||||||
|
TriStateFilter("Adult", "31"),
|
||||||
|
TriStateFilter("One Shot", "32"),
|
||||||
|
TriStateFilter("Smut", "33"),
|
||||||
|
TriStateFilter("Mecha", "34"),
|
||||||
|
TriStateFilter("Shotacon", "35"),
|
||||||
|
TriStateFilter("Lolicon", "36"),
|
||||||
|
TriStateFilter("Webtoons", "37"),
|
||||||
|
]),
|
||||||
|
SelectFilter("RatingList", "Minimum rating", 0, [
|
||||||
|
SelectFilterOption("No Stars", "0"),
|
||||||
|
SelectFilterOption("1 Star", "1"),
|
||||||
|
SelectFilterOption("2 Stars", "2"),
|
||||||
|
SelectFilterOption("3 Stars", "3"),
|
||||||
|
SelectFilterOption("4 Stars", "4"),
|
||||||
|
SelectFilterOption("5 Stars", "5"),
|
||||||
|
]),
|
||||||
|
TextFilter("YearFilter", "Year released"),
|
||||||
|
SelectFilter("CompletionList", "Completed series", 0, [
|
||||||
|
SelectFilterOption("Either", "0"),
|
||||||
|
SelectFilterOption("No", "1"),
|
||||||
|
SelectFilterOption("Yes", "2"),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> getHeader(String url) {
|
Map<String, String> getHeader(String url) {
|
||||||
@@ -2,7 +2,7 @@ import '../../../../model/source.dart';
|
|||||||
import '../../../../utils/utils.dart';
|
import '../../../../utils/utils.dart';
|
||||||
|
|
||||||
Source get mangahereSource => _mangahereSource;
|
Source get mangahereSource => _mangahereSource;
|
||||||
const mangahereVersion = "0.0.35";
|
const mangahereVersion = "0.0.4";
|
||||||
const mangahereSourceCodeUrl =
|
const mangahereSourceCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/en/mangahere/mangahere-v$mangahereVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/src/en/mangahere/mangahere-v$mangahereVersion.dart";
|
||||||
Source _mangahereSource = Source(
|
Source _mangahereSource = Source(
|
||||||
|
|||||||
Reference in New Issue
Block a user