Mangakimi: Fix images (#8316)

fix descramble image
This commit is contained in:
dngonz 2025-04-02 15:48:33 +02:00 committed by Draff
parent 9639b7c585
commit f210f27a7c
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
2 changed files with 108 additions and 2 deletions

View File

@ -3,8 +3,12 @@ ext {
extClass = '.MangaKimi'
themePkg = 'mangathemesia'
baseUrl = 'https://www.mangakimi.com'
overrideVersionCode = 0
overrideVersionCode = 1
isNsfw = true
}
apply from: "$rootDir/common.gradle"
dependencies {
implementation(project(':lib:unpacker'))
}

View File

@ -1,6 +1,21 @@
package eu.kanade.tachiyomi.extension.th.mangakimi
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Rect
import eu.kanade.tachiyomi.lib.unpacker.Unpacker
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.source.model.Page
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import org.jsoup.nodes.Document
import java.io.ByteArrayOutputStream
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.TimeZone
@ -12,4 +27,91 @@ class MangaKimi : MangaThemesia(
dateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("th")).apply {
timeZone = TimeZone.getTimeZone("Asia/Bangkok")
},
)
) {
override val client = super.client.newBuilder()
.addNetworkInterceptor(::imageDescrambler)
.build()
// Pages
override val pageSelector = "div#readerarea img, #readerarea div.displayImage + script:containsData(p,a,c,k,e,d)"
override fun pageListParse(document: Document): List<Page> {
countViews(document)
val location = document.location()
return document.select(pageSelector).mapIndexed { i, img ->
if (img.tagName() == "img") {
Page(i, location, img.imgAttr())
} else {
val unpackedScript = Unpacker.unpack(img.data())
val blockWidth = blockWidthRegex.find(unpackedScript)!!.groupValues[1].toInt()
val blockHeight = blockHeightRegex.find(unpackedScript)!!.groupValues[1].toInt()
val matrix = unpackedScript.substringAfter("[")
.substringBefore("];")
.let { "[$it]" }
val scrambledImageUrl = unpackedScript.substringAfter("url(")
.substringBefore(");")
val data = ScramblingData(
blockWidth = blockWidth,
blockHeight = blockHeight,
matrix = json.decodeFromString(matrix),
)
Page(i, location, "$scrambledImageUrl#${json.encodeToString(data)}")
}
}
}
private val blockWidthRegex = Regex("""width:\s*"?\s*\+?\s*(\d+)\s*\+?\s*"?px;""")
private val blockHeightRegex = Regex("""height:\s*"?\s*\+?\s*(\d+)\s*\+?\s*"?px;""")
@Serializable
class ScramblingData(
val blockWidth: Int,
val blockHeight: Int,
val matrix: List<List<Double>>,
)
private fun imageDescrambler(chain: Interceptor.Chain): Response {
val request = chain.request()
val response = chain.proceed(request)
if (request.url.fragment.isNullOrEmpty()) {
return response
}
val scramblingData = json.decodeFromString<ScramblingData>(request.url.fragment!!)
val scrambledImg = BitmapFactory.decodeStream(response.body.byteStream())
val descrambledImg = Bitmap.createBitmap(scrambledImg.width, scrambledImg.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(descrambledImg)
for (pos in scramblingData.matrix) {
val srcRect = Rect(
pos[2].toInt(),
pos[3].toInt(),
pos[2].toInt() + scramblingData.blockWidth,
pos[3].toInt() + scramblingData.blockHeight,
)
val destRect = Rect(
pos[0].toInt(),
pos[1].toInt(),
pos[0].toInt() + scramblingData.blockWidth,
pos[1].toInt() + scramblingData.blockHeight,
)
canvas.drawBitmap(scrambledImg, srcRect, destRect, null)
}
val output = ByteArrayOutputStream()
descrambledImg.compress(Bitmap.CompressFormat.JPEG, 90, output)
val image = output.toByteArray()
val body = image.toResponseBody("image/jpeg".toMediaType())
return response.newBuilder()
.body(body)
.build()
}
}