MirrorDesu: change domain and decrypt pagelist (#1738)

This commit is contained in:
AwkwardPeak7 2024-03-08 14:59:49 +05:00 committed by Draff
parent 20db7af324
commit 9a7187bf36
2 changed files with 78 additions and 5 deletions

View File

@ -2,9 +2,14 @@ ext {
extName = 'MirrorDesu'
extClass = '.MirrorDesu'
themePkg = 'mangathemesia'
baseUrl = 'https://mirrordesu.me'
overrideVersionCode = 0
baseUrl = 'https://mirrordesu.one'
overrideVersionCode = 1
isNsfw = true
}
apply from: "$rootDir/common.gradle"
dependencies {
implementation(project(":lib:cryptoaes"))
implementation(project(":lib:synchrony"))
}

View File

@ -1,13 +1,81 @@
package eu.kanade.tachiyomi.extension.id.mirrordesu
import android.util.Base64
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES
import eu.kanade.tachiyomi.lib.synchrony.Deobfuscator
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import okhttp3.OkHttpClient
import eu.kanade.tachiyomi.source.model.Page
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import org.jsoup.nodes.Document
class MirrorDesu : MangaThemesia("MirrorDesu", "https://mirrordesu.me", "id", "/komik") {
override val client: OkHttpClient = super.client.newBuilder()
class MirrorDesu : MangaThemesia(
"MirrorDesu",
"https://mirrordesu.one",
"id",
"/komik",
) {
override val client = super.client.newBuilder()
.rateLimit(4)
.build()
override val hasProjectPage = true
override fun pageListParse(document: Document): List<Page> {
val script = document.selectFirst("script:containsData(ts_reader)")?.data()
?: return super.pageListParse(document)
val deobfuscatedScript = Deobfuscator.deobfuscateScript(script)!!
val (dataKey, pwdKey) = obfuscatedNamesRegex.find(deobfuscatedScript)!!
.groupValues.let { it[1] to it[2] }
val encData = deobfuscatedScript.substringAfter(dataKey)
.substringAfter("\'")
.substringBefore("\'")
.let { json.decodeFromString<EncryptedDto>(it) }
val unsaltedCiphertext = Base64.decode(encData.cipherText, Base64.DEFAULT)
val salt = encData.salt.decodeHex()
val ciphertext = Base64.encodeToString(salted + salt + unsaltedCiphertext, Base64.DEFAULT)
val pwd = Regex("""let\s*$pwdKey\s*=\s*'(\w+)'""").find(deobfuscatedScript)!!
.groupValues[1]
val data = CryptoAES.decrypt(ciphertext, pwd)
val tsReader = json.decodeFromString<TSReader>(json.decodeFromString<String>(data))
val imageUrls = tsReader.sources.firstOrNull()?.images ?: return emptyList()
return imageUrls.mapIndexed { index, imageUrl -> Page(index, document.location(), imageUrl) }
}
private fun String.decodeHex(): ByteArray {
check(length % 2 == 0) { "Must have an even length" }
return chunked(2)
.map { it.toInt(16).toByte() }
.toByteArray()
}
private val salted = "Salted__".toByteArray(Charsets.UTF_8)
private val obfuscatedNamesRegex = Regex("""CryptoJSAesJson\.decrypt\(\s*(\w+)\s*,\s*(\w+)\s*\)""")
@Serializable
class EncryptedDto(
@SerialName("ct") val cipherText: String,
@SerialName("s") val salt: String,
)
@Serializable
class TSReader(
val sources: List<ReaderImageSource>,
)
@Serializable
class ReaderImageSource(
val images: List<String>,
)
}