add filter method

This commit is contained in:
kodjomoustapha
2023-11-25 18:22:10 +01:00
parent 7b2eec076d
commit 2789016420
6 changed files with 429 additions and 242 deletions

View File

@@ -56,7 +56,8 @@ class HeanCms extends MProvider {
}
@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);
String res = "";
if (!useNewQueryEndpoint(source.source)) {

View File

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

View File

@@ -1,225 +0,0 @@
import 'package:mangayomi/bridge_lib.dart';
import 'dart:convert';
class NepNep extends MProvider {
NepNep();
@override
Future<MPages> getPopular(MSource source, int page) async {
final data = {"url": "${source.baseUrl}/search/"};
final res = await http('GET', json.encode(data));
final directory = directoryFromDocument(res);
final resSort = sortMapList(json.decode(directory), "vm", 1);
return parseDirectory(resSort);
}
@override
Future<MPages> getLatestUpdates(MSource source, int page) async {
final data = {"url": "${source.baseUrl}/search/"};
final res = await http('GET', json.encode(data));
final directory = directoryFromDocument(res);
final resSort = sortMapList(json.decode(directory), "lt", 1);
return parseDirectory(resSort);
}
@override
Future<MPages> search(MSource source, String query, int page) async {
final data = {"url": "${source.baseUrl}/search/"};
final res = await http('GET', json.encode(data));
final directory = directoryFromDocument(res);
final resSort = sortMapList(json.decode(directory), "lt", 1);
final datas = json.decode(resSort) as List;
final queryRes = datas.where((e) {
String name = getMapValue(json.encode(e), 's');
return name.toLowerCase().contains(query.toLowerCase());
}).toList();
return parseDirectory(json.encode(queryRes));
}
@override
Future<MManga> getDetail(MSource source, String url) async {
final statusList = [
{"Ongoing": 0, "Completed": 1, "Cancelled": 3, "Hiatus": 2}
];
final headers = getHeader(source.baseUrl);
final data = {"url": '${source.baseUrl}/manga/$url', "headers": headers};
final res = await http('GET', json.encode(data));
MManga manga = MManga();
manga.author = xpath(res,
'//li[contains(@class,"list-group-item") and contains(text(),"Author")]/a/text()')
.first;
manga.description = xpath(res,
'//li[contains(@class,"list-group-item") and contains(text(),"Description:")]/div/text()')
.first;
final status = xpath(res,
'//li[contains(@class,"list-group-item") and contains(text(),"Status")]/a/text()')
.first;
manga.status = parseStatus(toStatus(status), statusList);
manga.genre = xpath(res,
'//li[contains(@class,"list-group-item") and contains(text(),"Genre(s)")]/a/text()');
final script =
xpath(res, '//script[contains(text(), "MainFunction")]/text()').first;
final vmChapters =
substringBefore(substringAfter(script, "vm.Chapters = "), ";");
final chapters = json.decode(vmChapters) as List;
List<MChapter> chaptersList = [];
for (var ch in chapters) {
final c = json.encode(ch);
MChapter chapter = MChapter();
String name = getMapValue(c, 'ChapterName');
String indexChapter = getMapValue(c, 'Chapter');
if (name.isEmpty) {
name = '${getMapValue(c, 'Type')} ${chapterImage(indexChapter, true)}';
}
chapter.name = name == "null" ? "" : name;
chapter.url =
'/read-online/${substringAfter(url, "/manga/")}${chapterURLEncode(getMapValue(c, 'Chapter'))}';
chapter.dateUpload = parseDates([getMapValue(c, 'Date')],
source.dateFormat, source.dateFormatLocale)
.first;
chaptersList.add(chapter);
}
manga.chapters = chaptersList;
return manga;
}
@override
Future<List<String>> getPageList(MSource source, String url) async {
final headers = getHeader(source.baseUrl);
List<String> pages = [];
final data = {"url": '${source.baseUrl}$url', "headers": headers};
print(data);
final res = await http('GET', json.encode(data));
final script =
xpath(res, '//script[contains(text(), "MainFunction")]/text()').first;
final chapScript =
substringBefore(substringAfter(script, "vm.CurChapter = "), ";");
final pathName = substringBefore(
substringAfter(script, "vm.CurPathName = \"", ""), "\"");
var directory = getMapValue(chapScript, 'Directory') == 'null'
? ''
: getMapValue(chapScript, 'Directory');
if (directory.length > 0) {
directory += '/';
}
final mangaName =
substringBefore(substringAfter(url, "/read-online/"), "-chapter");
var chNum = chapterImage(getMapValue(chapScript, 'Chapter'), false);
var totalPages = int.parse(getMapValue(chapScript, 'Page'));
for (int page = 1; page <= totalPages; page++) {
String paddedPageNumber = "$page".padLeft(3, '0');
String pageUrl =
'https://$pathName/manga/$mangaName/$directory$chNum-$paddedPageNumber.png';
pages.add(pageUrl);
}
return pages;
}
String directoryFromDocument(String res) {
final script =
xpath(res, '//script[contains(text(), "MainFunction")]/text()').first;
return substringBefore(
substringAfter(script, "vm.Directory = "), "vm.GetIntValue")
.replaceAll(";", " ");
}
MPages parseDirectory(String res) {
List<MManga> mangaList = [];
final datas = json.decode(res) as List;
for (var data in datas) {
final d = json.encode(data);
MManga manga = MManga();
manga.name = getMapValue(d, "s");
manga.imageUrl =
'https://temp.compsci88.com/cover/${getMapValue(d, "i")}.jpg';
manga.link = getMapValue(d, "i");
mangaList.add(manga);
}
return MPages(mangaList, true);
}
String chapterImage(String e, bool cleanString) {
var a = e.substring(1, e.length - 1);
if (cleanString) {
a = regExp(a, r'^0+', "", 0, 0);
}
var b = int.parse(e.substring(e.length - 1));
if (b == 0 && a.isNotEmpty) {
return a;
} else if (b == 0 && a.isEmpty) {
return '0';
} else {
return '$a.$b';
}
}
String toStatus(String status) {
if (status.contains("Ongoing")) {
return "Ongoing";
} else if (status.contains("Complete")) {
return "Complete";
} else if (status.contains("Cancelled")) {
return "Cancelled";
} else if (status.contains("Hiatus")) {
return "Hiatus";
}
return "";
}
String chapterURLEncode(String e) {
var index = ''.toString();
var t = int.parse(e.substring(0, 1));
if (t != 1) {
index = '-index-$t';
}
var dgt = 0;
var inta = int.parse(e);
if (inta < 100100) {
dgt = 4;
} else if (inta < 101000) {
dgt = 3;
} else if (inta < 110000) {
dgt = 2;
} else {
dgt = 1;
}
final n = e.substring(dgt, e.length - 1);
var suffix = ''.toString();
final path = int.parse(e.substring(e.length - 1));
if (path != 0) {
suffix = '.$path';
}
return '-chapter-$n$suffix$index.html';
}
}
Map<String, String> getHeader(String url) {
final headers = {
'Referer': '$url/',
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/77.0"
};
return headers;
}
NepNep main() {
return NepNep();
}

View File

@@ -0,0 +1,411 @@
import 'package:mangayomi/bridge_lib.dart';
import 'dart:convert';
class NepNep extends MProvider {
NepNep();
@override
Future<MPages> getPopular(MSource source, int page) async {
final data = {"url": "${source.baseUrl}/search/"};
final res = await http('GET', json.encode(data));
final directory = directoryFromDocument(res);
final resSort = sortMapList(json.decode(directory), "vm", 1);
return parseDirectory(resSort);
}
@override
Future<MPages> getLatestUpdates(MSource source, int page) async {
final data = {"url": "${source.baseUrl}/search/"};
final res = await http('GET', json.encode(data));
final directory = directoryFromDocument(res);
final resSort = sortMapList(json.decode(directory), "lt", 1);
return parseDirectory(resSort);
}
@override
Future<MPages> search(
MSource source, String query, int page, FilterList filterList) async {
final filters = filterList.filters;
List<dynamic> queryRes = [];
final data = {"url": "${source.baseUrl}/search/"};
final res = await http('GET', json.encode(data));
final directory = directoryFromDocument(res);
final resSort = sortMapList(json.decode(directory), "lt", 1);
final datas = json.decode(resSort) as List;
queryRes = datas.where((e) {
String name = getMapValue(json.encode(e), 's');
return name.toLowerCase().contains(query.toLowerCase());
}).toList();
for (var filter in filters) {
if (filter.type == "SortFilter") {
final ascending = filter.state.ascending;
String sortBy = "s";
if (filter.state.index == 1) {
sortBy = "v";
}
if (filter.state.index == 2) {
sortBy = "ls";
}
queryRes = json.decode(sortMapList(queryRes, sortBy, 1)) as List;
if (ascending) {
queryRes = queryRes.reversed.toList();
}
}
if (filter.type == "ScanStatusFilter") {
if (filter.state != 0) {
queryRes = queryRes.where((e) {
final name = getMapValue(json.encode(e), 'ss');
return name.toLowerCase().contains(
(filter.values[filter.state].value as String).toLowerCase());
}).toList();
}
} else if (filter.type == "PublishStatusFilter") {
if (filter.state != 0) {
queryRes = queryRes.where((e) {
final name = getMapValue(json.encode(e), 'ps');
return name.toLowerCase().contains(
(filter.values[filter.state].value as String).toLowerCase());
}).toList();
}
} else if (filter.type == "TypeFilter") {
if (filter.state != 0) {
queryRes = queryRes.where((e) {
final name = getMapValue(json.encode(e), 't');
return name.toLowerCase().contains(
(filter.values[filter.state].value as String).toLowerCase());
}).toList();
}
} else if (filter.type == "TranslationFilter") {
if (filter.state != 0) {
queryRes = queryRes.where((e) {
final name = getMapValue(json.encode(e), 'o');
return name.toLowerCase().contains("yes");
}).toList();
}
} else if (filter.type == "YearFilter") {
if (filter.state.isNotEmpty) {
queryRes = queryRes.where((e) {
final name = getMapValue(json.encode(e), 'y');
return name
.toLowerCase()
.contains((filter.name as String).toLowerCase());
}).toList();
}
} else if (filter.type == "AuthorFilter") {
if (filter.state.isNotEmpty) {
queryRes = queryRes.where((e) {
final name = getMapValue(json.encode(e), 'a');
return name
.toLowerCase()
.contains((filter.name as String).toLowerCase());
}).toList();
}
} else if (filter.type == "GenresFilter") {
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) {
queryRes = queryRes.where((e) {
final name = getMapValue(json.encode(e), 'g');
return name
.toLowerCase()
.contains((val.value as String).toLowerCase());
}).toList();
}
}
if (excluded.isNotEmpty) {
for (var val in excluded) {
queryRes = queryRes.where((e) {
final name = getMapValue(json.encode(e), 'g');
return !(name
.toLowerCase()
.contains((val.value as String).toLowerCase()));
}).toList();
}
}
}
}
return parseDirectory(json.encode(queryRes));
}
@override
Future<MManga> getDetail(MSource source, String url) async {
final statusList = [
{"Ongoing": 0, "Completed": 1, "Cancelled": 3, "Hiatus": 2}
];
final headers = getHeader(source.baseUrl);
final data = {"url": '${source.baseUrl}/manga/$url', "headers": headers};
final res = await http('GET', json.encode(data));
MManga manga = MManga();
manga.author = xpath(res,
'//li[contains(@class,"list-group-item") and contains(text(),"Author")]/a/text()')
.first;
manga.description = xpath(res,
'//li[contains(@class,"list-group-item") and contains(text(),"Description:")]/div/text()')
.first;
final status = xpath(res,
'//li[contains(@class,"list-group-item") and contains(text(),"Status")]/a/text()')
.first;
manga.status = parseStatus(toStatus(status), statusList);
manga.genre = xpath(res,
'//li[contains(@class,"list-group-item") and contains(text(),"Genre(s)")]/a/text()');
final script =
xpath(res, '//script[contains(text(), "MainFunction")]/text()').first;
final vmChapters =
substringBefore(substringAfter(script, "vm.Chapters = "), ";");
final chapters = json.decode(vmChapters) as List;
List<MChapter> chaptersList = [];
for (var ch in chapters) {
final c = json.encode(ch);
MChapter chapter = MChapter();
String name = getMapValue(c, 'ChapterName');
String indexChapter = getMapValue(c, 'Chapter');
if (name.isEmpty) {
name = '${getMapValue(c, 'Type')} ${chapterImage(indexChapter, true)}';
}
chapter.name = name == "null" ? "" : name;
chapter.url =
'/read-online/${substringAfter(url, "/manga/")}${chapterURLEncode(getMapValue(c, 'Chapter'))}';
chapter.dateUpload = parseDates([getMapValue(c, 'Date')],
source.dateFormat, source.dateFormatLocale)
.first;
chaptersList.add(chapter);
}
manga.chapters = chaptersList;
return manga;
}
@override
Future<List<String>> getPageList(MSource source, String url) async {
final headers = getHeader(source.baseUrl);
List<String> pages = [];
final data = {"url": '${source.baseUrl}$url', "headers": headers};
print(data);
final res = await http('GET', json.encode(data));
final script =
xpath(res, '//script[contains(text(), "MainFunction")]/text()').first;
final chapScript =
substringBefore(substringAfter(script, "vm.CurChapter = "), ";");
final pathName = substringBefore(
substringAfter(script, "vm.CurPathName = \"", ""), "\"");
var directory = getMapValue(chapScript, 'Directory') == 'null'
? ''
: getMapValue(chapScript, 'Directory');
if (directory.length > 0) {
directory += '/';
}
final mangaName =
substringBefore(substringAfter(url, "/read-online/"), "-chapter");
var chNum = chapterImage(getMapValue(chapScript, 'Chapter'), false);
var totalPages = int.parse(getMapValue(chapScript, 'Page'));
for (int page = 1; page <= totalPages; page++) {
String paddedPageNumber = "$page".padLeft(3, '0');
String pageUrl =
'https://$pathName/manga/$mangaName/$directory$chNum-$paddedPageNumber.png';
pages.add(pageUrl);
}
return pages;
}
String directoryFromDocument(String res) {
final script =
xpath(res, '//script[contains(text(), "MainFunction")]/text()').first;
return substringBefore(
substringAfter(script, "vm.Directory = "), "vm.GetIntValue")
.replaceAll(";", " ");
}
MPages parseDirectory(String res) {
List<MManga> mangaList = [];
final datas = json.decode(res) as List;
for (var data in datas) {
final d = json.encode(data);
MManga manga = MManga();
manga.name = getMapValue(d, "s");
manga.imageUrl =
'https://temp.compsci88.com/cover/${getMapValue(d, "i")}.jpg';
manga.link = getMapValue(d, "i");
mangaList.add(manga);
}
return MPages(mangaList, true);
}
String chapterImage(String e, bool cleanString) {
var a = e.substring(1, e.length - 1);
if (cleanString) {
a = regExp(a, r'^0+', "", 0, 0);
}
var b = int.parse(e.substring(e.length - 1));
if (b == 0 && a.isNotEmpty) {
return a;
} else if (b == 0 && a.isEmpty) {
return '0';
} else {
return '$a.$b';
}
}
String toStatus(String status) {
if (status.contains("Ongoing")) {
return "Ongoing";
} else if (status.contains("Complete")) {
return "Complete";
} else if (status.contains("Cancelled")) {
return "Cancelled";
} else if (status.contains("Hiatus")) {
return "Hiatus";
}
return "";
}
String chapterURLEncode(String e) {
var index = ''.toString();
var t = int.parse(e.substring(0, 1));
if (t != 1) {
index = '-index-$t';
}
var dgt = 0;
var inta = int.parse(e);
if (inta < 100100) {
dgt = 4;
} else if (inta < 101000) {
dgt = 3;
} else if (inta < 110000) {
dgt = 2;
} else {
dgt = 1;
}
final n = e.substring(dgt, e.length - 1);
var suffix = ''.toString();
final path = int.parse(e.substring(e.length - 1));
if (path != 0) {
suffix = '.$path';
}
return '-chapter-$n$suffix$index.html';
}
List<dynamic> getFilterList() {
return [
TextFilter("YearFilter", "Years"),
TextFilter("AuthorFilter", "Author"),
SelectFilter("ScanStatusFilter", "Scan Status", 0, [
SelectFilterOption("Any", "Any"),
SelectFilterOption("Complete", "Complete"),
SelectFilterOption("Discontinued", "Discontinued"),
SelectFilterOption("Hiatus", "Hiatus"),
SelectFilterOption("Incomplete", "Incomplete"),
SelectFilterOption("Ongoing", "Ongoing"),
]),
SelectFilter("PublishStatusFilter", "Publish Status", 0, [
SelectFilterOption("Any", "Any"),
SelectFilterOption("Cancelled", "Cancelled"),
SelectFilterOption("Complete", "Complete"),
SelectFilterOption("Discontinued", "Discontinued"),
SelectFilterOption("Hiatus", "Hiatus"),
SelectFilterOption("Incomplete", "Incomplete"),
SelectFilterOption("Ongoing", "Ongoing"),
SelectFilterOption("Unfinished", "Unfinished"),
]),
SelectFilter("TypeFilter", "Type", 0, [
SelectFilterOption("Any", "Any"),
SelectFilterOption("Doujinshi", "Doujinshi"),
SelectFilterOption("Manga", "Manga"),
SelectFilterOption("Manhua", "Manhua"),
SelectFilterOption("Manhwa", "Manhwa"),
SelectFilterOption("OEL", "OEL"),
SelectFilterOption("One-shot", "One-shot"),
]),
SelectFilter("TranslationFilter", "Translation", 0, [
SelectFilterOption("Any", "Any"),
SelectFilterOption("Official Only", "Official Only"),
]),
SortFilter("SortFilter", "Sort", SortState(2, false), [
SelectFilterOption("Alphabetically", "Alphabetically"),
SelectFilterOption("Date updated", "Date updated"),
SelectFilterOption("Popularity", "Popularity"),
]),
GroupFilter("GenresFilter", "Genres", [
TriStateFilter("Action", ""),
TriStateFilter("Adult", ""),
TriStateFilter("Adventure", ""),
TriStateFilter("Comedy", ""),
TriStateFilter("Doujinshi", ""),
TriStateFilter("Drama", ""),
TriStateFilter("Ecchi", ""),
TriStateFilter("Fantasy", ""),
TriStateFilter("Gender Bender", ""),
TriStateFilter("Harem", ""),
TriStateFilter("Hentai", ""),
TriStateFilter("Historical", ""),
TriStateFilter("Horror", ""),
TriStateFilter("Isekai", ""),
TriStateFilter("Josei", ""),
TriStateFilter("Lolicon", ""),
TriStateFilter("Martial Arts", ""),
TriStateFilter("Mature", ""),
TriStateFilter("Mecha", ""),
TriStateFilter("Mystery", ""),
TriStateFilter("Psychological", ""),
TriStateFilter("Romance", ""),
TriStateFilter("School Life", ""),
TriStateFilter("Sci-fi", ""),
TriStateFilter("Seinen", ""),
TriStateFilter("Shotacon", ""),
TriStateFilter("Shoujo", ""),
TriStateFilter("Shoujo Ai", ""),
TriStateFilter("Shounen", ""),
TriStateFilter("Shounen Ai", ""),
TriStateFilter("Slice of Life", ""),
TriStateFilter("Smut", ""),
TriStateFilter("Sports", ""),
TriStateFilter("Supernatural", ""),
TriStateFilter("Tragedy", ""),
TriStateFilter("Yaoi", ""),
TriStateFilter("Yuri", ""),
]),
];
}
String ll(String url) {
if (url.contains("?")) {
return "&";
}
return "?";
}
}
Map<String, String> getHeader(String url) {
final headers = {
'Referer': '$url/',
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/77.0"
};
return headers;
}
NepNep main() {
return NepNep();
}

View File

@@ -1,7 +1,7 @@
import '../../../model/source.dart';
import '../../../utils/utils.dart';
const nepnepVersion = "0.0.35";
const nepnepVersion = "0.0.4";
const nepnepSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/manga/multisrc/nepnep/nepnep-v$nepnepVersion.dart";
const defaultDateFormat = "yyyy-MM-dd HH:mm:ss";

View File

@@ -52,29 +52,29 @@ class MangaDex extends MProvider {
} else if (filter.type == "OriginalLanguageList") {
final langs = (filter.state as List).where((e) => e.state).toList();
if (langs.isNotEmpty) {
for (var ln in langs) {
url += "${ll(url)}${ln.value}";
for (var lang in langs) {
url += "${ll(url)}${lang.value}";
}
}
} else if (filter.type == "ContentRatingList") {
final langs = (filter.state as List).where((e) => e.state).toList();
if (langs.isNotEmpty) {
for (var ln in langs) {
url += "${ll(url)}${ln.value}";
final ctns = (filter.state as List).where((e) => e.state).toList();
if (ctns.isNotEmpty) {
for (var ctn in ctns) {
url += "${ll(url)}${ctn.value}";
}
}
} else if (filter.type == "DemographicList") {
final langs = (filter.state as List).where((e) => e.state).toList();
if (langs.isNotEmpty) {
for (var ln in langs) {
url += "${ll(url)}${ln.value}";
final demogr = (filter.state as List).where((e) => e.state).toList();
if (demogr.isNotEmpty) {
for (var demog in demogr) {
url += "${ll(url)}${demog.value}";
}
}
} else if (filter.type == "StatusList") {
final langs = (filter.state as List).where((e) => e.state).toList();
if (langs.isNotEmpty) {
for (var ln in langs) {
url += "${ll(url)}${ln.value}";
final statusL = (filter.state as List).where((e) => e.state).toList();
if (statusL.isNotEmpty) {
for (var status in statusL) {
url += "${ll(url)}${status.value}";
}
}
} else if (filter.type == "SortFilter") {