MyReadingManga: set User-Agent to get past Cloudflare (#13264)
* MyReadingManga: set User-Agent to get past Cloudflare * Remove custom Cloudflare interceptor
This commit is contained in:
parent
ba440a9792
commit
9ffce35bca
|
@ -5,7 +5,7 @@ ext {
|
|||
extName = 'MyReadingManga'
|
||||
pkgNameSuffix = 'all.myreadingmanga'
|
||||
extClass = '.MyReadingMangaFactory'
|
||||
extVersionCode = 44
|
||||
extVersionCode = 45
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
package eu.kanade.tachiyomi.extension.all.myreadingmanga
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.webkit.CookieManager
|
||||
import android.webkit.WebResourceError
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebSettings
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// TODO: remove after new stable release
|
||||
class CloudflareWafInterceptor(private val cookieDomain: String) : Interceptor {
|
||||
private val context = Injekt.get<Application>()
|
||||
private val handler by lazy { Handler(Looper.getMainLooper()) }
|
||||
private val cookieManager by lazy { CookieManager.getInstance() }
|
||||
|
||||
private val initWebView by lazy {
|
||||
WebSettings.getDefaultUserAgent(context)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
initWebView
|
||||
|
||||
val request = chain.request()
|
||||
val response = chain.proceed(request)
|
||||
|
||||
if (response.code != 403 || response.header("Server") !in SERVER_CHECK) {
|
||||
return response
|
||||
}
|
||||
|
||||
try {
|
||||
response.close()
|
||||
|
||||
// Remove all cookies and retry the Cloudflare WAF in a webview.
|
||||
// This is the key.
|
||||
cookieManager.setCookie(request.url.toString(), "__cf_bm=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=$cookieDomain")
|
||||
cookieManager.flush()
|
||||
resolveWithWebView(request)
|
||||
|
||||
return chain.proceed(request)
|
||||
} catch (e: Exception) {
|
||||
throw IOException(e)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
private fun resolveWithWebView(request: Request) {
|
||||
val latch = CountDownLatch(1)
|
||||
|
||||
var webView: WebView? = null
|
||||
|
||||
val origRequestUrl = request.url.toString()
|
||||
val headers = request.headers.toMultimap().mapValues { it.value.getOrNull(0) ?: "" }.toMutableMap()
|
||||
headers.remove("cookie")
|
||||
|
||||
handler.post {
|
||||
val webview = WebView(context)
|
||||
webView = webview
|
||||
with(webview.settings) {
|
||||
javaScriptEnabled = true
|
||||
domStorageEnabled = true
|
||||
databaseEnabled = true
|
||||
useWideViewPort = false
|
||||
loadWithOverviewMode = false
|
||||
userAgentString = request.header("User-Agent")
|
||||
}
|
||||
|
||||
webview.webViewClient = object : WebViewClient() {
|
||||
override fun onPageFinished(view: WebView, url: String) {
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
|
||||
latch.countDown()
|
||||
}
|
||||
}
|
||||
|
||||
webView?.loadUrl(origRequestUrl, headers)
|
||||
}
|
||||
|
||||
latch.await(TIMEOUT_SEC, TimeUnit.SECONDS)
|
||||
|
||||
handler.post {
|
||||
webView?.stopLoading()
|
||||
webView?.destroy()
|
||||
webView = null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SERVER_CHECK = arrayOf("cloudflare-nginx", "cloudflare")
|
||||
const val TIMEOUT_SEC: Long = 10
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
@ -22,20 +23,16 @@ import org.jsoup.nodes.Element
|
|||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
open class MyReadingManga(override val lang: String, private val siteLang: String, private val latestLang: String) : ParsedHttpSource() {
|
||||
|
||||
// Basic Info
|
||||
override val name = "MyReadingManga"
|
||||
final override val baseUrl = "https://myreadingmanga.info"
|
||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
||||
.addInterceptor(CloudflareWafInterceptor(".myreadingmanga.info"))
|
||||
.connectTimeout(1, TimeUnit.MINUTES)
|
||||
.readTimeout(1, TimeUnit.MINUTES)
|
||||
.retryOnConnectionFailure(true)
|
||||
.followRedirects(true)
|
||||
.build()!!
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
override fun headersBuilder(): Headers.Builder =
|
||||
super.headersBuilder()
|
||||
.set("User-Agent", USER_AGENT)
|
||||
override val supportsLatest = true
|
||||
|
||||
// Popular - Random
|
||||
|
@ -315,4 +312,8 @@ open class MyReadingManga(override val lang: String, private val siteLang: Strin
|
|||
private interface UriFilter {
|
||||
fun addToUri(uri: Uri.Builder, uriParam: String)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val USER_AGENT = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue