From 900a44839d92154afb57399eef5ccfe12557da81 Mon Sep 17 00:00:00 2001 From: Alessandro Jean <14254807+alessandrojean@users.noreply.github.com> Date: Fri, 27 Jan 2023 17:07:36 -0300 Subject: [PATCH] Fix bad URLs and missing pages in SS. (#15149) --- .../madara/sinensis/additional.gradle | 3 + .../madara/sinensis/src/SinensisScan.kt | 63 ++++++++++++++++++- .../multisrc/madara/MadaraGenerator.kt | 2 +- 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 multisrc/overrides/madara/sinensis/additional.gradle diff --git a/multisrc/overrides/madara/sinensis/additional.gradle b/multisrc/overrides/madara/sinensis/additional.gradle new file mode 100644 index 000000000..788ad9de1 --- /dev/null +++ b/multisrc/overrides/madara/sinensis/additional.gradle @@ -0,0 +1,3 @@ +dependencies { + implementation(project(':lib-cryptoaes')) +} diff --git a/multisrc/overrides/madara/sinensis/src/SinensisScan.kt b/multisrc/overrides/madara/sinensis/src/SinensisScan.kt index 47d58b278..a868e56c4 100644 --- a/multisrc/overrides/madara/sinensis/src/SinensisScan.kt +++ b/multisrc/overrides/madara/sinensis/src/SinensisScan.kt @@ -1,10 +1,18 @@ package eu.kanade.tachiyomi.extension.pt.sinensis +import android.util.Base64 +import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES import eu.kanade.tachiyomi.multisrc.madara.Madara import eu.kanade.tachiyomi.network.interceptor.rateLimit +import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonPrimitive +import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient +import org.jsoup.nodes.Document import org.jsoup.nodes.Element import java.text.SimpleDateFormat import java.util.Locale @@ -26,19 +34,68 @@ class SinensisScan : Madara( override fun popularMangaFromElement(element: Element): SManga { return super.popularMangaFromElement(element).apply { - url = url.removePrefix("/home") + setUrlWithoutDomain(url.removeBadPath("manga")) } } override fun searchMangaFromElement(element: Element): SManga { return super.searchMangaFromElement(element).apply { - url = url.removePrefix("/home") + setUrlWithoutDomain(url.removeBadPath("manga")) } } override fun chapterFromElement(element: Element): SChapter { return super.chapterFromElement(element).apply { - url = url.removePrefix("/home") + setUrlWithoutDomain(url.removeBadPath("manga")) } } + + override fun pageListParse(document: Document): List { + val chapterProtector = document.selectFirst("script#chapter-protector-data")?.data() + ?: return super.pageListParse(document) + + val password = chapterProtector + .substringAfter("wpmangaprotectornonce='") + .substringBefore("';") + val chapterData = chapterProtector + .substringAfter("chapter_data='") + .substringBefore("';") + .replace("\\/", "/") + .let { json.decodeFromString>(it) } + + val unsaltedCipherText = Base64.decode(chapterData["ct"]!!, Base64.DEFAULT) + val salt = chapterData["s"]!!.decodeHex() + val cipherText = SALTED + salt + unsaltedCipherText + + val rawImageArray = CryptoAES.decrypt(Base64.encodeToString(cipherText, Base64.DEFAULT), password) + val imageArrayString = json.parseToJsonElement(rawImageArray).jsonPrimitive.content + val imageArray = json.parseToJsonElement(imageArrayString).jsonArray + + return imageArray.mapIndexed { i, jsonElement -> + Page(i, document.location(), jsonElement.jsonPrimitive.content) + } + } + + private fun String.decodeHex(): ByteArray { + check(length % 2 == 0) { "Must have an even length" } + + return chunked(2) + .map { it.toInt(16).toByte() } + .toByteArray() + } + + private fun String.removeBadPath(expectedFirstPath: String): String { + val fullUrl = if (contains(baseUrl)) this else (baseUrl + this) + val url = fullUrl.toHttpUrl() + + if (url.pathSegments.firstOrNull() != expectedFirstPath) { + return url.newBuilder().removePathSegment(0).toString() + } + + return url.toString() + } + + companion object { + val SALTED = "Salted__".toByteArray(Charsets.UTF_8) + } } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt index 5cf41c1b9..78f778393 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt @@ -375,7 +375,7 @@ class MadaraGenerator : ThemeSourceGenerator { SingleLang("Shirai Scans", "https://shiraiscans.com.br", "pt-BR"), SingleLang("Shooting Star Scans", "https://shootingstarscans.com", "en"), SingleLang("ShoujoHearts", "https://shoujohearts.com", "en", overrideVersionCode = 2), - SingleLang("Sinensis Scan", "https://sinensisscans.com", "pt-BR", pkgName = "sinensis", overrideVersionCode = 4), + SingleLang("Sinensis Scan", "https://sinensisscans.com", "pt-BR", pkgName = "sinensis", overrideVersionCode = 5), SingleLang("SISI GELAP", "https://sigel.asia", "id", overrideVersionCode = 4), SingleLang("Siyahmelek", "https://siyahmelek.net", "tr", isNsfw = true, overrideVersionCode = 3), SingleLang("SkyManga.xyz", "https://skymanga.xyz", "en", isNsfw = true, className = "SkyMangaXyz"),