import 'package:mangayomi/bridge_lib.dart'; import 'dart:convert'; class HeanCms extends MProvider { HeanCms(); final Client client = Client(); @override Future getPopular(MSource source, int page) async { final headers = getHeader(source.baseUrl); String res = ""; if (!useNewQueryEndpoint(source.name)) { final url = "${source.apiUrl}/series/querysearch"; final body = { "page": page, "order": "desc", "order_by": "total_views", "series_status": "Ongoing", "series_type": "Comic" }; res = (await client.post(Uri.parse(url), headers: headers, body: body)) .body; } else { final newEndpointUrl = "${source.apiUrl}/query/?page=$page&query_string=&series_status=All&order=desc&orderBy=total_views&perPage=12&tags_ids=[]&series_type=Comic"; res = (await client.get(Uri.parse(newEndpointUrl), headers: headers)).body; } return mMangaRes(res, source); } @override Future getLatestUpdates(MSource source, int page) async { final headers = getHeader(source.baseUrl); String res = ""; if (!useNewQueryEndpoint(source.name)) { final url = "${source.apiUrl}/series/querysearch"; final body = { "page": page, "order": "desc", "order_by": "latest", "series_status": "Ongoing", "series_type": "Comic" }; res = (await client.post(Uri.parse(url), headers: headers, body: body)) .body; } else { final newEndpointUrl = "${source.apiUrl}/query/?page=$page&query_string=&series_status=All&order=desc&orderBy=latest&perPage=12&tags_ids=[]&series_type=Comic"; res = (await client.get(Uri.parse(newEndpointUrl), headers: headers)).body; } return mMangaRes(res, source); } @override Future search( MSource source, String query, int page, FilterList filterList) async { final headers = getHeader(source.baseUrl); String res = ""; if (!useNewQueryEndpoint(source.source)) { final url = "${source.apiUrl}/series/search"; final body = {"term": query}; res = (await client.post(Uri.parse(url), headers: headers, body: body)) .body; } else { final newEndpointUrl = "${source.apiUrl}/query/?page=$page&query_string=$query&series_status=All&order=desc&orderBy=total_views&perPage=12&tags_ids=[]&series_type=Comic"; res = (await client.get(Uri.parse(newEndpointUrl), headers: headers)).body; } return mMangaRes(res, source); } @override Future getDetail(MSource source, String url) async { MManga manga = MManga(); String currentSlug = substringAfterLast(url, "/"); final headers = getHeader(source.baseUrl); final res = (await client.get( Uri.parse("${source.apiUrl}/series/$currentSlug"), headers: headers)) .body; manga.author = getMapValue(res, "author"); manga.description = getMapValue(res, "description"); manga.genre = jsonPathToString(res, r"$.tags[*].name", "._").split("._"); List chapterTitles = []; List chapterUrls = []; List chapterDates = []; if (!useNewQueryEndpoint(source.name)) { for (var chapter in json.decode(res)["chapters"]) { final chapterName = chapter["chapter_name"]; final chapterSlug = chapter["chapter_slug"]; final chapterId = chapter["id"]; final createdAt = chapter["created_at"]; chapterUrls.add("/series/$currentSlug/$chapterSlug#$chapterId"); chapterTitles.add(chapterName); chapterDates.add(createdAt); } } else { final seasons = json.decode(res)["seasons"].first; for (var chapter in seasons["chapters"]) { final chapterName = chapter["chapter_name"]; final chapterSlug = chapter["chapter_slug"]; final chapterId = chapter["id"]; final createdAt = chapter["created_at"]; chapterUrls.add("/series/$currentSlug/$chapterSlug#$chapterId"); chapterTitles.add(chapterName); chapterDates.add(createdAt); } } final dateUploads = parseDates(chapterDates, "dd MMMM yyyy", "fr"); List? chaptersList = []; for (var i = 0; i < chapterTitles.length; i++) { MChapter chapter = MChapter(); chapter.name = chapterTitles[i]; chapter.url = chapterUrls[i]; chapter.dateUpload = dateUploads[i]; chaptersList.add(chapter); } if (!useNewQueryEndpoint(source.name)) { chaptersList = chaptersList.reversed.toList(); } manga.chapters = chaptersList; return manga; } @override Future> getPageList(MSource source, String url) async { final headers = getHeader(source.baseUrl); String res = "".toString(); if (!useslugStrategy(source.name)) { String chapterId = substringAfter(url, '#'); res = (await client.get( Uri.parse("${source.apiUrl}/series/chapter/$chapterId"), headers: headers)) .body; } else { res = (await client.get(Uri.parse("${source.baseUrl}$url"), headers: headers)) .body; List pageUrls = []; var imagesRes = parseHtml(res) .selectFirst("div.min-h-screen > div.container > p.items-center") .innerHtml; pageUrls = xpath(imagesRes, '//img/@src'); pageUrls.addAll(xpath(imagesRes, '//img/@data-src')); return pageUrls.where((e) => e.isNotEmpty).toList(); } final pages = jsonPathToList(res, r"$.content.images[*]", 0); List pageUrls = []; for (var u in pages) { final url = u.replaceAll('"', ""); if (url.startsWith("http")) { pageUrls.add(url); } else { pageUrls.add("${source.apiUrl}/$url"); } } return pageUrls; } MPages mMangaRes(String res, MSource source) { bool hasNextPage = true; List mangaList = []; List names = []; List urls = []; List images = []; if (res.startsWith("{")) { for (var a in json.decode(res)["data"]) { String thumbnail = a["thumbnail"]; if (thumbnail.startsWith("https://")) { images.add(thumbnail); } else { images.add("${source.apiUrl}/cover/$thumbnail"); } names.add(a["title"]); final seriesSlug = a["series_slug"]; urls.add("/series/$seriesSlug"); } } else { for (var a in json.decode(res)) { String thumbnail = a["thumbnail"]; if (thumbnail.startsWith("https://")) { images.add(thumbnail); } else { images.add("${source.apiUrl}/cover/$thumbnail"); } names.add(a["title"]); final seriesSlug = a["series_slug"]; urls.add("/series/$seriesSlug"); } hasNextPage = false; } for (var i = 0; i < names.length; i++) { MManga manga = MManga(); manga.name = names[i]; manga.imageUrl = images[i]; manga.link = urls[i]; mangaList.add(manga); } return MPages(mangaList, hasNextPage); } bool useNewQueryEndpoint(String sourceName) { List sources = ["YugenMangas", "Perf Scan", "Reaper Scans"]; return sources.contains(sourceName); } bool useslugStrategy(String sourceName) { List sources = ["YugenMangas", "Reaper Scans", "Perf Scan"]; return sources.contains(sourceName); } } Map getHeader(String url) { final headers = { 'Origin': url, 'Referer': '$url/', 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }; return headers; } HeanCms main() { return HeanCms(); }