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 24cc485c5..f156e0ead 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -3,10 +3,6 @@ package eu.kanade.tachiyomi.network import android.content.Context import android.os.Build import exh.log.maybeInjectEHLogger -import exh.patch.MANGADEX_DOMAIN -import exh.patch.MANGADEX_SOURCE_ID -import exh.patch.attachMangaDexLogin -import exh.patch.detectCaptchas import okhttp3.* import java.io.File import java.io.IOException @@ -35,8 +31,7 @@ open class NetworkHelper(context: Context) { open val cloudflareClient = client.newBuilder() .addInterceptor(CloudflareInterceptor(context)) - .attachMangaDexLogin() - .detectCaptchas(context, MANGADEX_SOURCE_ID, listOf(MANGADEX_DOMAIN)) + .maybeInjectEHLogger() .build() private fun OkHttpClient.Builder.enableTLS12(): OkHttpClient.Builder { 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 900b3e635..46e6d8357 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 @@ -6,13 +6,12 @@ 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 exh.patch.detectCaptchas +import exh.patch.injectPatches import exh.source.DelegatedHttpSource import okhttp3.* import rx.Observable import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -import uy.kohesive.injekt.injectLazy import java.lang.Exception import java.net.URI import java.net.URISyntaxException @@ -31,9 +30,15 @@ abstract class HttpSource : CatalogueSource { object : NetworkHelper(Injekt.get()) { override val client: OkHttpClient? get() = delegate?.networkHttpClient ?: original.client + .newBuilder() + .injectPatches { id } + .build() override val cloudflareClient: OkHttpClient? get() = delegate?.networkCloudflareClient ?: original.cloudflareClient + .newBuilder() + .injectPatches { id } + .build() override val cookieManager: AndroidCookieJar get() = original.cookieManager @@ -79,9 +84,6 @@ abstract class HttpSource : CatalogueSource { */ open val client: OkHttpClient get() = delegate?.baseHttpClient ?: network.client - .newBuilder() - .detectCaptchas(Injekt.get(), id, null) - .build() /** * Headers builder for requests. Implementations can override this method for custom headers. diff --git a/app/src/main/java/exh/patch/MangaDexLogin.kt b/app/src/main/java/exh/patch/MangaDexLogin.kt index 9092b6e67..38f349887 100644 --- a/app/src/main/java/exh/patch/MangaDexLogin.kt +++ b/app/src/main/java/exh/patch/MangaDexLogin.kt @@ -24,26 +24,63 @@ private fun verifyComplete(url: String): Boolean { } ?: false } -fun OkHttpClient.Builder.attachMangaDexLogin() = - addInterceptor { chain -> - val response = chain.proceed(chain.request()) - if(response.request().url().host() == MANGADEX_DOMAIN) { - 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(MANGADEX_SOURCE_ID) as? HttpSource)?.headers?.toMultimap()?.mapValues { - it.value.joinToString(",") - } ?: emptyMap() - ) - } - } - } else response +val MANGADEX_LOGIN_PATCH: EHInterceptor = { request, response, sourceId -> + if(request.url().host() == MANGADEX_DOMAIN) { + 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(sourceId) as? HttpSource)?.headers?.toMultimap()?.mapValues { + it.value.joinToString(",") + } ?: emptyMap() + ) + } } + } else response +} -const val MANGADEX_SOURCE_ID = 2499283573021220255 +val MANGADEX_SOURCE_IDS = listOf( + 2499283573021220255, + 8033579885162383068, + 1952071260038453057, + 2098905203823335614, + 5098537545549490547, + 4505830566611664829, + 9194073792736219759, + 6400665728063187402, + 4938773340256184018, + 5860541308324630662, + 5189216366882819742, + 2655149515337070132, + 1145824452519314725, + 3846770256925560569, + 3807502156582598786, + 4284949320785450865, + 5463447640980279236, + 8578871918181236609, + 6750440049024086587, + 3339599426223341161, + 5148895169070562838, + 1493666528525752601, + 1713554459881080228, + 4150470519566206911, + 1347402746269051958, + 3578612018159256808, + 425785191804166217, + 8254121249433835847, + 3260701926561129943, + 1411768577036936240, + 3285208643537017688, + 737986167355114438, + 1471784905273036181, + 5967745367608513818, + 3781216447842245147, + 4774459486579224459, + 4710920497926776490, + 5779037855201976894 +) const val MANGADEX_DOMAIN = "mangadex.org" diff --git a/app/src/main/java/exh/patch/NetworkPatches.kt b/app/src/main/java/exh/patch/NetworkPatches.kt new file mode 100644 index 000000000..2b263f97c --- /dev/null +++ b/app/src/main/java/exh/patch/NetworkPatches.kt @@ -0,0 +1,41 @@ +package exh.patch + +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response + +typealias EHInterceptor = (request: Request, response: Response, sourceId: Long) -> Response + +fun OkHttpClient.Builder.injectPatches(sourceIdProducer: () -> Long): OkHttpClient.Builder { + return addInterceptor { chain -> + val req = chain.request() + val response = chain.proceed(req) + val sourceId = sourceIdProducer() + findAndApplyPatches(sourceId)(req, response, sourceId) + } +} + +fun findAndApplyPatches(sourceId: Long): EHInterceptor { + return ((EH_INTERCEPTORS[sourceId] ?: emptyList()) + + (EH_INTERCEPTORS[EH_UNIVERSAL_INTERCEPTOR] ?: emptyList())).merge() +} + +fun List.merge(): EHInterceptor { + return { request, response, sourceId -> + fold(response) { acc, int -> + int(request, acc, sourceId) + } + } +} + +private const val EH_UNIVERSAL_INTERCEPTOR = -1L +private val EH_INTERCEPTORS: Map> = mapOf( + EH_UNIVERSAL_INTERCEPTOR to listOf( + CAPTCHA_DETECTION_PATCH // Auto captcha detection + ), + + // MangaDex login support + *MANGADEX_SOURCE_IDS.map { id -> + id to listOf(MANGADEX_LOGIN_PATCH) + }.toTypedArray() +) diff --git a/app/src/main/java/exh/patch/UniversalCaptchaDetection.kt b/app/src/main/java/exh/patch/UniversalCaptchaDetection.kt index d5a1c8044..9e512b377 100644 --- a/app/src/main/java/exh/patch/UniversalCaptchaDetection.kt +++ b/app/src/main/java/exh/patch/UniversalCaptchaDetection.kt @@ -1,28 +1,23 @@ package exh.patch -import android.content.Context +import android.app.Application import exh.ui.captcha.BrowserActionActivity import exh.util.interceptAsHtml -import okhttp3.OkHttpClient +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get -fun OkHttpClient.Builder.detectCaptchas(context: Context, sourceId: Long, domains: List? = null): OkHttpClient.Builder { - return addInterceptor { chain -> - // Automatic captcha detection - val response = chain.proceed(chain.request()) - if(!response.isSuccessful) { - if(domains != null && response.request().url().host() !in domains) - return@addInterceptor response - - response.interceptAsHtml { doc -> - if (doc.getElementsByClass("g-recaptcha").isNotEmpty()) { - // Found it, allow the user to solve this thing - BrowserActionActivity.launchUniversal( - context, - sourceId, - chain.request().url().toString() - ) - } +val CAPTCHA_DETECTION_PATCH: EHInterceptor = { request, response, sourceId -> + if(!response.isSuccessful) { + response.interceptAsHtml { doc -> + // Find captcha + if (doc.getElementsByClass("g-recaptcha").isNotEmpty()) { + // Found it, allow the user to solve this thing + BrowserActionActivity.launchUniversal( + Injekt.get(), + sourceId, + request.url().toString() + ) } - } else response - } + } + } else response } \ No newline at end of file