Remove usage of Duktape (#13048)
This commit is contained in:
parent
a83e04f237
commit
e96fd22d30
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'Comico'
|
extName = 'Comico'
|
||||||
pkgNameSuffix = 'all.comico'
|
pkgNameSuffix = 'all.comico'
|
||||||
extClass = '.ComicoFactory'
|
extClass = '.ComicoFactory'
|
||||||
extVersionCode = 3
|
extVersionCode = 4
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.extension.all.comico
|
package eu.kanade.tachiyomi.extension.all.comico
|
||||||
|
|
||||||
import android.webkit.CookieManager
|
import android.webkit.CookieManager
|
||||||
import com.squareup.duktape.Duktape
|
import app.cash.quickjs.QuickJs
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
|
@ -166,7 +166,7 @@ open class Comico(
|
||||||
private fun paginate(route: String, page: Int) =
|
private fun paginate(route: String, page: Int) =
|
||||||
GET("$apiUrl/$route?pageNo=${page - 1}&pageSize=25", apiHeaders)
|
GET("$apiUrl/$route?pageNo=${page - 1}&pageSize=25", apiHeaders)
|
||||||
|
|
||||||
private fun String.decrypt() = Duktape.create().use {
|
private fun String.decrypt() = QuickJs.create().use {
|
||||||
// javax.crypto.Cipher does not support empty IV
|
// javax.crypto.Cipher does not support empty IV
|
||||||
val script = """
|
val script = """
|
||||||
const key = CryptoJS.enc.Utf8.parse('$AES_KEY'), iv = {words: []}
|
const key = CryptoJS.enc.Utf8.parse('$AES_KEY'), iv = {words: []}
|
||||||
|
|
|
@ -5,7 +5,7 @@ ext {
|
||||||
extName = 'Mangahere'
|
extName = 'Mangahere'
|
||||||
pkgNameSuffix = 'en.mangahere'
|
pkgNameSuffix = 'en.mangahere'
|
||||||
extClass = '.Mangahere'
|
extClass = '.Mangahere'
|
||||||
extVersionCode = 18
|
extVersionCode = 19
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.mangahere
|
package eu.kanade.tachiyomi.extension.en.mangahere
|
||||||
|
|
||||||
import com.squareup.duktape.Duktape
|
import app.cash.quickjs.QuickJs
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
|
@ -212,7 +212,7 @@ class Mangahere : ParsedHttpSource() {
|
||||||
|
|
||||||
override fun pageListParse(document: Document): List<Page> {
|
override fun pageListParse(document: Document): List<Page> {
|
||||||
val bar = document.select("script[src*=chapter_bar]")
|
val bar = document.select("script[src*=chapter_bar]")
|
||||||
val duktape = Duktape.create()
|
val quickJs = QuickJs.create()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
function to drop last imageUrl if it's broken/unneccesary, working imageUrls are incremental (e.g. t001, t002, etc); if the difference between
|
function to drop last imageUrl if it's broken/unneccesary, working imageUrls are incremental (e.g. t001, t002, etc); if the difference between
|
||||||
|
@ -236,16 +236,16 @@ class Mangahere : ParsedHttpSource() {
|
||||||
// if-branch is for webtoon reader, else is for page-by-page
|
// if-branch is for webtoon reader, else is for page-by-page
|
||||||
return if (bar.isNotEmpty()) {
|
return if (bar.isNotEmpty()) {
|
||||||
val script = document.select("script:containsData(function(p,a,c,k,e,d))").html().removePrefix("eval")
|
val script = document.select("script:containsData(function(p,a,c,k,e,d))").html().removePrefix("eval")
|
||||||
val deobfuscatedScript = duktape.evaluate(script).toString()
|
val deobfuscatedScript = quickJs.evaluate(script).toString()
|
||||||
val urls = deobfuscatedScript.substringAfter("newImgs=['").substringBefore("'];").split("','")
|
val urls = deobfuscatedScript.substringAfter("newImgs=['").substringBefore("'];").split("','")
|
||||||
duktape.close()
|
quickJs.close()
|
||||||
|
|
||||||
urls.mapIndexed { index, s -> Page(index, "", "https:$s") }
|
urls.mapIndexed { index, s -> Page(index, "", "https:$s") }
|
||||||
} else {
|
} else {
|
||||||
val html = document.html()
|
val html = document.html()
|
||||||
val link = document.location()
|
val link = document.location()
|
||||||
|
|
||||||
var secretKey = extractSecretKey(html, duktape)
|
var secretKey = extractSecretKey(html, quickJs)
|
||||||
|
|
||||||
val chapterIdStartLoc = html.indexOf("chapterid")
|
val chapterIdStartLoc = html.indexOf("chapterid")
|
||||||
val chapterId = html.substring(
|
val chapterId = html.substring(
|
||||||
|
@ -285,7 +285,7 @@ class Mangahere : ParsedHttpSource() {
|
||||||
secretKey = ""
|
secretKey = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
val deobfuscatedScript = duktape.evaluate(responseText.removePrefix("eval")).toString()
|
val deobfuscatedScript = quickJs.evaluate(responseText.removePrefix("eval")).toString()
|
||||||
|
|
||||||
val baseLinkStartPos = deobfuscatedScript.indexOf("pix=") + 5
|
val baseLinkStartPos = deobfuscatedScript.indexOf("pix=") + 5
|
||||||
val baseLinkEndPos = deobfuscatedScript.indexOf(";", baseLinkStartPos) - 1
|
val baseLinkEndPos = deobfuscatedScript.indexOf(";", baseLinkStartPos) - 1
|
||||||
|
@ -299,15 +299,15 @@ class Mangahere : ParsedHttpSource() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dropLastIfBroken()
|
.dropLastIfBroken()
|
||||||
.also { duktape.close() }
|
.also { quickJs.close() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractSecretKey(html: String, duktape: Duktape): String {
|
private fun extractSecretKey(html: String, quickJs: QuickJs): String {
|
||||||
val secretKeyScriptLocation = html.indexOf("eval(function(p,a,c,k,e,d)")
|
val secretKeyScriptLocation = html.indexOf("eval(function(p,a,c,k,e,d)")
|
||||||
val secretKeyScriptEndLocation = html.indexOf("</script>", secretKeyScriptLocation)
|
val secretKeyScriptEndLocation = html.indexOf("</script>", secretKeyScriptLocation)
|
||||||
val secretKeyScript = html.substring(secretKeyScriptLocation, secretKeyScriptEndLocation).removePrefix("eval")
|
val secretKeyScript = html.substring(secretKeyScriptLocation, secretKeyScriptEndLocation).removePrefix("eval")
|
||||||
|
|
||||||
val secretKeyDeobfuscatedScript = duktape.evaluate(secretKeyScript).toString()
|
val secretKeyDeobfuscatedScript = quickJs.evaluate(secretKeyScript).toString()
|
||||||
|
|
||||||
val secretKeyStartLoc = secretKeyDeobfuscatedScript.indexOf("'")
|
val secretKeyStartLoc = secretKeyDeobfuscatedScript.indexOf("'")
|
||||||
val secretKeyEndLoc = secretKeyDeobfuscatedScript.indexOf(";")
|
val secretKeyEndLoc = secretKeyDeobfuscatedScript.indexOf(";")
|
||||||
|
@ -317,7 +317,7 @@ class Mangahere : ParsedHttpSource() {
|
||||||
secretKeyEndLoc
|
secretKeyEndLoc
|
||||||
)
|
)
|
||||||
|
|
||||||
return duktape.evaluate(secretKeyResultScript).toString()
|
return quickJs.evaluate(secretKeyResultScript).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
||||||
|
|
|
@ -5,7 +5,7 @@ ext {
|
||||||
extName = 'Mangabz'
|
extName = 'Mangabz'
|
||||||
pkgNameSuffix = 'zh.mangabz'
|
pkgNameSuffix = 'zh.mangabz'
|
||||||
extClass = '.Mangabz'
|
extClass = '.Mangabz'
|
||||||
extVersionCode = 4
|
extVersionCode = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.extension.zh.mangabz
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import com.squareup.duktape.Duktape
|
import app.cash.quickjs.QuickJs
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
||||||
|
@ -276,7 +276,7 @@ class Mangabz : ConfigurableSource, HttpSource() {
|
||||||
|
|
||||||
private fun fetchImageUrlListFromAPI(apiUrl: String, requestHeaders: Headers = headers): JSONArray {
|
private fun fetchImageUrlListFromAPI(apiUrl: String, requestHeaders: Headers = headers): JSONArray {
|
||||||
val jsEvalPayload = client.newCall(GET(apiUrl, requestHeaders)).execute().body!!.string()
|
val jsEvalPayload = client.newCall(GET(apiUrl, requestHeaders)).execute().body!!.string()
|
||||||
val imgUrlDecode = Duktape.create().use {
|
val imgUrlDecode = QuickJs.create().use {
|
||||||
it.evaluate("$jsEvalPayload; JSON.stringify(d);") as String
|
it.evaluate("$jsEvalPayload; JSON.stringify(d);") as String
|
||||||
}
|
}
|
||||||
return JSONArray(imgUrlDecode)
|
return JSONArray(imgUrlDecode)
|
||||||
|
|
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'ManHuaGui'
|
extName = 'ManHuaGui'
|
||||||
pkgNameSuffix = 'zh.manhuagui'
|
pkgNameSuffix = 'zh.manhuagui'
|
||||||
extClass = '.Manhuagui'
|
extClass = '.Manhuagui'
|
||||||
extVersionCode = 14
|
extVersionCode = 15
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.extension.zh.manhuagui
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import com.squareup.duktape.Duktape
|
import app.cash.quickjs.QuickJs
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
@ -289,7 +289,7 @@ class Manhuagui : ConfigurableSource, ParsedHttpSource() {
|
||||||
if (hiddenEncryptedChapterList != null) {
|
if (hiddenEncryptedChapterList != null) {
|
||||||
if (getShowR18()) {
|
if (getShowR18()) {
|
||||||
// Hidden chapter list is LZString encoded
|
// Hidden chapter list is LZString encoded
|
||||||
val decodedHiddenChapterList = Duktape.create().use {
|
val decodedHiddenChapterList = QuickJs.create().use {
|
||||||
it.evaluate(
|
it.evaluate(
|
||||||
jsDecodeFunc +
|
jsDecodeFunc +
|
||||||
"""LZString.decompressFromBase64('${hiddenEncryptedChapterList.`val`()}');"""
|
"""LZString.decompressFromBase64('${hiddenEncryptedChapterList.`val`()}');"""
|
||||||
|
@ -381,7 +381,7 @@ class Manhuagui : ConfigurableSource, ParsedHttpSource() {
|
||||||
|
|
||||||
val html = document.html()
|
val html = document.html()
|
||||||
val imgCode = re.find(html)?.groups?.get(1)?.value
|
val imgCode = re.find(html)?.groups?.get(1)?.value
|
||||||
val imgDecode = Duktape.create().use {
|
val imgDecode = QuickJs.create().use {
|
||||||
it.evaluate(jsDecodeFunc + imgCode) as String
|
it.evaluate(jsDecodeFunc + imgCode) as String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'QiXiManhua'
|
extName = 'QiXiManhua'
|
||||||
pkgNameSuffix = 'zh.qiximh'
|
pkgNameSuffix = 'zh.qiximh'
|
||||||
extClass = '.Qiximh'
|
extClass = '.Qiximh'
|
||||||
extVersionCode = 4
|
extVersionCode = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.extension.zh.qiximh
|
package eu.kanade.tachiyomi.extension.zh.qiximh
|
||||||
|
|
||||||
import com.squareup.duktape.Duktape
|
import app.cash.quickjs.QuickJs
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
|
@ -302,10 +302,11 @@ class Qiximh : HttpSource() {
|
||||||
|
|
||||||
// Special thanks to author who created Mangahere.kt
|
// Special thanks to author who created Mangahere.kt
|
||||||
val script = document.select("script:containsData(function(p,a,c,k,e,d))").html().removePrefix("eval")
|
val script = document.select("script:containsData(function(p,a,c,k,e,d))").html().removePrefix("eval")
|
||||||
val deobfuscatedScript = Duktape.create().use { it.evaluate(script).toString() }
|
val deobfuscatedScript = QuickJs.create().use { it.evaluate(script).toString() }
|
||||||
val urls = deobfuscatedScript.substringAfter("newImgs=[\"").substringBefore("\"]").split("\",\"")
|
val imageUrlListString = deobfuscatedScript.substringAfter("newImgs=").trim()
|
||||||
|
val imageUrlList = json.parseToJsonElement(imageUrlListString).jsonArray.map { it.jsonPrimitive.content }
|
||||||
|
|
||||||
return urls.mapIndexed { index, s -> Page(index, "", s) }
|
return imageUrlList.mapIndexed { index, s -> Page(index, imageUrl = s) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unused
|
// Unused
|
||||||
|
|
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'Tencent Comics (ac.qq.com)'
|
extName = 'Tencent Comics (ac.qq.com)'
|
||||||
pkgNameSuffix = 'zh.tencentcomics'
|
pkgNameSuffix = 'zh.tencentcomics'
|
||||||
extClass = '.TencentComics'
|
extClass = '.TencentComics'
|
||||||
extVersionCode = 5
|
extVersionCode = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.extension.zh.tencentcomics
|
package eu.kanade.tachiyomi.extension.zh.tencentcomics
|
||||||
|
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import com.squareup.duktape.Duktape
|
import app.cash.quickjs.QuickJs
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
|
@ -146,7 +146,7 @@ class TencentComics : ParsedHttpSource() {
|
||||||
|
|
||||||
val raw = html.substringAfterLast("var DATA =").substringBefore("PRELOAD_NUM").trim().replace(Regex("^\'|\',$"), "")
|
val raw = html.substringAfterLast("var DATA =").substringBefore("PRELOAD_NUM").trim().replace(Regex("^\'|\',$"), "")
|
||||||
val decodePrefix = "var raw = \"$raw\"; var nonce = $nonce"
|
val decodePrefix = "var raw = \"$raw\"; var nonce = $nonce"
|
||||||
val full = Duktape.create().use { it.evaluate(decodePrefix + jsDecodeFunction).toString() }
|
val full = QuickJs.create().use { it.evaluate(decodePrefix + jsDecodeFunction).toString() }
|
||||||
val chapterData = json.parseToJsonElement(String(Base64.decode(full, Base64.DEFAULT))).jsonObject
|
val chapterData = json.parseToJsonElement(String(Base64.decode(full, Base64.DEFAULT))).jsonObject
|
||||||
|
|
||||||
if (!chapterData["chapter"]!!.jsonObject["canRead"]!!.jsonPrimitive.boolean) throw Exception("[此章节为付费内容]")
|
if (!chapterData["chapter"]!!.jsonObject["canRead"]!!.jsonPrimitive.boolean) throw Exception("[此章节为付费内容]")
|
||||||
|
|
Loading…
Reference in New Issue