From f6a81be166fd6fb10e9f52a4aa4db578c3cceebb Mon Sep 17 00:00:00 2001 From: Blatzar <46196380+Blatzar@users.noreply.github.com> Date: Mon, 4 Oct 2021 19:54:15 +0200 Subject: [PATCH] Added WebViewResolver.kt to bypass captcha and such evils --- .../lagradost/cloudstream3/AcraApplication.kt | 12 +++ .../cloudstream3/network/Requests.kt | 16 ++-- .../cloudstream3/network/WebViewResolver.kt | 90 +++++++++++++++++++ 3 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt diff --git a/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt b/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt index 113e7291..92ed9aff 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt @@ -14,6 +14,7 @@ import org.acra.data.StringFormat import org.acra.ktx.initAcra import org.acra.sender.ReportSender import org.acra.sender.ReportSenderFactory +import java.lang.ref.WeakReference import kotlin.concurrent.thread class CustomReportSender : ReportSender { @@ -55,6 +56,7 @@ class CustomSenderFactory : ReportSenderFactory { class AcraApplication : Application() { override fun attachBaseContext(base: Context?) { super.attachBaseContext(base) + context = base initAcra { //core configuration: @@ -75,4 +77,14 @@ class AcraApplication : Application() { }*/ } } + + companion object { + private var _context: WeakReference? = null + var context + get() = _context?.get() + private set(value) { + _context = WeakReference(value) + } + + } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/network/Requests.kt b/app/src/main/java/com/lagradost/cloudstream3/network/Requests.kt index 2f6f9aae..41e8b69a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/network/Requests.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/network/Requests.kt @@ -73,9 +73,10 @@ fun getCache(cacheTime: Int, cacheUnit: TimeUnit): CacheControl { fun getHeaders(headers: Map, referer: String?, cookie: Map): Headers { val refererMap = (referer ?: DEFAULT_REFERER)?.let { mapOf("referer" to it) } ?: mapOf() val cookieHeaders = (DEFAULT_COOKIES + cookie) - val cookieMap = if(cookieHeaders.isNotEmpty()) mapOf("Cookie" to cookieHeaders.entries.joinToString(separator = "; ") { - "${it.key}=${it.value};" - }) else mapOf() + val cookieMap = + if (cookieHeaders.isNotEmpty()) mapOf("Cookie" to cookieHeaders.entries.joinToString(separator = "; ") { + "${it.key}=${it.value};" + }) else mapOf() val tempHeaders = (DEFAULT_HEADERS + cookieMap + headers + refererMap) return tempHeaders.toHeaders() } @@ -89,16 +90,19 @@ fun get( allowRedirects: Boolean = true, cacheTime: Int = DEFAULT_TIME, cacheUnit: TimeUnit = DEFAULT_TIME_UNIT, - timeout: Long = 0L + timeout: Long = 0L, + interceptor: Interceptor? = null ): Response { + val client = OkHttpClient().newBuilder() .followRedirects(allowRedirects) .followSslRedirects(allowRedirects) .callTimeout(timeout, TimeUnit.SECONDS) - .build() + + if (interceptor != null) client.addInterceptor(interceptor) val request = getRequestCreator(url, headers, referer, params, cookies, cacheTime, cacheUnit) - return client.newCall(request).execute() + return client.build().newCall(request).execute() } diff --git a/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt b/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt new file mode 100644 index 00000000..ff2e061c --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt @@ -0,0 +1,90 @@ +package com.lagradost.cloudstream3.network + +import android.annotation.SuppressLint +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebView +import android.webkit.WebViewClient +import com.lagradost.cloudstream3.AcraApplication +import com.lagradost.cloudstream3.utils.Coroutines.main +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import okhttp3.Interceptor +import okhttp3.Request +import okhttp3.Response +import java.util.concurrent.TimeUnit + +class WebViewResolver(val interceptUrl: Regex) : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + return runBlocking { + val fixedRequest = resolveUsingWebView(request) + return@runBlocking chain.proceed(fixedRequest ?: request) + } + } + + @SuppressLint("SetJavaScriptEnabled") + suspend fun resolveUsingWebView(request: Request): Request? { + val url = request.url.toString() + var webView: WebView? = null + + fun destroyWebView() { + main { + webView?.stopLoading() + webView?.destroy() + webView = null + println("Destroyed webview") + } + } + + var fixedRequest: Request? = null + + main { + webView = WebView( + AcraApplication.context ?: throw RuntimeException("No base context in WebViewResolver") + ).apply { + settings.javaScriptEnabled = true + } + + webView?.webViewClient = object : WebViewClient() { + override fun shouldInterceptRequest( + view: WebView, + request: WebResourceRequest + ): WebResourceResponse? { + val webViewUrl = request.url.toString() + if (interceptUrl.containsMatchIn(webViewUrl)) { + fixedRequest = getRequestCreator( + webViewUrl, + request.requestHeaders, + null, + mapOf(), + mapOf(), + 10, + TimeUnit.MINUTES + ) + destroyWebView() + } + return super.shouldInterceptRequest(view, request) + } + } + + webView?.loadUrl(url) + } + + var loop = 0 + // Timeouts after this amount, 20s + val totalTime = 20000L + val delayTime = 100L + + // A bit sloppy, but couldn't find a better way + while (loop < totalTime / delayTime) { + if (fixedRequest != null) return fixedRequest + delay(delayTime) + loop += 1 + } + + destroyWebView() + return null + } + +} \ No newline at end of file