forked from recloudstream/cloudstream
Merge pull request #121 from Blatzar/master
Added WebViewResolver.kt to bypass captcha and such evils
This commit is contained in:
commit
d86a80ae14
3 changed files with 112 additions and 6 deletions
|
@ -14,6 +14,7 @@ import org.acra.data.StringFormat
|
||||||
import org.acra.ktx.initAcra
|
import org.acra.ktx.initAcra
|
||||||
import org.acra.sender.ReportSender
|
import org.acra.sender.ReportSender
|
||||||
import org.acra.sender.ReportSenderFactory
|
import org.acra.sender.ReportSenderFactory
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class CustomReportSender : ReportSender {
|
class CustomReportSender : ReportSender {
|
||||||
|
@ -55,6 +56,7 @@ class CustomSenderFactory : ReportSenderFactory {
|
||||||
class AcraApplication : Application() {
|
class AcraApplication : Application() {
|
||||||
override fun attachBaseContext(base: Context?) {
|
override fun attachBaseContext(base: Context?) {
|
||||||
super.attachBaseContext(base)
|
super.attachBaseContext(base)
|
||||||
|
context = base
|
||||||
|
|
||||||
initAcra {
|
initAcra {
|
||||||
//core configuration:
|
//core configuration:
|
||||||
|
@ -75,4 +77,14 @@ class AcraApplication : Application() {
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private var _context: WeakReference<Context>? = null
|
||||||
|
var context
|
||||||
|
get() = _context?.get()
|
||||||
|
private set(value) {
|
||||||
|
_context = WeakReference(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -73,9 +73,10 @@ fun getCache(cacheTime: Int, cacheUnit: TimeUnit): CacheControl {
|
||||||
fun getHeaders(headers: Map<String, String>, referer: String?, cookie: Map<String, String>): Headers {
|
fun getHeaders(headers: Map<String, String>, referer: String?, cookie: Map<String, String>): Headers {
|
||||||
val refererMap = (referer ?: DEFAULT_REFERER)?.let { mapOf("referer" to it) } ?: mapOf()
|
val refererMap = (referer ?: DEFAULT_REFERER)?.let { mapOf("referer" to it) } ?: mapOf()
|
||||||
val cookieHeaders = (DEFAULT_COOKIES + cookie)
|
val cookieHeaders = (DEFAULT_COOKIES + cookie)
|
||||||
val cookieMap = if(cookieHeaders.isNotEmpty()) mapOf("Cookie" to cookieHeaders.entries.joinToString(separator = "; ") {
|
val cookieMap =
|
||||||
"${it.key}=${it.value};"
|
if (cookieHeaders.isNotEmpty()) mapOf("Cookie" to cookieHeaders.entries.joinToString(separator = "; ") {
|
||||||
}) else mapOf()
|
"${it.key}=${it.value};"
|
||||||
|
}) else mapOf()
|
||||||
val tempHeaders = (DEFAULT_HEADERS + cookieMap + headers + refererMap)
|
val tempHeaders = (DEFAULT_HEADERS + cookieMap + headers + refererMap)
|
||||||
return tempHeaders.toHeaders()
|
return tempHeaders.toHeaders()
|
||||||
}
|
}
|
||||||
|
@ -89,16 +90,19 @@ fun get(
|
||||||
allowRedirects: Boolean = true,
|
allowRedirects: Boolean = true,
|
||||||
cacheTime: Int = DEFAULT_TIME,
|
cacheTime: Int = DEFAULT_TIME,
|
||||||
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
|
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
|
||||||
timeout: Long = 0L
|
timeout: Long = 0L,
|
||||||
|
interceptor: Interceptor? = null
|
||||||
): Response {
|
): Response {
|
||||||
|
|
||||||
val client = OkHttpClient().newBuilder()
|
val client = OkHttpClient().newBuilder()
|
||||||
.followRedirects(allowRedirects)
|
.followRedirects(allowRedirects)
|
||||||
.followSslRedirects(allowRedirects)
|
.followSslRedirects(allowRedirects)
|
||||||
.callTimeout(timeout, TimeUnit.SECONDS)
|
.callTimeout(timeout, TimeUnit.SECONDS)
|
||||||
.build()
|
|
||||||
|
if (interceptor != null) client.addInterceptor(interceptor)
|
||||||
|
|
||||||
val request = getRequestCreator(url, headers, referer, params, cookies, cacheTime, cacheUnit)
|
val request = getRequestCreator(url, headers, referer, params, cookies, cacheTime, cacheUnit)
|
||||||
return client.newCall(request).execute()
|
return client.build().newCall(request).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue