From 2b5359ca2656e182ecb29674db32920dd6e19000 Mon Sep 17 00:00:00 2001 From: jopejoe1 <34899572+jopejoe1@users.noreply.github.com> Date: Mon, 7 Mar 2022 03:48:27 +1300 Subject: [PATCH] Mangadex: Add support for MDLists url intent (#11024) * Update build.gradle * Added list support * Add error message for empty list * Update AndroidManifest.xml --- src/all/mangadex/AndroidManifest.xml | 26 ++----- src/all/mangadex/build.gradle | 2 +- .../extension/all/mangadex/MDConstants.kt | 2 + .../extension/all/mangadex/MangaDex.kt | 74 ++++++++++++++++--- .../all/mangadex/MangadexUrlActivity.kt | 1 + .../extension/all/mangadex/dto/ListDto.kt | 25 +++++++ 6 files changed, 101 insertions(+), 29 deletions(-) create mode 100644 src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/dto/ListDto.kt diff --git a/src/all/mangadex/AndroidManifest.xml b/src/all/mangadex/AndroidManifest.xml index d3558b582..78a723a92 100644 --- a/src/all/mangadex/AndroidManifest.xml +++ b/src/all/mangadex/AndroidManifest.xml @@ -15,25 +15,15 @@ + - - - - - - + + + + + + + diff --git a/src/all/mangadex/build.gradle b/src/all/mangadex/build.gradle index f9141ab5a..32e799278 100644 --- a/src/all/mangadex/build.gradle +++ b/src/all/mangadex/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'MangaDex' pkgNameSuffix = 'all.mangadex' extClass = '.MangaDexFactory' - extVersionCode = 156 + extVersionCode = 157 isNsfw = true } diff --git a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MDConstants.kt b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MDConstants.kt index c605f1306..4549a7a99 100644 --- a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MDConstants.kt +++ b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MDConstants.kt @@ -24,6 +24,7 @@ object MDConstants { const val apiUrl = "https://api.mangadex.org" const val apiMangaUrl = "$apiUrl/manga" const val apiChapterUrl = "$apiUrl/chapter" + const val apiListUrl = "$apiUrl/list" const val atHomePostUrl = "https://api.mangadex.network/report" val whitespaceRegex = "\\s".toRegex() @@ -37,6 +38,7 @@ object MDConstants { const val prefixGrpSearch = "grp:" const val prefixAuthSearch = "author:" const val prefixUsrSearch = "usr:" + const val prefixListSearch = "list:" const val coverQualityPref = "thumbnailQuality" diff --git a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDex.kt b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDex.kt index eb02b7136..ea65289a7 100644 --- a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDex.kt +++ b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDex.kt @@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.extension.all.mangadex.dto.AggregateDto import eu.kanade.tachiyomi.extension.all.mangadex.dto.AtHomeDto import eu.kanade.tachiyomi.extension.all.mangadex.dto.ChapterDto import eu.kanade.tachiyomi.extension.all.mangadex.dto.ChapterListDto +import eu.kanade.tachiyomi.extension.all.mangadex.dto.ListDto import eu.kanade.tachiyomi.extension.all.mangadex.dto.MangaDto import eu.kanade.tachiyomi.extension.all.mangadex.dto.MangaListDto import eu.kanade.tachiyomi.network.GET @@ -191,17 +192,22 @@ abstract class MangaDex(override val lang: String, val dexLang: String) : // SEARCH section override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { - if (query.startsWith(MDConstants.prefixChSearch)) { - return getMangaIdFromChapterId(query.removePrefix(MDConstants.prefixChSearch)).flatMap { manga_id -> - super.fetchSearchManga(page, MDConstants.prefixIdSearch + manga_id, filters) - } + when { + query.startsWith(MDConstants.prefixChSearch) -> + return getMangaIdFromChapterId(query.removePrefix(MDConstants.prefixChSearch)).flatMap { manga_id -> + super.fetchSearchManga(page, MDConstants.prefixIdSearch + manga_id, filters) + } + query.startsWith(MDConstants.prefixUsrSearch) -> + return client.newCall(searchMangaUploaderRequest(page, query.removePrefix(MDConstants.prefixUsrSearch))) + .asObservableSuccess() + .map { latestUpdatesParse(it) } + query.startsWith(MDConstants.prefixListSearch) -> + return client.newCall(GET(MDConstants.apiListUrl + "/" + query.removePrefix(MDConstants.prefixListSearch), headers, CacheControl.FORCE_NETWORK)) + .asObservableSuccess() + .map { searchMangaListRequest(it, page) } + else -> + return super.fetchSearchManga(page, query, filters) } - if (query.startsWith(MDConstants.prefixUsrSearch)) { - return client.newCall(searchMangaUploaderRequest(page, query.removePrefix(MDConstants.prefixUsrSearch))) - .asObservableSuccess() - .map { latestUpdatesParse(it) } - } - return super.fetchSearchManga(page, query, filters) } private fun getMangaIdFromChapterId(id: String): Observable { @@ -277,6 +283,54 @@ abstract class MangaDex(override val lang: String, val dexLang: String) : override fun searchMangaParse(response: Response): MangasPage = popularMangaParse(response) + private fun searchMangaListRequest(response: Response, page: Int): MangasPage { + if (response.isSuccessful.not()) { + throw Exception("HTTP ${response.code}") + } + + val listDto = helper.json.decodeFromString(response.body!!.string()) + val listDtoFiltered = listDto.data.relationships.filter { it.type != "Manga" } + val amount = listDtoFiltered.count() + if (amount < 1){ + throw Exception("No Manga in List") + } + val minIndex = (page - 1) * MDConstants.mangaLimit + + val url = MDConstants.apiMangaUrl.toHttpUrl().newBuilder().apply { + addQueryParameter("limit", MDConstants.mangaLimit.toString()) + addQueryParameter("offset", "0") + addQueryParameter("includes[]", MDConstants.coverArt) + } + listDtoFiltered.forEachIndexed() { index, relationshipDto -> + if (index >= minIndex && index < (minIndex + MDConstants.mangaLimit)) { + url.addQueryParameter("ids[]", relationshipDto.id) + } + } + + val request = client.newCall(GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK)) + val mangaList = searchMangaListParse(request.execute()) + return MangasPage(mangaList, amount.toFloat() / MDConstants.mangaLimit - (page.toFloat() - 1) > 1) + } + + private fun searchMangaListParse(response: Response): List { + if (response.isSuccessful.not()) { + throw Exception("HTTP ${response.code}") + } + + val mangaListDto = helper.json.decodeFromString(response.body!!.string()) + + val coverSuffix = preferences.getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "") + + val mangaList = mangaListDto.data.map { mangaDataDto -> + val fileName = mangaDataDto.relationships.firstOrNull { relationshipDto -> + relationshipDto.type.equals(MDConstants.coverArt, true) + }?.attributes?.fileName + helper.createBasicManga(mangaDataDto, fileName, coverSuffix, dexLang) + } + + return mangaList + } + private fun searchMangaUploaderRequest(page: Int, uploader: String): Request { val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder().apply { addQueryParameter("offset", helper.getLatestChapterOffset(page)) diff --git a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangadexUrlActivity.kt b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangadexUrlActivity.kt index 490f60201..fc473bdf6 100644 --- a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangadexUrlActivity.kt +++ b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangadexUrlActivity.kt @@ -31,6 +31,7 @@ class MangadexUrlActivity : Activity() { equals("group") -> putExtra("query", "${MDConstants.prefixGrpSearch}$titleid") equals("user") -> putExtra("query", "${MDConstants.prefixUsrSearch}$titleid") equals("author") -> putExtra("query", "${MDConstants.prefixAuthSearch}$titleid") + equals("list") -> putExtra("query", "${MDConstants.prefixListSearch}$titleid") else -> putExtra("query", "${MDConstants.prefixIdSearch}$titleid") } } diff --git a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/dto/ListDto.kt b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/dto/ListDto.kt new file mode 100644 index 000000000..c7b71e69f --- /dev/null +++ b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/dto/ListDto.kt @@ -0,0 +1,25 @@ +package eu.kanade.tachiyomi.extension.all.mangadex.dto + +import kotlinx.serialization.Serializable + +@Serializable +data class ListDto( + val result: String, + val response: String, + val data: ListDataDto, +) + +@Serializable +data class ListDataDto( + val id: String, + val type: String, + val attributes: ListAttributesDto, + val relationships: List, +) + +@Serializable +data class ListAttributesDto( + val name: String, + val visibility: String, + val version: Int, +)