made WebViewResolver.kt more powerful

This commit is contained in:
Blatzar 2022-01-16 16:35:06 +01:00
parent ef9d6e11a7
commit 55fb24a51f

View file

@ -8,24 +8,40 @@ import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.Coroutines.main
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import java.net.URI
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
/**
* When used as Interceptor additionalUrls cannot be returned, use WebViewResolver(...).resolveUsingWebView(...)
* @param interceptUrl will stop the WebView when reaching this url.
* @param additionalUrls this will make resolveUsingWebView also return all other requests matching the list of Regex.
* */
class WebViewResolver(val interceptUrl: Regex, val additionalUrls: List<Regex> = emptyList()) :
Interceptor {
class WebViewResolver(val interceptUrl: Regex) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
return runBlocking {
val fixedRequest = resolveUsingWebView(request)
val fixedRequest = resolveUsingWebView(request).first
return@runBlocking chain.proceed(fixedRequest ?: request)
}
}
/**
* @param requestCallBack asynchronously return matched requests by either interceptUrl or additionalUrls.
* @return the final request (by interceptUrl) and all the collected urls (by additionalUrls).
* */
@SuppressLint("SetJavaScriptEnabled")
suspend fun resolveUsingWebView(request: Request): Request? {
suspend fun resolveUsingWebView(
request: Request,
requestCallBack: (Request) -> Unit = {}
): Pair<Request?, List<Request>> {
val url = request.url.toString()
val headers = request.headers
println("Initial web-view request: $url")
@ -41,17 +57,21 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor {
}
var fixedRequest: Request? = null
val extraRequestList = mutableListOf<Request>()
main {
// Useful for debugging
// WebView.setWebContentsDebuggingEnabled(true)
webView = WebView(
AcraApplication.context ?: throw RuntimeException("No base context in WebViewResolver")
AcraApplication.context
?: throw RuntimeException("No base context in WebViewResolver")
).apply {
// Bare minimum to bypass captcha
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
settings.userAgentString = USER_AGENT
// Blocks unnecessary images, remove if captcha fucks.
settings.blockNetworkImage = true
}
webView?.webViewClient = object : WebViewClient() {
@ -63,23 +83,19 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor {
// println("Loading WebView URL: $webViewUrl")
if (interceptUrl.containsMatchIn(webViewUrl)) {
fixedRequest = getRequestCreator(
webViewUrl,
request.requestHeaders,
null,
mapOf(),
mapOf(),
10,
TimeUnit.MINUTES
)
fixedRequest = request.toRequest().also(requestCallBack)
println("Web-view request finished: $webViewUrl")
destroyWebView()
return null
}
if (additionalUrls.any { it.containsMatchIn(webViewUrl) }) {
extraRequestList.add(request.toRequest().also(requestCallBack))
}
// Suppress image requests as we don't display them anywhere
// Less data, low chance of causing issues.
// blockNetworkImage also does this job but i will keep it for the future.
val blacklistedFiles = listOf(".jpg", ".png", ".webp", ".jpeg", ".webm", ".mp4")
/** NOTE! request.requestHeaders is not perfect!
@ -97,7 +113,10 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor {
null
)
webViewUrl.contains("recaptcha") -> super.shouldInterceptRequest(view, request)
webViewUrl.contains("recaptcha") -> super.shouldInterceptRequest(
view,
request
)
request.method == "GET" -> app.get(
webViewUrl,
@ -115,7 +134,11 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor {
}
}
override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
override fun onReceivedSslError(
view: WebView?,
handler: SslErrorHandler?,
error: SslError?
) {
handler?.proceed() // Ignore ssl issues
}
}
@ -130,14 +153,41 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor {
// A bit sloppy, but couldn't find a better way
while (loop < totalTime / delayTime) {
if (fixedRequest != null) return fixedRequest
if (fixedRequest != null) return fixedRequest to extraRequestList
delay(delayTime)
loop += 1
}
println("Web-view timeout after ${totalTime / 1000}s")
destroyWebView()
return null
return null to extraRequestList
}
fun WebResourceRequest.toRequest(): Request {
val webViewUrl = this.url.toString()
return when (this.method) {
"POST" -> postRequestCreator(
webViewUrl,
this.requestHeaders,
null,
emptyMap(),
emptyMap(),
emptyMap(),
10,
TimeUnit.MINUTES
)
// "GET",
else -> getRequestCreator(
webViewUrl,
this.requestHeaders,
null,
emptyMap(),
emptyMap(),
10,
TimeUnit.MINUTES
)
}
}
fun Response.toWebResourceResponse(): WebResourceResponse {