Fix ColaManga (#10147)
Co-authored-by: Howard Wu <HowardWu20@outlook.com>
This commit is contained in:
parent
9ea67f22dd
commit
9f1f449d96
1
src/zh/onemanhua/assets/webview-script.js
Normal file
1
src/zh/onemanhua/assets/webview-script.js
Normal file
@ -0,0 +1 @@
|
||||
function _0x95d1(_0x32014e,_0x469951){const _0x95d1c6=['W6f0W63dUtNcUHxdKCoUWQ4','W5NcLfztWRdcJqq','WPmwWRvCW5e','hgxdUX0fW7qR','fmkGW59KWOS','oCoyWPZcRCoCfW','W7u9zufMWOX3eWuk','xSoDsmodWPC','nXNcJdi','BKmGWO3dTSo0W5pcQ0ZcLW','BKmGWO3dTSo0','DmkpgSoPWPKCW6SPWRlcTW','eqVcLuerCXpcRG','hNldSGKz','jdDDW6vJW5ayDXtcHG','edBcImopW4lcGZJcKG','z8ksoSkfW5FdHmkW','W6ddQWlcNmkAWP96WQGSW5y','W7bagJNcQSot','W5ZdQXpcJ8kxWQvWWQOgW5C','tCkVW4m','kMNdQ18nW78aW4ijWPK','gbKHW6L7W5RdK8oADq','kvK7qaGSWRuQWPdcPa','kqpcNCkoW4pdTSkVWR9FWP4','zCkoc8ohWPev','F8kgWPNcUSkdW7K+W4BcVmk8','W7CCWRtdUL/dICkogCkF','zCojc8kWWOSMzq','W5hdPmk4WQfVxNWAW6NdOq','W4BcGCoHW7mmWP4hW5iTW5O','W53dQHNcJW','FCoVWPBcPmkEk8kmWQmsiW','lCoJrxa','lqfZ','mbNcIW','qSk+W6ZdKSoJWQFdKSkaW6FcLG','owqfW6y','W60nWQC','ds/cSCoOdcRdMa','W7ddP2mYA8oor8o3CG','bmoFWOJcJCowewm','vCkpmCkr','D8oohmkB'];return _0x95d1=function(_0x440613,_0x4b3a2d){_0x440613=_0x440613-0x16c;let _0x7773d6=_0x95d1c6[_0x440613];if(_0x95d1['gWugEI']===undefined){var _0x41c754=function(_0x3b655d){const _0x437ca5='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x1547fb='',_0x1044a1='';for(let _0x251fbf=0x0,_0x2f9372,_0x31bb78,_0x2aad47=0x0;_0x31bb78=_0x3b655d['charAt'](_0x2aad47++);~_0x31bb78&&(_0x2f9372=_0x251fbf%0x4?_0x2f9372*0x40+_0x31bb78:_0x31bb78,_0x251fbf++%0x4)?_0x1547fb+=String['fromCharCode'](0xff&_0x2f9372>>(-0x2*_0x251fbf&0x6)):0x0){_0x31bb78=_0x437ca5['indexOf'](_0x31bb78);}for(let _0x39ad47=0x0,_0x515fdf=_0x1547fb['length'];_0x39ad47<_0x515fdf;_0x39ad47++){_0x1044a1+='%'+('00'+_0x1547fb['charCodeAt'](_0x39ad47)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1044a1);};const _0x5a8916=function(_0x466652,_0x539550){let _0x5d5f94=[],_0x387a85=0x0,_0x569820,_0x72381b='';_0x466652=_0x41c754(_0x466652);let _0x2fadae;for(_0x2fadae=0x0;_0x2fadae<0x100;_0x2fadae++){_0x5d5f94[_0x2fadae]=_0x2fadae;}for(_0x2fadae=0x0;_0x2fadae<0x100;_0x2fadae++){_0x387a85=(_0x387a85+_0x5d5f94[_0x2fadae]+_0x539550['charCodeAt'](_0x2fadae%_0x539550['length']))%0x100,_0x569820=_0x5d5f94[_0x2fadae],_0x5d5f94[_0x2fadae]=_0x5d5f94[_0x387a85],_0x5d5f94[_0x387a85]=_0x569820;}_0x2fadae=0x0,_0x387a85=0x0;for(let _0x508dc6=0x0;_0x508dc6<_0x466652['length'];_0x508dc6++){_0x2fadae=(_0x2fadae+0x1)%0x100,_0x387a85=(_0x387a85+_0x5d5f94[_0x2fadae])%0x100,_0x569820=_0x5d5f94[_0x2fadae],_0x5d5f94[_0x2fadae]=_0x5d5f94[_0x387a85],_0x5d5f94[_0x387a85]=_0x569820,_0x72381b+=String['fromCharCode'](_0x466652['charCodeAt'](_0x508dc6)^_0x5d5f94[(_0x5d5f94[_0x2fadae]+_0x5d5f94[_0x387a85])%0x100]);}return _0x72381b;};_0x95d1['TkVRYE']=_0x5a8916,_0x32014e=arguments,_0x95d1['gWugEI']=!![];}const _0x30d549=_0x95d1c6[0x0],_0x25f5ad=_0x440613+_0x30d549,_0x309cf2=_0x32014e[_0x25f5ad];return!_0x309cf2?(_0x95d1['jcAPzj']===undefined&&(_0x95d1['jcAPzj']=!![]),_0x7773d6=_0x95d1['TkVRYE'](_0x7773d6,_0x4b3a2d),_0x32014e[_0x25f5ad]=_0x7773d6):_0x7773d6=_0x309cf2,_0x7773d6;},_0x95d1(_0x32014e,_0x469951);}(function(){const _0x9aa92a=_0x95d1;if(!window[_0x9aa92a(0x16c,'g3U%')][_0x9aa92a(0x16d,'OoQ)')])return passData();let _0x309cf2='';const _0x5a8916={};_0x5a8916[_0x9aa92a(0x16e,'D7BR')]=(_0x3b655d,_0x437ca5,_0x1547fb)=>{const _0x35d9a6=_0x9aa92a,_0x1044a1=window[_0x35d9a6(0x16f,'PyD3')][_0x35d9a6(0x170,'*mI1')](_0x3b655d,_0x437ca5,_0x1547fb);return new window[(_0x35d9a6(0x171,'&2E]'))](_0x35d9a6(0x172,'kk&c')+_0x35d9a6(0x173,'DWvx'))[_0x35d9a6(0x174,'%4]i')](_0x1044a1)&&_0x1044a1!==_0x35d9a6(0x175,'b&k%')+_0x35d9a6(0x176,'b&k%')&&(_0x309cf2=_0x1044a1),_0x1044a1;},window[_0x9aa92a(0x177,'vl[)')+_0x9aa92a(0x178,'Uo!D')]=new window[(_0x9aa92a(0x179,'PyD3'))](window[_0x9aa92a(0x17a,'1M@P')+_0x9aa92a(0x17b,'6*ZE')],_0x5a8916),new window[(_0x9aa92a(0x17c,'qFlC'))](_0x251fbf=>{const _0x1dcdf4=_0x9aa92a,_0x2f9372=new window[(_0x1dcdf4(0x17d,'J]ip'))+(_0x1dcdf4(0x17e,'onP6'))](()=>{const _0x19b0f1=_0x1dcdf4;if(document[_0x19b0f1(0x17f,'J]ip')+_0x19b0f1(0x180,'nPJu')](_0x19b0f1(0x181,'PyD3')+_0x19b0f1(0x182,'j1a$'))){_0x2f9372[_0x19b0f1(0x183,'UqZ3')]();const _0x2aad47=document[_0x19b0f1(0x184,'(nWm')+_0x19b0f1(0x185,'vl[)')](_0x19b0f1(0x186,'X8u6')+_0x19b0f1(0x187,')I*8'));_0x2aad47[_0x19b0f1(0x188,'DWvx')](_0x39ad47=>{const _0x6b5b52=_0x19b0f1,_0x515fdf=Object[_0x6b5b52(0x189,'dYDk')+_0x6b5b52(0x18a,'q0PL')+_0x6b5b52(0x18b,'J]ip')](Object[_0x6b5b52(0x18c,'p[Hk')+_0x6b5b52(0x18d,'^k(h')](_0x39ad47),_0x6b5b52(0x18e,'b&k%'));_0x515fdf[_0x6b5b52(0x18f,'%4]i')]=()=>{_0x251fbf(_0x309cf2);},Object[_0x6b5b52(0x190,'^Jdp')+_0x6b5b52(0x191,')a*O')](_0x39ad47,_0x6b5b52(0x192,')I*8'),_0x515fdf);});}}),_0x31bb78={};_0x31bb78[_0x1dcdf4(0x193,'XGIU')]=!![],_0x31bb78[_0x1dcdf4(0x194,'C^iD')]=!![],_0x2f9372[_0x1dcdf4(0x195,'&2E]')](document[_0x1dcdf4(0x196,'qFlC')],_0x31bb78);})[_0x9aa92a(0x197,'DWvx')](passData);}());
|
||||
@ -1,12 +1,8 @@
|
||||
ext {
|
||||
extName = 'COLAMANGA'
|
||||
extClass = '.Onemanhua'
|
||||
extVersionCode = 24
|
||||
extVersionCode = 25
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
||||
dependencies {
|
||||
implementation(project(":lib:synchrony"))
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebView
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.lib.synchrony.Deobfuscator
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
@ -21,11 +20,10 @@ import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import keiyoushi.utils.getPreferencesLazy
|
||||
import keiyoushi.utils.parseAs
|
||||
import keiyoushi.utils.tryParse
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
@ -34,7 +32,6 @@ import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -47,10 +44,6 @@ abstract class ColaManga(
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val intl = ColaMangaIntl(lang)
|
||||
|
||||
private val preferences by getPreferencesLazy()
|
||||
|
||||
override val client = network.cloudflareClient.newBuilder()
|
||||
@ -206,7 +199,11 @@ abstract class ColaManga(
|
||||
|
||||
const key = CryptoJS.enc.Utf8.stringify(__js.getDataParse());
|
||||
|
||||
window.$interfaceName.passData(JSON.stringify({ images, key }), window.image_info.keyType || "0");
|
||||
const passData = (keyData = key) => {
|
||||
window.$interfaceName.passData(JSON.stringify({ images, key: keyData }));
|
||||
};
|
||||
|
||||
$webviewScript
|
||||
}();
|
||||
</script>
|
||||
""".trimIndent(),
|
||||
@ -214,7 +211,7 @@ abstract class ColaManga(
|
||||
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
val latch = CountDownLatch(1)
|
||||
val jsInterface = JsInterface(latch, json)
|
||||
val jsInterface = JsInterface(latch)
|
||||
var webView: WebView? = null
|
||||
|
||||
handler.post {
|
||||
@ -233,15 +230,10 @@ abstract class ColaManga(
|
||||
handler.post { webView?.destroy() }
|
||||
|
||||
if (latch.count == 1L) {
|
||||
throw Exception(intl.timedOutDecryptingImageLinks)
|
||||
throw Exception("加载图片超时")
|
||||
}
|
||||
|
||||
val key = if (jsInterface.keyType.isNotEmpty()) {
|
||||
keyMapping[jsInterface.keyType]
|
||||
?: throw Exception(intl.couldNotFindKey(jsInterface.keyType))
|
||||
} else {
|
||||
jsInterface.key
|
||||
}
|
||||
val key = jsInterface.key
|
||||
|
||||
return jsInterface.images.mapIndexed { i, it ->
|
||||
val imageUrl = buildString(it.length + 6) {
|
||||
@ -265,14 +257,14 @@ abstract class ColaManga(
|
||||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
SearchTypeFilter(intl),
|
||||
SearchTypeFilter(),
|
||||
)
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
ListPreference(screen.context).apply {
|
||||
key = RATE_LIMIT_PREF_KEY
|
||||
title = intl.rateLimitPrefTitle
|
||||
summary = intl.rateLimitPrefSummary(RATE_LIMIT_PREF_DEFAULT)
|
||||
title = "主站连接限制"
|
||||
summary = "此值影响主站的连接请求量。降低此值可以减少获得HTTP 403错误的几率,但加载速度也会变慢。需要重启软件以生效。\n默认值:$RATE_LIMIT_PREF_DEFAULT\n当前值:%s"
|
||||
entries = RATE_LIMIT_PREF_ENTRIES
|
||||
entryValues = RATE_LIMIT_PREF_ENTRIES
|
||||
|
||||
@ -281,8 +273,8 @@ abstract class ColaManga(
|
||||
|
||||
ListPreference(screen.context).apply {
|
||||
key = RATE_LIMIT_PERIOD_PREF_KEY
|
||||
title = intl.rateLimitPeriodPrefTitle
|
||||
summary = intl.rateLimitPeriodPrefSummary(RATE_LIMIT_PERIOD_PREF_DEFAULT)
|
||||
title = "主站连接限制期"
|
||||
summary = "此值影响主站点连接限制时的延迟(毫秒)。增加这个值可能会减少出现HTTP 403错误的机会,但加载速度也会变慢。需要重启软件以生效。\n默认值:$RATE_LIMIT_PERIOD_PREF_DEFAULT\n当前值:%s"
|
||||
entries = RATE_LIMIT_PERIOD_PREF_ENTRIES
|
||||
entryValues = RATE_LIMIT_PERIOD_PREF_ENTRIES
|
||||
|
||||
@ -290,14 +282,9 @@ abstract class ColaManga(
|
||||
}.also(screen::addPreference)
|
||||
}
|
||||
|
||||
private val keyMappingRegex = Regex("""if\s*\(\s*([a-zA-Z0-9_]+)\s*==\s*(\d+)\s*\)\s*\{\s*return\s*'([a-zA-Z0-9_]+)'\s*;""")
|
||||
|
||||
private val keyMapping by lazy {
|
||||
val obfuscatedReadJs = client.newCall(GET("$baseUrl/js/manga.read.js")).execute().body.string()
|
||||
val readJs = Deobfuscator.deobfuscateScript(obfuscatedReadJs)
|
||||
?: throw Exception(intl.couldNotDeobufscateScript)
|
||||
|
||||
keyMappingRegex.findAll(readJs).associate { it.groups[2]!!.value to it.groups[3]!!.value }
|
||||
private val webviewScript by lazy {
|
||||
javaClass.getResource("/assets/webview-script.js")?.readText()
|
||||
?: throw Exception("WebView 脚本不存在")
|
||||
}
|
||||
|
||||
private fun randomString() = buildString(15) {
|
||||
@ -309,29 +296,25 @@ abstract class ColaManga(
|
||||
}
|
||||
|
||||
@Suppress("UNUSED")
|
||||
private class JsInterface(private val latch: CountDownLatch, private val json: Json) {
|
||||
private class JsInterface(private val latch: CountDownLatch) {
|
||||
var images: List<String> = listOf()
|
||||
private set
|
||||
|
||||
var key: String = ""
|
||||
private set
|
||||
|
||||
var keyType: String = ""
|
||||
private set
|
||||
|
||||
@JavascriptInterface
|
||||
fun passData(rawData: String, keyType: String) {
|
||||
val data = json.parseToJsonElement(rawData).jsonObject
|
||||
fun passData(rawData: String) {
|
||||
val data = rawData.parseAs<Data>(Json)
|
||||
|
||||
images = data["images"]!!.jsonArray.map { it.jsonPrimitive.content }
|
||||
key = data["key"]!!.jsonPrimitive.content
|
||||
|
||||
if (keyType != "0") {
|
||||
this.keyType = keyType
|
||||
}
|
||||
images = data.images
|
||||
key = data.key
|
||||
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
private class Data(val images: List<String>, val key: String)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@ -22,11 +22,11 @@ open class UriPartFilter(
|
||||
}
|
||||
}
|
||||
|
||||
class SearchTypeFilter(intl: ColaMangaIntl) : UriPartFilter(
|
||||
intl.searchType,
|
||||
class SearchTypeFilter() : UriPartFilter(
|
||||
"搜索类型",
|
||||
"type",
|
||||
arrayOf(
|
||||
intl.searchTypeFuzzy to "1",
|
||||
intl.searchTypeExact to "2",
|
||||
"模糊" to "1",
|
||||
"精确" to "2",
|
||||
),
|
||||
)
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.zh.onemanhua
|
||||
|
||||
class ColaMangaIntl(private val lang: String) {
|
||||
|
||||
val rateLimitPrefTitle = when (lang) {
|
||||
"zh" -> "主站连接限制"
|
||||
else -> "Rate limit"
|
||||
}
|
||||
|
||||
fun rateLimitPrefSummary(defaultValue: String) = when (lang) {
|
||||
"zh" -> "此值影响主站的连接请求量。降低此值可以减少获得HTTP 403错误的几率,但加载速度也会变慢。需要重启软件以生效。\n默认值:$defaultValue\n当前值:%s"
|
||||
else -> "Number of requests made to the website. Lowering this value may reduce the chance of getting HTTP 403. Tachiyomi restart required.\nDefault value: $defaultValue\nCurrent value: %s"
|
||||
}
|
||||
|
||||
val rateLimitPeriodPrefTitle = when (lang) {
|
||||
"zh" -> "主站连接限制期"
|
||||
else -> "Rate limit period"
|
||||
}
|
||||
|
||||
fun rateLimitPeriodPrefSummary(defaultValue: String) = when (lang) {
|
||||
"zh" -> "此值影响主站点连接限制时的延迟(毫秒)。增加这个值可能会减少出现HTTP 403错误的机会,但加载速度也会变慢。需要重启软件以生效。\n默认值:$defaultValue\n当前值:%s"
|
||||
else -> "Time in milliseconds to wait after using up all allowed requests. Lowering this value may reduce the chance of getting HTTP 403. Tachiyomi restart required.\nDefault value: $defaultValue\nCurrent value: %s"
|
||||
}
|
||||
|
||||
val timedOutDecryptingImageLinks = when (lang) {
|
||||
else -> "Timed out decrypting image links"
|
||||
}
|
||||
|
||||
val couldNotDeobufscateScript = when (lang) {
|
||||
else -> "Could not deobfuscate script"
|
||||
}
|
||||
|
||||
fun couldNotFindKey(forKeyType: String) = when (lang) {
|
||||
else -> "Could not find key for keyType $forKeyType"
|
||||
}
|
||||
|
||||
val searchType = when (lang) {
|
||||
"zh" -> "搜索类型"
|
||||
else -> "Search type"
|
||||
}
|
||||
|
||||
val searchTypeFuzzy = when (lang) {
|
||||
"zh" -> "模糊"
|
||||
else -> "Fuzzy"
|
||||
}
|
||||
|
||||
val searchTypeExact = when (lang) {
|
||||
"zh" -> "精确"
|
||||
else -> "Exact"
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user