rewrite Comick source code in JS
This commit is contained in:
parent
2ca9be2319
commit
d972abbe87
5 changed files with 433 additions and 734 deletions
|
|
@ -1,658 +0,0 @@
|
|||
import 'package:mangayomi/bridge_lib.dart';
|
||||
|
||||
class ComickFun extends MProvider {
|
||||
ComickFun({required this.source});
|
||||
|
||||
MSource source;
|
||||
|
||||
final Client client = Client(source);
|
||||
|
||||
@override
|
||||
Future<MPages> getPopular(int page) async {
|
||||
final res = (await client.get(
|
||||
Uri.parse(
|
||||
"${source.apiUrl}/v1.0/search?sort=follow&page=$page&tachiyomi=true"),
|
||||
headers: getHeader(source.baseUrl)))
|
||||
.body;
|
||||
return mangaRes(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> getLatestUpdates(int page) async {
|
||||
final res = (await client.get(
|
||||
Uri.parse(
|
||||
"${source.apiUrl}/v1.0/search?sort=uploaded&page=$page&tachiyomi=true"),
|
||||
headers: getHeader(source.baseUrl)))
|
||||
.body;
|
||||
return mangaRes(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> search(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 res =
|
||||
(await client.get(Uri.parse(url), headers: getHeader(source.baseUrl)))
|
||||
.body;
|
||||
return mangaRes(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MManga> getDetail(String url) async {
|
||||
final statusList = [
|
||||
{"1": 0, "2": 1, "3": 3, "4": 2}
|
||||
];
|
||||
final headers = getHeader(source.baseUrl);
|
||||
final res = (await client.get(
|
||||
Uri.parse(
|
||||
"${source.apiUrl}${url.replaceAll("#", '')}?tachiyomi=true"),
|
||||
headers: headers))
|
||||
.body;
|
||||
final lang = "${source.lang != "all" ? "&lang=${source.lang}" : ""}";
|
||||
MManga manga = MManga();
|
||||
manga.author = jsonPathToString(res, r'$.authors[*].name', '');
|
||||
manga.genre = jsonPathToString(
|
||||
res, r'$.comic.md_comic_md_genres[*].md_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}&tachiyomi=true&page=1";
|
||||
final request =
|
||||
(await client.get(Uri.parse(chapUrlReq), headers: headers)).body;
|
||||
var total = jsonPathToString(request, r'$.total', '');
|
||||
final chapterLimit = int.parse(total);
|
||||
final newChapUrlReq =
|
||||
"${source.apiUrl}${url.replaceAll("#", '')}chapters?limit=$chapterLimit${lang}&tachiyomi=true&page=1";
|
||||
|
||||
final newRequest =
|
||||
(await client.get(Uri.parse(newChapUrlReq), headers: headers)).body;
|
||||
|
||||
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(String url) async {
|
||||
final res = (await client.get(
|
||||
Uri.parse("${source.apiUrl}/chapter/$url?tachiyomi=true"),
|
||||
headers: getHeader(url)))
|
||||
.body;
|
||||
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 "?";
|
||||
}
|
||||
|
||||
@override
|
||||
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(MSource source) {
|
||||
return ComickFun(source: source);
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
import '../../../../../model/source.dart';
|
||||
|
||||
const _comickVersion = "0.0.75";
|
||||
const _comickSourceCodeUrl =
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/src/all/comick/comick.dart";
|
||||
|
||||
String _iconUrl =
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/manga/src/all/comick/icon.png";
|
||||
const _apiUrl = 'https://api.comick.fun';
|
||||
const _baseUrl = 'https://comick.app';
|
||||
const _isNsfw = true;
|
||||
|
||||
List<String> _languages = [
|
||||
"all",
|
||||
"en",
|
||||
"pt-br",
|
||||
"ru",
|
||||
"fr",
|
||||
"es-419",
|
||||
"pl",
|
||||
"tr",
|
||||
"it",
|
||||
"es",
|
||||
"id",
|
||||
"hu",
|
||||
"vi",
|
||||
"zh-hk",
|
||||
"ar",
|
||||
"de",
|
||||
"zh",
|
||||
"ca",
|
||||
"bg",
|
||||
"th",
|
||||
"fa",
|
||||
"uk",
|
||||
"mn",
|
||||
"ro",
|
||||
"he",
|
||||
"ms",
|
||||
"tl",
|
||||
"ja",
|
||||
"hi",
|
||||
"my",
|
||||
"ko",
|
||||
"cs",
|
||||
"pt",
|
||||
"nl",
|
||||
"sv",
|
||||
"bn",
|
||||
"no",
|
||||
"lt",
|
||||
"el",
|
||||
"sr",
|
||||
"da",
|
||||
];
|
||||
|
||||
List<Source> get comickSourcesList => _comickSourcesList;
|
||||
List<Source> _comickSourcesList = _languages
|
||||
.map((e) => Source(
|
||||
name: 'Comick',
|
||||
apiUrl: _apiUrl,
|
||||
baseUrl: _baseUrl,
|
||||
lang: e,
|
||||
typeSource: "comick",
|
||||
iconUrl: _iconUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: _isNsfw,
|
||||
dateFormatLocale: "en",
|
||||
version: _comickVersion,
|
||||
itemType: ItemType.manga,
|
||||
sourceCodeUrl: _comickSourceCodeUrl))
|
||||
.toList();
|
||||
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
424
javascript/manga/src/all/comick.js
Normal file
424
javascript/manga/src/all/comick.js
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
const mangayomiSources = [
|
||||
{
|
||||
"name": "Comick test",
|
||||
"langs": ["all", "en", "pt-br", "ru", "fr", "es-419", "pl", "tr", "it", "es", "id", "hu", "vi", "zh-hk", "ar", "de", "zh", "ca", "bg", "th", "fa", "uk", "mn", "ro", "he", "ms", "tl", "ja", "hi", "my", "ko", "cs", "pt", "nl", "sv", "bn", "no", "lt", "el", "sr", "da"],
|
||||
"ids": {
|
||||
"all": 370890607,
|
||||
"en": 955190069,
|
||||
"pt-br": 494197461,
|
||||
"ru": 1050814052,
|
||||
"fr": 380505196,
|
||||
"es-419": 296390197,
|
||||
"pl": 242913014,
|
||||
"tr": 507059585,
|
||||
"it": 851891714,
|
||||
"es": 115169439,
|
||||
"id": 719269008,
|
||||
"hu": 719759654,
|
||||
"vi": 301477894,
|
||||
"zh-hk": 113594984,
|
||||
"ar": 602472856,
|
||||
"de": 401493183,
|
||||
"zh": 752155292,
|
||||
"ca": 1069764002,
|
||||
"bg": 678531099,
|
||||
"th": 311480598,
|
||||
"fa": 141560456,
|
||||
"uk": 8261465,
|
||||
"mn": 565474938,
|
||||
"ro": 533803532,
|
||||
"he": 459976450,
|
||||
"ms": 375702775,
|
||||
"tl": 737984097,
|
||||
"ja": 796489006,
|
||||
"hi": 683471552,
|
||||
"my": 778623467,
|
||||
"ko": 1065236294,
|
||||
"cs": 422767524,
|
||||
"pt": 678647945,
|
||||
"nl": 698202010,
|
||||
"sv": 359879447,
|
||||
"bn": 532878423,
|
||||
"no": 481504622,
|
||||
"lt": 112887841,
|
||||
"el": 824905526,
|
||||
"sr": 373675453,
|
||||
"da": 574420905
|
||||
},
|
||||
"baseUrl": "https://comick.io",
|
||||
"apiUrl": "https://api.comick.fun",
|
||||
"iconUrl": "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/javascript/icon/all.comick.png",
|
||||
"typeSource": "single",
|
||||
"itemType": 0,
|
||||
"version": "0.0.8",
|
||||
"pkgPath": "manga/src/all/comick.js"
|
||||
}];
|
||||
|
||||
class DefaultExtension extends MProvider {
|
||||
constructor() {
|
||||
super();
|
||||
this.client = new Client();
|
||||
}
|
||||
getHeaders(url) {
|
||||
return {
|
||||
"Referer": `${this.source.baseUrl}/`,
|
||||
'User-Agent':
|
||||
"Tachiyomi Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0"
|
||||
};
|
||||
}
|
||||
|
||||
async getPopular(page) {
|
||||
const url = `${this.source.apiUrl}/v1.0/search?sort=follow&page=${page}&tachiyomi=true`;
|
||||
const res = await this.client.get(url, this.getHeaders());
|
||||
return this.mangaRes(res.body);
|
||||
}
|
||||
|
||||
async getLatestUpdates(page) {
|
||||
const url = `${this.source.apiUrl}/v1.0/search?sort=uploaded&page=${page}&tachiyomi=true`;
|
||||
const res = await this.client.get(url, this.getHeaders());
|
||||
return this.mangaRes(res.body);
|
||||
}
|
||||
async search(query, page, filterList) {
|
||||
let url = `${this.source.apiUrl}/v1.0/search`;
|
||||
|
||||
if (query) {
|
||||
url += `?q=${encodeURIComponent(query)}&tachiyomi=true`;
|
||||
} else {
|
||||
filterList.forEach(filter => {
|
||||
if (filter.type === "CompletedFilter" && filter.state) {
|
||||
url += `${this.ll(url)}completed=true`;
|
||||
} else if (filter.type === "GenreFilter") {
|
||||
const included = filter.state.filter(e => e.state === 1);
|
||||
const excluded = filter.state.filter(e => e.state === 2);
|
||||
included.forEach(val => url += `${this.ll(url)}genres=${val.value}`);
|
||||
excluded.forEach(val => url += `${this.ll(url)}excludes=${val.value}`);
|
||||
} else if (filter.type === "DemographicFilter") {
|
||||
const included = filter.state.filter(e => e.state === 1);
|
||||
included.forEach(val => url += `${this.ll(url)}demographic=${val.value}`);
|
||||
} else if (filter.type === "TypeFilter") {
|
||||
const country = filter.state.filter(e => e.state);
|
||||
country.forEach(coun => url += `${this.ll(url)}country=${coun.value}`);
|
||||
} else if (filter.type === "SortFilter") {
|
||||
url += `${this.ll(url)}sort=${filter.values[filter.state].value}`;
|
||||
} else if (filter.type === "StatusFilter") {
|
||||
url += `${this.ll(url)}status=${filter.values[filter.state].value}`;
|
||||
} else if (filter.type === "CreatedAtFilter" && filter.state > 0) {
|
||||
url += `${this.ll(url)}time=${filter.values[filter.state].value}`;
|
||||
} else if (filter.type === "MinimumFilter" && filter.state) {
|
||||
url += `${this.ll(url)}minimum=${filter.state}`;
|
||||
} else if (filter.type === "FromYearFilter" && filter.state) {
|
||||
url += `${this.ll(url)}from=${filter.state}`;
|
||||
} else if (filter.type === "ToYearFilter" && filter.state) {
|
||||
url += `${this.ll(url)}to=${filter.state}`;
|
||||
} else if (filter.type === "TagFilter" && filter.state) {
|
||||
const tags = filter.state.split(",");
|
||||
tags.forEach(tag => url += `${this.ll(url)}tags=${tag}`);
|
||||
}
|
||||
});
|
||||
url += `&page=${page}&tachiyomi=true`;
|
||||
}
|
||||
const res = await this.client.get(url, this.getHeaders());
|
||||
return this.mangaRes(res.body);
|
||||
}
|
||||
|
||||
async getDetail(url) {
|
||||
const apiUrl = `${this.source.apiUrl}${url.replace("#", "")}?tachiyomi=true`;
|
||||
const res = await this.client.get(apiUrl, this.getHeaders());
|
||||
const data = JSON.parse(res.body);
|
||||
const lang = this.source.lang != "all" ? `&lang=${this.source.lang}` : "";
|
||||
const chapUrlReq =
|
||||
`${this.source.apiUrl}${url.replaceAll("#", '')}chapters?${lang}&tachiyomi=true&page=1`;
|
||||
const total = JSON.parse((await this.client.get(chapUrlReq, this.getHeaders())).body).total;
|
||||
const newChapUrlReq =
|
||||
`${this.source.apiUrl}${url.replaceAll("#", '')}chapters?limit=${parseInt(total, 10)}${lang}&tachiyomi=true&page=1`;
|
||||
const newRes = await this.client.get(newChapUrlReq, this.getHeaders());
|
||||
const chapters = JSON.parse(newRes.body).chapters.map(chapter => {
|
||||
let title = "";
|
||||
let scanlator = "";
|
||||
|
||||
if (chapter.chap !== "null" && chapter.vol !== "null") {
|
||||
title = this.beautifyChapterName(
|
||||
chapter.vol,
|
||||
chapter.chap,
|
||||
chapter.title
|
||||
);
|
||||
} else {
|
||||
title = chapter.title;
|
||||
}
|
||||
|
||||
if (chapter.group_name !== "null") {
|
||||
scanlator = chapter.group_name
|
||||
.toString()
|
||||
.replace(/]/g, "")
|
||||
.replace(/\[/g, "");
|
||||
}
|
||||
|
||||
return {
|
||||
name: title,
|
||||
url: chapter.hid,
|
||||
scanlator: scanlator ?? "",
|
||||
dateUpload: new Date(chapter.created_at).valueOf().toString(),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
author: data.authors?.map(author => author.name).join(', '),
|
||||
description: data.comic.desc,
|
||||
genres: Array.from(data.comic.md_comic_md_genres.map(g => g.md_genres.name)),
|
||||
status: { "1": 0, "2": 1, "3": 3, "4": 2 }[data.comic.status],
|
||||
chapters
|
||||
};
|
||||
}
|
||||
|
||||
async getPageList(url) {
|
||||
const apiUrl = `${this.source.apiUrl}/chapter/${url}?tachiyomi=true`;
|
||||
const res = await this.client.get(apiUrl, this.getHeaders());
|
||||
const data = JSON.parse(res.body);
|
||||
return data.chapter.images.map(image => ({
|
||||
url: image.url
|
||||
}));
|
||||
}
|
||||
getFilterList() {
|
||||
return [
|
||||
{
|
||||
type_name: "HeaderFilter",
|
||||
name: "The filter is ignored when using text search.",
|
||||
},
|
||||
{
|
||||
type_name: "GroupFilter",
|
||||
type: "GenreFilter",
|
||||
name: "Genre",
|
||||
state: [
|
||||
["4-Koma", "4-koma"],
|
||||
["Action", "action"],
|
||||
["Adaptation", "adaptation"],
|
||||
["Adult", "adult"],
|
||||
["Adventure", "adventure"],
|
||||
["Aliens", "aliens"],
|
||||
["Animals", "animals"],
|
||||
["Anthology", "anthology"],
|
||||
["Award Winning", "award-winning"],
|
||||
["Comedy", "comedy"],
|
||||
["Cooking", "cooking"],
|
||||
["Crime", "crime"],
|
||||
["Crossdressing", "crossdressing"],
|
||||
["Delinquents", "delinquents"],
|
||||
["Demons", "demons"],
|
||||
["Doujinshi", "doujinshi"],
|
||||
["Drama", "drama"],
|
||||
["Ecchi", "ecchi"],
|
||||
["Fan Colored", "fan-colored"],
|
||||
["Fantasy", "fantasy"],
|
||||
["Full Color", "full-color"],
|
||||
["Gender Bender", "gender-bender"],
|
||||
["Genderswap", "genderswap"],
|
||||
["Ghosts", "ghosts"],
|
||||
["Gore", "gore"],
|
||||
["Gyaru", "gyaru"],
|
||||
["Harem", "harem"],
|
||||
["Historical", "historical"],
|
||||
["Horror", "horror"],
|
||||
["Incest", "incest"],
|
||||
["Isekai", "isekai"],
|
||||
["Loli", "loli"],
|
||||
["Long Strip", "long-strip"],
|
||||
["Mafia", "mafia"],
|
||||
["Magic", "magic"],
|
||||
["Magical Girls", "magical-girls"],
|
||||
["Martial Arts", "martial-arts"],
|
||||
["Mature", "mature"],
|
||||
["Mecha", "mecha"],
|
||||
["Medical", "medical"],
|
||||
["Military", "military"],
|
||||
["Monster Girls", "monster-girls"],
|
||||
["Monsters", "monsters"],
|
||||
["Music", "music"],
|
||||
["Mystery", "mystery"],
|
||||
["Ninja", "ninja"],
|
||||
["Office Workers", "office-workers"],
|
||||
["Official Colored", "official-colored"],
|
||||
["Oneshot", "oneshot"],
|
||||
["Philosophical", "philosophical"],
|
||||
["Police", "police"],
|
||||
["Post-Apocalyptic", "post-apocalyptic"],
|
||||
["Psychological", "psychological"],
|
||||
["Reincarnation", "reincarnation"],
|
||||
["Reverse Harem", "reverse-harem"],
|
||||
["Romance", "romance"],
|
||||
["Samurai", "samurai"],
|
||||
["School Life", "school-life"],
|
||||
["Sci-Fi", "sci-fi"],
|
||||
["Sexual Violence", "sexual-violence"],
|
||||
["Shota", "shota"],
|
||||
["Shoujo Ai", "shoujo-ai"],
|
||||
["Shounen Ai", "shounen-ai"],
|
||||
["Slice of Life", "slice-of-life"],
|
||||
["Smut", "smut"],
|
||||
["Sports", "sports"],
|
||||
["Superhero", "superhero"],
|
||||
["Supernatural", "supernatural"],
|
||||
["Survival", "survival"],
|
||||
["Thriller", "thriller"],
|
||||
["Time Travel", "time-travel"],
|
||||
["Traditional Games", "traditional-games"],
|
||||
["Tragedy", "tragedy"],
|
||||
["User Created", "user-created"],
|
||||
["Vampires", "vampires"],
|
||||
["Video Games", "video-games"],
|
||||
["Villainess", "villainess"],
|
||||
["Virtual Reality", "virtual-reality"],
|
||||
["Web Comic", "web-comic"],
|
||||
["Wuxia", "wuxia"],
|
||||
["Yaoi", "yaoi"],
|
||||
["Yuri", "yuri"],
|
||||
["Zombies", "zombies"]
|
||||
].map(x => ({ type_name: 'TriState', name: x[0], value: x[1] }))
|
||||
},
|
||||
{
|
||||
type_name: "GroupFilter",
|
||||
type: "DemographicFilter",
|
||||
name: "Demographic",
|
||||
state: [
|
||||
["Shounen", "1"],
|
||||
["Shoujo", "2"],
|
||||
["Seinen", "3"],
|
||||
["Josei", "4"]
|
||||
].map(x => ({ type_name: 'TriState', name: x[0], value: x[1] }))
|
||||
},
|
||||
{
|
||||
type_name: "GroupFilter",
|
||||
type: "TypeFilter",
|
||||
name: "Type",
|
||||
state: [
|
||||
["Manga", "jp"],
|
||||
["Manhwa", "kr"],
|
||||
["Manhua", "cn"]
|
||||
].map(x => ({ type_name: 'CheckBox', name: x[0], value: x[1] }))
|
||||
},
|
||||
{
|
||||
type_name: "SelectFilter",
|
||||
type: "SortFilter",
|
||||
name: "Sort",
|
||||
state: 0,
|
||||
values: [
|
||||
["Most popular", "follow"],
|
||||
["Most follows", "user_follow_count"],
|
||||
["Most views", "view"],
|
||||
["High rating", "rating"],
|
||||
["Last updated", "uploaded"],
|
||||
["Newest", "created_at"]
|
||||
].map(x => ({ type_name: 'SelectOption', name: x[0], value: x[1] }))
|
||||
},
|
||||
{
|
||||
type_name: "SelectFilter",
|
||||
type: "StatusFilter",
|
||||
name: "Status",
|
||||
state: 0,
|
||||
values: [
|
||||
["All", "0"],
|
||||
["Ongoing", "1"],
|
||||
["Completed", "2"],
|
||||
["Cancelled", "3"],
|
||||
["Hiatus", "4"]
|
||||
].map(x => ({ type_name: 'SelectOption', name: x[0], value: x[1] }))
|
||||
},
|
||||
{
|
||||
type_name: 'CheckBox',
|
||||
type: "CompletedFilter",
|
||||
name: "Completely Scanlated?",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
type_name: "SelectFilter",
|
||||
type: "CreatedAtFilter",
|
||||
name: "Created at",
|
||||
state: 0,
|
||||
values: [
|
||||
["", ""],
|
||||
["3 days", "3"],
|
||||
["7 days", "7"],
|
||||
["30 days", "30"],
|
||||
["3 months", "90"],
|
||||
["6 months", "180"],
|
||||
["1 year", "365"]
|
||||
].map(x => ({ type_name: 'SelectOption', name: x[0], value: x[1] }))
|
||||
},
|
||||
{
|
||||
type_name: "TextFilter",
|
||||
type: "MinimumFilter",
|
||||
name: "Minimum Chapters",
|
||||
},
|
||||
{
|
||||
type_name: "HeaderFilter",
|
||||
name: "From Year, ex: 2010",
|
||||
},
|
||||
{
|
||||
type_name: "TextFilter",
|
||||
type: "FromYearFilter",
|
||||
name: "From",
|
||||
},
|
||||
{
|
||||
type_name: "HeaderFilter",
|
||||
name: "To Year, ex: 2021",
|
||||
},
|
||||
{
|
||||
type_name: "TextFilter",
|
||||
type: "ToYearFilter",
|
||||
name: "To",
|
||||
},
|
||||
{
|
||||
type_name: "HeaderFilter",
|
||||
name: "Separate tags with commas",
|
||||
},
|
||||
{
|
||||
type_name: "TextFilter",
|
||||
type: "TagFilter",
|
||||
name: "Tags",
|
||||
},
|
||||
];
|
||||
}
|
||||
mangaRes(body) {
|
||||
body = JSON.parse(body);
|
||||
return {
|
||||
list: body.map(manga => ({
|
||||
name: manga.title,
|
||||
imageUrl: manga.cover_url,
|
||||
link: `/comic/${manga.hid}/#`
|
||||
})),
|
||||
hasNextPage: body.hasNextPage || false
|
||||
};
|
||||
}
|
||||
beautifyChapterName(vol, chap, title) {
|
||||
let result = "";
|
||||
|
||||
if (vol && vol.trim() !== "") {
|
||||
if (chap && chap.trim() === "") {
|
||||
result += `Volume ${vol} `;
|
||||
} else {
|
||||
result += `Vol. ${vol} `;
|
||||
}
|
||||
}
|
||||
|
||||
if (chap && chap.trim() !== "") {
|
||||
if (vol && vol.trim() === "") {
|
||||
result += `Chapter ${chap}`;
|
||||
} else {
|
||||
result += `Ch. ${chap} `;
|
||||
}
|
||||
}
|
||||
|
||||
if (title && title.trim() !== "") {
|
||||
if (chap && chap.trim() === "") {
|
||||
result += title;
|
||||
} else {
|
||||
result += ` : ${title}`;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ll(url) {
|
||||
return url.includes("?") ? "&" : "?";
|
||||
}
|
||||
}
|
||||
|
|
@ -8,9 +8,12 @@ import 'model/source.dart';
|
|||
|
||||
void main() {
|
||||
final jsSources = _searchJsSources(Directory("javascript"));
|
||||
genManga(jsSources.where((element) => element.itemType!.name == "manga").toList());
|
||||
genAnime(jsSources.where((element) => element.itemType!.name == "anime").toList());
|
||||
genNovel(jsSources.where((element) => element.itemType!.name == "novel").toList());
|
||||
genManga(
|
||||
jsSources.where((element) => element.itemType!.name == "manga").toList());
|
||||
genAnime(
|
||||
jsSources.where((element) => element.itemType!.name == "anime").toList());
|
||||
genNovel(
|
||||
jsSources.where((element) => element.itemType!.name == "novel").toList());
|
||||
}
|
||||
|
||||
void genManga(List<Source> jsMangasourceList) {
|
||||
|
|
@ -83,9 +86,11 @@ List<Source> _searchJsSources(Directory dir) {
|
|||
}
|
||||
if (langs?.isNotEmpty ?? false) {
|
||||
for (var lang in langs!) {
|
||||
final id = sourceJson["ids"]?[lang] as int?;
|
||||
sourceList.add(Source.fromJson(source.toJson())
|
||||
..lang = lang
|
||||
..id = 'mangayomi-js-"$lang"."${source.name}"'.hashCode);
|
||||
..id =
|
||||
id ?? 'mangayomi-js-"$lang"."${source.name}"'.hashCode);
|
||||
}
|
||||
} else {
|
||||
sourceList.add(source);
|
||||
|
|
|
|||
Loading…
Reference in a new issue