From e5a68f8ba4b78d78ef1d2c1aa390272653abe766 Mon Sep 17 00:00:00 2001 From: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com> Date: Mon, 29 Jul 2024 08:02:09 +0500 Subject: [PATCH] MangaThemesiaAlt: use slug map (#4310) * MangaThemesiaAlt: use slug map * selector variable * better name --- .../mangathemesia/MangaThemesiaAlt.kt | 289 +++++++----------- src/all/thunderscans/build.gradle | 4 +- .../all/thunderscans/ThunderScansFactory.kt | 2 +- src/en/luminousscans/build.gradle | 2 +- src/en/magusmanga/build.gradle | 4 +- .../extension/en/magusmanga/MagusManga.kt | 2 +- src/en/nightscans/build.gradle | 2 +- .../extension/en/nightscans/NightScans.kt | 3 + src/en/rizzcomic/build.gradle | 2 +- .../extension/en/rizzcomic/RizzComic.kt | 5 +- 10 files changed, 120 insertions(+), 195 deletions(-) diff --git a/lib-multisrc/mangathemesia/src/eu/kanade/tachiyomi/multisrc/mangathemesia/MangaThemesiaAlt.kt b/lib-multisrc/mangathemesia/src/eu/kanade/tachiyomi/multisrc/mangathemesia/MangaThemesiaAlt.kt index 473baf511..1c26a123f 100644 --- a/lib-multisrc/mangathemesia/src/eu/kanade/tachiyomi/multisrc/mangathemesia/MangaThemesiaAlt.kt +++ b/lib-multisrc/mangathemesia/src/eu/kanade/tachiyomi/multisrc/mangathemesia/MangaThemesiaAlt.kt @@ -5,7 +5,6 @@ import android.content.SharedPreferences import androidx.preference.PreferenceScreen import androidx.preference.SwitchPreferenceCompat import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.SManga @@ -32,8 +31,18 @@ abstract class MangaThemesiaAlt( private val randomUrlPrefKey: String = "pref_auto_random_url", ) : MangaThemesia(name, baseUrl, lang, mangaUrlDirectory, dateFormat), ConfigurableSource { + protected open val listUrl = "$mangaUrlDirectory/list-mode/" + protected open val listSelector = "div#content div.soralist ul li a.series" + protected val preferences: SharedPreferences by lazy { - Injekt.get().getSharedPreferences("source_$id", 0x0000) + Injekt.get().getSharedPreferences("source_$id", 0x0000).also { + if (it.contains("__random_part_cache")) { + it.edit().remove("__random_part_cache").apply() + } + if (it.contains("titles_without_random_part")) { + it.edit().remove("titles_without_random_part").apply() + } + } } override fun setupPreferenceScreen(screen: PreferenceScreen) { @@ -47,183 +56,11 @@ abstract class MangaThemesiaAlt( private fun getRandomUrlPref() = preferences.getBoolean(randomUrlPrefKey, true) - private var randomPartCache = SuspendLazy(::getUpdatedRandomPart) { preferences.randomPartCache = it } - - // cache in preference for webview urls - private var SharedPreferences.randomPartCache: String - get() = getString("__random_part_cache", "")!! - set(newValue) = edit().putString("__random_part_cache", newValue).apply() - - // some new titles don't have random part - // se we save their slug and when they - // finally add it, we remove the slug in the interceptor - private var SharedPreferences.titlesWithoutRandomPart: MutableSet - get() { - val value = getString("titles_without_random_part", null) - ?: return mutableSetOf() - - return json.decodeFromString(value) - } - set(newValue) { - val encodedValue = json.encodeToString(newValue) - - edit().putString("titles_without_random_part", encodedValue).apply() - } - - protected open fun getRandomPartFromUrl(url: String): String { - val slug = url - .removeSuffix("/") - .substringAfterLast("/") - - return slugRegex.find(slug)?.groupValues?.get(1) ?: "" - } - - protected open fun getRandomPartFromResponse(response: Response): String { - return response.asJsoup() - .selectFirst(searchMangaSelector())!! - .select("a").attr("href") - .let(::getRandomPartFromUrl) - } - - protected suspend fun getUpdatedRandomPart(): String = - client.newCall(GET("$baseUrl$mangaUrlDirectory/", headers)) - .await() - .use(::getRandomPartFromResponse) - - override fun searchMangaParse(response: Response): MangasPage { - val mp = super.searchMangaParse(response) - - if (!getRandomUrlPref()) return mp - - // extract random part during browsing to avoid extra call - mp.mangas.firstOrNull()?.run { - val randomPart = getRandomPartFromUrl(url) - - if (randomPart.isNotEmpty()) { - randomPartCache.set(randomPart) - } - } - - val mangas = mp.mangas.toPermanentMangaUrls() - - return MangasPage(mangas, mp.hasNextPage) - } - - protected fun List.toPermanentMangaUrls(): List { - // some absolutely new titles don't have the random part yet - // save them so we know where to not apply it - val foundTitlesWithoutRandomPart = mutableSetOf() - - for (i in indices) { - val slug = this[i].url - .removeSuffix("/") - .substringAfterLast("/") - - if (slugRegex.find(slug)?.groupValues?.get(1) == null) { - foundTitlesWithoutRandomPart.add(slug) - } - - val permaSlug = slug - .replaceFirst(slugRegex, "") - - this[i].url = "$mangaUrlDirectory/$permaSlug/" - } - - if (foundTitlesWithoutRandomPart.isNotEmpty()) { - foundTitlesWithoutRandomPart.addAll(preferences.titlesWithoutRandomPart) - - preferences.titlesWithoutRandomPart = foundTitlesWithoutRandomPart - } - - return this - } - - protected open val slugRegex = Regex("""^(\d+-)""") - - override val client = super.client.newBuilder() - .addInterceptor { chain -> - val request = chain.request() - val response = chain.proceed(request) - - if (request.url.fragment != "titlesWithoutRandomPart") { - return@addInterceptor response - } - - if (!response.isSuccessful && response.code == 404) { - response.close() - - val slug = request.url.toString() - .substringBefore("#") - .removeSuffix("/") - .substringAfterLast("/") - - preferences.titlesWithoutRandomPart.run { - remove(slug) - - preferences.titlesWithoutRandomPart = this - } - - val randomPart = randomPartCache.blockingGet() - val newRequest = request.newBuilder() - .url("$baseUrl$mangaUrlDirectory/$randomPart$slug/") - .build() - - return@addInterceptor chain.proceed(newRequest) - } - - return@addInterceptor response - } - .build() - - override fun mangaDetailsRequest(manga: SManga): Request { - if (!getRandomUrlPref()) return super.mangaDetailsRequest(manga) - - val slug = manga.url - .substringBefore("#") - .removeSuffix("/") - .substringAfterLast("/") - .replaceFirst(slugRegex, "") - - if (preferences.titlesWithoutRandomPart.contains(slug)) { - return GET("$baseUrl${manga.url}#titlesWithoutRandomPart") - } - - val randomPart = randomPartCache.blockingGet() - - return GET("$baseUrl$mangaUrlDirectory/$randomPart$slug/", headers) - } - - override fun getMangaUrl(manga: SManga): String { - if (!getRandomUrlPref()) return super.getMangaUrl(manga) - - val slug = manga.url - .substringBefore("#") - .removeSuffix("/") - .substringAfterLast("/") - .replaceFirst(slugRegex, "") - - if (preferences.titlesWithoutRandomPart.contains(slug)) { - return "$baseUrl${manga.url}" - } - - val randomPart = randomPartCache.peek() ?: preferences.randomPartCache - - return "$baseUrl$mangaUrlDirectory/$randomPart$slug/" - } - - override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga) -} - -internal class SuspendLazy( - private val initializer: suspend () -> String, - private val saveCache: (String) -> Unit, -) { - private val mutex = Mutex() - private var cachedValue: SoftReference? = null + private var cachedValue: SoftReference>? = null private var fetchTime = 0L - suspend fun get(): String { + private suspend fun getUrlMapInternal(): Map { if (fetchTime + 3600000 < System.currentTimeMillis()) { // reset cache cachedValue = null @@ -238,22 +75,104 @@ internal class SuspendLazy( return it } - initializer().also { set(it) } + fetchUrlMap().also { + cachedValue = SoftReference(it) + fetchTime = System.currentTimeMillis() + preferences.urlMapCache = it + } } } - fun set(newVal: String) { - cachedValue = SoftReference(newVal) - fetchTime = System.currentTimeMillis() + protected open fun fetchUrlMap(): Map { + client.newCall(GET("$baseUrl$listUrl", headers)).execute().use { response -> + val document = response.asJsoup() - saveCache(newVal) + return document.select(listSelector).associate { + val url = it.absUrl("href") + + val slug = url.removeSuffix("/") + .substringAfterLast("/") + + val permaSlug = slug + .replaceFirst(slugRegex, "") + + permaSlug to slug + } + } } - fun peek(): String? { - return cachedValue?.get() + protected fun getUrlMap(cached: Boolean = false): Map { + return if (cached && cachedValue == null) { + preferences.urlMapCache + } else { + runBlocking { getUrlMapInternal() } + } } - fun blockingGet(): String { - return runBlocking { get() } + // cache in preference for webview urls + private var SharedPreferences.urlMapCache: Map + get(): Map { + val value = getString("url_map_cache", "{}")!! + return try { + json.decodeFromString(value) + } catch (_: Exception) { + emptyMap() + } + } + set(newMap) = edit().putString("url_map_cache", json.encodeToString(newMap)).apply() + + override fun searchMangaParse(response: Response): MangasPage { + val mp = super.searchMangaParse(response) + + if (!getRandomUrlPref()) return mp + + val mangas = mp.mangas.toPermanentMangaUrls() + + return MangasPage(mangas, mp.hasNextPage) } + + protected fun List.toPermanentMangaUrls(): List { + return onEach { + val slug = it.url + .removeSuffix("/") + .substringAfterLast("/") + + val permaSlug = slug + .replaceFirst(slugRegex, "") + + it.url = "$mangaUrlDirectory/$permaSlug/" + } + } + + protected open val slugRegex = Regex("""^(\d+-)""") + + override fun mangaDetailsRequest(manga: SManga): Request { + if (!getRandomUrlPref()) return super.mangaDetailsRequest(manga) + + val slug = manga.url + .substringBefore("#") + .removeSuffix("/") + .substringAfterLast("/") + .replaceFirst(slugRegex, "") + + val randomSlug = getUrlMap()[slug] ?: slug + + return GET("$baseUrl$mangaUrlDirectory/$randomSlug/", headers) + } + + override fun getMangaUrl(manga: SManga): String { + if (!getRandomUrlPref()) return super.getMangaUrl(manga) + + val slug = manga.url + .substringBefore("#") + .removeSuffix("/") + .substringAfterLast("/") + .replaceFirst(slugRegex, "") + + val randomSlug = getUrlMap(true)[slug] ?: slug + + return "$baseUrl$mangaUrlDirectory/$randomSlug/" + } + + override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga) } diff --git a/src/all/thunderscans/build.gradle b/src/all/thunderscans/build.gradle index 3c7d03ab1..22261d498 100644 --- a/src/all/thunderscans/build.gradle +++ b/src/all/thunderscans/build.gradle @@ -2,8 +2,8 @@ ext { extName = 'Thunder Scans' extClass = '.ThunderScansFactory' themePkg = 'mangathemesia' - baseUrl = 'https://en-thunderepic.com' - overrideVersionCode = 3 + baseUrl = 'https://en-thunderscans.com' + overrideVersionCode = 4 } apply from: "$rootDir/common.gradle" diff --git a/src/all/thunderscans/src/eu/kanade/tachiyomi/extension/all/thunderscans/ThunderScansFactory.kt b/src/all/thunderscans/src/eu/kanade/tachiyomi/extension/all/thunderscans/ThunderScansFactory.kt index cc10eda27..6520017ed 100644 --- a/src/all/thunderscans/src/eu/kanade/tachiyomi/extension/all/thunderscans/ThunderScansFactory.kt +++ b/src/all/thunderscans/src/eu/kanade/tachiyomi/extension/all/thunderscans/ThunderScansFactory.kt @@ -21,7 +21,7 @@ class ThunderScansAR : MangaThemesiaAlt( class ThunderScansEN : MangaThemesiaAlt( "Thunder Scans", - "https://en-thunderepic.com", + "https://en-thunderscans.com", "en", mangaUrlDirectory = "/comics", ) diff --git a/src/en/luminousscans/build.gradle b/src/en/luminousscans/build.gradle index ea43c3beb..de750c99a 100644 --- a/src/en/luminousscans/build.gradle +++ b/src/en/luminousscans/build.gradle @@ -3,7 +3,7 @@ ext { extClass = '.LuminousScans' themePkg = 'mangathemesia' baseUrl = 'https://luminous-scans.com' - overrideVersionCode = 7 + overrideVersionCode = 8 isNsfw = false } diff --git a/src/en/magusmanga/build.gradle b/src/en/magusmanga/build.gradle index 59186fc69..ff89fccd1 100644 --- a/src/en/magusmanga/build.gradle +++ b/src/en/magusmanga/build.gradle @@ -2,8 +2,8 @@ ext { extName = 'Magus Manga' extClass = '.MagusManga' themePkg = 'mangathemesia' - baseUrl = 'https://dmvdepot.com' - overrideVersionCode = 5 + baseUrl = 'https://recipeslik.online' + overrideVersionCode = 6 } apply from: "$rootDir/common.gradle" diff --git a/src/en/magusmanga/src/eu/kanade/tachiyomi/extension/en/magusmanga/MagusManga.kt b/src/en/magusmanga/src/eu/kanade/tachiyomi/extension/en/magusmanga/MagusManga.kt index 304673f6b..746683274 100644 --- a/src/en/magusmanga/src/eu/kanade/tachiyomi/extension/en/magusmanga/MagusManga.kt +++ b/src/en/magusmanga/src/eu/kanade/tachiyomi/extension/en/magusmanga/MagusManga.kt @@ -13,7 +13,7 @@ import java.util.concurrent.TimeUnit class MagusManga : MangaThemesiaAlt( "Magus Manga", - "https://dmvdepot.com", + "https://recipeslik.online", "en", mangaUrlDirectory = "/series", dateFormat = SimpleDateFormat("MMMMM dd, yyyy", Locale("en")), diff --git a/src/en/nightscans/build.gradle b/src/en/nightscans/build.gradle index a9a6a4a36..16524e48c 100644 --- a/src/en/nightscans/build.gradle +++ b/src/en/nightscans/build.gradle @@ -3,7 +3,7 @@ ext { extClass = '.NightScans' themePkg = 'mangathemesia' baseUrl = 'https://night-scans.com' - overrideVersionCode = 6 + overrideVersionCode = 7 isNsfw = true } diff --git a/src/en/nightscans/src/eu/kanade/tachiyomi/extension/en/nightscans/NightScans.kt b/src/en/nightscans/src/eu/kanade/tachiyomi/extension/en/nightscans/NightScans.kt index 36f98beb0..385a93d0e 100644 --- a/src/en/nightscans/src/eu/kanade/tachiyomi/extension/en/nightscans/NightScans.kt +++ b/src/en/nightscans/src/eu/kanade/tachiyomi/extension/en/nightscans/NightScans.kt @@ -7,6 +7,9 @@ import java.util.concurrent.TimeUnit class NightScans : MangaThemesiaAlt("NIGHT SCANS", "https://night-scans.com", "en", "/series") { + override val listUrl = "/manga/list-mode" + override val slugRegex = Regex("""^(\d+(st)?-)""") + override val client: OkHttpClient = super.client.newBuilder() .rateLimit(20, 4, TimeUnit.SECONDS) .build() diff --git a/src/en/rizzcomic/build.gradle b/src/en/rizzcomic/build.gradle index c46552348..275a59e32 100644 --- a/src/en/rizzcomic/build.gradle +++ b/src/en/rizzcomic/build.gradle @@ -3,7 +3,7 @@ ext { extClass = '.RizzComic' themePkg = 'mangathemesia' baseUrl = 'https://rizzfables.com' - overrideVersionCode = 4 + overrideVersionCode = 5 } apply from: "$rootDir/common.gradle" diff --git a/src/en/rizzcomic/src/eu/kanade/tachiyomi/extension/en/rizzcomic/RizzComic.kt b/src/en/rizzcomic/src/eu/kanade/tachiyomi/extension/en/rizzcomic/RizzComic.kt index 510faaeff..7feb5c9fb 100644 --- a/src/en/rizzcomic/src/eu/kanade/tachiyomi/extension/en/rizzcomic/RizzComic.kt +++ b/src/en/rizzcomic/src/eu/kanade/tachiyomi/extension/en/rizzcomic/RizzComic.kt @@ -57,7 +57,10 @@ class RizzComic : MangaThemesiaAlt( override val slugRegex = Regex("""^(r\d+-)""") // don't allow disabling random part setting - override fun setupPreferenceScreen(screen: PreferenceScreen) { } + override fun setupPreferenceScreen(screen: PreferenceScreen) = Unit + + override val listUrl = mangaUrlDirectory + override val listSelector = "div.bsx a" override fun popularMangaRequest(page: Int) = searchMangaRequest(page, "", SortFilter.POPULAR) override fun popularMangaParse(response: Response) = searchMangaParse(response)