HeanCMS: Fix filters and fetch genres from api (#2312)

Fix filters
This commit is contained in:
bapeey 2024-04-08 21:31:45 -05:00 committed by Draff
parent a9bfc1d348
commit ad0d859a87
7 changed files with 58 additions and 56 deletions

View File

@ -4,6 +4,8 @@ status_all=All
status_ongoing=Ongoing status_ongoing=Ongoing
status_onhiatus=On hiatus status_onhiatus=On hiatus
status_dropped=Dropped status_dropped=Dropped
status_completed=Completed
status_canceled=Canceled
sort_by_filter_title=Sort By sort_by_filter_title=Sort By
sort_by_title=Title sort_by_title=Title
sort_by_views=Views sort_by_views=Views
@ -19,3 +21,4 @@ pref_credentials_summary=Ignored if empty.
login_failed_unknown_error=Unknown error occurred while logging in login_failed_unknown_error=Unknown error occurred while logging in
paid_chapter_error=Paid chapter unavailable. paid_chapter_error=Paid chapter unavailable.
id_not_found_error=Failed to get the ID for slug: %s id_not_found_error=Failed to get the ID for slug: %s
genre_missing_warning=Press 'Reset' to attempt to show the genres

View File

@ -2,7 +2,7 @@ plugins {
id("lib-multisrc") id("lib-multisrc")
} }
baseVersionCode = 22 baseVersionCode = 23
dependencies { dependencies {
api(project(":lib:i18n")) api(project(":lib:i18n"))

View File

@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.lib.i18n.Intl
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
@ -29,6 +30,7 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import kotlin.concurrent.thread
abstract class HeanCms( abstract class HeanCms(
override val name: String, override val name: String,
@ -45,6 +47,8 @@ abstract class HeanCms(
override val client: OkHttpClient = network.cloudflareClient override val client: OkHttpClient = network.cloudflareClient
protected open val useNewQueryEndpoint = false
protected open val useNewChapterEndpoint = false protected open val useNewChapterEndpoint = false
protected open val enableLogin = false protected open val enableLogin = false
@ -117,7 +121,7 @@ abstract class HeanCms(
override fun popularMangaRequest(page: Int): Request { override fun popularMangaRequest(page: Int): Request {
val url = "$apiUrl/query".toHttpUrl().newBuilder() val url = "$apiUrl/query".toHttpUrl().newBuilder()
.addQueryParameter("query_string", "") .addQueryParameter("query_string", "")
.addQueryParameter("series_status", "All") .addQueryParameter(if (useNewQueryEndpoint) "status" else "series_status", "All")
.addQueryParameter("order", "desc") .addQueryParameter("order", "desc")
.addQueryParameter("orderBy", "total_views") .addQueryParameter("orderBy", "total_views")
.addQueryParameter("series_type", "Comic") .addQueryParameter("series_type", "Comic")
@ -134,7 +138,7 @@ abstract class HeanCms(
override fun latestUpdatesRequest(page: Int): Request { override fun latestUpdatesRequest(page: Int): Request {
val url = "$apiUrl/query".toHttpUrl().newBuilder() val url = "$apiUrl/query".toHttpUrl().newBuilder()
.addQueryParameter("query_string", "") .addQueryParameter("query_string", "")
.addQueryParameter("series_status", "All") .addQueryParameter(if (useNewQueryEndpoint) "status" else "series_status", "All")
.addQueryParameter("order", "desc") .addQueryParameter("order", "desc")
.addQueryParameter("orderBy", "latest") .addQueryParameter("orderBy", "latest")
.addQueryParameter("series_type", "Comic") .addQueryParameter("series_type", "Comic")
@ -185,7 +189,7 @@ abstract class HeanCms(
val url = "$apiUrl/query".toHttpUrl().newBuilder() val url = "$apiUrl/query".toHttpUrl().newBuilder()
.addQueryParameter("query_string", query) .addQueryParameter("query_string", query)
.addQueryParameter("series_status", statusFilter?.selected?.value ?: "All") .addQueryParameter(if (useNewQueryEndpoint) "status" else "series_status", statusFilter?.selected?.value ?: "All")
.addQueryParameter("order", if (sortByFilter?.state?.ascending == true) "asc" else "desc") .addQueryParameter("order", if (sortByFilter?.state?.ascending == true) "asc" else "desc")
.addQueryParameter("orderBy", sortByFilter?.selected ?: "total_views") .addQueryParameter("orderBy", sortByFilter?.selected ?: "total_views")
.addQueryParameter("series_type", "Comic") .addQueryParameter("series_type", "Comic")
@ -342,7 +346,7 @@ abstract class HeanCms(
} }
private fun String.toAbsoluteUrl(): String { private fun String.toAbsoluteUrl(): String {
return if (startsWith("https://") || startsWith("http://")) this else "$apiUrl/$this" return if (startsWith("https://") || startsWith("http://")) this else "$apiUrl/$coverPath$this"
} }
override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!) override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!)
@ -362,6 +366,8 @@ abstract class HeanCms(
Status(intl["status_ongoing"], "Ongoing"), Status(intl["status_ongoing"], "Ongoing"),
Status(intl["status_onhiatus"], "Hiatus"), Status(intl["status_onhiatus"], "Hiatus"),
Status(intl["status_dropped"], "Dropped"), Status(intl["status_dropped"], "Dropped"),
Status(intl["status_completed"], "Completed"),
Status(intl["status_canceled"], "Canceled"),
) )
protected open fun getSortProperties(): List<SortProperty> = listOf( protected open fun getSortProperties(): List<SortProperty> = listOf(
@ -371,17 +377,47 @@ abstract class HeanCms(
SortProperty(intl["sort_by_created_at"], "created_at"), SortProperty(intl["sort_by_created_at"], "created_at"),
) )
protected open fun getGenreList(): List<Genre> = emptyList() private var genresList: List<Genre> = emptyList()
private var fetchFiltersAttempts = 0
private var filtersState = FiltersState.NOT_FETCHED
private fun fetchFilters() {
if (filtersState != FiltersState.NOT_FETCHED || fetchFiltersAttempts >= 3) return
filtersState = FiltersState.FETCHING
fetchFiltersAttempts++
thread {
try {
val response = client.newCall(GET("$apiUrl/tags", headers)).execute()
val genres = json.decodeFromString<List<HeanCmsGenreDto>>(response.body.string())
genresList = genres.map { Genre(it.name, it.id) }
filtersState = FiltersState.FETCHED
} catch (e: Throwable) {
filtersState = FiltersState.NOT_FETCHED
}
}
}
override fun getFilterList(): FilterList { override fun getFilterList(): FilterList {
val genres = getGenreList() fetchFilters()
val filters = listOfNotNull( val filters = mutableListOf<Filter<*>>(
StatusFilter(intl["status_filter_title"], getStatusList()), StatusFilter(intl["status_filter_title"], getStatusList()),
SortByFilter(intl["sort_by_filter_title"], getSortProperties()), SortByFilter(intl["sort_by_filter_title"], getSortProperties()),
GenreFilter(intl["genre_filter_title"], genres).takeIf { genres.isNotEmpty() },
) )
if (filtersState == FiltersState.FETCHED) {
filters += listOfNotNull(
GenreFilter(intl["genre_filter_title"], genresList),
)
} else {
filters += listOf(
Filter.Separator(),
Filter.Header(intl["genre_missing_warning"]),
)
}
return FilterList(filters) return FilterList(filters)
} }
@ -448,6 +484,8 @@ abstract class HeanCms(
edit().putString(TOKEN_PREF, json.encodeToString(data)).apply() edit().putString(TOKEN_PREF, json.encodeToString(data)).apply()
} }
private enum class FiltersState { NOT_FETCHED, FETCHING, FETCHED }
companion object { companion object {
private const val ACCEPT_IMAGE = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8" private const val ACCEPT_IMAGE = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"
private const val ACCEPT_JSON = "application/json, text/plain, */*" private const val ACCEPT_JSON = "application/json, text/plain, */*"

View File

@ -155,6 +155,12 @@ class HeanCmsPageDataDto(
val images: List<String>? = emptyList(), val images: List<String>? = emptyList(),
) )
@Serializable
class HeanCmsGenreDto(
val id: Int,
val name: String,
)
private fun String.toAbsoluteThumbnailUrl(apiUrl: String, coverPath: String): String { private fun String.toAbsoluteThumbnailUrl(apiUrl: String, coverPath: String): String {
return if (startsWith("https://") || startsWith("http://")) this else "$apiUrl/$coverPath$this" return if (startsWith("https://") || startsWith("http://")) this else "$apiUrl/$coverPath$this"
} }

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.extension.en.omegascans package eu.kanade.tachiyomi.extension.en.omegascans
import eu.kanade.tachiyomi.multisrc.heancms.Genre
import eu.kanade.tachiyomi.multisrc.heancms.HeanCms import eu.kanade.tachiyomi.multisrc.heancms.HeanCms
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
@ -15,33 +14,6 @@ class OmegaScans : HeanCms("Omega Scans", "https://omegascans.org", "en") {
override val versionId = 2 override val versionId = 2
override val useNewChapterEndpoint = true override val useNewChapterEndpoint = true
override val useNewQueryEndpoint = true
override val enableLogin = true override val enableLogin = true
override fun getGenreList() = listOf(
Genre("Romance", 1),
Genre("Drama", 2),
Genre("Fantasy", 3),
Genre("Hardcore", 4),
Genre("SM", 5),
Genre("Harem", 8),
Genre("Hypnosis", 9),
Genre("Novel Adaptation", 10),
Genre("Netori", 11),
Genre("Netorare", 12),
Genre("Isekai", 13),
Genre("Yuri", 14),
Genre("MILF", 16),
Genre("Office", 17),
Genre("Short Story", 18),
Genre("Comedy", 19),
Genre("Campus", 20),
Genre("Crime", 21),
Genre("Revenge", 22),
Genre("Supernatural", 23),
Genre("Action", 24),
Genre("Military", 25),
Genre("Ability", 26),
Genre("Cohabitation", 27),
Genre("Training", 28),
)
} }

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.extension.en.templescan package eu.kanade.tachiyomi.extension.en.templescan
import eu.kanade.tachiyomi.multisrc.heancms.Genre
import eu.kanade.tachiyomi.multisrc.heancms.HeanCms import eu.kanade.tachiyomi.multisrc.heancms.HeanCms
import eu.kanade.tachiyomi.network.interceptor.rateLimit import eu.kanade.tachiyomi.network.interceptor.rateLimit
@ -18,21 +17,4 @@ class TempleScan : HeanCms(
.build() .build()
override val mangaSubDirectory = "comic" override val mangaSubDirectory = "comic"
override fun getGenreList() = listOf(
Genre("Drama", 1),
Genre("Josei", 2),
Genre("Romance", 3),
Genre("Girls Love", 4),
Genre("Reincarnation", 5),
Genre("Fantasia", 6),
Genre("Ecchi", 7),
Genre("Adventure", 8),
Genre("Boys Love", 9),
Genre("School Life", 10),
Genre("Action", 11),
Genre("Military", 13),
Genre("Comedy", 14),
Genre("Apocalypse", 15),
)
} }

View File

@ -19,5 +19,6 @@ class PerfScan : HeanCms("Perf Scan", "https://perf-scan.fr", "fr") {
} }
} }
override val useNewQueryEndpoint = true
override val useNewChapterEndpoint = true override val useNewChapterEndpoint = true
} }