Overhaul 2025 (See PR for changes)

This commit is contained in:
Mio.
2025-06-27 23:44:38 +02:00
parent c52d8831aa
commit 965c2a4f43
81 changed files with 4404 additions and 2086 deletions

View File

@@ -0,0 +1,45 @@
package eu.kanade.tachiyomi.multisrc.gmanga
import android.util.Base64
import java.security.MessageDigest
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
fun decrypt(responseData: String): String {
val enc = responseData.split("|")
val secretKey = enc[3].sha256().hexStringToByteArray()
return enc[0].aesDecrypt(secretKey, enc[2])
}
private fun String.hexStringToByteArray(): ByteArray {
val len = length
val data = ByteArray(len / 2)
var i = 0
while (i < len) {
data[i / 2] = (
(Character.digit(this[i], 16) shl 4) +
Character.digit(this[i + 1], 16)
).toByte()
i += 2
}
return data
}
private fun String.sha256(): String {
return MessageDigest
.getInstance("SHA-256")
.digest(toByteArray())
.fold("") { str, it -> str + "%02x".format(it) }
}
private fun String.aesDecrypt(secretKey: ByteArray, ivString: String): String {
val c = Cipher.getInstance("AES/CBC/PKCS5Padding")
val sk = SecretKeySpec(secretKey, "AES")
val iv = IvParameterSpec(Base64.decode(ivString.toByteArray(Charsets.UTF_8), Base64.DEFAULT))
c.init(Cipher.DECRYPT_MODE, sk, iv)
val byteStr = Base64.decode(toByteArray(Charsets.UTF_8), Base64.DEFAULT)
return String(c.doFinal(byteStr))
}

View File

@@ -0,0 +1,41 @@
package eu.kanade.tachiyomi.multisrc.mangaworld
import eu.kanade.tachiyomi.network.GET
import okhttp3.Cookie
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
class CookieRedirectInterceptor(private val client: OkHttpClient) : Interceptor {
private val cookieRegex = Regex("""document\.cookie="(MWCookie[^"]+)""")
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val response = chain.proceed(request)
val contentType = response.header("content-type")
if (contentType != null && contentType.startsWith("image/", ignoreCase = true)) {
return response
}
// ignore requests that already have completed the JS challenge
if (response.headers["vary"] != null) return response
val content = response.body.string()
val results = cookieRegex.find(content)
?: return response.newBuilder().body(content.toResponseBody(response.body.contentType())).build()
val (cookieString) = results.destructured
return chain.proceed(loadCookie(request, cookieString))
}
private fun loadCookie(request: Request, cookieString: String): Request {
val cookie = Cookie.parse(request.url, cookieString)!!
client.cookieJar.saveFromResponse(request.url, listOf(cookie))
val headers = request.headers.newBuilder()
.add("Cookie", cookie.toString())
.build()
return GET(request.url, headers)
}
}