From 93bc84108c7f146788997e1afdad4182bb45f8d5 Mon Sep 17 00:00:00 2001 From: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com> Date: Thu, 6 Jul 2023 03:30:02 +0500 Subject: [PATCH] Move `wpchapterprotector` logic to Madara base class (#17006) * move wpchapterprotector logic to Madara base class * selectFirst --- .../madara/aiyumanga/src/AiYuManga.kt | 47 -------------- .../overrides/madara/amuy/additional.gradle | 3 - multisrc/overrides/madara/amuy/src/Amuy.kt | 47 -------------- .../madara/cerisescans/additional.gradle | 3 - .../madara/cerisescans/src/CeriseScans.kt | 47 -------------- .../{aiyumanga => default}/additional.gradle | 0 .../madara/leviatanscans/additional.gradle | 3 - .../madara/leviatanscans/src/LeviatanScans.kt | 47 -------------- .../madara/mangacrab/additional.gradle | 3 - .../madara/mangacrab/src/MangaCrab.kt | 54 +--------------- .../madara/manhuasy/additional.gradle | 3 - .../overrides/madara/manhuasy/src/ManhuaSY.kt | 46 -------------- .../madara/manhwalatino/additional.gradle | 3 - .../madara/manhwalatino/src/ManhwaLatino.kt | 55 ---------------- .../madara/sinensis/additional.gradle | 3 - .../madara/sinensis/src/SinensisScan.kt | 45 -------------- .../tachiyomi/multisrc/madara/Madara.kt | 62 ++++++++++++++++--- .../multisrc/madara/MadaraGenerator.kt | 2 +- 18 files changed, 55 insertions(+), 418 deletions(-) delete mode 100644 multisrc/overrides/madara/amuy/additional.gradle delete mode 100644 multisrc/overrides/madara/cerisescans/additional.gradle rename multisrc/overrides/madara/{aiyumanga => default}/additional.gradle (100%) delete mode 100644 multisrc/overrides/madara/leviatanscans/additional.gradle delete mode 100644 multisrc/overrides/madara/mangacrab/additional.gradle delete mode 100644 multisrc/overrides/madara/manhuasy/additional.gradle delete mode 100644 multisrc/overrides/madara/manhwalatino/additional.gradle delete mode 100644 multisrc/overrides/madara/sinensis/additional.gradle diff --git a/multisrc/overrides/madara/aiyumanga/src/AiYuManga.kt b/multisrc/overrides/madara/aiyumanga/src/AiYuManga.kt index d25ff29fe..83ad2347b 100644 --- a/multisrc/overrides/madara/aiyumanga/src/AiYuManga.kt +++ b/multisrc/overrides/madara/aiyumanga/src/AiYuManga.kt @@ -1,13 +1,6 @@ package eu.kanade.tachiyomi.extension.es.aiyumanga -import android.util.Base64 -import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES import eu.kanade.tachiyomi.multisrc.madara.Madara -import eu.kanade.tachiyomi.source.model.Page -import kotlinx.serialization.json.jsonArray -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import org.jsoup.nodes.Document import java.text.SimpleDateFormat import java.util.Locale @@ -21,44 +14,4 @@ class AiYuManga : Madara( override val chapterUrlSuffix = "" override val mangaDetailsSelectorStatus = "div.post-content_item:contains(Status) > div.summary-content" - - override fun pageListParse(document: Document): List { - val chapterProtector = document.getElementById("chapter-protector-data")?.html() - ?: return super.pageListParse(document) - - val password = chapterProtector - .substringAfter("wpmangaprotectornonce='") - .substringBefore("';") - val chapterData = json.parseToJsonElement( - chapterProtector - .substringAfter("chapter_data='") - .substringBefore("';") - .replace("\\/", "/"), - ).jsonObject - - val unsaltedCiphertext = Base64.decode(chapterData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT) - val salt = chapterData["s"]!!.jsonPrimitive.content.decodeHex() - val ciphertext = SALTED + salt + unsaltedCiphertext - - val rawImgArray = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), password) - val imgArrayString = json.parseToJsonElement(rawImgArray).jsonPrimitive.content - val imgArray = json.parseToJsonElement(imgArrayString).jsonArray - - return imgArray.mapIndexed { idx, it -> - Page(idx, document.location(), it.jsonPrimitive.content) - } - } - - // https://stackoverflow.com/a/66614516 - private fun String.decodeHex(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - - return chunked(2) - .map { it.toInt(16).toByte() } - .toByteArray() - } - - companion object { - val SALTED = "Salted__".toByteArray(Charsets.UTF_8) - } } diff --git a/multisrc/overrides/madara/amuy/additional.gradle b/multisrc/overrides/madara/amuy/additional.gradle deleted file mode 100644 index 04805cd35..000000000 --- a/multisrc/overrides/madara/amuy/additional.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - implementation(project(':lib-cryptoaes')) -} diff --git a/multisrc/overrides/madara/amuy/src/Amuy.kt b/multisrc/overrides/madara/amuy/src/Amuy.kt index 802c1fbb1..b73010737 100644 --- a/multisrc/overrides/madara/amuy/src/Amuy.kt +++ b/multisrc/overrides/madara/amuy/src/Amuy.kt @@ -1,15 +1,8 @@ package eu.kanade.tachiyomi.extension.pt.amuy -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 kotlinx.serialization.json.jsonArray -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive import okhttp3.OkHttpClient -import org.jsoup.nodes.Document import java.text.SimpleDateFormat import java.util.Locale import java.util.concurrent.TimeUnit @@ -26,44 +19,4 @@ class Amuy : Madara( .build() override val useNewChapterEndpoint = true - - override fun pageListParse(document: Document): List { - val chapterProtector = document.getElementById("chapter-protector-data")?.html() - ?: return super.pageListParse(document) - - val password = chapterProtector - .substringAfter("wpmangaprotectornonce='") - .substringBefore("';") - val chapterData = json.parseToJsonElement( - chapterProtector - .substringAfter("chapter_data='") - .substringBefore("';") - .replace("\\/", "/"), - ).jsonObject - - val unsaltedCiphertext = Base64.decode(chapterData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT) - val salt = chapterData["s"]!!.jsonPrimitive.content.decodeHex() - val ciphertext = SALTED + salt + unsaltedCiphertext - - val rawImgArray = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), password) - val imgArrayString = json.parseToJsonElement(rawImgArray).jsonPrimitive.content - val imgArray = json.parseToJsonElement(imgArrayString).jsonArray - - return imgArray.mapIndexed { idx, it -> - Page(idx, document.location(), it.jsonPrimitive.content) - } - } - - // https://stackoverflow.com/a/66614516 - private fun String.decodeHex(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - - return chunked(2) - .map { it.toInt(16).toByte() } - .toByteArray() - } - - companion object { - val SALTED = "Salted__".toByteArray(Charsets.UTF_8) - } } diff --git a/multisrc/overrides/madara/cerisescans/additional.gradle b/multisrc/overrides/madara/cerisescans/additional.gradle deleted file mode 100644 index 04805cd35..000000000 --- a/multisrc/overrides/madara/cerisescans/additional.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - implementation(project(':lib-cryptoaes')) -} diff --git a/multisrc/overrides/madara/cerisescans/src/CeriseScans.kt b/multisrc/overrides/madara/cerisescans/src/CeriseScans.kt index fb486e72c..53d0ebbce 100644 --- a/multisrc/overrides/madara/cerisescans/src/CeriseScans.kt +++ b/multisrc/overrides/madara/cerisescans/src/CeriseScans.kt @@ -1,15 +1,8 @@ package eu.kanade.tachiyomi.extension.pt.cerisescans -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 kotlinx.serialization.json.jsonArray -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive import okhttp3.OkHttpClient -import org.jsoup.nodes.Document import java.text.SimpleDateFormat import java.util.Locale import java.util.concurrent.TimeUnit @@ -26,44 +19,4 @@ class CeriseScans : Madara( .build() override val useNewChapterEndpoint = true - - override fun pageListParse(document: Document): List { - val chapterProtector = document.getElementById("chapter-protector-data")?.html() - ?: return super.pageListParse(document) - - val password = chapterProtector - .substringAfter("wpmangaprotectornonce='") - .substringBefore("';") - val chapterData = json.parseToJsonElement( - chapterProtector - .substringAfter("chapter_data='") - .substringBefore("';") - .replace("\\/", "/"), - ).jsonObject - - val unsaltedCiphertext = Base64.decode(chapterData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT) - val salt = chapterData["s"]!!.jsonPrimitive.content.decodeHex() - val ciphertext = SALTED + salt + unsaltedCiphertext - - val rawImgArray = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), password) - val imgArrayString = json.parseToJsonElement(rawImgArray).jsonPrimitive.content - val imgArray = json.parseToJsonElement(imgArrayString).jsonArray - - return imgArray.mapIndexed { idx, it -> - Page(idx, document.location(), it.jsonPrimitive.content) - } - } - - // https://stackoverflow.com/a/66614516 - private fun String.decodeHex(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - - return chunked(2) - .map { it.toInt(16).toByte() } - .toByteArray() - } - - companion object { - val SALTED = "Salted__".toByteArray(Charsets.UTF_8) - } } diff --git a/multisrc/overrides/madara/aiyumanga/additional.gradle b/multisrc/overrides/madara/default/additional.gradle similarity index 100% rename from multisrc/overrides/madara/aiyumanga/additional.gradle rename to multisrc/overrides/madara/default/additional.gradle diff --git a/multisrc/overrides/madara/leviatanscans/additional.gradle b/multisrc/overrides/madara/leviatanscans/additional.gradle deleted file mode 100644 index 06abd18c6..000000000 --- a/multisrc/overrides/madara/leviatanscans/additional.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - implementation(project(':lib-cryptoaes')) -} \ No newline at end of file diff --git a/multisrc/overrides/madara/leviatanscans/src/LeviatanScans.kt b/multisrc/overrides/madara/leviatanscans/src/LeviatanScans.kt index 7b3ad7081..247bd399c 100644 --- a/multisrc/overrides/madara/leviatanscans/src/LeviatanScans.kt +++ b/multisrc/overrides/madara/leviatanscans/src/LeviatanScans.kt @@ -1,15 +1,8 @@ package eu.kanade.tachiyomi.extension.all.leviatanscans -import android.util.Base64 -import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES import eu.kanade.tachiyomi.multisrc.madara.Madara -import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga -import kotlinx.serialization.json.jsonArray -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import org.jsoup.nodes.Document import org.jsoup.nodes.Element import java.text.SimpleDateFormat @@ -59,44 +52,4 @@ abstract class LeviatanScans( chapter.url = baseUrl + split.slice(split.indexOf("manga") until split.size).joinToString("/", "/") return chapter } - - override fun pageListParse(document: Document): List { - val chapterProtector = document.getElementById("chapter-protector-data")?.html() - ?: return super.pageListParse(document) - - val password = chapterProtector - .substringAfter("wpmangaprotectornonce='") - .substringBefore("';") - val chapterData = json.parseToJsonElement( - chapterProtector - .substringAfter("chapter_data='") - .substringBefore("';") - .replace("\\/", "/"), - ).jsonObject - - val unsaltedCiphertext = Base64.decode(chapterData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT) - val salt = chapterData["s"]!!.jsonPrimitive.content.decodeHex() - val ciphertext = SALTED + salt + unsaltedCiphertext - - val rawImgArray = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), password) - val imgArrayString = json.parseToJsonElement(rawImgArray).jsonPrimitive.content - val imgArray = json.parseToJsonElement(imgArrayString).jsonArray - - return imgArray.mapIndexed { idx, it -> - Page(idx, document.location(), it.jsonPrimitive.content) - } - } - - // https://stackoverflow.com/a/66614516 - private fun String.decodeHex(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - - return chunked(2) - .map { it.toInt(16).toByte() } - .toByteArray() - } - - companion object { - val SALTED = "Salted__".toByteArray(Charsets.UTF_8) - } } diff --git a/multisrc/overrides/madara/mangacrab/additional.gradle b/multisrc/overrides/madara/mangacrab/additional.gradle deleted file mode 100644 index 06abd18c6..000000000 --- a/multisrc/overrides/madara/mangacrab/additional.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - implementation(project(':lib-cryptoaes')) -} \ No newline at end of file diff --git a/multisrc/overrides/madara/mangacrab/src/MangaCrab.kt b/multisrc/overrides/madara/mangacrab/src/MangaCrab.kt index 5161c0524..d5333863c 100644 --- a/multisrc/overrides/madara/mangacrab/src/MangaCrab.kt +++ b/multisrc/overrides/madara/mangacrab/src/MangaCrab.kt @@ -1,18 +1,9 @@ package eu.kanade.tachiyomi.extension.es.mangacrab -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 kotlinx.serialization.json.jsonArray -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import okhttp3.OkHttpClient -import org.jsoup.nodes.Document import java.text.SimpleDateFormat import java.util.Locale -import java.util.concurrent.TimeUnit class MangaCrab : Madara( "Manga Crab", @@ -20,53 +11,10 @@ class MangaCrab : Madara( "es", SimpleDateFormat("dd/MM/yyyy", Locale("es")), ) { - override val client: OkHttpClient = network.cloudflareClient.newBuilder() - .addInterceptor(uaIntercept) - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(30, TimeUnit.SECONDS) + override val client = super.client.newBuilder() .rateLimit(1, 2) .build() override fun chapterListSelector() = "div.listing-chapters_wrap > ul > li" override val mangaDetailsSelectorDescription = "div.c-page__content div.contenedor" - - override fun pageListParse(document: Document): List { - val chapterProtector = document.getElementById("chapter-protector-data")?.html() - ?: return super.pageListParse(document) - - val password = chapterProtector - .substringAfter("wpmangaprotectornonce='") - .substringBefore("';") - val chapterData = json.parseToJsonElement( - chapterProtector - .substringAfter("chapter_data='") - .substringBefore("';") - .replace("\\/", "/"), - ).jsonObject - - val unsaltedCiphertext = Base64.decode(chapterData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT) - val salt = chapterData["s"]!!.jsonPrimitive.content.decodeHex() - val ciphertext = SALTED + salt + unsaltedCiphertext - - val rawImgArray = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), password) - val imgArrayString = json.parseToJsonElement(rawImgArray).jsonPrimitive.content - val imgArray = json.parseToJsonElement(imgArrayString).jsonArray - - return imgArray.mapIndexed { idx, it -> - Page(idx, document.location(), it.jsonPrimitive.content) - } - } - - // https://stackoverflow.com/a/66614516 - private fun String.decodeHex(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - - return chunked(2) - .map { it.toInt(16).toByte() } - .toByteArray() - } - - companion object { - val SALTED = "Salted__".toByteArray(Charsets.UTF_8) - } } diff --git a/multisrc/overrides/madara/manhuasy/additional.gradle b/multisrc/overrides/madara/manhuasy/additional.gradle deleted file mode 100644 index 06abd18c6..000000000 --- a/multisrc/overrides/madara/manhuasy/additional.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - implementation(project(':lib-cryptoaes')) -} \ No newline at end of file diff --git a/multisrc/overrides/madara/manhuasy/src/ManhuaSY.kt b/multisrc/overrides/madara/manhuasy/src/ManhuaSY.kt index d4bebcedf..bbaab373a 100644 --- a/multisrc/overrides/madara/manhuasy/src/ManhuaSY.kt +++ b/multisrc/overrides/madara/manhuasy/src/ManhuaSY.kt @@ -1,53 +1,7 @@ package eu.kanade.tachiyomi.extension.en.manhuasy -import android.util.Base64 -import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES import eu.kanade.tachiyomi.multisrc.madara.Madara -import eu.kanade.tachiyomi.source.model.Page -import kotlinx.serialization.json.jsonArray -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import org.jsoup.nodes.Document class ManhuaSY : Madara("Manhua SY", "https://www.manhuasy.com", "en") { override val mangaSubString = "manhua" - override fun pageListParse(document: Document): List { - val chapterProtector = document.getElementById("chapter-protector-data")?.html() - ?: return super.pageListParse(document) - - val password = chapterProtector - .substringAfter("wpmangaprotectornonce='") - .substringBefore("';") - val chapterData = json.parseToJsonElement( - chapterProtector - .substringAfter("chapter_data='") - .substringBefore("';") - .replace("\\/", "/"), - ).jsonObject - - val unsaltedCiphertext = Base64.decode(chapterData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT) - val salt = chapterData["s"]!!.jsonPrimitive.content.decodeHex() - val ciphertext = SALTED + salt + unsaltedCiphertext - - val rawImgArray = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), password) - val imgArrayString = json.parseToJsonElement(rawImgArray).jsonPrimitive.content - val imgArray = json.parseToJsonElement(imgArrayString).jsonArray - - return imgArray.mapIndexed { idx, it -> - Page(idx, document.location(), it.jsonPrimitive.content) - } - } - - // https://stackoverflow.com/a/66614516 - private fun String.decodeHex(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - - return chunked(2) - .map { it.toInt(16).toByte() } - .toByteArray() - } - - companion object { - val SALTED = "Salted__".toByteArray(Charsets.UTF_8) - } } diff --git a/multisrc/overrides/madara/manhwalatino/additional.gradle b/multisrc/overrides/madara/manhwalatino/additional.gradle deleted file mode 100644 index f9e6f25e0..000000000 --- a/multisrc/overrides/madara/manhwalatino/additional.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - implementation(project(':lib-cryptoaes')) -} diff --git a/multisrc/overrides/madara/manhwalatino/src/ManhwaLatino.kt b/multisrc/overrides/madara/manhwalatino/src/ManhwaLatino.kt index 33336c2c3..9222c3e48 100644 --- a/multisrc/overrides/madara/manhwalatino/src/ManhwaLatino.kt +++ b/multisrc/overrides/madara/manhwalatino/src/ManhwaLatino.kt @@ -1,14 +1,6 @@ package eu.kanade.tachiyomi.extension.es.manhwalatino -import android.util.Base64 -import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES import eu.kanade.tachiyomi.multisrc.madara.Madara -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.source.model.Page -import kotlinx.serialization.json.jsonArray -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import org.jsoup.nodes.Document import java.text.SimpleDateFormat import java.util.Locale @@ -26,51 +18,4 @@ class ManhwaLatino : Madara( override val chapterUrlSelector = "a:eq(1)" override val mangaDetailsSelectorStatus = "div.post-content_item:contains(Estado del comic) > div.summary-content" - - override fun pageListParse(document: Document): List { - val script = document.selectFirst("div.reading-content script") - ?: return super.pageListParse(document) - - val scriptData: String = if (script.hasAttr("src")) { - client.newCall(GET(script.attr("src"), headers)).execute().body.string() - } else { - script.data() - } - - val password = scriptData - .substringAfter("wpmangaprotectornonce='") - .substringBefore("';") - - val chapterData = json.parseToJsonElement( - scriptData - .substringAfter("chapter_data='") - .substringBefore("';") - .replace("\\/", "/"), - ).jsonObject - - val unsaltedCiphertext = Base64.decode(chapterData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT) - val salt = chapterData["s"]!!.jsonPrimitive.content.decodeHex() - val ciphertext = SALTED + salt + unsaltedCiphertext - - val rawImgArray = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), password) - val imgArrayString = json.parseToJsonElement(rawImgArray).jsonPrimitive.content - val imgArray = json.parseToJsonElement(imgArrayString).jsonArray - - return imgArray.mapIndexed { idx, it -> - Page(idx, document.location(), it.jsonPrimitive.content) - } - } - - // https://stackoverflow.com/a/66614516 - private fun String.decodeHex(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - - return chunked(2) - .map { it.toInt(16).toByte() } - .toByteArray() - } - - companion object { - val SALTED = "Salted__".toByteArray(Charsets.UTF_8) - } } diff --git a/multisrc/overrides/madara/sinensis/additional.gradle b/multisrc/overrides/madara/sinensis/additional.gradle deleted file mode 100644 index 788ad9de1..000000000 --- a/multisrc/overrides/madara/sinensis/additional.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - implementation(project(':lib-cryptoaes')) -} diff --git a/multisrc/overrides/madara/sinensis/src/SinensisScan.kt b/multisrc/overrides/madara/sinensis/src/SinensisScan.kt index 21c19402f..b5b697f43 100644 --- a/multisrc/overrides/madara/sinensis/src/SinensisScan.kt +++ b/multisrc/overrides/madara/sinensis/src/SinensisScan.kt @@ -1,18 +1,11 @@ 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 @@ -50,40 +43,6 @@ class SinensisScan : Madara( } } - 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() @@ -94,8 +53,4 @@ class SinensisScan : Madara( return url.toString() } - - companion object { - val SALTED = "Salted__".toByteArray(Charsets.UTF_8) - } } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/Madara.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/Madara.kt index 4c002d15a..249fd7724 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/Madara.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/Madara.kt @@ -2,11 +2,13 @@ package eu.kanade.tachiyomi.multisrc.madara import android.app.Application import android.content.SharedPreferences +import android.util.Base64 import android.util.Log import android.widget.Toast import androidx.preference.EditTextPreference import androidx.preference.PreferenceScreen import androidx.preference.SwitchPreferenceCompat +import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.asObservable @@ -21,6 +23,7 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.util.asJsoup import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonPrimitive import okhttp3.CacheControl @@ -630,7 +633,17 @@ abstract class Madara( } } - manga.genre = genres.toList().joinToString(", ") { it.capitalize(Locale.ROOT) } + manga.genre = genres.toList().joinToString(", ") { genre -> + genre.replaceFirstChar { + if (it.isLowerCase()) { + it.titlecase( + Locale.ROOT, + ) + } else { + it.toString() + } + } + } // add alternative name to manga description document.select(altNameSelector).firstOrNull()?.ownText()?.let { @@ -868,17 +881,37 @@ abstract class Madara( open val pageListParseSelector = "div.page-break, li.blocks-gallery-item, .reading-content .text-left:not(:has(.blocks-gallery-item)) img" + open val chapterProtectorSelector = "#chapter-protector-data" + override fun pageListParse(document: Document): List { countViews(document) - return document.select(pageListParseSelector).mapIndexed { index, element -> - Page( - index, - document.location(), - element.select("img").first()?.let { - it.absUrl(if (it.hasAttr("data-src")) "data-src" else "src") - }, - ) + val chapterProtector = document.selectFirst(chapterProtectorSelector) + ?: return document.select(pageListParseSelector).mapIndexed { index, element -> + val imageUrl = element.selectFirst("img")?.let { imageFromElement(it) } + Page(index, document.location(), imageUrl) + } + val chapterProtectorHtml = chapterProtector.html() + val password = chapterProtectorHtml + .substringAfter("wpmangaprotectornonce='") + .substringBefore("';") + val chapterData = json.parseToJsonElement( + chapterProtectorHtml + .substringAfter("chapter_data='") + .substringBefore("';") + .replace("\\/", "/"), + ).jsonObject + + val unsaltedCiphertext = Base64.decode(chapterData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT) + val salt = chapterData["s"]!!.jsonPrimitive.content.decodeHex() + val ciphertext = SALTED + salt + unsaltedCiphertext + + val rawImgArray = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), password) + val imgArrayString = json.parseToJsonElement(rawImgArray).jsonPrimitive.content + val imgArray = json.parseToJsonElement(imgArrayString).jsonArray + + return imgArray.mapIndexed { idx, it -> + Page(idx, document.location(), it.jsonPrimitive.content) } } @@ -1035,6 +1068,15 @@ abstract class Madara( } } + // https://stackoverflow.com/a/66614516 + private fun String.decodeHex(): ByteArray { + check(length % 2 == 0) { "Must have an even length" } + + return chunked(2) + .map { it.toInt(16).toByte() } + .toByteArray() + } + companion object { const val TITLE_RANDOM_UA = "Use Random Latest User-Agent" const val PREF_KEY_RANDOM_UA = "pref_key_random_ua" @@ -1048,6 +1090,8 @@ abstract class Madara( const val DOESNOT_SUPPORT_STRING = "This extension doesn't support User-Agent options." const val URL_SEARCH_PREFIX = "slug:" private const val UA_DB_URL = "https://tachiyomiorg.github.io/user-agents/user-agents.json" + + 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 30b4452ff..7e1386364 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 @@ -10,7 +10,7 @@ class MadaraGenerator : ThemeSourceGenerator { override val themeClass = "Madara" - override val baseVersionCode: Int = 29 + override val baseVersionCode: Int = 30 override val sources = listOf( MultiLang("Atlantis Scan", "https://atlantisscan.com", listOf("es", "pt-BR"), isNsfw = true),