mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Add MangaDex login
This commit is contained in:
		
							
								
								
									
										46
									
								
								app/src/main/java/exh/patch/MangaDexLogin.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								app/src/main/java/exh/patch/MangaDexLogin.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
package exh.patch
 | 
			
		||||
 | 
			
		||||
import android.app.Application
 | 
			
		||||
import eu.kanade.tachiyomi.source.SourceManager
 | 
			
		||||
import eu.kanade.tachiyomi.source.online.HttpSource
 | 
			
		||||
import exh.ui.captcha.BrowserActionActivity
 | 
			
		||||
import exh.util.interceptAsHtml
 | 
			
		||||
import okhttp3.HttpUrl
 | 
			
		||||
import okhttp3.OkHttpClient
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
private val HIDE_SCRIPT = """
 | 
			
		||||
            document.querySelector("#forgot_button").style.visibility = "hidden";
 | 
			
		||||
            document.querySelector("#signup_button").style.visibility = "hidden";
 | 
			
		||||
            document.querySelector("#announcement").style.visibility = "hidden";
 | 
			
		||||
            document.querySelector("nav").style.visibility = "hidden";
 | 
			
		||||
            document.querySelector("footer").style.visibility = "hidden";
 | 
			
		||||
        """.trimIndent()
 | 
			
		||||
 | 
			
		||||
private fun verifyComplete(url: String): Boolean {
 | 
			
		||||
    return HttpUrl.parse(url)?.let { parsed ->
 | 
			
		||||
        parsed.host() == "mangadex.org" && parsed.pathSegments().none { it.isNotBlank() }
 | 
			
		||||
    } ?: false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun OkHttpClient.Builder.attachMangaDexLogin() =
 | 
			
		||||
        addInterceptor { chain ->
 | 
			
		||||
            val response = chain.proceed(chain.request())
 | 
			
		||||
            if(response.request().url().host() == "mangadex.org") {
 | 
			
		||||
                response.interceptAsHtml { doc ->
 | 
			
		||||
                    if (doc.title().trim().equals("Login - MangaDex", true)) {
 | 
			
		||||
                        BrowserActionActivity.launchAction(
 | 
			
		||||
                                Injekt.get<Application>(),
 | 
			
		||||
                                ::verifyComplete,
 | 
			
		||||
                                HIDE_SCRIPT,
 | 
			
		||||
                                "https://mangadex.org/login",
 | 
			
		||||
                                "Login",
 | 
			
		||||
                                (Injekt.get<SourceManager>().get(2499283573021220255) as? HttpSource)?.headers?.toMultimap()?.mapValues {
 | 
			
		||||
                                    it.value.joinToString(",")
 | 
			
		||||
                                } ?: emptyMap()
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else response
 | 
			
		||||
        }
 | 
			
		||||
@@ -2,6 +2,7 @@ package exh.source
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.*
 | 
			
		||||
import eu.kanade.tachiyomi.source.online.HttpSource
 | 
			
		||||
import okhttp3.OkHttpClient
 | 
			
		||||
import okhttp3.Request
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
import rx.Observable
 | 
			
		||||
@@ -93,16 +94,16 @@ abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() {
 | 
			
		||||
    /**
 | 
			
		||||
     * Base url of the website without the trailing slash, like: http://mysite.com
 | 
			
		||||
     */
 | 
			
		||||
    override val baseUrl = delegate.baseUrl
 | 
			
		||||
    override val baseUrl get() = delegate.baseUrl
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Whether the source has support for latest updates.
 | 
			
		||||
     */
 | 
			
		||||
    override val supportsLatest = delegate.supportsLatest
 | 
			
		||||
    override val supportsLatest get() = delegate.supportsLatest
 | 
			
		||||
    /**
 | 
			
		||||
     * Name of the source.
 | 
			
		||||
     */
 | 
			
		||||
    final override val name = delegate.name
 | 
			
		||||
    final override val name get() = delegate.name
 | 
			
		||||
 | 
			
		||||
    // ===> OPTIONAL FIELDS
 | 
			
		||||
 | 
			
		||||
@@ -111,11 +112,18 @@ abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() {
 | 
			
		||||
     * of the MD5 of the string: sourcename/language/versionId
 | 
			
		||||
     * Note the generated id sets the sign bit to 0.
 | 
			
		||||
     */
 | 
			
		||||
    override val id = delegate.id
 | 
			
		||||
    override val id get() = delegate.id
 | 
			
		||||
    /**
 | 
			
		||||
     * Default network client for doing requests.
 | 
			
		||||
     */
 | 
			
		||||
    override val client = delegate.client
 | 
			
		||||
    final override val client get() = delegate.client
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * You must NEVER call super.client if you override this!
 | 
			
		||||
     */
 | 
			
		||||
    open val baseHttpClient: OkHttpClient? = null
 | 
			
		||||
    open val networkHttpClient: OkHttpClient get() = network.client
 | 
			
		||||
    open val networkCloudflareClient: OkHttpClient get() = network.cloudflareClient
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Visible name of the source.
 | 
			
		||||
@@ -235,4 +243,8 @@ abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class IncompatibleDelegateException(message: String) : RuntimeException(message)
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        delegate.bindDelegate(this)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -96,21 +96,21 @@ class EnhancedHttpSource(val originalSource: HttpSource,
 | 
			
		||||
    /**
 | 
			
		||||
     * Base url of the website without the trailing slash, like: http://mysite.com
 | 
			
		||||
     */
 | 
			
		||||
    override val baseUrl = source().baseUrl
 | 
			
		||||
    override val baseUrl get() = source().baseUrl
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Whether the source has support for latest updates.
 | 
			
		||||
     */
 | 
			
		||||
    override val supportsLatest = source().supportsLatest
 | 
			
		||||
    override val supportsLatest get() = source().supportsLatest
 | 
			
		||||
    /**
 | 
			
		||||
     * Name of the source.
 | 
			
		||||
     */
 | 
			
		||||
    override val name = source().name
 | 
			
		||||
    override val name get() = source().name
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * An ISO 639-1 compliant language code (two letters in lower case).
 | 
			
		||||
     */
 | 
			
		||||
    override val lang = source().lang
 | 
			
		||||
    override val lang get() = source().lang
 | 
			
		||||
 | 
			
		||||
    // ===> OPTIONAL FIELDS
 | 
			
		||||
 | 
			
		||||
@@ -119,11 +119,11 @@ class EnhancedHttpSource(val originalSource: HttpSource,
 | 
			
		||||
     * of the MD5 of the string: sourcename/language/versionId
 | 
			
		||||
     * Note the generated id sets the sign bit to 0.
 | 
			
		||||
     */
 | 
			
		||||
    override val id = source().id
 | 
			
		||||
    override val id get() = source().id
 | 
			
		||||
    /**
 | 
			
		||||
     * Default network client for doing requests.
 | 
			
		||||
     */
 | 
			
		||||
    override val client = source().client
 | 
			
		||||
    override val client get() = source().client
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Visible name of the source.
 | 
			
		||||
 
 | 
			
		||||
@@ -6,17 +6,17 @@ import android.webkit.WebResourceRequest
 | 
			
		||||
import android.webkit.WebResourceResponse
 | 
			
		||||
import android.webkit.WebView
 | 
			
		||||
import eu.kanade.tachiyomi.util.asJsoup
 | 
			
		||||
import exh.ui.captcha.SolveCaptchaActivity.Companion.CROSS_WINDOW_SCRIPT_INNER
 | 
			
		||||
import exh.ui.captcha.BrowserActionActivity.Companion.CROSS_WINDOW_SCRIPT_INNER
 | 
			
		||||
import org.jsoup.nodes.DataNode
 | 
			
		||||
import org.jsoup.nodes.Element
 | 
			
		||||
import java.nio.charset.Charset
 | 
			
		||||
 | 
			
		||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
 | 
			
		||||
class AutoSolvingWebViewClient(activity: SolveCaptchaActivity,
 | 
			
		||||
                               source: CaptchaCompletionVerifier,
 | 
			
		||||
class AutoSolvingWebViewClient(activity: BrowserActionActivity,
 | 
			
		||||
                               verifyComplete: (String) -> Boolean,
 | 
			
		||||
                               injectScript: String?,
 | 
			
		||||
                               headers: Map<String, String>)
 | 
			
		||||
    : HeadersInjectingWebViewClient(activity, source, injectScript, headers) {
 | 
			
		||||
    : HeadersInjectingWebViewClient(activity, verifyComplete, injectScript, headers) {
 | 
			
		||||
 | 
			
		||||
    override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
 | 
			
		||||
        // Inject our custom script into the recaptcha iframes
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,13 @@ package exh.ui.captcha
 | 
			
		||||
import android.webkit.WebView
 | 
			
		||||
import android.webkit.WebViewClient
 | 
			
		||||
 | 
			
		||||
open class BasicWebViewClient(protected val activity: SolveCaptchaActivity,
 | 
			
		||||
                              protected val source: CaptchaCompletionVerifier,
 | 
			
		||||
open class BasicWebViewClient(protected val activity: BrowserActionActivity,
 | 
			
		||||
                              protected val verifyComplete: (String) -> Boolean,
 | 
			
		||||
                              private val injectScript: String?) : WebViewClient() {
 | 
			
		||||
    override fun onPageFinished(view: WebView, url: String) {
 | 
			
		||||
        super.onPageFinished(view, url)
 | 
			
		||||
 | 
			
		||||
        if(source.verifyNoCaptcha(url)) {
 | 
			
		||||
        if(verifyComplete(url)) {
 | 
			
		||||
            activity.finish()
 | 
			
		||||
        } else {
 | 
			
		||||
            if(injectScript != null) view.loadUrl("javascript:(function() {$injectScript})();")
 | 
			
		||||
 
 | 
			
		||||
@@ -31,8 +31,10 @@ import eu.kanade.tachiyomi.source.online.HttpSource
 | 
			
		||||
import exh.source.DelegatedHttpSource
 | 
			
		||||
import exh.util.melt
 | 
			
		||||
import rx.Observable
 | 
			
		||||
import java.io.Serializable
 | 
			
		||||
import kotlin.collections.HashMap
 | 
			
		||||
 | 
			
		||||
class SolveCaptchaActivity : AppCompatActivity() {
 | 
			
		||||
class BrowserActionActivity : AppCompatActivity() {
 | 
			
		||||
    private val sourceManager: SourceManager by injectLazy()
 | 
			
		||||
    private val preferencesHelper: PreferencesHelper by injectLazy()
 | 
			
		||||
    private val networkHelper: NetworkHelper by injectLazy()
 | 
			
		||||
@@ -54,31 +56,38 @@ class SolveCaptchaActivity : AppCompatActivity() {
 | 
			
		||||
        val sourceId = intent.getLongExtra(SOURCE_ID_EXTRA, -1)
 | 
			
		||||
        val originalSource = if(sourceId != -1L) sourceManager.get(sourceId) else null
 | 
			
		||||
        val source = if(originalSource != null) {
 | 
			
		||||
            originalSource as? CaptchaCompletionVerifier
 | 
			
		||||
            originalSource as? ActionCompletionVerifier
 | 
			
		||||
                    ?: run {
 | 
			
		||||
                        (originalSource as? HttpSource)?.let {
 | 
			
		||||
                            NoopCaptchaCompletionVerifier(it)
 | 
			
		||||
                            NoopActionCompletionVerifier(it)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
        } else null
 | 
			
		||||
 | 
			
		||||
        val headers = (source as? HttpSource)?.headers?.toMultimap()?.mapValues {
 | 
			
		||||
        val headers = ((source as? HttpSource)?.headers?.toMultimap()?.mapValues {
 | 
			
		||||
            it.value.joinToString(",")
 | 
			
		||||
        } ?: emptyMap()
 | 
			
		||||
        } ?: emptyMap()) + (intent.getSerializableExtra(HEADERS_EXTRA) as? HashMap<String, String> ?: emptyMap())
 | 
			
		||||
 | 
			
		||||
        val cookies: HashMap<String, String>?
 | 
			
		||||
                = intent.getSerializableExtra(COOKIES_EXTRA) as? HashMap<String, String>
 | 
			
		||||
 | 
			
		||||
        val script: String? = intent.getStringExtra(SCRIPT_EXTRA)
 | 
			
		||||
 | 
			
		||||
        val url: String? = intent.getStringExtra(URL_EXTRA)
 | 
			
		||||
        val actionName = intent.getStringExtra(ACTION_NAME_EXTRA)
 | 
			
		||||
 | 
			
		||||
        if(source == null || url == null) {
 | 
			
		||||
        val verifyComplete = if(source != null) {
 | 
			
		||||
            source::verifyComplete!!
 | 
			
		||||
        } else intent.getSerializableExtra(VERIFY_LAMBDA_EXTRA) as? (String) -> Boolean
 | 
			
		||||
 | 
			
		||||
        if(verifyComplete == null || url == null) {
 | 
			
		||||
            finish()
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        toolbar.title = source.name + ": Solve captcha"
 | 
			
		||||
        val actionStr = actionName ?: "Solve captcha"
 | 
			
		||||
 | 
			
		||||
        toolbar.title = if(source != null) {
 | 
			
		||||
            "${source.name}: $actionStr"
 | 
			
		||||
        } else actionStr
 | 
			
		||||
 | 
			
		||||
        val parsedUrl = URL(url)
 | 
			
		||||
 | 
			
		||||
@@ -94,6 +103,9 @@ class SolveCaptchaActivity : AppCompatActivity() {
 | 
			
		||||
 | 
			
		||||
        webview.settings.javaScriptEnabled = true
 | 
			
		||||
        webview.settings.domStorageEnabled = true
 | 
			
		||||
        headers.entries.find { it.key.equals("user-agent", true) }?.let {
 | 
			
		||||
            webview.settings.userAgentString = it.value
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var loadedInners = 0
 | 
			
		||||
 | 
			
		||||
@@ -125,7 +137,7 @@ class SolveCaptchaActivity : AppCompatActivity() {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        webview.webViewClient = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
 | 
			
		||||
            if(preferencesHelper.eh_autoSolveCaptchas().getOrDefault()) {
 | 
			
		||||
            if(actionName == null && preferencesHelper.eh_autoSolveCaptchas().getOrDefault()) {
 | 
			
		||||
                // Fetch auto-solve credentials early for speed
 | 
			
		||||
                credentialsObservable = httpClient.newCall(Request.Builder()
 | 
			
		||||
                        // Rob demo credentials
 | 
			
		||||
@@ -139,13 +151,13 @@ class SolveCaptchaActivity : AppCompatActivity() {
 | 
			
		||||
                            json["token"].string
 | 
			
		||||
                        }.melt()
 | 
			
		||||
 | 
			
		||||
                webview.addJavascriptInterface(this@SolveCaptchaActivity, "exh")
 | 
			
		||||
                AutoSolvingWebViewClient(this, source, script, headers)
 | 
			
		||||
                webview.addJavascriptInterface(this@BrowserActionActivity, "exh")
 | 
			
		||||
                AutoSolvingWebViewClient(this, verifyComplete, script, headers)
 | 
			
		||||
            } else {
 | 
			
		||||
                HeadersInjectingWebViewClient(this, source, script, headers)
 | 
			
		||||
                HeadersInjectingWebViewClient(this, verifyComplete, script, headers)
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            BasicWebViewClient(this, source, script)
 | 
			
		||||
            BasicWebViewClient(this, verifyComplete, script)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        webview.loadUrl(url, headers)
 | 
			
		||||
@@ -490,11 +502,14 @@ class SolveCaptchaActivity : AppCompatActivity() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val VERIFY_LAMBDA_EXTRA = "verify_lambda_extra"
 | 
			
		||||
        const val SOURCE_ID_EXTRA = "source_id_extra"
 | 
			
		||||
        const val COOKIES_EXTRA = "cookies_extra"
 | 
			
		||||
        const val SCRIPT_EXTRA = "script_extra"
 | 
			
		||||
        const val URL_EXTRA = "url_extra"
 | 
			
		||||
        const val ASBTN_EXTRA = "asbtn_extra"
 | 
			
		||||
        const val ACTION_NAME_EXTRA = "action_name_extra"
 | 
			
		||||
        const val HEADERS_EXTRA = "headers_extra"
 | 
			
		||||
 | 
			
		||||
        const val STAGE_CHECKBOX = 0
 | 
			
		||||
        const val STAGE_GET_AUDIO_BTN_LOCATION = 1
 | 
			
		||||
@@ -600,13 +615,13 @@ class SolveCaptchaActivity : AppCompatActivity() {
 | 
			
		||||
        val TRANSCRIPT_CLEANER_REGEX = Regex("[^0-9a-zA-Z_ -]")
 | 
			
		||||
        val SPACE_DEDUPE_REGEX = Regex(" +")
 | 
			
		||||
 | 
			
		||||
        fun launch(context: Context,
 | 
			
		||||
                   source: CaptchaCompletionVerifier,
 | 
			
		||||
                   cookies: Map<String, String>,
 | 
			
		||||
                   script: String,
 | 
			
		||||
                   url: String,
 | 
			
		||||
                   autoSolveSubmitBtnSelector: String? = null) {
 | 
			
		||||
            val intent = Intent(context, SolveCaptchaActivity::class.java).apply {
 | 
			
		||||
        fun launchCaptcha(context: Context,
 | 
			
		||||
                          source: ActionCompletionVerifier,
 | 
			
		||||
                          cookies: Map<String, String>,
 | 
			
		||||
                          script: String?,
 | 
			
		||||
                          url: String,
 | 
			
		||||
                          autoSolveSubmitBtnSelector: String? = null) {
 | 
			
		||||
            val intent = Intent(context, BrowserActionActivity::class.java).apply {
 | 
			
		||||
                putExtra(SOURCE_ID_EXTRA, source.id)
 | 
			
		||||
                putExtra(COOKIES_EXTRA, HashMap(cookies))
 | 
			
		||||
                putExtra(SCRIPT_EXTRA, script)
 | 
			
		||||
@@ -620,25 +635,57 @@ class SolveCaptchaActivity : AppCompatActivity() {
 | 
			
		||||
        fun launchUniversal(context: Context,
 | 
			
		||||
                            source: HttpSource,
 | 
			
		||||
                            url: String) {
 | 
			
		||||
            val intent = Intent(context, SolveCaptchaActivity::class.java).apply {
 | 
			
		||||
            val intent = Intent(context, BrowserActionActivity::class.java).apply {
 | 
			
		||||
                putExtra(SOURCE_ID_EXTRA, source.id)
 | 
			
		||||
                putExtra(URL_EXTRA, url)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            context.startActivity(intent)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun launchAction(context: Context,
 | 
			
		||||
                         completionVerifier: ActionCompletionVerifier,
 | 
			
		||||
                         script: String?,
 | 
			
		||||
                         url: String,
 | 
			
		||||
                         actionName: String) {
 | 
			
		||||
            val intent = Intent(context, BrowserActionActivity::class.java).apply {
 | 
			
		||||
                putExtra(SOURCE_ID_EXTRA, completionVerifier.id)
 | 
			
		||||
                putExtra(SCRIPT_EXTRA, script)
 | 
			
		||||
                putExtra(URL_EXTRA, url)
 | 
			
		||||
                putExtra(ACTION_NAME_EXTRA, actionName)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            context.startActivity(intent)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun launchAction(context: Context,
 | 
			
		||||
                         completionVerifier: (String) -> Boolean,
 | 
			
		||||
                         script: String?,
 | 
			
		||||
                         url: String,
 | 
			
		||||
                         actionName: String,
 | 
			
		||||
                         headers: Map<String, String>? = emptyMap()) {
 | 
			
		||||
            val intent = Intent(context, BrowserActionActivity::class.java).apply {
 | 
			
		||||
                putExtra(HEADERS_EXTRA, HashMap(headers))
 | 
			
		||||
                putExtra(VERIFY_LAMBDA_EXTRA, completionVerifier as Serializable)
 | 
			
		||||
                putExtra(SCRIPT_EXTRA, script)
 | 
			
		||||
                putExtra(URL_EXTRA, url)
 | 
			
		||||
                putExtra(ACTION_NAME_EXTRA, actionName)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            context.startActivity(intent)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class NoopCaptchaCompletionVerifier(private val source: HttpSource): DelegatedHttpSource(source),
 | 
			
		||||
        CaptchaCompletionVerifier {
 | 
			
		||||
class NoopActionCompletionVerifier(private val source: HttpSource): DelegatedHttpSource(source),
 | 
			
		||||
        ActionCompletionVerifier {
 | 
			
		||||
    override val versionId get() = source.versionId
 | 
			
		||||
    override val lang: String get() = source.lang
 | 
			
		||||
 | 
			
		||||
    override fun verifyNoCaptcha(url: String) = false
 | 
			
		||||
    override fun verifyComplete(url: String) = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface CaptchaCompletionVerifier : Source {
 | 
			
		||||
    fun verifyNoCaptcha(url: String): Boolean
 | 
			
		||||
interface ActionCompletionVerifier : Source {
 | 
			
		||||
    fun verifyComplete(url: String): Boolean
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -7,11 +7,11 @@ import android.webkit.WebResourceResponse
 | 
			
		||||
import android.webkit.WebView
 | 
			
		||||
 | 
			
		||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
 | 
			
		||||
open class HeadersInjectingWebViewClient(activity: SolveCaptchaActivity,
 | 
			
		||||
                                         source: CaptchaCompletionVerifier,
 | 
			
		||||
open class HeadersInjectingWebViewClient(activity: BrowserActionActivity,
 | 
			
		||||
                                         verifyComplete: (String) -> Boolean,
 | 
			
		||||
                                         injectScript: String?,
 | 
			
		||||
                                         private val headers: Map<String, String>)
 | 
			
		||||
    : BasicWebViewClient(activity, source, injectScript) {
 | 
			
		||||
    : BasicWebViewClient(activity, verifyComplete, injectScript) {
 | 
			
		||||
 | 
			
		||||
    override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
 | 
			
		||||
        // Temp disabled as it's unreliable
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										31
									
								
								app/src/main/java/exh/util/OkHttpUtil.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								app/src/main/java/exh/util/OkHttpUtil.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
package exh.util
 | 
			
		||||
 | 
			
		||||
import com.elvishew.xlog.XLog
 | 
			
		||||
import eu.kanade.tachiyomi.util.asJsoup
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
import okhttp3.ResponseBody
 | 
			
		||||
import org.jsoup.nodes.Document
 | 
			
		||||
 | 
			
		||||
fun Response.interceptAsHtml(block: (Document) -> Unit): Response {
 | 
			
		||||
    val body = body()
 | 
			
		||||
    if(body != null) {
 | 
			
		||||
        if (body.contentType()?.type() == "text"
 | 
			
		||||
                && body.contentType()?.subtype() == "html") {
 | 
			
		||||
            val bodyString = body.string()
 | 
			
		||||
            val rebuiltResponse = newBuilder()
 | 
			
		||||
                    .body(ResponseBody.create(body.contentType(), bodyString))
 | 
			
		||||
                    .build()
 | 
			
		||||
            try {
 | 
			
		||||
                // Search for captcha
 | 
			
		||||
                val parsed = asJsoup(html = bodyString)
 | 
			
		||||
                block(parsed)
 | 
			
		||||
            } catch (t: Throwable) {
 | 
			
		||||
                // Ignore all errors
 | 
			
		||||
                XLog.w("Interception error!", t)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return rebuiltResponse
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return this
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user