diff --git a/lib-multisrc/heancms/assets/i18n/messages_en.properties b/lib-multisrc/heancms/assets/i18n/messages_en.properties index 6d73b316b..f98c0af36 100644 --- a/lib-multisrc/heancms/assets/i18n/messages_en.properties +++ b/lib-multisrc/heancms/assets/i18n/messages_en.properties @@ -4,6 +4,8 @@ status_all=All status_ongoing=Ongoing status_onhiatus=On hiatus status_dropped=Dropped +status_completed=Completed +status_canceled=Canceled sort_by_filter_title=Sort By sort_by_title=Title sort_by_views=Views @@ -19,3 +21,4 @@ pref_credentials_summary=Ignored if empty. login_failed_unknown_error=Unknown error occurred while logging in paid_chapter_error=Paid chapter unavailable. id_not_found_error=Failed to get the ID for slug: %s +genre_missing_warning=Press 'Reset' to attempt to show the genres diff --git a/lib-multisrc/heancms/build.gradle.kts b/lib-multisrc/heancms/build.gradle.kts index b93314227..6993f59da 100644 --- a/lib-multisrc/heancms/build.gradle.kts +++ b/lib-multisrc/heancms/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("lib-multisrc") } -baseVersionCode = 22 +baseVersionCode = 23 dependencies { api(project(":lib:i18n")) diff --git a/lib-multisrc/heancms/src/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt b/lib-multisrc/heancms/src/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt index b912b453d..d3074a0a5 100644 --- a/lib-multisrc/heancms/src/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt +++ b/lib-multisrc/heancms/src/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt @@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.lib.i18n.Intl import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.POST 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.MangasPage import eu.kanade.tachiyomi.source.model.Page @@ -29,6 +30,7 @@ import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.text.SimpleDateFormat import java.util.Locale +import kotlin.concurrent.thread abstract class HeanCms( override val name: String, @@ -45,6 +47,8 @@ abstract class HeanCms( override val client: OkHttpClient = network.cloudflareClient + protected open val useNewQueryEndpoint = false + protected open val useNewChapterEndpoint = false protected open val enableLogin = false @@ -117,7 +121,7 @@ abstract class HeanCms( override fun popularMangaRequest(page: Int): Request { val url = "$apiUrl/query".toHttpUrl().newBuilder() .addQueryParameter("query_string", "") - .addQueryParameter("series_status", "All") + .addQueryParameter(if (useNewQueryEndpoint) "status" else "series_status", "All") .addQueryParameter("order", "desc") .addQueryParameter("orderBy", "total_views") .addQueryParameter("series_type", "Comic") @@ -134,7 +138,7 @@ abstract class HeanCms( override fun latestUpdatesRequest(page: Int): Request { val url = "$apiUrl/query".toHttpUrl().newBuilder() .addQueryParameter("query_string", "") - .addQueryParameter("series_status", "All") + .addQueryParameter(if (useNewQueryEndpoint) "status" else "series_status", "All") .addQueryParameter("order", "desc") .addQueryParameter("orderBy", "latest") .addQueryParameter("series_type", "Comic") @@ -185,7 +189,7 @@ abstract class HeanCms( val url = "$apiUrl/query".toHttpUrl().newBuilder() .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("orderBy", sortByFilter?.selected ?: "total_views") .addQueryParameter("series_type", "Comic") @@ -342,7 +346,7 @@ abstract class HeanCms( } 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 = Observable.just(page.imageUrl!!) @@ -362,6 +366,8 @@ abstract class HeanCms( Status(intl["status_ongoing"], "Ongoing"), Status(intl["status_onhiatus"], "Hiatus"), Status(intl["status_dropped"], "Dropped"), + Status(intl["status_completed"], "Completed"), + Status(intl["status_canceled"], "Canceled"), ) protected open fun getSortProperties(): List = listOf( @@ -371,17 +377,47 @@ abstract class HeanCms( SortProperty(intl["sort_by_created_at"], "created_at"), ) - protected open fun getGenreList(): List = emptyList() + private var genresList: List = 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>(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 { - val genres = getGenreList() + fetchFilters() - val filters = listOfNotNull( + val filters = mutableListOf>( StatusFilter(intl["status_filter_title"], getStatusList()), 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) } @@ -448,6 +484,8 @@ abstract class HeanCms( edit().putString(TOKEN_PREF, json.encodeToString(data)).apply() } + private enum class FiltersState { NOT_FETCHED, FETCHING, FETCHED } + companion object { 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, */*" diff --git a/lib-multisrc/heancms/src/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt b/lib-multisrc/heancms/src/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt index 7507820cd..06d3f38df 100644 --- a/lib-multisrc/heancms/src/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt +++ b/lib-multisrc/heancms/src/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt @@ -155,6 +155,12 @@ class HeanCmsPageDataDto( val images: List? = emptyList(), ) +@Serializable +class HeanCmsGenreDto( + val id: Int, + val name: String, +) + private fun String.toAbsoluteThumbnailUrl(apiUrl: String, coverPath: String): String { return if (startsWith("https://") || startsWith("http://")) this else "$apiUrl/$coverPath$this" } diff --git a/src/en/omegascans/src/eu/kanade/tachiyomi/extension/en/omegascans/OmegaScans.kt b/src/en/omegascans/src/eu/kanade/tachiyomi/extension/en/omegascans/OmegaScans.kt index d2fa7404a..a7487ab14 100644 --- a/src/en/omegascans/src/eu/kanade/tachiyomi/extension/en/omegascans/OmegaScans.kt +++ b/src/en/omegascans/src/eu/kanade/tachiyomi/extension/en/omegascans/OmegaScans.kt @@ -1,6 +1,5 @@ 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.network.interceptor.rateLimitHost import okhttp3.HttpUrl.Companion.toHttpUrl @@ -15,33 +14,6 @@ class OmegaScans : HeanCms("Omega Scans", "https://omegascans.org", "en") { override val versionId = 2 override val useNewChapterEndpoint = true + override val useNewQueryEndpoint = 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), - ) } diff --git a/src/en/templescan/src/eu/kanade/tachiyomi/extension/en/templescan/TempleScan.kt b/src/en/templescan/src/eu/kanade/tachiyomi/extension/en/templescan/TempleScan.kt index 11666a020..96e2cb6f2 100644 --- a/src/en/templescan/src/eu/kanade/tachiyomi/extension/en/templescan/TempleScan.kt +++ b/src/en/templescan/src/eu/kanade/tachiyomi/extension/en/templescan/TempleScan.kt @@ -1,6 +1,5 @@ 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.network.interceptor.rateLimit @@ -18,21 +17,4 @@ class TempleScan : HeanCms( .build() 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), - ) } diff --git a/src/fr/perfscan/src/eu/kanade/tachiyomi/extension/fr/perfscan/PerfScan.kt b/src/fr/perfscan/src/eu/kanade/tachiyomi/extension/fr/perfscan/PerfScan.kt index 02e06a16f..1c0c818da 100644 --- a/src/fr/perfscan/src/eu/kanade/tachiyomi/extension/fr/perfscan/PerfScan.kt +++ b/src/fr/perfscan/src/eu/kanade/tachiyomi/extension/fr/perfscan/PerfScan.kt @@ -19,5 +19,6 @@ class PerfScan : HeanCms("Perf Scan", "https://perf-scan.fr", "fr") { } } + override val useNewQueryEndpoint = true override val useNewChapterEndpoint = true }