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:
Vetle Ledaal 2022-08-29 16:04:01 +02:00 committed by GitHub
parent ba440a9792
commit 9ffce35bca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 10 additions and 115 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'MyReadingManga'
pkgNameSuffix = 'all.myreadingmanga'
extClass = '.MyReadingMangaFactory'
extVersionCode = 44
extVersionCode = 45
isNsfw = true
}

View File

@ -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
}
}

View File

@ -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"
}
}