diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8d325e744..4e890e170 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -219,7 +219,7 @@
diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt
index 482fe202b..69fa75e7d 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.network
import android.content.Context
import android.os.Build
import exh.log.maybeInjectEHLogger
+import exh.patch.attachMangaDexLogin
import okhttp3.*
import java.io.File
import java.io.IOException
@@ -14,23 +15,24 @@ import java.security.KeyStore
import java.security.NoSuchAlgorithmException
import javax.net.ssl.*
-class NetworkHelper(context: Context) {
+open class NetworkHelper(context: Context) {
private val cacheDir = File(context.cacheDir, "network_cache")
private val cacheSize = 5L * 1024 * 1024 // 5 MiB
- val cookieManager = AndroidCookieJar(context)
+ open val cookieManager = AndroidCookieJar(context)
- val client = OkHttpClient.Builder()
+ open val client = OkHttpClient.Builder()
.cookieJar(cookieManager)
.cache(Cache(cacheDir, cacheSize))
.enableTLS12()
.maybeInjectEHLogger()
.build()
- val cloudflareClient = client.newBuilder()
+ open val cloudflareClient = client.newBuilder()
.addInterceptor(CloudflareInterceptor(context))
+ .attachMangaDexLogin()
.build()
private fun OkHttpClient.Builder.enableTLS12(): OkHttpClient.Builder {
diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt b/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt
index 6bb544ffb..0f58f4dc9 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt
@@ -24,7 +24,6 @@ import exh.metadata.metadata.PervEdenLang
import exh.source.BlacklistedSources
import exh.source.DelegatedHttpSource
import exh.source.EnhancedHttpSource
-import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import kotlin.reflect.KClass
diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt
index 2c503b5f5..cf7df3608 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt
@@ -1,15 +1,14 @@
package eu.kanade.tachiyomi.source.online
import android.app.Application
-import com.elvishew.xlog.XLog
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.network.NetworkHelper
-import eu.kanade.tachiyomi.network.asObservableSuccess
-import eu.kanade.tachiyomi.network.newCallWithProgress
+import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.data.preference.getOrDefault
+import eu.kanade.tachiyomi.network.*
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.model.*
-import eu.kanade.tachiyomi.util.asJsoup
-import exh.ui.captcha.SolveCaptchaActivity
+import exh.source.DelegatedHttpSource
+import exh.ui.captcha.BrowserActionActivity
+import exh.util.interceptAsHtml
import okhttp3.*
import rx.Observable
import uy.kohesive.injekt.Injekt
@@ -28,7 +27,19 @@ abstract class HttpSource : CatalogueSource {
/**
* Network service.
*/
- protected val network: NetworkHelper by injectLazy()
+ protected val network: NetworkHelper by lazy {
+ val original = Injekt.get()
+ object : NetworkHelper(Injekt.get()) {
+ override val client: OkHttpClient?
+ get() = delegate?.networkHttpClient ?: original.client
+
+ override val cloudflareClient: OkHttpClient?
+ get() = delegate?.networkCloudflareClient ?: original.cloudflareClient
+
+ override val cookieManager: AndroidCookieJar
+ get() = original.cookieManager
+ }
+ }
// /**
// * Preferences that a source may need.
@@ -68,36 +79,21 @@ abstract class HttpSource : CatalogueSource {
* Default network client for doing requests.
*/
open val client: OkHttpClient
- get() = network.client.newBuilder().addInterceptor { chain ->
+ get() = delegate?.baseHttpClient ?: network.client.newBuilder().addInterceptor { chain ->
+ // Automatic captcha detection
val response = chain.proceed(chain.request())
- val body = response.body()
- if(!response.isSuccessful && body != null) {
- if(body.contentType()?.type() == "text"
- && body.contentType()?.subtype() == "html") {
- val bodyString = body.string()
- val rebuiltResponse = response.newBuilder()
- .body(ResponseBody.create(body.contentType(), bodyString))
- .build()
- try {
- // Search for captcha
- val parsed = response.asJsoup(html = bodyString)
- if(parsed.getElementsByClass("g-recaptcha").isNotEmpty()) {
- // Found it, allow the user to solve this thing
- SolveCaptchaActivity.launchUniversal(
- Injekt.get(),
- this,
- chain.request().url().toString()
- )
- }
- } catch(t: Throwable) {
- // Ignore all errors
- XLog.w("Captcha detection error!", t)
+ if(!response.isSuccessful) {
+ response.interceptAsHtml { doc ->
+ if (doc.getElementsByClass("g-recaptcha").isNotEmpty()) {
+ // Found it, allow the user to solve this thing
+ BrowserActionActivity.launchUniversal(
+ Injekt.get(),
+ this,
+ chain.request().url().toString()
+ )
}
-
- return@addInterceptor rebuiltResponse
}
- }
- response
+ } else response
}.build()
/**
@@ -397,4 +393,14 @@ abstract class HttpSource : CatalogueSource {
* Returns the list of filters for the source.
*/
override fun getFilterList() = FilterList()
+
+ // EXH -->
+ private var delegate: DelegatedHttpSource? = null
+ get() = if(Injekt.get().eh_delegateSources().getOrDefault())
+ field
+ else null
+ fun bindDelegate(delegate: DelegatedHttpSource) {
+ this.delegate = delegate
+ }
+ // EXH <--
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt
index 960bd0871..4172ba7b5 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt
@@ -16,8 +16,8 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.toast
import exh.TSUMINO_SOURCE_ID
-import exh.ui.captcha.CaptchaCompletionVerifier
-import exh.ui.captcha.SolveCaptchaActivity
+import exh.ui.captcha.ActionCompletionVerifier
+import exh.ui.captcha.BrowserActionActivity
import exh.metadata.metadata.TsuminoSearchMetadata
import exh.metadata.metadata.TsuminoSearchMetadata.Companion.BASE_URL
import exh.metadata.metadata.TsuminoSearchMetadata.Companion.TAG_TYPE_DEFAULT
@@ -33,7 +33,7 @@ import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
import java.util.*
-class Tsumino(private val context: Context): ParsedHttpSource(), LewdSource, CaptchaCompletionVerifier {
+class Tsumino(private val context: Context): ParsedHttpSource(), LewdSource, ActionCompletionVerifier {
override val metaClass = TsuminoSearchMetadata::class
private val preferences: PreferencesHelper by injectLazy()
@@ -343,7 +343,7 @@ class Tsumino(private val context: Context): ParsedHttpSource(), LewdSource
+ 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(),
+ ::verifyComplete,
+ HIDE_SCRIPT,
+ "https://mangadex.org/login",
+ "Login",
+ (Injekt.get().get(2499283573021220255) as? HttpSource)?.headers?.toMultimap()?.mapValues {
+ it.value.joinToString(",")
+ } ?: emptyMap()
+ )
+ }
+ }
+ } else response
+ }
diff --git a/app/src/main/java/exh/source/DelegatedHttpSource.kt b/app/src/main/java/exh/source/DelegatedHttpSource.kt
index f306f4c5e..b5743537e 100644
--- a/app/src/main/java/exh/source/DelegatedHttpSource.kt
+++ b/app/src/main/java/exh/source/DelegatedHttpSource.kt
@@ -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)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/exh/source/EnhancedHttpSource.kt b/app/src/main/java/exh/source/EnhancedHttpSource.kt
index 7738ab801..d556cba50 100644
--- a/app/src/main/java/exh/source/EnhancedHttpSource.kt
+++ b/app/src/main/java/exh/source/EnhancedHttpSource.kt
@@ -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.
diff --git a/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt b/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt
index 4dcf50279..f0a6acea1 100644
--- a/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt
+++ b/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt
@@ -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)
- : 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
diff --git a/app/src/main/java/exh/ui/captcha/BasicWebViewClient.kt b/app/src/main/java/exh/ui/captcha/BasicWebViewClient.kt
index c791ecfd0..c2ba8eba1 100644
--- a/app/src/main/java/exh/ui/captcha/BasicWebViewClient.kt
+++ b/app/src/main/java/exh/ui/captcha/BasicWebViewClient.kt
@@ -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})();")
diff --git a/app/src/main/java/exh/ui/captcha/SolveCaptchaActivity.kt b/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt
similarity index 86%
rename from app/src/main/java/exh/ui/captcha/SolveCaptchaActivity.kt
rename to app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt
index 42f7d30b4..d328b6ed7 100644
--- a/app/src/main/java/exh/ui/captcha/SolveCaptchaActivity.kt
+++ b/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt
@@ -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 ?: emptyMap())
val cookies: HashMap?
= intent.getSerializableExtra(COOKIES_EXTRA) as? HashMap
-
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,
- script: String,
- url: String,
- autoSolveSubmitBtnSelector: String? = null) {
- val intent = Intent(context, SolveCaptchaActivity::class.java).apply {
+ fun launchCaptcha(context: Context,
+ source: ActionCompletionVerifier,
+ cookies: Map,
+ 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? = 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
}
diff --git a/app/src/main/java/exh/ui/captcha/HeadersInjectingWebViewClient.kt b/app/src/main/java/exh/ui/captcha/HeadersInjectingWebViewClient.kt
index a66f68c8f..5938543d5 100644
--- a/app/src/main/java/exh/ui/captcha/HeadersInjectingWebViewClient.kt
+++ b/app/src/main/java/exh/ui/captcha/HeadersInjectingWebViewClient.kt
@@ -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)
- : BasicWebViewClient(activity, source, injectScript) {
+ : BasicWebViewClient(activity, verifyComplete, injectScript) {
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
// Temp disabled as it's unreliable
diff --git a/app/src/main/java/exh/util/OkHttpUtil.kt b/app/src/main/java/exh/util/OkHttpUtil.kt
new file mode 100644
index 000000000..bdafb258f
--- /dev/null
+++ b/app/src/main/java/exh/util/OkHttpUtil.kt
@@ -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
+}
\ No newline at end of file