forked from recloudstream/cloudstream
		
	made WebViewResolver.kt more powerful
This commit is contained in:
		
							parent
							
								
									ef9d6e11a7
								
							
						
					
					
						commit
						55fb24a51f
					
				
					 1 changed files with 68 additions and 18 deletions
				
			
		|  | @ -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 { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue