Add ManhwaBreakup (#2735)
This commit is contained in:
parent
02a6fb32ba
commit
4516e2f208
|
@ -0,0 +1,14 @@
|
|||
ext {
|
||||
extName = 'ManhwaBreakup'
|
||||
extClass = '.ManhwaBreakup'
|
||||
themePkg = 'madara'
|
||||
baseUrl = 'https://www.manhwabreakup.com'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
||||
dependencies {
|
||||
implementation(project(":lib:unpacker"))
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
|
@ -0,0 +1,117 @@
|
|||
package eu.kanade.tachiyomi.extension.th.manhwabreakup
|
||||
|
||||
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 ManhwaBreakup : Madara(
|
||||
"ManhwaBreakup",
|
||||
"https://www.manhwabreakup.com",
|
||||
"th",
|
||||
dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale("th")),
|
||||
) {
|
||||
override val useLoadMoreRequest = LoadMoreStrategy.Never
|
||||
override val useNewChapterEndpoint = false
|
||||
|
||||
override val filterNonMangaItems = false
|
||||
|
||||
// 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()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue