Refactor in cloudflare interceptor and quickjs dependency
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -29,4 +29,5 @@ build/
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
/aniyomi-extensions/
|
||||
|
||||
@@ -63,19 +63,7 @@
|
||||
<version>4.6.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JavaScript Engine -->
|
||||
<dependency>
|
||||
<groupId>org.graalvm.polyglot</groupId>
|
||||
<artifactId>polyglot</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.graalvm.js</groupId>-->
|
||||
<!-- <artifactId>js-scriptengine</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.graalvm.js</groupId>-->
|
||||
<!-- <artifactId>js-language</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- JavaScript Engine (provided by aniyomibridge-core module) -->
|
||||
|
||||
<!-- RxJava -->
|
||||
<dependency>
|
||||
|
||||
@@ -135,6 +135,13 @@ public class WebView {
|
||||
);
|
||||
|
||||
webViewClient.onReceivedError(this, request, error);
|
||||
|
||||
// Sync cookies back so CloudflareInterceptor can evaluate cf_clearance
|
||||
syncCookiesFromHtmlUnitToAndroid(url);
|
||||
|
||||
// Notify page finished — Android's real WebView calls this even on error,
|
||||
// and CloudflareInterceptor relies on it to count down the latch.
|
||||
webViewClient.onPageFinished(this, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,33 +93,13 @@
|
||||
<dependency>
|
||||
<groupId>io.github.dokar3</groupId>
|
||||
<artifactId>quickjs-kt-jvm</artifactId>
|
||||
<version>1.0.0-alpha11</version>
|
||||
<version>1.0.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.datlag.jsunpacker</groupId>
|
||||
<artifactId>jsunpacker-jvm</artifactId>
|
||||
<version>1.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.polyglot</groupId>
|
||||
<artifactId>polyglot</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js-scriptengine</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js-language</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.sdk</groupId>
|
||||
<artifactId>graal-sdk</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.truffle</groupId>
|
||||
<artifactId>truffle-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
@@ -178,7 +158,7 @@
|
||||
<plugin>kotlinx-serialization</plugin>
|
||||
</compilerPlugins>
|
||||
<args>
|
||||
<arg>-Xcontext-receivers</arg>
|
||||
<arg>-Xcontext-parameters</arg>
|
||||
</args>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
package app.cash.quickjs;
|
||||
|
||||
import org.graalvm.polyglot.Context;
|
||||
import org.graalvm.polyglot.HostAccess;
|
||||
import org.graalvm.polyglot.PolyglotAccess;
|
||||
import org.graalvm.polyglot.Value;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class QuickJs implements Closeable {
|
||||
private Context context;
|
||||
|
||||
public static QuickJs create() {
|
||||
return new QuickJs();
|
||||
}
|
||||
|
||||
public QuickJs() {
|
||||
this.context = Context
|
||||
.newBuilder("js")
|
||||
.allowHostAccess(HostAccess.ALL)
|
||||
.allowPolyglotAccess(PolyglotAccess.NONE)
|
||||
.allowHostClassLoading(false)
|
||||
.build();
|
||||
context.enter();
|
||||
}
|
||||
|
||||
public Object evaluate(String script, String ignoredFileName) {
|
||||
return this.evaluate(script);
|
||||
}
|
||||
|
||||
public Object evaluate(String script) {
|
||||
Value value = context.eval("js", script);
|
||||
return translateType(value);
|
||||
}
|
||||
|
||||
private Object translateType(Value obj) {
|
||||
if (obj.isBoolean()) {
|
||||
return obj.asBoolean();
|
||||
} else if (obj.hasArrayElements()) {
|
||||
if (obj.getArraySize() == 0) {
|
||||
return new int[0];
|
||||
} else {
|
||||
Value element = obj.getArrayElement(0);
|
||||
if (element.isBoolean()) {
|
||||
return obj.as(boolean[].class);
|
||||
} else if (element.isNumber()) {
|
||||
if (element.fitsInInt()) {
|
||||
return obj.as(int[].class);
|
||||
} else if (element.fitsInBigInteger()) {
|
||||
return Arrays.stream(obj.as(BigInteger[].class)).map(BigInteger::longValue).toArray();
|
||||
} else {
|
||||
return obj.as(double[].class);
|
||||
}
|
||||
} else if (element.isHostObject()) {
|
||||
return obj.as(Object[].class);
|
||||
} else if (element.isString()) {
|
||||
return obj.as(String[].class);
|
||||
}
|
||||
}
|
||||
} else if (obj.isNumber()) {
|
||||
if (obj.fitsInInt()) {
|
||||
return obj.asInt();
|
||||
} else if (obj.fitsInBigInteger()) {
|
||||
return obj.asBigInteger().longValue();
|
||||
} else {
|
||||
return obj.asDouble();
|
||||
}
|
||||
} else if (obj.isHostObject()) {
|
||||
return obj.asHostObject();
|
||||
} else if (obj.isString()) {
|
||||
return obj.asString();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public byte[] compile(String sourceCode, String ignoredFileName) {
|
||||
return sourceCode.getBytes();
|
||||
}
|
||||
|
||||
public Object execute(byte[] bytecode) {
|
||||
return this.evaluate(new String(bytecode));
|
||||
}
|
||||
|
||||
public <T> void set(String name, Class<T> ignoredType, T object) {
|
||||
context.getBindings("js").putMember(name, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (this.context != null) {
|
||||
this.context.leave();
|
||||
this.context.close();
|
||||
this.context = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package dev.k3vinb5.aniyomibridge.loader.interceptors;
|
||||
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.zorotheme.ZoroThemeFilters;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
|
||||
public class HiAnimeInterceptor {
|
||||
|
||||
public static class ZoroThemeFiltersGetSearchParamsInterceptor {
|
||||
@RuntimeType
|
||||
public static Object intercept(@AllArguments Object[] args) {
|
||||
// Create and return a new FilterSearchParams
|
||||
return new ZoroThemeFilters.FilterSearchParams();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package app.cash.quickjs
|
||||
|
||||
import com.dokar.quickjs.QuickJs as DokarQuickJs
|
||||
import com.dokar.quickjs.binding.define
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.io.Closeable
|
||||
|
||||
/**
|
||||
* Stub implementation of Cash App's QuickJS that delegates to dokar3's quickjs-kt-jvm
|
||||
* (real QuickJS via JNI) instead of GraalVM.
|
||||
*
|
||||
* Binary-compatible with extensions that import app.cash.quickjs.QuickJs.
|
||||
*/
|
||||
class QuickJs private constructor() : Closeable {
|
||||
private val quickJs: DokarQuickJs = DokarQuickJs.create(Dispatchers.Default)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun create(): QuickJs = QuickJs()
|
||||
}
|
||||
|
||||
fun evaluate(script: String): Any? {
|
||||
val result = runBlocking {
|
||||
quickJs.evaluate<Any?>(script)
|
||||
}
|
||||
return translateValue(result)
|
||||
}
|
||||
|
||||
fun evaluate(script: String, ignoredFileName: String): Any? {
|
||||
return evaluate(script)
|
||||
}
|
||||
|
||||
fun compile(sourceCode: String, ignoredFileName: String): ByteArray {
|
||||
return quickJs.compile(sourceCode, ignoredFileName, asModule = false)
|
||||
}
|
||||
|
||||
fun execute(bytecode: ByteArray): Any? {
|
||||
val result = runBlocking {
|
||||
quickJs.evaluate<Any?>(bytecode)
|
||||
}
|
||||
return translateValue(result)
|
||||
}
|
||||
|
||||
fun <T> set(name: String, ignoredType: Class<T>, `object`: T) {
|
||||
if (`object` == null) {
|
||||
runBlocking {
|
||||
quickJs.evaluate<Any?>("globalThis.$name = null")
|
||||
}
|
||||
} else {
|
||||
quickJs.define(name, ignoredType, `object`)
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
quickJs.close()
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates dokar3 QuickJS return types to match the legacy GraalVM stub behavior.
|
||||
* Most importantly: JS arrays were returned as primitive/Object arrays.
|
||||
*/
|
||||
private fun translateValue(value: Any?): Any? {
|
||||
if (value !is List<*>) {
|
||||
return value
|
||||
}
|
||||
if (value.isEmpty()) {
|
||||
return emptyArray<Any?>()
|
||||
}
|
||||
return when {
|
||||
value.all { it is Int } -> value.map { it as Int }.toIntArray()
|
||||
value.all { it is Long } -> value.map { it as Long }.toLongArray()
|
||||
value.all { it is Double } -> value.map { it as Double }.toDoubleArray()
|
||||
value.all { it is Boolean } -> value.map { it as Boolean }.toBooleanArray()
|
||||
value.all { it is String } -> value.map { it as String }.toTypedArray()
|
||||
else -> value.toTypedArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.okio.decodeFromBufferedSource
|
||||
|
||||
import okhttp3.Call
|
||||
import okhttp3.Callback
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
@@ -133,34 +133,12 @@ fun OkHttpClient.newCachelessCallWithProgress(request: Request, listener: Progre
|
||||
}
|
||||
|
||||
|
||||
//context(Json)
|
||||
//inline fun <reified T> Response.parseAs(): T {
|
||||
// return decodeFromJsonResponse<T>(serializer(), this)
|
||||
//}
|
||||
|
||||
inline fun <reified T> Response.parseAs(): T {
|
||||
// val bodyJson = this.body?.string() ?: ""
|
||||
// return Gson().fromJson(bodyJson, T::class.java)
|
||||
return json.decodeFromString(this.body?.string() ?: "{}")
|
||||
}
|
||||
|
||||
inline fun <reified T> String.parseAs(): T {
|
||||
// val bodyJson = this.body?.string() ?: ""
|
||||
// return Gson().fromJson(bodyJson, T::class.java)
|
||||
return json.decodeFromString(this ?: "{}")
|
||||
}
|
||||
|
||||
|
||||
|
||||
context(Json)
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
fun <T> decodeFromJsonResponse(
|
||||
deserializer: DeserializationStrategy<T>,
|
||||
response: Response,
|
||||
): T {
|
||||
return response.body!!.source().use {
|
||||
decodeFromBufferedSource(deserializer, it)
|
||||
}
|
||||
return json.decodeFromString(this)
|
||||
}
|
||||
|
||||
class HttpException(val code: Int) : IllegalStateException("HTTP error $code")
|
||||
|
||||
32
pom.xml
32
pom.xml
@@ -21,11 +21,10 @@
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<kotlin.version>2.1.0</kotlin.version>
|
||||
<kotlin.version>2.3.20</kotlin.version>
|
||||
<kotlinx.serialization.version>1.7.3</kotlinx.serialization.version>
|
||||
<kotlinx.coroutines.version>1.8.1</kotlinx.coroutines.version>
|
||||
<kotlinx.coroutines.version>1.10.2</kotlinx.coroutines.version>
|
||||
<okhttp.version>5.0.0-alpha.14</okhttp.version>
|
||||
<graalvm.version>24.2.0</graalvm.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -73,33 +72,6 @@
|
||||
<artifactId>okhttp-brotli</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- GraalVM -->
|
||||
<dependency>
|
||||
<groupId>org.graalvm.polyglot</groupId>
|
||||
<artifactId>polyglot</artifactId>
|
||||
<version>${graalvm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js-scriptengine</artifactId>
|
||||
<version>${graalvm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js-language</artifactId>
|
||||
<version>${graalvm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.sdk</groupId>
|
||||
<artifactId>graal-sdk</artifactId>
|
||||
<version>${graalvm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.truffle</groupId>
|
||||
<artifactId>truffle-api</artifactId>
|
||||
<version>${graalvm.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
2
test.sh
2
test.sh
@@ -1 +1 @@
|
||||
CP_FILE=$(mktemp) && mvn -pl aniyomibridge-core -q dependency:build-classpath -Dmdep.outputFile="$CP_FILE" && java -cp "aniyomibridge-core/target/classes:$(cat "$CP_FILE")" dev.k3vinb5.aniyomibridge.Main; rm -f "$CP_FILE"´
|
||||
CP_FILE=$(mktemp) && mvn -pl aniyomibridge-core -q dependency:build-classpath -Dmdep.outputFile="$CP_FILE" && java -cp "aniyomibridge-core/target/classes:$(cat "$CP_FILE")" dev.k3vinb5.aniyomibridge.Main; rm -f "$CP_FILE"
|
||||
|
||||
Reference in New Issue
Block a user