pull/2431/head
kunfei 2 years ago
parent 3068eb2138
commit b95856ff84
  1. 2
      app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt
  2. 67
      app/src/main/java/io/legado/app/utils/RegexExtensions.kt

@ -145,7 +145,7 @@ class Coroutine<T>(
context: CoroutineContext, context: CoroutineContext,
block: suspend CoroutineScope.() -> T block: suspend CoroutineScope.() -> T
): Job { ): Job {
return (scope + Dispatchers.Main).launch(start = startOption) { return (scope.plus(Dispatchers.Main)).launch(start = startOption) {
try { try {
start?.let { dispatchVoidCallback(this, it) } start?.let { dispatchVoidCallback(this, it) }
ensureActive() ensureActive()

@ -1,35 +1,64 @@
package io.legado.app.utils package io.legado.app.utils
import android.util.Log
import androidx.core.os.postDelayed
import com.script.SimpleBindings import com.script.SimpleBindings
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import io.legado.app.exception.RegexTimeoutException import io.legado.app.exception.RegexTimeoutException
import io.legado.app.help.CrashHandler
import io.legado.app.help.coroutine.Coroutine
import kotlinx.coroutines.suspendCancellableCoroutine
import splitties.init.appCtx
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
private val handler by lazy { buildMainHandler() }
/** /**
* 带有超时检测的正则替换 * 带有超时检测的正则替换
*/ */
fun CharSequence.replace(regex: Regex, replacement: String, timeout: Long): String { suspend fun CharSequence.replace(regex: Regex, replacement: String, timeout: Long): String {
val startTime = System.currentTimeMillis() val charSequence = this@replace
val charSequence = this
val isJs = replacement.startsWith("@js:") val isJs = replacement.startsWith("@js:")
val replacement1 = if (isJs) replacement.substring(4) else replacement val replacement1 = if (isJs) replacement.substring(4) else replacement
val pattern = regex.toPattern() return suspendCancellableCoroutine { block ->
val matcher = pattern.matcher(charSequence) val coroutine = Coroutine.async {
val stringBuffer = StringBuffer() try {
while (matcher.find()) { val pattern = regex.toPattern()
if (System.currentTimeMillis() - startTime > timeout) { val matcher = pattern.matcher(charSequence)
val timeoutMsg = "替换超时,将禁用替换规则" val stringBuffer = StringBuffer()
throw RegexTimeoutException(timeoutMsg) while (matcher.find()) {
if (isJs) {
val bindings = SimpleBindings()
bindings["result"] = matcher.group()
val jsResult =
AppConst.SCRIPT_ENGINE.eval(replacement1, bindings).toString()
matcher.appendReplacement(stringBuffer, jsResult)
} else {
matcher.appendReplacement(stringBuffer, replacement1)
}
}
matcher.appendTail(stringBuffer)
Log.e("regex", "end")
block.resume(stringBuffer.toString())
} catch (e: Exception) {
block.resumeWithException(e)
}
} }
if (isJs) { handler.postDelayed(timeout) {
val bindings = SimpleBindings() if (coroutine.isActive) {
bindings["result"] = matcher.group() val timeoutMsg = "替换超时,3秒后还未结束将重启应用\n替换规则$regex\n替换内容:${this}"
val jsResult = AppConst.SCRIPT_ENGINE.eval(replacement1, bindings).toString() val exception = RegexTimeoutException(timeoutMsg)
matcher.appendReplacement(stringBuffer, jsResult) block.cancel(exception)
} else { appCtx.longToastOnUi(timeoutMsg)
matcher.appendReplacement(stringBuffer, replacement1) CrashHandler.saveCrashInfo2File(exception)
handler.postDelayed(3000) {
if (coroutine.isActive) {
appCtx.restart()
}
}
}
} }
} }
matcher.appendTail(stringBuffer)
return stringBuffer.toString()
} }

Loading…
Cancel
Save