优化
This commit is contained in:
@@ -5,6 +5,7 @@ import android.webkit.WebSettings
|
||||
import androidx.annotation.Keep
|
||||
import cn.hutool.core.codec.Base64
|
||||
import cn.hutool.core.util.HexUtil
|
||||
import com.script.rhino.RhinoContext
|
||||
import io.legado.app.constant.AppConst
|
||||
import io.legado.app.constant.AppConst.dateFormat
|
||||
import io.legado.app.constant.AppLog
|
||||
@@ -50,6 +51,7 @@ import kotlinx.coroutines.runBlocking
|
||||
import okio.use
|
||||
import org.jsoup.Connection
|
||||
import org.jsoup.Jsoup
|
||||
import org.mozilla.javascript.Context
|
||||
import splitties.init.appCtx
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
@@ -65,6 +67,8 @@ import java.util.SimpleTimeZone
|
||||
import java.util.UUID
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
/**
|
||||
* js扩展类, 在js中通过java变量调用
|
||||
@@ -78,6 +82,12 @@ interface JsExtensions : JsEncodeUtils {
|
||||
|
||||
fun getSource(): BaseSource?
|
||||
|
||||
private val context: CoroutineContext
|
||||
get() {
|
||||
val rhinoContext = Context.getCurrentContext() as RhinoContext
|
||||
return rhinoContext.coroutineContext ?: EmptyCoroutineContext
|
||||
}
|
||||
|
||||
/**
|
||||
* 访问网络,返回String
|
||||
*/
|
||||
@@ -87,9 +97,9 @@ interface JsExtensions : JsEncodeUtils {
|
||||
} else {
|
||||
url.toString()
|
||||
}
|
||||
return runBlocking {
|
||||
val analyzeUrl = AnalyzeUrl(urlStr, source = getSource(), coroutineContext = context)
|
||||
return runBlocking(context) {
|
||||
kotlin.runCatching {
|
||||
val analyzeUrl = AnalyzeUrl(urlStr, source = getSource())
|
||||
analyzeUrl.getStrResponseAwait().body
|
||||
}.onFailure {
|
||||
AppLog.put("ajax(${urlStr}) error\n${it.localizedMessage}", it)
|
||||
@@ -103,7 +113,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
* 并发访问网络
|
||||
*/
|
||||
fun ajaxAll(urlList: Array<String>): Array<StrResponse?> {
|
||||
return runBlocking {
|
||||
return runBlocking(context) {
|
||||
val asyncArray = Array(urlList.size) {
|
||||
async(IO) {
|
||||
val url = urlList[it]
|
||||
@@ -122,7 +132,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
* 访问网络,返回Response<String>
|
||||
*/
|
||||
fun connect(urlStr: String): StrResponse {
|
||||
return runBlocking {
|
||||
return runBlocking(context) {
|
||||
val analyzeUrl = AnalyzeUrl(urlStr, source = getSource())
|
||||
kotlin.runCatching {
|
||||
analyzeUrl.getStrResponseAwait()
|
||||
@@ -135,7 +145,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
}
|
||||
|
||||
fun connect(urlStr: String, header: String?): StrResponse {
|
||||
return runBlocking {
|
||||
return runBlocking(context) {
|
||||
val headerMap = GSON.fromJsonObject<Map<String, String>>(header).getOrNull()
|
||||
val analyzeUrl = AnalyzeUrl(urlStr, headerMapF = headerMap, source = getSource())
|
||||
kotlin.runCatching {
|
||||
@@ -156,7 +166,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
* @return 返回js获取的内容
|
||||
*/
|
||||
fun webView(html: String?, url: String?, js: String?): String? {
|
||||
return runBlocking {
|
||||
return runBlocking(context) {
|
||||
BackstageWebView(
|
||||
url = url,
|
||||
html = html,
|
||||
@@ -171,7 +181,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
* 使用webView获取资源url
|
||||
*/
|
||||
fun webViewGetSource(html: String?, url: String?, js: String?, sourceRegex: String): String? {
|
||||
return runBlocking {
|
||||
return runBlocking(context) {
|
||||
BackstageWebView(
|
||||
url = url,
|
||||
html = html,
|
||||
@@ -192,7 +202,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
js: String?,
|
||||
overrideUrlRegex: String
|
||||
): String? {
|
||||
return runBlocking {
|
||||
return runBlocking(context) {
|
||||
BackstageWebView(
|
||||
url = url,
|
||||
html = html,
|
||||
@@ -294,7 +304,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
* @return 下载的文件相对路径
|
||||
*/
|
||||
fun downloadFile(url: String): String {
|
||||
val analyzeUrl = AnalyzeUrl(url, source = getSource())
|
||||
val analyzeUrl = AnalyzeUrl(url, source = getSource(), coroutineContext = context)
|
||||
val type = UrlUtil.getSuffix(url, analyzeUrl.type)
|
||||
val path = FileUtils.getPath(
|
||||
File(FileUtils.getCachePath()),
|
||||
@@ -321,7 +331,8 @@ interface JsExtensions : JsEncodeUtils {
|
||||
ReplaceWith("downloadFile(url: String)")
|
||||
)
|
||||
fun downloadFile(content: String, url: String): String {
|
||||
val type = AnalyzeUrl(url, source = getSource()).type ?: return ""
|
||||
val type = AnalyzeUrl(url, source = getSource(), coroutineContext = context).type
|
||||
?: return ""
|
||||
val path = FileUtils.getPath(
|
||||
FileUtils.createFolderIfNotExist(FileUtils.getCachePath()),
|
||||
"${MD5Utils.md5Encode16(url)}.${type}"
|
||||
@@ -689,7 +700,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
*/
|
||||
fun getZipByteArrayContent(url: String, path: String): ByteArray? {
|
||||
val bytes = if (url.isAbsUrl()) {
|
||||
AnalyzeUrl(url, source = getSource()).getByteArray()
|
||||
AnalyzeUrl(url, source = getSource(), coroutineContext = context).getByteArray()
|
||||
} else {
|
||||
HexUtil.decodeHex(url)
|
||||
}
|
||||
@@ -717,7 +728,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
*/
|
||||
fun getRarByteArrayContent(url: String, path: String): ByteArray? {
|
||||
val bytes = if (url.isAbsUrl()) {
|
||||
AnalyzeUrl(url, source = getSource()).getByteArray()
|
||||
AnalyzeUrl(url, source = getSource(), coroutineContext = context).getByteArray()
|
||||
} else {
|
||||
HexUtil.decodeHex(url)
|
||||
}
|
||||
@@ -735,7 +746,7 @@ interface JsExtensions : JsEncodeUtils {
|
||||
*/
|
||||
fun get7zByteArrayContent(url: String, path: String): ByteArray? {
|
||||
val bytes = if (url.isAbsUrl()) {
|
||||
AnalyzeUrl(url, source = getSource()).getByteArray()
|
||||
AnalyzeUrl(url, source = getSource(), coroutineContext = context).getByteArray()
|
||||
} else {
|
||||
HexUtil.decodeHex(url)
|
||||
}
|
||||
@@ -769,14 +780,20 @@ interface JsExtensions : JsEncodeUtils {
|
||||
when (data) {
|
||||
is String -> {
|
||||
if (useCache) {
|
||||
key = MessageDigest.getInstance("SHA-256").digest(data.toByteArray()).toHexString()
|
||||
key = MessageDigest.getInstance("SHA-256").digest(data.toByteArray())
|
||||
.toHexString()
|
||||
qTTF = CacheManager.getQueryTTF(key)
|
||||
if (qTTF != null) return qTTF
|
||||
}
|
||||
val font: ByteArray? = when {
|
||||
data.isContentScheme() -> Uri.parse(data).readBytes(appCtx)
|
||||
data.startsWith("/storage") -> File(data).readBytes()
|
||||
data.isAbsUrl() -> AnalyzeUrl(data, source = getSource()).getByteArray()
|
||||
data.isAbsUrl() -> AnalyzeUrl(
|
||||
data,
|
||||
source = getSource(),
|
||||
coroutineContext = context
|
||||
).getByteArray()
|
||||
|
||||
else -> base64DecodeToByteArray(data)
|
||||
}
|
||||
font ?: return null
|
||||
|
||||
@@ -32,7 +32,9 @@ import java.util.regex.Pattern
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.set
|
||||
import kotlin.coroutines.ContinuationInterceptor
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
/**
|
||||
* 解析规则获取结果
|
||||
@@ -67,7 +69,7 @@ class AnalyzeRule(
|
||||
|
||||
private val stringRuleCache = hashMapOf<String, List<SourceRule>>()
|
||||
|
||||
private var coroutineContext: CoroutineContext? = null
|
||||
private var coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
|
||||
@JvmOverloads
|
||||
fun setContent(content: Any?, baseUrl: String? = null): AnalyzeRule {
|
||||
@@ -84,8 +86,8 @@ class AnalyzeRule(
|
||||
return this
|
||||
}
|
||||
|
||||
fun setCoroutineContext(context: CoroutineContext?): AnalyzeRule {
|
||||
coroutineContext = context
|
||||
fun setCoroutineContext(context: CoroutineContext): AnalyzeRule {
|
||||
coroutineContext = context.minusKey(ContinuationInterceptor)
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -777,9 +779,14 @@ class AnalyzeRule(
|
||||
} else {
|
||||
url.toString()
|
||||
}
|
||||
return runBlocking {
|
||||
val analyzeUrl = AnalyzeUrl(
|
||||
urlStr,
|
||||
source = source,
|
||||
ruleData = book,
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
return runBlocking(coroutineContext) {
|
||||
kotlin.runCatching {
|
||||
val analyzeUrl = AnalyzeUrl(urlStr, source = source, ruleData = book)
|
||||
analyzeUrl.getStrResponseAwait().body
|
||||
}.onFailure {
|
||||
log("ajax(${urlStr}) error\n${it.stackTraceToString()}")
|
||||
@@ -797,7 +804,7 @@ class AnalyzeRule(
|
||||
val bookSource = source as? BookSource
|
||||
val book = book as? Book
|
||||
if (bookSource == null || book == null) return
|
||||
runBlocking {
|
||||
runBlocking(coroutineContext) {
|
||||
withTimeout(1800000) {
|
||||
WebBook.preciseSearchAwait(this, bookSource, book.name, book.author)
|
||||
.getOrThrow().let {
|
||||
@@ -818,7 +825,7 @@ class AnalyzeRule(
|
||||
val bookSource = source as? BookSource
|
||||
val book = book as? Book
|
||||
if (bookSource == null || book == null) return
|
||||
runBlocking {
|
||||
runBlocking(coroutineContext) {
|
||||
withTimeout(1800000) {
|
||||
WebBook.getBookInfoAwait(bookSource, book)
|
||||
}
|
||||
@@ -832,7 +839,7 @@ class AnalyzeRule(
|
||||
val bookSource = source as? BookSource
|
||||
val book = book as? Book
|
||||
if (bookSource == null || book == null) return
|
||||
runBlocking {
|
||||
runBlocking(coroutineContext) {
|
||||
withTimeout(1800000) {
|
||||
WebBook.getBookInfoAwait(bookSource, book)
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@ import java.io.InputStream
|
||||
import java.net.URLEncoder
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.coroutines.ContinuationInterceptor
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
@@ -55,6 +58,7 @@ class AnalyzeUrl(
|
||||
private val ruleData: RuleDataInterface? = null,
|
||||
private val chapter: BookChapter? = null,
|
||||
private val readTimeout: Long? = null,
|
||||
private var coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
headerMapF: Map<String, String>? = null,
|
||||
) : JsExtensions {
|
||||
companion object {
|
||||
@@ -89,6 +93,7 @@ class AnalyzeUrl(
|
||||
private set
|
||||
|
||||
init {
|
||||
coroutineContext = coroutineContext.minusKey(ContinuationInterceptor)
|
||||
val urlMatcher = paramPattern.matcher(baseUrl)
|
||||
if (urlMatcher.find()) baseUrl = baseUrl.substring(0, urlMatcher.start())
|
||||
(headerMapF ?: source?.getHeaderMap(true))?.let {
|
||||
@@ -278,7 +283,7 @@ class AnalyzeUrl(
|
||||
source?.getShareScope()?.let {
|
||||
scope.prototype = it
|
||||
}
|
||||
return RhinoScriptEngine.eval(jsStr, scope)
|
||||
return RhinoScriptEngine.eval(jsStr, scope, coroutineContext)
|
||||
}
|
||||
|
||||
fun put(key: String, value: String): String {
|
||||
@@ -476,7 +481,7 @@ class AnalyzeUrl(
|
||||
sourceRegex: String? = null,
|
||||
useWebView: Boolean = true,
|
||||
): StrResponse {
|
||||
return runBlocking {
|
||||
return runBlocking(coroutineContext) {
|
||||
getStrResponseAwait(jsStr, sourceRegex, useWebView)
|
||||
}
|
||||
}
|
||||
@@ -527,7 +532,7 @@ class AnalyzeUrl(
|
||||
}
|
||||
|
||||
fun getResponse(): Response {
|
||||
return runBlocking {
|
||||
return runBlocking(coroutineContext) {
|
||||
getResponseAwait()
|
||||
}
|
||||
}
|
||||
@@ -553,7 +558,7 @@ class AnalyzeUrl(
|
||||
}
|
||||
|
||||
fun getByteArray(): ByteArray {
|
||||
return runBlocking {
|
||||
return runBlocking(coroutineContext) {
|
||||
getByteArrayAwait()
|
||||
}
|
||||
}
|
||||
@@ -569,7 +574,7 @@ class AnalyzeUrl(
|
||||
}
|
||||
|
||||
fun getInputStream(): InputStream {
|
||||
return runBlocking {
|
||||
return runBlocking(coroutineContext) {
|
||||
getInputStreamAwait()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,12 +63,14 @@ object BookChapterList {
|
||||
var nextUrl = chapterData.second[0]
|
||||
while (nextUrl.isNotEmpty() && !nextUrlList.contains(nextUrl)) {
|
||||
nextUrlList.add(nextUrl)
|
||||
val res = AnalyzeUrl(
|
||||
val analyzeUrl = AnalyzeUrl(
|
||||
mUrl = nextUrl,
|
||||
source = bookSource,
|
||||
ruleData = book,
|
||||
headerMapF = bookSource.getHeaderMap()
|
||||
).getStrResponseAwait() //控制并发访问
|
||||
headerMapF = bookSource.getHeaderMap(),
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
val res = analyzeUrl.getStrResponseAwait() //控制并发访问
|
||||
res.body?.let { nextBody ->
|
||||
chapterData = analyzeChapterList(
|
||||
book, nextUrl, nextUrl,
|
||||
@@ -91,12 +93,14 @@ object BookChapterList {
|
||||
emit(urlStr)
|
||||
}
|
||||
}.mapAsync(AppConfig.threadCount) { urlStr ->
|
||||
val res = AnalyzeUrl(
|
||||
val analyzeUrl = AnalyzeUrl(
|
||||
mUrl = urlStr,
|
||||
source = bookSource,
|
||||
ruleData = book,
|
||||
headerMapF = bookSource.getHeaderMap()
|
||||
).getStrResponseAwait() //控制并发访问
|
||||
headerMapF = bookSource.getHeaderMap(),
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
val res = analyzeUrl.getStrResponseAwait() //控制并发访问
|
||||
analyzeChapterList(
|
||||
book, urlStr, res.url,
|
||||
res.body!!, tocRule, listRule, bookSource, false
|
||||
|
||||
@@ -86,12 +86,14 @@ object BookContent {
|
||||
) break
|
||||
nextUrlList.add(nextUrl)
|
||||
coroutineContext.ensureActive()
|
||||
val res = AnalyzeUrl(
|
||||
val analyzeUrl = AnalyzeUrl(
|
||||
mUrl = nextUrl,
|
||||
source = bookSource,
|
||||
ruleData = book,
|
||||
headerMapF = bookSource.getHeaderMap()
|
||||
).getStrResponseAwait() //控制并发访问
|
||||
headerMapF = bookSource.getHeaderMap(),
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
val res = analyzeUrl.getStrResponseAwait() //控制并发访问
|
||||
res.body?.let { nextBody ->
|
||||
contentData = analyzeContent(
|
||||
book, nextUrl, res.url, nextBody, contentRule,
|
||||
@@ -112,12 +114,14 @@ object BookContent {
|
||||
emit(urlStr)
|
||||
}
|
||||
}.mapAsync(AppConfig.threadCount) { urlStr ->
|
||||
val res = AnalyzeUrl(
|
||||
val analyzeUrl = AnalyzeUrl(
|
||||
mUrl = urlStr,
|
||||
source = bookSource,
|
||||
ruleData = book,
|
||||
headerMapF = bookSource.getHeaderMap()
|
||||
).getStrResponseAwait() //控制并发访问
|
||||
headerMapF = bookSource.getHeaderMap(),
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
val res = analyzeUrl.getStrResponseAwait() //控制并发访问
|
||||
analyzeContent(
|
||||
book, urlStr, res.url, res.body!!, contentRule,
|
||||
bookChapter, bookSource, mNextChapterUrl,
|
||||
|
||||
@@ -61,6 +61,7 @@ object WebBook {
|
||||
headerMapF = bookSource.getHeaderMap(true),
|
||||
source = bookSource,
|
||||
ruleData = ruleData,
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
var res = analyzeUrl.getStrResponseAwait()
|
||||
//检测书源是否已登录
|
||||
@@ -107,7 +108,8 @@ object WebBook {
|
||||
baseUrl = bookSource.bookSourceUrl,
|
||||
source = bookSource,
|
||||
ruleData = ruleData,
|
||||
headerMapF = bookSource.getHeaderMap(true)
|
||||
headerMapF = bookSource.getHeaderMap(true),
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
var res = analyzeUrl.getStrResponseAwait()
|
||||
//检测书源是否已登录
|
||||
@@ -164,7 +166,8 @@ object WebBook {
|
||||
baseUrl = bookSource.bookSourceUrl,
|
||||
source = bookSource,
|
||||
ruleData = book,
|
||||
headerMapF = bookSource.getHeaderMap(true)
|
||||
headerMapF = bookSource.getHeaderMap(true),
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
var res = analyzeUrl.getStrResponseAwait()
|
||||
//检测书源是否已登录
|
||||
@@ -244,7 +247,8 @@ object WebBook {
|
||||
baseUrl = book.bookUrl,
|
||||
source = bookSource,
|
||||
ruleData = book,
|
||||
headerMapF = bookSource.getHeaderMap(true)
|
||||
headerMapF = bookSource.getHeaderMap(true),
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
var res = analyzeUrl.getStrResponseAwait()
|
||||
//检测书源是否已登录
|
||||
@@ -317,7 +321,8 @@ object WebBook {
|
||||
source = bookSource,
|
||||
ruleData = book,
|
||||
chapter = bookChapter,
|
||||
headerMapF = bookSource.getHeaderMap(true)
|
||||
headerMapF = bookSource.getHeaderMap(true),
|
||||
coroutineContext = coroutineContext
|
||||
)
|
||||
var res = analyzeUrl.getStrResponseAwait(
|
||||
jsStr = bookSource.getContentRule().webJs,
|
||||
|
||||
Reference in New Issue
Block a user