From dc9ba9e00809de3986d4597c8afe44b1bbcd023b Mon Sep 17 00:00:00 2001 From: mobi2002 <48650614+mobi2002@users.noreply.github.com> Date: Tue, 25 Apr 2023 22:20:09 +0500 Subject: [PATCH] Toonily: fix search (#16172) * Toonily: fix search * use CookieInterceptor instead --- .../madara/toonily/src/CookieInterceptor.kt | 46 +++++++++++++ .../overrides/madara/toonily/src/Toonily.kt | 64 ++++++++++++++++++- .../multisrc/madara/MadaraGenerator.kt | 2 +- 3 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 multisrc/overrides/madara/toonily/src/CookieInterceptor.kt diff --git a/multisrc/overrides/madara/toonily/src/CookieInterceptor.kt b/multisrc/overrides/madara/toonily/src/CookieInterceptor.kt new file mode 100644 index 000000000..e73d3f1ba --- /dev/null +++ b/multisrc/overrides/madara/toonily/src/CookieInterceptor.kt @@ -0,0 +1,46 @@ +package eu.kanade.tachiyomi.extension.en.toonily + +import android.util.Log +import android.webkit.CookieManager +import okhttp3.Interceptor +import okhttp3.Response + +class CookieInterceptor( + private val domain: String, + private val key: String, + private val value: String, +) : Interceptor { + + init { + val url = "https://$domain/" + val cookie = "$key=$value; Domain=$domain; Path=/" + setCookie(url, cookie) + } + + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + if (!request.url.host.endsWith(domain)) return chain.proceed(request) + + val cookie = "$key=$value" + val cookieList = request.header("Cookie")?.split("; ") ?: emptyList() + if (cookie in cookieList) return chain.proceed(request) + + setCookie("https://$domain/", "$cookie; Domain=$domain; Path=/") + val prefix = "$key=" + val newCookie = buildList(cookieList.size + 1) { + cookieList.filterNotTo(this) { it.startsWith(prefix) } + add(cookie) + }.joinToString("; ") + val newRequest = request.newBuilder().header("Cookie", newCookie).build() + return chain.proceed(newRequest) + } + + private fun setCookie(url: String, value: String) { + try { + CookieManager.getInstance().setCookie(url, value) + } catch (e: Exception) { + // Probably running on Tachidesk + Log.e("Toonily", "failed to set cookie", e) + } + } +} diff --git a/multisrc/overrides/madara/toonily/src/Toonily.kt b/multisrc/overrides/madara/toonily/src/Toonily.kt index 657ed0e37..4f1958c91 100644 --- a/multisrc/overrides/madara/toonily/src/Toonily.kt +++ b/multisrc/overrides/madara/toonily/src/Toonily.kt @@ -1,16 +1,73 @@ package eu.kanade.tachiyomi.extension.en.toonily import eu.kanade.tachiyomi.multisrc.madara.Madara +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.source.model.FilterList +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import okhttp3.OkHttpClient +import okhttp3.Request import java.text.SimpleDateFormat import java.util.Locale +private const val domain = "toonily.com" class Toonily : Madara( "Toonily", - "https://toonily.com", + "https://$domain", "en", SimpleDateFormat("MMM d, yy", Locale.US), ) { + private val cookieInterceptor = CookieInterceptor(domain, "toonily-mature", "1") + override val client: OkHttpClient = super.client.newBuilder() + .addNetworkInterceptor(cookieInterceptor) + .build() + + override val mangaSubString = "webtoons" + + override fun searchPage(page: Int): String { + return if (page > 1) { + "page/$page/" + } else { + "" + } + } + + private fun searchPage(page: Int, query: String): String { + val urlQuery = query.trim() + .lowercase(Locale.US) + .replace(titleSpecialCharactersRegex, "-") + .replace(trailingHyphenRegex, "") + .let { if (it.isNotEmpty()) "$it/" else it } + return if (page > 1) { + "search/${urlQuery}page/$page/" + } else { + "search/$urlQuery" + } + } + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + val request = super.searchMangaRequest(page, query, filters) + + val queries = request.url.queryParameterNames + .filterNot { it == "s" } + + val newUrl = "$baseUrl/${searchPage(page, query)}".toHttpUrlOrNull()!!.newBuilder().apply { + queries.map { q -> + request.url.queryParameterValues(q).map { + this.addQueryParameter(q, it) + } + } + }.build() + + return request.newBuilder() + .url(newUrl) + .build() + } + + override fun genresRequest(): Request { + return GET("$baseUrl/search/?post_type=wp-manga", headers) + } + // The source customized the Madara theme and broke the filter. override val filterNonMangaItems = false @@ -24,4 +81,9 @@ class Toonily : Madara( val formattedDate = if (date?.contains("UP") == true) "today" else date return super.parseChapterDate(formattedDate) } + + companion object { + val titleSpecialCharactersRegex = "[^a-z0-9]+".toRegex() + val trailingHyphenRegex = "-+$".toRegex() + } } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt index dec4a2ef4..9f86b9f59 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt @@ -407,7 +407,7 @@ class MadaraGenerator : ThemeSourceGenerator { SingleLang("TonizuToon", "https://tonizutoon.com", "tr", isNsfw = true), SingleLang("ToonChill", "https://toonchill.com", "en", overrideVersionCode = 1), SingleLang("ToonGod", "https://www.toongod.com", "en", isNsfw = true, overrideVersionCode = 4), - SingleLang("Toonily", "https://toonily.com", "en", isNsfw = true, overrideVersionCode = 9), + SingleLang("Toonily", "https://toonily.com", "en", isNsfw = true, overrideVersionCode = 10), SingleLang("Toonily.net", "https://toonily.net", "en", isNsfw = true, className = "Toonilynet", overrideVersionCode = 2), SingleLang("ToonMany", "https://toonmany.com", "en", isNsfw = true), SingleLang("Top Manhua", "https://topmanhua.com", "en", overrideVersionCode = 2),