From c0a6c67cfd183af4574eb4083795431073222292 Mon Sep 17 00:00:00 2001 From: Seew <90949336+seew3l@users.noreply.github.com> Date: Mon, 9 Jan 2023 18:38:36 -0500 Subject: [PATCH] HeanCms: Fix Search (#14843) * Fix Search * Fix Search * Fix Search * Apply requested changes * Apply requested changes * Apply requested changes * Apply requested changes * Apply requested changes --- .../tachiyomi/multisrc/heancms/HeanCms.kt | 95 ++++++++++++++----- .../tachiyomi/multisrc/heancms/HeanCmsDto.kt | 21 +++- .../multisrc/heancms/HeanCmsGenerator.kt | 2 +- .../tachiyomi/multisrc/heancms/HeanCmsIntl.kt | 6 ++ 4 files changed, 94 insertions(+), 30 deletions(-) diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt index 638752b38..c1c3f6e34 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt @@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.multisrc.heancms import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.asObservableSuccess +import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.Page @@ -41,14 +42,14 @@ abstract class HeanCms( protected open val coverPath: String = "cover/" - private var seriesSlugMap: Map? = null + private var seriesSlugMap: Map? = null override fun headersBuilder(): Headers.Builder = Headers.Builder() .add("Origin", baseUrl) .add("Referer", "$baseUrl/") override fun popularMangaRequest(page: Int): Request { - val payloadObj = HeanCmsSearchPayloadDto( + val payloadObj = HeanCmsQuerySearchPayloadDto( page = page, order = "desc", orderBy = "total_views", @@ -70,7 +71,7 @@ abstract class HeanCms( val json = response.body?.string().orEmpty() if (json.startsWith("{")) { - val result = json.parseAs() + val result = json.parseAs() val mangaList = result.data.map { it.toSManga(apiUrl, coverPath) } fetchAllTitles() @@ -87,7 +88,7 @@ abstract class HeanCms( } override fun latestUpdatesRequest(page: Int): Request { - val payloadObj = HeanCmsSearchPayloadDto( + val payloadObj = HeanCmsQuerySearchPayloadDto( page = page, order = "desc", orderBy = "latest", @@ -110,7 +111,7 @@ abstract class HeanCms( override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { val sortByFilter = filters.firstInstanceOrNull() - val payloadObj = HeanCmsSearchPayloadDto( + val payloadObj = HeanCmsQuerySearchPayloadDto( page = page, order = if (sortByFilter?.state?.ascending == true) "asc" else "desc", orderBy = sortByFilter?.selected ?: "total_views", @@ -122,15 +123,25 @@ abstract class HeanCms( .orEmpty() ) + val searchPayloadObj = HeanCmsSearchPayloadDto( + term = query + ) + val payload = json.encodeToString(payloadObj).toRequestBody(JSON_MEDIA_TYPE) + val searchPayload = json.encodeToString(searchPayloadObj).toRequestBody(JSON_MEDIA_TYPE) val apiHeaders = headersBuilder() .add("Accept", ACCEPT_JSON) .add("Content-Type", payload.contentType().toString()) .build() + if (query.isNotBlank()) { + val apiUrl = "$apiUrl/series/search".toHttpUrl().newBuilder() + .toString() + return POST(apiUrl, apiHeaders, searchPayload) + } + val apiUrl = "$apiUrl/series/querysearch".toHttpUrl().newBuilder() - .addQueryParameter("q", query) .toString() return POST(apiUrl, apiHeaders, payload) @@ -138,33 +149,54 @@ abstract class HeanCms( override fun searchMangaParse(response: Response): MangasPage { val json = response.body?.string().orEmpty() - val query = response.request.url.queryParameter("q").orEmpty() + + if (response.request.url.pathSegments.last() == "search") { + val result = json.parseAs>() + val mangaList = result + .filter { it.type == "Comic" } + .map { + createSearchResult(it.slug.replace(TIMESTAMP_REGEX, ""), it.title) + } + + fetchAllTitles() + + return MangasPage(mangaList, false) + } if (json.startsWith("{")) { - val result = json.parseAs() - var mangaList = result.data.map { it.toSManga(apiUrl, coverPath) } - - if (query.isNotBlank()) { - mangaList = mangaList.filter { it.title.contains(query, ignoreCase = true) } - } + val result = json.parseAs() + val mangaList = result.data.map { it.toSManga(apiUrl, coverPath) } fetchAllTitles() return MangasPage(mangaList, result.meta?.hasNextPage ?: false) } - var mangaList = json.parseAs>() + val mangaList = json.parseAs>() .map { it.toSManga(apiUrl, coverPath) } - if (query.isNotBlank()) { - mangaList = mangaList.filter { it.title.contains(query, ignoreCase = true) } - } - fetchAllTitles() return MangasPage(mangaList, hasNextPage = false) } + private fun createSearchResult(slug: String, title: String): SManga { + val theSeries = seriesSlugMap?.get(slug) + + return SManga.create().apply { + url = "/series/$slug" + this.title = title + thumbnail_url = "$apiUrl/$coverPath${theSeries?.thumbnailUrl}" + this.status = when (theSeries?.status) { + "Ongoing" -> SManga.ONGOING + "Hiatus" -> SManga.ON_HIATUS + "Dropped" -> SManga.CANCELLED + "Completed", "Finished" -> SManga.COMPLETED + else -> SManga.UNKNOWN + } + } + } + // Workaround to allow "Open in browser" use the real URL. override fun fetchMangaDetails(manga: SManga): Observable { return client.newCall(seriesDetailsRequest(manga)) @@ -179,7 +211,7 @@ abstract class HeanCms( .substringAfterLast("/") .replace(TIMESTAMP_REGEX, "") - val currentSlug = seriesSlugMap?.get(seriesSlug) ?: seriesSlug + val currentSlug = seriesSlugMap?.get(seriesSlug)?.slug ?: seriesSlug return GET("$baseUrl/series/$currentSlug", headers) } @@ -191,7 +223,7 @@ abstract class HeanCms( fetchAllTitles() - val currentSlug = seriesSlugMap?.get(seriesSlug) ?: seriesSlug + val currentSlug = seriesSlugMap?.get(seriesSlug)?.slug ?: seriesSlug val apiHeaders = headersBuilder() .add("Accept", ACCEPT_JSON) @@ -271,14 +303,14 @@ abstract class HeanCms( val result = runCatching { var hasNextPage = true var page = 1 - val tempMap = mutableMapOf() + val tempMap = mutableMapOf() while (hasNextPage) { val response = client.newCall(allTitlesRequest(page)).execute() val json = response.body?.string().orEmpty() if (json.startsWith("{")) { - val result = json.parseAs() + val result = json.parseAs() tempMap.putAll(parseAllTitles(result.data)) hasNextPage = result.meta?.hasNextPage ?: false page++ @@ -296,7 +328,7 @@ abstract class HeanCms( } protected open fun allTitlesRequest(page: Int): Request { - val payloadObj = HeanCmsSearchPayloadDto( + val payloadObj = HeanCmsQuerySearchPayloadDto( page = page, order = "desc", orderBy = "total_views", @@ -314,12 +346,18 @@ abstract class HeanCms( return POST("$apiUrl/series/querysearch", apiHeaders, payload) } - protected open fun parseAllTitles(result: List): Map { + protected open fun parseAllTitles(result: List): Map { return result .filter { it.type == "Comic" } .associateBy( keySelector = { it.slug.replace(TIMESTAMP_REGEX, "") }, - valueTransform = HeanCmsSeriesDto::slug + valueTransform = { + HeanCmsTitle( + it.slug, + it.thumbnail, + it.status.orEmpty() + ) + } ) } @@ -327,6 +365,7 @@ abstract class HeanCms( val genres = getGenreList() val filters = listOfNotNull( + Filter.Header(intl.filterWarning), StatusFilter(intl.statusFilterTitle, getStatusList()), SortByFilter(intl.sortByFilterTitle, getSortProperties()), GenreFilter(intl.genreFilterTitle, genres).takeIf { genres.isNotEmpty() } @@ -352,4 +391,10 @@ abstract class HeanCms( val TIMESTAMP_REGEX = "-\\d+$".toRegex() } + + data class HeanCmsTitle( + val slug: String, + val thumbnailUrl: String, + val status: String + ) } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt index a9e86a890..b5e788766 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt @@ -9,13 +9,13 @@ import java.text.SimpleDateFormat import java.util.Locale @Serializable -data class HeanCmsSearchDto( +data class HeanCmsQuerySearchDto( val data: List = emptyList(), - val meta: HeanCmsSearchMetaDto? = null + val meta: HeanCmsQuerySearchMetaDto? = null ) @Serializable -data class HeanCmsSearchMetaDto( +data class HeanCmsQuerySearchMetaDto( @SerialName("current_page") val currentPage: Int, @SerialName("last_page") val lastPage: Int ) { @@ -24,6 +24,14 @@ data class HeanCmsSearchMetaDto( get() = currentPage < lastPage } +@Serializable +data class HeanCmsSearchDto( + val description: String? = null, + @SerialName("series_slug") val slug: String, + @SerialName("series_type") val type: String, + val title: String +) + @Serializable data class HeanCmsSeriesDto( val id: Int, @@ -100,7 +108,7 @@ data class HeanCmsReaderContentDto( ) @Serializable -data class HeanCmsSearchPayloadDto( +data class HeanCmsQuerySearchPayloadDto( val order: String, val page: Int, @SerialName("order_by") val orderBy: String, @@ -108,3 +116,8 @@ data class HeanCmsSearchPayloadDto( @SerialName("series_type") val type: String, @SerialName("tags_ids") val tagIds: List = emptyList() ) + +@Serializable +data class HeanCmsSearchPayloadDto( + val term: String, +) diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsGenerator.kt index 5bd5da4db..5e8a38359 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsGenerator.kt @@ -9,7 +9,7 @@ class HeanCmsGenerator : ThemeSourceGenerator { override val themeClass = "HeanCms" - override val baseVersionCode: Int = 6 + override val baseVersionCode: Int = 7 override val sources = listOf( SingleLang("Reaper Scans", "https://reaperscans.net", "pt-BR", overrideVersionCode = 35), diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsIntl.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsIntl.kt index a63beaf92..232774310 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsIntl.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsIntl.kt @@ -64,6 +64,12 @@ class HeanCmsIntl(lang: String) { else -> "Recently added" } + val filterWarning: String = when (availableLang) { + BRAZILIAN_PORTUGUESE -> "Os filtros serão ignorados se a busca não estiver vazia." + SPANISH -> "Los filtros serán ignorados si la búsqueda no está vacía." + else -> "Filters will be ignored if the search is not empty." + } + fun urlChangedError(sourceName: String): String = when (availableLang) { BRAZILIAN_PORTUGUESE -> "A URL da série mudou. Migre de $sourceName " +