From 1b6e122a8c1a992d40b3bd6af41a5f2adfe5d7cd Mon Sep 17 00:00:00 2001 From: xMohnad Date: Wed, 25 Jun 2025 18:56:50 +0000 Subject: [PATCH 1/4] fix(nyaa): ensure `chapters` is List to avoid type cast error --- dart/anime/src/all/nyaa/nyaa.dart | 66 ++++++++++++++++--------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/dart/anime/src/all/nyaa/nyaa.dart b/dart/anime/src/all/nyaa/nyaa.dart index 4083052b..5059169e 100644 --- a/dart/anime/src/all/nyaa/nyaa.dart +++ b/dart/anime/src/all/nyaa/nyaa.dart @@ -9,23 +9,21 @@ class Nyaa extends MProvider { @override Future getPopular(int page) async { - final res = - (await client.get( - Uri.parse( - "${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=&s=downloads&o=desc&p=$page", - ), - )).body; + final res = (await client.get( + Uri.parse( + "${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=&s=downloads&o=desc&p=$page", + ), + )).body; return parseAnimeList(res); } @override Future getLatestUpdates(int page) async { - final res = - (await client.get( - Uri.parse( - "${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=$page", - ), - )).body; + final res = (await client.get( + Uri.parse( + "${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=$page", + ), + )).body; return parseAnimeList(res); } @@ -57,11 +55,17 @@ class Nyaa extends MProvider { description += "\n\n${(document.xpathFirst('//div[@class="panel panel-default"]/text()') ?? "").trim().replaceAll("\n", "")}"; anime.description = description; - MChapter ep = MChapter(); - ep.name = "Torrent"; - ep.url = - "${source.baseUrl}/download/${substringAfterLast(url, '/')}.torrent"; - anime.chapters = [ep]; + + List chapters = []; + chapters.add( + MChapter( + name: "Torrent", + url: + "${source.baseUrl}/download/${substringAfterLast(url, '/')}.torrent", + ), + ); + anime.chapters = chapters; + return anime; } @@ -114,27 +118,25 @@ class Nyaa extends MProvider { MManga anime = MManga(); anime.imageUrl = "${source.baseUrl}${getUrlWithoutDomain(value.selectFirst("td:nth-child(1) > a > img").getSrc)}"; - MElement firstElement = - value - .select("td > a") - .where( - (MElement e) => - e.outerHtml.contains("/view/") && - !e.outerHtml.contains("#comments"), - ) - .toList() - .first; + MElement firstElement = value + .select("td > a") + .where( + (MElement e) => + e.outerHtml.contains("/view/") && + !e.outerHtml.contains("#comments"), + ) + .toList() + .first; anime.link = "${source.baseUrl}${getUrlWithoutDomain(firstElement.getHref)}"; anime.name = firstElement.attr("title"); animeList.add(anime); } - final hasNextPage = - xpath( - res, - '//ul[@class="pagination"]/li[contains(text(),"»")]/a/@href', - ).isNotEmpty; + final hasNextPage = xpath( + res, + '//ul[@class="pagination"]/li[contains(text(),"»")]/a/@href', + ).isNotEmpty; return MPages(animeList, hasNextPage); } From 829c86150208623701a4884a139271136fe06dcf Mon Sep 17 00:00:00 2001 From: xMohnad Date: Wed, 25 Jun 2025 20:31:45 +0000 Subject: [PATCH 2/4] feat(nyaa): extract and format torrent info, optionally append full description --- dart/anime/src/all/nyaa/nyaa.dart | 60 +++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/dart/anime/src/all/nyaa/nyaa.dart b/dart/anime/src/all/nyaa/nyaa.dart index 5059169e..98f846f8 100644 --- a/dart/anime/src/all/nyaa/nyaa.dart +++ b/dart/anime/src/all/nyaa/nyaa.dart @@ -44,17 +44,58 @@ class Nyaa extends MProvider { return parseAnimeList(res); } + String extractPanelBody(MDocument document) { + final panelBody = document.selectFirst('.panel-body'); + if (panelBody == null) return ""; + + final rows = panelBody.select('.row'); + + final Map info = {}; + for (var row in rows) { + final labels = row.select('.col-md-1'); + for (var label in labels) { + final key = label.text.replaceAll(":", "").trim(); + final valueDiv = label.nextElementSibling; + if (valueDiv == null) continue; + + final links = valueDiv.select('a'); + String value; + if (links.isNotEmpty) { + value = links.map((a) => a.text.trim()).join(' - '); + } else { + value = valueDiv.text.trim(); + } + + info[key] = value; + } + } + + final buffer = StringBuffer(); + buffer.writeln("Torrent Info:\n"); + info.forEach((k, v) { + buffer.writeln("${k.padRight(11)}: $v"); + }); + if (getPreferenceValue(source.id, "torrent_description_visible")) { + buffer.writeln("\n\n"); + buffer.writeln("Torrent Description: \n"); + buffer.writeln( + document + .select("#torrent-description") + .map((e) => e.text.trim()) + .join("\n\n"), + ); + } + + return buffer.toString(); + } + @override Future getDetail(String url) async { MManga anime = MManga(); final res = (await client.get(Uri.parse(url))).body; final document = parseHtml(res); - String description = - (document.xpathFirst('//div[@class="panel-body"]/text()') ?? "") - .replaceAll("\n", ""); - description += - "\n\n${(document.xpathFirst('//div[@class="panel panel-default"]/text()') ?? "").trim().replaceAll("\n", "")}"; - anime.description = description; + + anime.description = extractPanelBody(document); List chapters = []; chapters.add( @@ -104,6 +145,13 @@ class Nyaa extends MProvider { entries: ["Anime", "Live Action"], entryValues: ["1_0", "4_0"], ), + SwitchPreferenceCompat( + key: "torrent_description_visible", + title: "Display Torrent Description", + summary: + "Enable to show the full torrent description in the details view.", + value: false, + ), ]; } From 0e79bfce26ae94f16d01eba80e9ff8caabc2f2d1 Mon Sep 17 00:00:00 2001 From: xMohnad Date: Wed, 25 Jun 2025 20:44:29 +0000 Subject: [PATCH 3/4] refactor(nyaa): use getBaseUrl() to support dynamic domain from preferences --- dart/anime/src/all/nyaa/nyaa.dart | 33 ++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/dart/anime/src/all/nyaa/nyaa.dart b/dart/anime/src/all/nyaa/nyaa.dart index 98f846f8..ef21fcb8 100644 --- a/dart/anime/src/all/nyaa/nyaa.dart +++ b/dart/anime/src/all/nyaa/nyaa.dart @@ -11,7 +11,7 @@ class Nyaa extends MProvider { Future getPopular(int page) async { final res = (await client.get( Uri.parse( - "${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=&s=downloads&o=desc&p=$page", + "${getBaseUrl()}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=&s=downloads&o=desc&p=$page", ), )).body; return parseAnimeList(res); @@ -21,7 +21,7 @@ class Nyaa extends MProvider { Future getLatestUpdates(int page) async { final res = (await client.get( Uri.parse( - "${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=$page", + "${getBaseUrl()}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=$page", ), )).body; return parseAnimeList(res); @@ -32,7 +32,7 @@ class Nyaa extends MProvider { final filters = filterList.filters; String url = ""; url = - "${source.baseUrl}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=${query.replaceAll(" ", "+")}&p=$page"; + "${getBaseUrl()}/?f=0&c=${getPreferenceValue(source.id, "preferred_categorie_page")}&q=${query.replaceAll(" ", "+")}&p=$page"; for (var filter in filters) { if (filter.type == "SortFilter") { url += "${ll(url)}s=${filter.values[filter.state.index].value}"; @@ -101,8 +101,7 @@ class Nyaa extends MProvider { chapters.add( MChapter( name: "Torrent", - url: - "${source.baseUrl}/download/${substringAfterLast(url, '/')}.torrent", + url: "${getBaseUrl()}/download/${substringAfterLast(url, '/')}.torrent", ), ); anime.chapters = chapters; @@ -152,9 +151,29 @@ class Nyaa extends MProvider { "Enable to show the full torrent description in the details view.", value: false, ), + EditTextPreference( + key: "domain_url", + title: 'Edit URL', + summary: "", + value: source.baseUrl, + dialogTitle: "URL", + dialogMessage: "", + ), ]; } + String getBaseUrl() { + final baseUrl = getPreferenceValue(source.id, "domain_url")?.trim(); + + if (baseUrl == null || baseUrl.isEmpty) { + return source.baseUrl; + } + + return baseUrl.endsWith("/") + ? baseUrl.substring(0, baseUrl.length - 1) + : baseUrl; + } + MPages parseAnimeList(String res) { List animeList = []; final document = parseHtml(res); @@ -165,7 +184,7 @@ class Nyaa extends MProvider { for (var value in values) { MManga anime = MManga(); anime.imageUrl = - "${source.baseUrl}${getUrlWithoutDomain(value.selectFirst("td:nth-child(1) > a > img").getSrc)}"; + "${getBaseUrl()}${getUrlWithoutDomain(value.selectFirst("td:nth-child(1) > a > img").getSrc)}"; MElement firstElement = value .select("td > a") .where( @@ -176,7 +195,7 @@ class Nyaa extends MProvider { .toList() .first; anime.link = - "${source.baseUrl}${getUrlWithoutDomain(firstElement.getHref)}"; + "${getBaseUrl()}${getUrlWithoutDomain(firstElement.getHref)}"; anime.name = firstElement.attr("title"); animeList.add(anime); } From 27266a92b1417ffb6899e075172ecbf50c1d6bb2 Mon Sep 17 00:00:00 2001 From: xMohnad Date: Wed, 25 Jun 2025 20:50:27 +0000 Subject: [PATCH 4/4] chore: Bump nyaa version --- dart/anime/src/all/nyaa/source.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dart/anime/src/all/nyaa/source.dart b/dart/anime/src/all/nyaa/source.dart index e48e5501..59168bfe 100644 --- a/dart/anime/src/all/nyaa/source.dart +++ b/dart/anime/src/all/nyaa/source.dart @@ -1,6 +1,6 @@ import '../../../../../model/source.dart'; -const _nyaaVersion = "0.0.3"; +const _nyaaVersion = "0.0.4"; const _nyaaSourceCodeUrl = "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/all/nyaa/nyaa.dart";