From 10a45da680d05613519fd66ee839be01a2e0f34e Mon Sep 17 00:00:00 2001 From: Vetle Ledaal Date: Sat, 2 Dec 2023 15:41:35 +0000 Subject: [PATCH] A3Manga: decrypt page URLs for whole multisrc, update domains (#19160) A3Manga: decrypt page URLs for whole multisrc --- .../overrides/a3manga/ocumeo/src/OCuMeo.kt | 52 ------------------- .../tachiyomi/multisrc/a3manga/A3Manga.kt | 38 +++++++++++++- .../multisrc/a3manga/A3MangaGenerator.kt | 6 +-- 3 files changed, 39 insertions(+), 57 deletions(-) delete mode 100644 multisrc/overrides/a3manga/ocumeo/src/OCuMeo.kt diff --git a/multisrc/overrides/a3manga/ocumeo/src/OCuMeo.kt b/multisrc/overrides/a3manga/ocumeo/src/OCuMeo.kt deleted file mode 100644 index 8a56b9897..000000000 --- a/multisrc/overrides/a3manga/ocumeo/src/OCuMeo.kt +++ /dev/null @@ -1,52 +0,0 @@ -package eu.kanade.tachiyomi.extension.vi.ocumeo - -import eu.kanade.tachiyomi.multisrc.a3manga.A3Manga -import eu.kanade.tachiyomi.source.model.Page -import org.jsoup.Jsoup -import org.jsoup.nodes.Document - -class OCuMeo : A3Manga("Ổ Cú Mèo", "https://www.ocumoe.com", "vi") { - - override fun pageListParse(document: Document): List { - val imgListHtml = decodeImgList(document) - - return Jsoup.parseBodyFragment(imgListHtml).select("img").mapIndexed { idx, element -> - val encryptedUrl = element.attributes().find { it.key.startsWith("data") }?.value - Page(idx, imageUrl = encryptedUrl?.decodeUrl()) - } - } - - private fun String.decodeUrl(): String { - // We expect the URL to start with `https://`, where the last 3 characters are encoded. - // The length of the encoded character is not known, but it is the same across all. - // Essentially we are looking for the two encoded slashes, which tells us the length. - val patternIdx = patternsLengthCheck.indexOfFirst { pattern -> - val matchResult = pattern.find(this) - val g1 = matchResult?.groupValues?.get(1) - val g2 = matchResult?.groupValues?.get(2) - g1 == g2 && g1 != null - } - if (patternIdx == -1) { - throw Exception("Failed to decrypt URL") - } - - // With a known length we can predict all the encoded characters. - // This is a slightly more expensive pattern, hence the separation. - val matchResult = patternsSubstitution[patternIdx].find(this) - return matchResult?.destructured?.let { (colon, slash, period) -> - this - .replace(colon, ":") - .replace(slash, "/") - .replace(period, ".") - } ?: throw Exception("Failed to reconstruct URL") - } - - companion object { - private val patternsLengthCheck: List = (20 downTo 1).map { i -> - """^https.{$i}(.{$i})(.{$i})""".toRegex() - } - private val patternsSubstitution: List = (20 downTo 1).map { i -> - """^https(.{$i})(.{$i}).*(.{$i})(?:webp|jpeg|tiff|.{3})$""".toRegex() - } - } -} diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3Manga.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3Manga.kt index 79d7d3802..daf21dd05 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3Manga.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3Manga.kt @@ -181,8 +181,35 @@ open class A3Manga( override fun pageListParse(document: Document): List { val imgListHtml = decodeImgList(document) - return Jsoup.parseBodyFragment(imgListHtml).select("img").mapIndexed { idx, it -> - Page(idx, imageUrl = it.attr("abs:src")) + return Jsoup.parseBodyFragment(imgListHtml).select("img").mapIndexed { idx, element -> + val encryptedUrl = element.attributes().find { it.key.startsWith("data") }?.value + val effectiveUrl = encryptedUrl?.decodeUrl() ?: element.attr("abs:src") + Page(idx, imageUrl = effectiveUrl) + } + } + + private fun String.decodeUrl(): String? { + // We expect the URL to start with `https://`, where the last 3 characters are encoded. + // The length of the encoded character is not known, but it is the same across all. + // Essentially we are looking for the two encoded slashes, which tells us the length. + val patternIdx = patternsLengthCheck.indexOfFirst { pattern -> + val matchResult = pattern.find(this) + val g1 = matchResult?.groupValues?.get(1) + val g2 = matchResult?.groupValues?.get(2) + g1 == g2 && g1 != null + } + if (patternIdx == -1) { + return null + } + + // With a known length we can predict all the encoded characters. + // This is a slightly more expensive pattern, hence the separation. + val matchResult = patternsSubstitution[patternIdx].find(this) + return matchResult?.destructured?.let { (colon, slash, period) -> + this + .replace(colon, ":") + .replace(slash, "/") + .replace(period, ".") } } @@ -209,5 +236,12 @@ open class A3Manga( val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.US).apply { timeZone = TimeZone.getTimeZone("Asia/Ho_Chi_Minh") } + + private val patternsLengthCheck: List = (20 downTo 1).map { i -> + """^https.{$i}(.{$i})(.{$i})""".toRegex() + } + private val patternsSubstitution: List = (20 downTo 1).map { i -> + """^https(.{$i})(.{$i}).*(.{$i})(?:webp|jpeg|tiff|.{3})$""".toRegex() + } } } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaGenerator.kt index 3a1a86ec3..5e7ac5ed4 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaGenerator.kt @@ -9,11 +9,11 @@ class A3MangaGenerator : ThemeSourceGenerator { override val themeClass = "A3Manga" - override val baseVersionCode: Int = 1 + override val baseVersionCode: Int = 2 override val sources = listOf( - SingleLang("A3 Manga", "https://www.a3mnga.com", "vi"), - SingleLang("Team Lanh Lung", "https://teamlanhlung.vip", "vi", sourceName = "Team Lạnh Lùng", overrideVersionCode = 1), + SingleLang("A3 Manga", "https://www.a3manga.info", "vi"), + SingleLang("Team Lanh Lung", "https://teamlanhlung.me", "vi", sourceName = "Team Lạnh Lùng", overrideVersionCode = 1), SingleLang("Ngon Phong", "https://www.ngonphong.com", "vi", sourceName = "Ngôn Phong", overrideVersionCode = 1), SingleLang("O Cu Meo", "https://www.ocumoe.com", "vi", sourceName = "Ổ Cú Mèo", overrideVersionCode = 1), )