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
This commit is contained in:
Seew 2023-01-09 18:38:36 -05:00 committed by GitHub
parent 9c000859b9
commit c0a6c67cfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 94 additions and 30 deletions

View File

@ -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<String, String>? = null
private var seriesSlugMap: Map<String, HeanCmsTitle>? = 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<HeanCmsSearchDto>()
val result = json.parseAs<HeanCmsQuerySearchDto>()
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<SortByFilter>()
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<List<HeanCmsSearchDto>>()
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<HeanCmsSearchDto>()
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<HeanCmsQuerySearchDto>()
val mangaList = result.data.map { it.toSManga(apiUrl, coverPath) }
fetchAllTitles()
return MangasPage(mangaList, result.meta?.hasNextPage ?: false)
}
var mangaList = json.parseAs<List<HeanCmsSeriesDto>>()
val mangaList = json.parseAs<List<HeanCmsSeriesDto>>()
.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<SManga> {
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<String, String>()
val tempMap = mutableMapOf<String, HeanCmsTitle>()
while (hasNextPage) {
val response = client.newCall(allTitlesRequest(page)).execute()
val json = response.body?.string().orEmpty()
if (json.startsWith("{")) {
val result = json.parseAs<HeanCmsSearchDto>()
val result = json.parseAs<HeanCmsQuerySearchDto>()
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<HeanCmsSeriesDto>): Map<String, String> {
protected open fun parseAllTitles(result: List<HeanCmsSeriesDto>): Map<String, HeanCmsTitle> {
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
)
}

View File

@ -9,13 +9,13 @@ import java.text.SimpleDateFormat
import java.util.Locale
@Serializable
data class HeanCmsSearchDto(
data class HeanCmsQuerySearchDto(
val data: List<HeanCmsSeriesDto> = 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<Int> = emptyList()
)
@Serializable
data class HeanCmsSearchPayloadDto(
val term: String,
)

View File

@ -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),

View File

@ -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 " +