diff --git a/src/en/yakshascans/build.gradle b/src/en/yakshascans/build.gradle index 9f61feb28..20b668659 100644 --- a/src/en/yakshascans/build.gradle +++ b/src/en/yakshascans/build.gradle @@ -3,7 +3,7 @@ ext { extClass = '.YakshaScans' themePkg = 'madara' baseUrl = 'https://yakshascans.com' - overrideVersionCode = 0 + overrideVersionCode = 1 isNsfw = true } diff --git a/src/en/yakshascans/src/eu/kanade/tachiyomi/extension/en/yakshascans/YakshaScans.kt b/src/en/yakshascans/src/eu/kanade/tachiyomi/extension/en/yakshascans/YakshaScans.kt index 00dfe18d7..d712f79e4 100644 --- a/src/en/yakshascans/src/eu/kanade/tachiyomi/extension/en/yakshascans/YakshaScans.kt +++ b/src/en/yakshascans/src/eu/kanade/tachiyomi/extension/en/yakshascans/YakshaScans.kt @@ -1,8 +1,15 @@ package eu.kanade.tachiyomi.extension.en.yakshascans import eu.kanade.tachiyomi.multisrc.madara.Madara +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.interceptor.rateLimit +import okhttp3.FormBody +import okhttp3.Interceptor import okhttp3.OkHttpClient +import okhttp3.Response +import java.io.IOException +import java.security.MessageDigest class YakshaScans : Madara( "YakshaScans", @@ -12,8 +19,45 @@ class YakshaScans : Madara( override val client: OkHttpClient = super.client.newBuilder() .rateLimit(1) + .addInterceptor(::jsChallengeInterceptor) .build() + private fun jsChallengeInterceptor(chain: Interceptor.Chain): Response { + val request = chain.request() + val origRes = chain.proceed(request) + if (origRes.code != 403) return origRes + origRes.close() + + // Same delay as the source + Thread.sleep(3000L) + val token = fetchToken(chain).sha256() + + val body = FormBody.Builder().add("challenge", token).build() + val challengeReq = POST("$baseUrl/hcdn-cgi/jschallenge-validate", headers, body = body) + + val challengeResponse = chain.proceed(challengeReq) + challengeResponse.close() + if (challengeResponse.code != 200) throw IOException("Failed to bypass js challenge!") + + return chain.proceed(request) + } + + private tailrec fun fetchToken(chain: Interceptor.Chain, attempt: Int = 0): String { + if (attempt > 5) throw IOException("Failed to fetch challenge token!") + val request = GET("$baseUrl/hcdn-cgi/jschallenge", headers) + val res = chain.proceed(request).body.string() + + return res.substringAfter("cjs = '").substringBefore("'") + .takeUnless { it == "nil" } ?: fetchToken(chain, attempt + 1) + } + + private fun String.sha256(): String { + return MessageDigest + .getInstance("SHA-256") + .digest(toByteArray()) + .fold("", { str, it -> str + "%02x".format(it) }) + } + override val useNewChapterEndpoint = true override val mangaDetailsSelectorDescription: String =