From 27b2d172d4f57f4f5019bc6757a53db34c46d2cc Mon Sep 17 00:00:00 2001 From: Alessandro Jean <14254807+alessandrojean@users.noreply.github.com> Date: Mon, 20 Jun 2022 15:20:40 -0300 Subject: [PATCH] Refactor the MangaPlus code a bit. (#12262) --- src/all/mangaplus/build.gradle | 2 +- .../extension/all/mangaplus/MangaPlus.kt | 104 ++++++++++-------- .../extension/all/mangaplus/MangaPlusDto.kt | 3 +- .../extension/all/mangaplus/MangaPlusIntl.kt | 10 ++ .../all/mangaplus/MangaPlusUrlActivity.kt | 12 +- 5 files changed, 78 insertions(+), 53 deletions(-) diff --git a/src/all/mangaplus/build.gradle b/src/all/mangaplus/build.gradle index b495eaa2f..0cd94b80b 100644 --- a/src/all/mangaplus/build.gradle +++ b/src/all/mangaplus/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'MANGA Plus by SHUEISHA' pkgNameSuffix = 'all.mangaplus' extClass = '.MangaPlusFactory' - extVersionCode = 34 + extVersionCode = 35 } apply from: "$rootDir/common.gradle" diff --git a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlus.kt b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlus.kt index 1f5ea3bc5..18332be1e 100644 --- a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlus.kt +++ b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlus.kt @@ -139,53 +139,22 @@ abstract class MangaPlus( return MangasPage(mangas, false) } - private fun fetchTitleIdFromChapterId(chapterId: String): Observable { - - return Observable.defer { - client.newCall(pageListRequestFromChapterId(chapterId)).asObservableSuccess() - }.map { response -> - titleIdParse(response) - } - } - - private fun titleIdParse(response: Response): Int { - val result = response.asMangaPlusResponse() - - checkNotNull(result.success) { result.error!!.langPopup(langCode).body } - - return checkNotNull(result.success.mangaViewer?.titleId) { "Chapter is invalid or expired" } - } - - override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { - if (query.startsWith(PREFIX_CHAPTER_ID_SEARCH) && query.matches(CHAPTER_ID_SEARCH_PATTERN)) { - return fetchTitleIdFromChapterId(query.removePrefix(PREFIX_CHAPTER_ID_SEARCH)).flatMap { - fetchSearchManga(page, "$PREFIX_ID_SEARCH$it", filters) - } - } - return super.fetchSearchManga(page, query, filters) - .map { - if (it.mangas.size == 1) { - return@map it - } - - val filteredResult = it.mangas.filter { manga -> - manga.title.contains(query.trim(), true) - } - - MangasPage(filteredResult, it.hasNextPage) - } - } - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { if (query.startsWith(PREFIX_ID_SEARCH) && query.matches(ID_SEARCH_PATTERN)) { return titleDetailsRequest(query.removePrefix(PREFIX_ID_SEARCH)) + } else if (query.startsWith(PREFIX_CHAPTER_ID_SEARCH) && query.matches(CHAPTER_ID_SEARCH_PATTERN)) { + return mangaViewerRequest(query.removePrefix(PREFIX_CHAPTER_ID_SEARCH)) } val newHeaders = headersBuilder() .set("Referer", "$baseUrl/manga_list/all") .build() - return GET("$API_URL/title_list/allV2?format=json", newHeaders) + val apiUrl = "$API_URL/title_list/allV2".toHttpUrl().newBuilder() + .addQueryParameter("filter", query.trim()) + .addQueryParameter("format", "json") + + return GET(apiUrl.toString(), newHeaders) } override fun searchMangaParse(response: Response): MangasPage { @@ -207,9 +176,39 @@ abstract class MangaPlus( return MangasPage(listOf(manga), hasNextPage = false) } + if (result.success.mangaViewer != null) { + checkNotNull(result.success.mangaViewer.titleId) { intl.chapterExpired } + + val titleId = result.success.mangaViewer.titleId + val cacheTitle = titleList.orEmpty().firstOrNull { it.titleId == titleId } + + val manga = if (cacheTitle != null) { + SManga.create().apply { + title = result.success.mangaViewer.titleName!! + thumbnail_url = cacheTitle.portraitImageUrl + url = "#/titles/$titleId" + } + } else { + val titleRequest = titleDetailsRequest(titleId.toString()) + val titleResult = client.newCall(titleRequest).execute().asMangaPlusResponse() + + checkNotNull(titleResult.success) { titleResult.error!!.langPopup(langCode).body } + + titleDetailsParse(titleResult.success.titleDetailView!!) + } + + return MangasPage(listOfNotNull(manga), hasNextPage = false) + } + + val filter = response.request.url.queryParameter("filter").orEmpty() + titleList = result.success.allTitlesViewV2!!.allTitlesGroup .flatMap(AllTitlesGroup::titles) .filter { it.language == langCode } + .filter { title -> + title.name.contains(filter, ignoreCase = true) || + title.author.contains(filter, ignoreCase = true) + } val mangas = titleList!!.map { SManga.create().apply { @@ -251,17 +250,25 @@ abstract class MangaPlus( checkNotNull(result.success) { result.error!!.langPopup(langCode).body } - val details = result.success.titleDetailView!! - val title = details.title + return titleDetailsParse(result.success.titleDetailView!!) + ?: throw Exception(intl.notAvailable) + } - return SManga.create().apply { - author = title.author.replace(" / ", ", ") + private fun titleDetailsParse(details: TitleDetailView): SManga? { + val titleObj = details.title + + val manga = SManga.create().apply { + title = titleObj.name + author = titleObj.author.replace(" / ", ", ") artist = author description = details.overview + "\n\n" + details.viewingPeriodDescription status = if (details.isCompleted) SManga.COMPLETED else SManga.ONGOING genre = details.genres.filter(String::isNotEmpty).joinToString() - thumbnail_url = title.portraitImageUrl + thumbnail_url = titleObj.portraitImageUrl + url = "#/titles/${titleObj.titleId}" } + + return manga.takeIf { titleObj.language == langCode } } override fun chapterListRequest(manga: SManga): Request = titleDetailsRequest(manga.url) @@ -290,10 +297,11 @@ abstract class MangaPlus( override fun pageListRequest(chapter: SChapter): Request { val chapterId = chapter.url.substringAfterLast("/") - return pageListRequestFromChapterId(chapterId) + + return mangaViewerRequest(chapterId) } - private fun pageListRequestFromChapterId(chapterId: String): Request { + private fun mangaViewerRequest(chapterId: String): Request { val newHeaders = headersBuilder() .set("Referer", "$baseUrl/viewer/$chapterId") .build() @@ -443,7 +451,7 @@ abstract class MangaPlus( companion object { private const val API_URL = "https://jumpg-webapi.tokyo-cdn.com/api" private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + - "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36" + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" private const val QUALITY_PREF_KEY = "imageResolution" private val QUALITY_PREF_ENTRY_VALUES = arrayOf("low", "high", "super_high") @@ -459,7 +467,7 @@ abstract class MangaPlus( const val PREFIX_ID_SEARCH = "id:" private val ID_SEARCH_PATTERN = "^id:(\\d+)$".toRegex() - const val PREFIX_CHAPTER_ID_SEARCH = "ch_id:" - private val CHAPTER_ID_SEARCH_PATTERN = "^ch_id:(\\d+)$".toRegex() + const val PREFIX_CHAPTER_ID_SEARCH = "chapter-id:" + private val CHAPTER_ID_SEARCH_PATTERN = "^chapter-id:(\\d+)$".toRegex() } } diff --git a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusDto.kt b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusDto.kt index b6621618c..770004bfc 100644 --- a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusDto.kt +++ b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusDto.kt @@ -96,7 +96,8 @@ data class TitleDetailView( @Serializable data class MangaViewer( val pages: List = emptyList(), - val titleId: Int? = null + val titleId: Int? = null, + val titleName: String? = null ) @Serializable diff --git a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusIntl.kt b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusIntl.kt index fa8978254..fa4313c34 100644 --- a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusIntl.kt +++ b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusIntl.kt @@ -31,4 +31,14 @@ class MangaPlusIntl(lang: Language) { Language.PORTUGUESE_BR -> "Somente poucos títulos suportam a desativação desta configuração." else -> "Only a few titles supports disabling this setting." } + + val chapterExpired: String = when (lang) { + Language.PORTUGUESE_BR -> "O período de leitura do capítulo expirou." + else -> "The chapter reading period has expired." + } + + val notAvailable: String = when (lang) { + Language.PORTUGUESE_BR -> "Título não disponível neste idioma." + else -> "Title not available in this language." + } } diff --git a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusUrlActivity.kt b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusUrlActivity.kt index 2fa5b2d59..e6a7c1f3d 100644 --- a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusUrlActivity.kt +++ b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusUrlActivity.kt @@ -14,9 +14,15 @@ class MangaPlusUrlActivity : Activity() { val pathSegments = intent?.data?.pathSegments if (pathSegments != null && pathSegments.size > 1) { + // Using Java's equals to not cause crashes in the activity. val query = when { - pathSegments[0].equals("viewer") -> MangaPlus.PREFIX_CHAPTER_ID_SEARCH + pathSegments[1] - pathSegments[0].equals("sns_share") -> intent?.data?.getQueryParameter("title_id")?.let { MangaPlus.PREFIX_ID_SEARCH + it } + pathSegments[0].equals("viewer") -> { + MangaPlus.PREFIX_CHAPTER_ID_SEARCH + pathSegments[1] + } + pathSegments[0].equals("sns_share") -> { + intent?.data?.getQueryParameter("title_id") + ?.let { MangaPlus.PREFIX_ID_SEARCH + it } + } else -> MangaPlus.PREFIX_ID_SEARCH + pathSegments[1] } @@ -33,7 +39,7 @@ class MangaPlusUrlActivity : Activity() { Log.e("MangaPlusUrlActivity", e.toString()) } } else { - Log.e("MangaPlusUrlActivity", "Missing title/chapter ID from the URL") + Log.e("MangaPlusUrlActivity", "Missing the title or chapter ID from the URL") } } else { Log.e("MangaPlusUrlActivity", "Could not parse URI from intent $intent")