TuMangaOnline: Fix chapter images don't load and no pages found for some chapters (#16317)

* Open WebView before load a chapter image

* Move to Interceptor

* Add function to redirect to read page (fix no pages found)
This commit is contained in:
seew3l 2023-05-06 09:17:21 -05:00 committed by GitHub
parent 7303f8eae3
commit 9c64f03b27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 88 additions and 6 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'TuMangaOnline' extName = 'TuMangaOnline'
pkgNameSuffix = 'es.tumangaonline' pkgNameSuffix = 'es.tumangaonline'
extClass = '.TuMangaOnline' extClass = '.TuMangaOnline'
extVersionCode = 41 extVersionCode = 42
isNsfw = true isNsfw = true
} }

View File

@ -2,7 +2,13 @@ package eu.kanade.tachiyomi.extension.es.tumangaonline
import android.app.Application import android.app.Application
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Handler
import android.os.Looper
import android.view.View
import android.webkit.WebChromeClient
import android.webkit.WebView
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
@ -14,6 +20,7 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.FormBody
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -26,6 +33,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 java.util.concurrent.CountDownLatch
class TuMangaOnline : ConfigurableSource, ParsedHttpSource() { class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
@ -52,7 +60,44 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
} }
private var loadWebView = true
override val client: OkHttpClient = network.client.newBuilder() override val client: OkHttpClient = network.client.newBuilder()
.addInterceptor { chain ->
val request = chain.request()
val url = request.url.toString()
if (url.startsWith(imageCDNUrl) && loadWebView) {
val handler = Handler(Looper.getMainLooper())
val latch = CountDownLatch(1)
var webView: WebView? = null
handler.post {
val webview = WebView(Injekt.get<Application>())
webView = webview
webview.settings.domStorageEnabled = true
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
webview.settings.useWideViewPort = false
webview.settings.loadWithOverviewMode = false
webview.settings.userAgentString = userAgent
webview.webChromeClient = object : WebChromeClient() {
override fun onProgressChanged(view: WebView?, newProgress: Int) {
if (newProgress == 100) {
latch.countDown()
}
}
}
val headers = mutableMapOf<String, String>()
headers["Referer"] = baseUrl
webview.loadUrl(url, headers)
}
latch.await()
loadWebView = false
handler.post { webView?.destroy() }
}
chain.proceed(request)
}
.rateLimitHost( .rateLimitHost(
baseUrl.toHttpUrlOrNull()!!, baseUrl.toHttpUrlOrNull()!!,
preferences.getString(WEB_RATELIMIT_PREF, WEB_RATELIMIT_PREF_DEFAULT_VALUE)!!.toInt(), preferences.getString(WEB_RATELIMIT_PREF, WEB_RATELIMIT_PREF_DEFAULT_VALUE)!!.toInt(),
@ -218,17 +263,19 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
return GET(chapter.url, headers) return GET(chapter.url, headers)
} }
override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply { override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply {
val currentUrl = document.body().baseUri() var doc = redirectToReadPage(document)
val newUrl = if (getPageMethodPref() == "cascade" && currentUrl.contains("paginated")) { val currentUrl = doc.location()
val newUrl = if (getPageMethodPref() == "cascade") {
currentUrl.substringBefore("paginated") + "cascade" currentUrl.substringBefore("paginated") + "cascade"
} else if (getPageMethodPref() == "paginated" && currentUrl.contains("cascade")) { } else if (getPageMethodPref() == "paginated") {
currentUrl.substringBefore("cascade") + "paginated" currentUrl.substringBefore("cascade") + "paginated"
} else { } else {
currentUrl currentUrl
} }
val doc = client.newCall(GET(newUrl, headers)).execute().asJsoup() doc = client.newCall(GET(newUrl, headers)).execute().asJsoup()
if (getPageMethodPref() == "cascade") { if (getPageMethodPref() == "cascade") {
doc.select("div.viewer-container img").forEach { doc.select("div.viewer-container img").forEach {
@ -255,7 +302,42 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
} }
} }
// Note: At this moment (24/08/2021) it's necessary to make the image request with headers to prevent 403. //Some old chapters uses JavaScript to redirect to read page
private fun redirectToReadPage(document: Document): Document {
val script1 = document.selectFirst("script:containsData(uniqid)")
val script2 = document.selectFirst("script:containsData(window.location.replace)")
if (script1 != null) {
val data = script1.data()
val regexParams = """\{uniqid:'(.+)',cascade:(.+)\}""".toRegex()
val regexAction = """form\.action\s?=\s?'(.+)'""".toRegex()
val params = regexParams.find(data)!!
val action = regexAction.find(data)!!.groupValues[1]
val bodyBuilder = FormBody.Builder()
bodyBuilder.add("uniqid", params.groupValues[1])
bodyBuilder.add("cascade", params.groupValues[2])
return redirectToReadPage(
client.newCall(POST(action, headers, bodyBuilder.build())).execute().asJsoup()
)
}
if (script2 != null) {
val data = script2.data()
val regexRedirect = """window\.location\.replace\('(.+)'\)""".toRegex()
val url = regexRedirect.find(data)!!.groupValues[1]
return redirectToReadPage(
client.newCall(GET(url, headers)).execute().asJsoup()
)
}
return document
}
// Note: At this moment (05/04/2023) it's necessary to make the image request with headers to prevent 403.
override fun imageRequest(page: Page) = GET(page.imageUrl!!, headers) override fun imageRequest(page: Page) = GET(page.imageUrl!!, headers)
override fun imageUrlParse(document: Document): String { override fun imageUrlParse(document: Document): String {