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.app | ||||||
| import com.lagradost.cloudstream3.utils.Coroutines.main | import com.lagradost.cloudstream3.utils.Coroutines.main | ||||||
| import kotlinx.coroutines.delay | import kotlinx.coroutines.delay | ||||||
|  | import kotlinx.coroutines.flow.callbackFlow | ||||||
| import kotlinx.coroutines.runBlocking | import kotlinx.coroutines.runBlocking | ||||||
| import okhttp3.Interceptor | import okhttp3.Interceptor | ||||||
| import okhttp3.Request | import okhttp3.Request | ||||||
| import okhttp3.Response | import okhttp3.Response | ||||||
| import java.net.URI | import java.net.URI | ||||||
| import java.util.concurrent.TimeUnit | 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 { |     override fun intercept(chain: Interceptor.Chain): Response { | ||||||
|         val request = chain.request() |         val request = chain.request() | ||||||
|         return runBlocking { |         return runBlocking { | ||||||
|             val fixedRequest = resolveUsingWebView(request) |             val fixedRequest = resolveUsingWebView(request).first | ||||||
|             return@runBlocking chain.proceed(fixedRequest ?: request) |             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") |     @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 url = request.url.toString() | ||||||
|         val headers = request.headers |         val headers = request.headers | ||||||
|         println("Initial web-view request: $url") |         println("Initial web-view request: $url") | ||||||
|  | @ -41,17 +57,21 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         var fixedRequest: Request? = null |         var fixedRequest: Request? = null | ||||||
|  |         val extraRequestList = mutableListOf<Request>() | ||||||
| 
 | 
 | ||||||
|         main { |         main { | ||||||
|             // Useful for debugging |             // Useful for debugging | ||||||
| //            WebView.setWebContentsDebuggingEnabled(true) | //            WebView.setWebContentsDebuggingEnabled(true) | ||||||
|             webView = WebView( |             webView = WebView( | ||||||
|                 AcraApplication.context ?: throw RuntimeException("No base context in WebViewResolver") |                 AcraApplication.context | ||||||
|  |                     ?: throw RuntimeException("No base context in WebViewResolver") | ||||||
|             ).apply { |             ).apply { | ||||||
|                 // Bare minimum to bypass captcha |                 // Bare minimum to bypass captcha | ||||||
|                 settings.javaScriptEnabled = true |                 settings.javaScriptEnabled = true | ||||||
|                 settings.domStorageEnabled = true |                 settings.domStorageEnabled = true | ||||||
|                 settings.userAgentString = USER_AGENT |                 settings.userAgentString = USER_AGENT | ||||||
|  |                 // Blocks unnecessary images, remove if captcha fucks. | ||||||
|  |                 settings.blockNetworkImage = true | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             webView?.webViewClient = object : WebViewClient() { |             webView?.webViewClient = object : WebViewClient() { | ||||||
|  | @ -63,23 +83,19 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor { | ||||||
| //                    println("Loading WebView URL: $webViewUrl") | //                    println("Loading WebView URL: $webViewUrl") | ||||||
| 
 | 
 | ||||||
|                     if (interceptUrl.containsMatchIn(webViewUrl)) { |                     if (interceptUrl.containsMatchIn(webViewUrl)) { | ||||||
|                         fixedRequest = getRequestCreator( |                         fixedRequest = request.toRequest().also(requestCallBack) | ||||||
|                             webViewUrl, |  | ||||||
|                             request.requestHeaders, |  | ||||||
|                             null, |  | ||||||
|                             mapOf(), |  | ||||||
|                             mapOf(), |  | ||||||
|                             10, |  | ||||||
|                             TimeUnit.MINUTES |  | ||||||
|                         ) |  | ||||||
| 
 |  | ||||||
|                         println("Web-view request finished: $webViewUrl") |                         println("Web-view request finished: $webViewUrl") | ||||||
|                         destroyWebView() |                         destroyWebView() | ||||||
|                         return null |                         return null | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|  |                     if (additionalUrls.any { it.containsMatchIn(webViewUrl) }) { | ||||||
|  |                         extraRequestList.add(request.toRequest().also(requestCallBack)) | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|                     // Suppress image requests as we don't display them anywhere |                     // Suppress image requests as we don't display them anywhere | ||||||
|                     // Less data, low chance of causing issues. |                     // 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") |                     val blacklistedFiles = listOf(".jpg", ".png", ".webp", ".jpeg", ".webm", ".mp4") | ||||||
| 
 | 
 | ||||||
|                     /** NOTE!  request.requestHeaders is not perfect! |                     /** NOTE!  request.requestHeaders is not perfect! | ||||||
|  | @ -97,7 +113,10 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor { | ||||||
|                                 null |                                 null | ||||||
|                             ) |                             ) | ||||||
| 
 | 
 | ||||||
|                             webViewUrl.contains("recaptcha") -> super.shouldInterceptRequest(view, request) |                             webViewUrl.contains("recaptcha") -> super.shouldInterceptRequest( | ||||||
|  |                                 view, | ||||||
|  |                                 request | ||||||
|  |                             ) | ||||||
| 
 | 
 | ||||||
|                             request.method == "GET" -> app.get( |                             request.method == "GET" -> app.get( | ||||||
|                                 webViewUrl, |                                 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 |                     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 |         // A bit sloppy, but couldn't find a better way | ||||||
|         while (loop < totalTime / delayTime) { |         while (loop < totalTime / delayTime) { | ||||||
|             if (fixedRequest != null) return fixedRequest |             if (fixedRequest != null) return fixedRequest to extraRequestList | ||||||
|             delay(delayTime) |             delay(delayTime) | ||||||
|             loop += 1 |             loop += 1 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         println("Web-view timeout after ${totalTime / 1000}s") |         println("Web-view timeout after ${totalTime / 1000}s") | ||||||
|         destroyWebView() |         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 { |     fun Response.toWebResourceResponse(): WebResourceResponse { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue