Ổ Cú Mèo: Update domain and decrypt page URLs (#18771)

This commit is contained in:
Vetle Ledaal 2023-10-28 15:45:34 +00:00 committed by GitHub
parent 61274c5aa0
commit 3a5f8c9fd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 2 deletions

View File

@ -0,0 +1,52 @@
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<Page> {
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<Regex> = (20 downTo 1).map { i ->
"""^https.{$i}(.{$i})(.{$i})""".toRegex()
}
private val patternsSubstitution: List<Regex> = (20 downTo 1).map { i ->
"""^https(.{$i})(.{$i}).*(.{$i})(?:webp|jpeg|tiff|.{3})$""".toRegex()
}
}
}

View File

@ -147,7 +147,7 @@ open class A3Manga(
}.getOrNull() ?: 0
}
override fun pageListParse(document: Document): List<Page> {
protected fun decodeImgList(document: Document): String {
val htmlContentScript = document.selectFirst("script:containsData(htmlContent)")?.html()
?.substringAfter("var htmlContent=\"")
?.substringBefore("\";")
@ -175,6 +175,12 @@ open class A3Manga(
val imgListHtml = cipher.doFinal(ciphertext).toString(Charsets.UTF_8)
return imgListHtml
}
override fun pageListParse(document: Document): List<Page> {
val imgListHtml = decodeImgList(document)
return Jsoup.parseBodyFragment(imgListHtml).select("img").mapIndexed { idx, it ->
Page(idx, imageUrl = it.attr("abs:src"))
}

View File

@ -15,7 +15,7 @@ class A3MangaGenerator : ThemeSourceGenerator {
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("Ngon Phong", "https://www.ngonphong.com", "vi", sourceName = "Ngôn Phong", overrideVersionCode = 1),
SingleLang("O Cu Meo", "https://www.ocumeo.com", "vi", sourceName = "Ổ Cú Mèo"),
SingleLang("O Cu Meo", "https://www.ocumoe.com", "vi", sourceName = "Ổ Cú Mèo", overrideVersionCode = 1),
)
companion object {