Add ManhuaBug (#2732)

This commit is contained in:
Vetle Ledaal 2024-05-02 01:04:31 +00:00 committed by Draff
parent e84664029d
commit a6439e6316
7 changed files with 136 additions and 0 deletions

View File

@ -0,0 +1,14 @@
ext {
extName = 'ManhuaBug'
extClass = '.ManhuaBug'
themePkg = 'madara'
baseUrl = 'https://www.manhuabug.com'
overrideVersionCode = 0
isNsfw = false
}
apply from: "$rootDir/common.gradle"
dependencies {
implementation(project(":lib:unpacker"))
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -0,0 +1,122 @@
package eu.kanade.tachiyomi.extension.th.manhuabug
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.madara.Madara
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
class ManhuaBug : Madara(
"ManhuaBug",
"https://www.manhuabug.com",
"th",
dateFormat = SimpleDateFormat("d MMMM yyyy", Locale("en")),
) {
override val supportsLatest = false
override val useLoadMoreRequest = LoadMoreStrategy.Never
override val useNewChapterEndpoint = false
override val filterNonMangaItems = false
override val fetchGenres = false // While genres exist, they can't be used in standard Madara search
// Descrambling logic from ManhuaKey
override val client = super.client.newBuilder()
.addNetworkInterceptor(::imageDescrambler)
.build()
override val pageListParseSelector = ".reading-content img, .reading-content div.displayImage + script:containsData(p,a,c,k,e,d)"
override fun pageListParse(document: Document): List<Page> {
launchIO { countViews(document) }
val location = document.location()
return document.select(pageListParseSelector).mapIndexed { idx, element ->
if (element.tagName().equals("img")) {
Page(idx, location, imageFromElement(element))
} else {
val unpackedScript = Unpacker.unpack(element.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(idx, 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()
}
}