From bf6740e7e050cb6b8efbf21ce3e4e9d16b367b06 Mon Sep 17 00:00:00 2001
From: beerpsi <92439990+beerpiss@users.noreply.github.com>
Date: Thu, 3 Aug 2023 00:52:22 +0700
Subject: [PATCH] DragonTea: Decrypt image attributes (#17343)

* DragonTea: Decrypt image attributes

* Remove unnecessary import

* Trim whitespace
---
 .../madara/dragontea/src/DragonTea.kt         | 41 ++++++++++++++++++-
 .../multisrc/madara/MadaraGenerator.kt        |  2 +-
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/multisrc/overrides/madara/dragontea/src/DragonTea.kt b/multisrc/overrides/madara/dragontea/src/DragonTea.kt
index d8502af46..84a67d9c9 100644
--- a/multisrc/overrides/madara/dragontea/src/DragonTea.kt
+++ b/multisrc/overrides/madara/dragontea/src/DragonTea.kt
@@ -4,9 +4,13 @@ import android.graphics.Bitmap
 import android.graphics.BitmapFactory
 import android.graphics.Canvas
 import android.graphics.Rect
+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.jsonObject
+import kotlinx.serialization.json.jsonPrimitive
 import okhttp3.Interceptor
 import okhttp3.MediaType.Companion.toMediaType
 import okhttp3.OkHttpClient
@@ -53,7 +57,31 @@ class DragonTea : Madara(
             .firstOrNull() != null
 
         if (!hasSplitImages) {
-            return super.pageListParse(document)
+            return document.select(pageListParseSelector).mapIndexed { index, element ->
+                val imageUrl = element.selectFirst("img")?.let {
+                    val src = when {
+                        it.hasAttr("data-src") -> it.attr("data-src")
+                        it.hasAttr("data-lazy-src") -> it.attr("data-lazy-src")
+                        it.hasAttr("srcset") -> it.attr("srcset").substringBefore(" ")
+                        else -> it.attr("src")
+                    }.trim()
+
+                    if (!src.startsWith("{\"")) {
+                        return@let imageFromElement(it)
+                    }
+
+                    val srcData = json.parseToJsonElement(src).jsonObject
+
+                    val unsaltedCiphertext = Base64.decode(srcData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT)
+                    val salt = srcData["s"]!!.jsonPrimitive.content.decodeHex()
+                    val ciphertext = SALTED + salt + unsaltedCiphertext
+
+                    val plaintext = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), PASSWORD)
+                    json.parseToJsonElement(plaintext).jsonPrimitive.content
+                }
+
+                Page(index, document.location(), imageUrl)
+            }
         }
 
         return document.select("div.page-break, li.blocks-gallery-item, $begonepeconSelector")
@@ -119,8 +147,19 @@ class DragonTea : Madara(
             .build()
     }
 
+    fun String.decodeHex(): ByteArray {
+        check(length % 2 == 0) { "Must have an even length" }
+
+        return chunked(2)
+            .map { it.toInt(16).toByte() }
+            .toByteArray()
+    }
+
     companion object {
         private const val BEGONEPECON_SUFFIX = "?begonepecon"
         private val PNG_MEDIA_TYPE = "image/png".toMediaType()
+
+        private val SALTED = "Salted__".toByteArray(Charsets.UTF_8)
+        private val PASSWORD = "releasethestormy888"
     }
 }
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 9ae371cc0..8cd38c7c6 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
@@ -83,7 +83,7 @@ class MadaraGenerator : ThemeSourceGenerator {
         SingleLang("DokkoManga", "https://dokkomanga.com", "es", overrideVersionCode = 1),
         SingleLang("Doodmanga", "https://www.doodmanga.com", "th"),
         SingleLang("DoujinHentai", "https://doujinhentai.net", "es", isNsfw = true, overrideVersionCode = 1),
-        SingleLang("DragonTea", "https://dragontea.ink", "en"),
+        SingleLang("DragonTea", "https://dragontea.ink", "en", overrideVersionCode = 1),
         SingleLang("DragonTranslation.net", "https://dragontranslation.net", "es", isNsfw = true, className = "DragonTranslationNet"),
         SingleLang("Drake Scans", "https://drakescans.com", "en", overrideVersionCode = 3),
         SingleLang("Dream Manga", "https://www.swarmmanga.com", "en", overrideVersionCode = 3),