From 128476a9b5b8b3a8e9c64ac8d47022d1fc1d55cf Mon Sep 17 00:00:00 2001 From: kodjomoustapha <107993382+kodjodevf@users.noreply.github.com> Date: Tue, 26 Dec 2023 14:38:46 +0100 Subject: [PATCH] New source: DramaCool (EN) --- anime/source_generator.dart | 4 +- anime/src/en/dramacool/dramacool.dart | 213 ++++++++++++++++++++++++++ anime/src/en/dramacool/icon.png | Bin 0 -> 6955 bytes anime/src/en/dramacool/source.dart | 16 ++ 4 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 anime/src/en/dramacool/dramacool.dart create mode 100644 anime/src/en/dramacool/icon.png create mode 100644 anime/src/en/dramacool/source.dart diff --git a/anime/source_generator.dart b/anime/source_generator.dart index f1c9c4d8..ca5fe23f 100644 --- a/anime/source_generator.dart +++ b/anime/source_generator.dart @@ -7,6 +7,7 @@ import 'multisrc/dopeflix/sources.dart'; import 'multisrc/zorotheme/sources.dart'; import 'src/ar/okanime/source.dart'; import 'src/en/aniwave/source.dart'; +import 'src/en/dramacool/source.dart'; import 'src/en/gogoanime/source.dart'; import 'src/en/kisskh/source.dart'; import 'src/en/uhdmovies/source.dart'; @@ -36,7 +37,8 @@ void main() { animesaturn, uhdmoviesSource, ...datalifeengineSourcesList, - filma24 + filma24, + dramacoolSource ]; final List> jsonList = _sourcesList.map((source) => source.toJson()).toList(); diff --git a/anime/src/en/dramacool/dramacool.dart b/anime/src/en/dramacool/dramacool.dart new file mode 100644 index 00000000..9ebc27ec --- /dev/null +++ b/anime/src/en/dramacool/dramacool.dart @@ -0,0 +1,213 @@ +import 'package:mangayomi/bridge_lib.dart'; +import 'dart:convert'; + +class DramaCool extends MProvider { + DramaCool(); + @override + Future getPopular(MSource source, int page) async { + final data = { + "url": "${preferenceBaseUrl(source.id)}/most-popular-drama?page=$page" + }; + final res = await http('GET', json.encode(data)); + final document = parseHtml(res); + return animeFromElement(document.select("ul.list-episode-item li a"), + document.selectFirst("li.next a")?.attr("href") != null); + } + + @override + Future getLatestUpdates(MSource source, int page) async { + final data = { + "url": "${preferenceBaseUrl(source.id)}/recently-added?page=$page" + }; + final res = await http('GET', json.encode(data)); + final document = parseHtml(res); + return animeFromElement(document.select("ul.switch-block a"), + document.selectFirst("li.next a")?.attr("href") != null); + } + + @override + Future search( + MSource source, String query, int page, FilterList filterList) async { + final data = { + "url": "${preferenceBaseUrl(source.id)}/search?keyword=$query&page=$page" + }; + final res = await http('GET', json.encode(data)); + final document = parseHtml(res); + return animeFromElement(document.select("ul.list-episode-item li a"), + document.selectFirst("li.next a")?.attr("href") != null); + } + + @override + Future getDetail(MSource source, String url) async { + final statusList = [ + {"Ongoing": 0, "Completed": 1} + ]; + url = Uri.parse(url).path; + if (url.contains("-episode-") && url.endsWith(".html")) { + final data = {"url": "${preferenceBaseUrl(source.id)}$url"}; + final res = await http('GET', json.encode(data)); + url = parseHtml(res).selectFirst("div.category a").attr("href"); + } + url = Uri.parse(url).path; + + final data = {"url": "${preferenceBaseUrl(source.id)}$url"}; + final res = await http('GET', json.encode(data)); + final document = parseHtml(res); + MManga anime = MManga(); + anime.description = document + .selectFirst("div.info") + .select("p") + .map((MElement e) { + if (!e.outerHtml.contains(" episodesList = []; + final episodeListElements = document.select("ul.all-episode li a"); + + for (var element in episodeListElements) { + var epNum = + substringAfterLast(element.selectFirst("h3").text, "Episode "); + var type = element.selectFirst("span.type")?.text ?? "RAW"; + var date = element.selectFirst("span.time")?.text ?? ""; + MChapter ep = MChapter(); + ep.name = "$type: Episode $epNum".trim(); + ep.url = element.getHref; + if (date.isNotEmpty) + ep.dateUpload = parseDates([element.selectFirst("span.time")?.text], + "yyyy-MM-dd HH:mm:ss", "en") + .first; + episodesList.add(ep); + } + + anime.chapters = episodesList; + return anime; + } + + @override + Future> getVideoList(MSource source, String url) async { + url = Uri.parse(url).path; + final data = {"url": "${preferenceBaseUrl(source.id)}$url"}; + final res = await http('GET', json.encode(data)); + final document = parseHtml(res); + String iframeUrl = document.selectFirst("iframe")?.getSrc ?? ""; + if (iframeUrl.isEmpty) return []; + if (iframeUrl.startsWith("//")) { + iframeUrl = "https:$iframeUrl"; + } + var iframeDoc = + parseHtml(await http('GET', json.encode({"url": iframeUrl}))); + final serverElements = iframeDoc.select("ul.list-server-items li"); + List videos = []; + for (var serverElement in serverElements) { + var url = serverElement.attr("data-video"); + List a = []; + if (url.contains("dood")) { + a = await doodExtractor(url, "DoodStream"); + } else if (url.contains("dwish")) { + a = await streamWishExtractor(url, "StreamWish"); + } else if (url.contains("streamtape")) { + a = await streamTapeExtractor(url, "StreamTape"); + } + videos.addAll(a); + } + return sortVideos(videos, source.id); + } + + @override + List getSourcePreferences(MSource source) { + return [ + EditTextPreference( + key: "overrideBaseUrl", + title: "Override BaseUrl", + summary: "", + value: "https://dramacool.pa", + dialogTitle: "Override BaseUrl", + dialogMessage: "", + text: "https://dramacool.pa"), + ListPreference( + key: "preferred_quality", + title: "Preferred quality", + summary: "", + valueIndex: 0, + entries: [ + "1080p", + "720p", + "480p", + "360p", + "Doodstream", + "StreamTape" + ], + entryValues: [ + "1080", + "720", + "480", + "360", + "Doodstream", + "StreamTape" + ]) + ]; + } + + String preferenceBaseUrl(int sourceId) { + return getPreferenceValue(sourceId, "overrideBaseUrl"); + } + + MPages animeFromElement(List elements, bool hasNextPage) { + List animeList = []; + for (var element in elements) { + MManga anime = MManga(); + anime.name = element.selectFirst("h3")?.text ?? "Serie"; + anime.imageUrl = (element.selectFirst("img")?.attr("data-original") ?? "") + .replaceAll(" ", "%20") ?? + ""; + anime.link = element.getHref; + animeList.add(anime); + } + return MPages(animeList, hasNextPage); + } + + List sortVideos(List videos, int sourceId) { + String quality = getPreferenceValue(sourceId, "preferred_quality"); + + videos.sort((MVideo a, MVideo b) { + int qualityMatchA = 0; + if (a.quality.contains(quality)) { + qualityMatchA = 1; + } + int qualityMatchB = 0; + if (b.quality.contains(quality)) { + qualityMatchB = 1; + } + if (qualityMatchA != qualityMatchB) { + return qualityMatchB - qualityMatchA; + } + + final regex = RegExp(r'(\d+)p'); + final matchA = regex.firstMatch(a.quality); + final matchB = regex.firstMatch(b.quality); + final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0; + final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0; + return qualityNumB - qualityNumA; + }); + + return videos; + } +} + +DramaCool main() { + return DramaCool(); +} diff --git a/anime/src/en/dramacool/icon.png b/anime/src/en/dramacool/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ceb49c5d358c16b17efc8937f283f624a41efb53 GIT binary patch literal 6955 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 _dramacoolSource; +const _dramacoolVersion = "0.0.1"; +const _dramacoolSourceCodeUrl = + "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/anime/src/en/dramacool/dramacool.dart"; +Source _dramacoolSource = Source( + name: "DramaCool", + baseUrl: "https://dramacool.pa", + lang: "en", + typeSource: "single", + iconUrl: + "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/anime/src/en/dramacool/icon.png", + sourceCodeUrl: _dramacoolSourceCodeUrl, + version: _dramacoolVersion, + isManga: false);