[Main] Make downloading significantly better
This commit is contained in:
parent
123b0c1af9
commit
20cc346334
3 changed files with 46 additions and 57 deletions
17
.idea/deploymentTargetDropDown.xml
generated
17
.idea/deploymentTargetDropDown.xml
generated
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetDropDown">
|
||||
<runningDeviceTargetSelectedWithDropDown>
|
||||
<Target>
|
||||
<type value="RUNNING_DEVICE_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="SERIAL_NUMBER" />
|
||||
<value value="29171FDH200B0M" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</runningDeviceTargetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2023-05-08T22:05:30.827281100Z" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -38,6 +38,7 @@ android {
|
|||
dependencies {
|
||||
compileOnly("de.robv.android.xposed:api:82")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
|
||||
implementation("io.ktor:ktor-client-core:2.3.0")
|
||||
implementation("io.ktor:ktor-client-cio:2.3.0")
|
||||
}
|
||||
|
|
@ -1,35 +1,24 @@
|
|||
package dev.beefers.vendetta.xposed
|
||||
|
||||
// Java
|
||||
import java.io.File
|
||||
|
||||
// Kotlin
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
// Android
|
||||
import java.lang.Exception
|
||||
import kotlinx.coroutines.*
|
||||
import android.content.res.AssetManager
|
||||
import android.content.res.XModuleResources
|
||||
import android.util.Log
|
||||
|
||||
// Xposed
|
||||
import android.os.Build
|
||||
import de.robv.android.xposed.IXposedHookLoadPackage
|
||||
import de.robv.android.xposed.IXposedHookZygoteInit
|
||||
import de.robv.android.xposed.XC_MethodHook
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
|
||||
// Ktor
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.engine.cio.*
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.engine.cio.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.client.plugins.*
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.isSuccess
|
||||
import io.ktor.utils.io.reader
|
||||
import java.lang.Exception
|
||||
import io.ktor.http.*
|
||||
|
||||
class Main : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
||||
private lateinit var resources: XModuleResources
|
||||
|
|
@ -44,34 +33,44 @@ class Main : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
|||
override fun handleLoadPackage(param: XC_LoadPackage.LoadPackageParam) = with(param) {
|
||||
// Stop executing when we aren't in Discord's React Native context
|
||||
val catalystInstance = try { classLoader.loadClass("com.facebook.react.bridge.CatalystInstanceImpl") } catch(e: ClassNotFoundException) { return }
|
||||
|
||||
val cache = File(appInfo.dataDir, "cache").also { it.mkdirs() }
|
||||
val bundle = File(cache, "vendetta.js")
|
||||
val etag = File(cache, "vendetta_etag.txt")
|
||||
|
||||
val scope = MainScope()
|
||||
val httpJob = scope.async(Dispatchers.IO) {
|
||||
try {
|
||||
val client = HttpClient(CIO) {
|
||||
install(HttpTimeout) { requestTimeoutMillis = 1000 }
|
||||
// TODO: This should follow proper User Agent format
|
||||
install(UserAgent) { agent = "VendettaXposed on ${Build.MODEL} (${Build.DEVICE}), Android ${Build.VERSION.RELEASE} (SDK ${Build.VERSION.SDK_INT})" }
|
||||
}
|
||||
val response: HttpResponse = client.get("https://raw.githubusercontent.com/vendetta-mod/builds/master/vendetta.js") {
|
||||
headers { if (etag.exists() && bundle.exists()) append(HttpHeaders.IfNoneMatch, etag.readText()) }
|
||||
}
|
||||
|
||||
if (response.status.value == 200) {
|
||||
bundle.writeBytes(response.body())
|
||||
if (response.headers.contains("Etag")) etag.writeText(response.headers["Etag"] as String)
|
||||
}
|
||||
|
||||
return@async
|
||||
} catch (e: Exception) {
|
||||
Log.e("Vendetta", "Failed to download Vendetta")
|
||||
}
|
||||
}
|
||||
|
||||
val loadScriptFromAssets = catalystInstance.getDeclaredMethod("jniLoadScriptFromAssets", AssetManager::class.java, String::class.java, Boolean::class.javaPrimitiveType)
|
||||
val loadScriptFromFile = catalystInstance.getDeclaredMethod("jniLoadScriptFromFile", String::class.java, String::class.java, Boolean::class.javaPrimitiveType)
|
||||
|
||||
val cache = File(appInfo.dataDir, "cache").also { it.mkdirs() }
|
||||
val bundle = File(cache, "vendetta.js")
|
||||
val etag = File(cache, "vendetta_etag.txt")
|
||||
|
||||
// TODO: loader config
|
||||
// TODO: make fast.
|
||||
// TODO: Loader config
|
||||
// TODO: It's fast now, but we have the Hindi timestamps issue. Probably requires a JS side fix.
|
||||
|
||||
val hook = object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam): Unit = runBlocking {
|
||||
Log.i("Vendetta", "beforeHookedMethod called")
|
||||
|
||||
try {
|
||||
val client = HttpClient(CIO) { install(HttpTimeout) { requestTimeoutMillis = 3000 } }
|
||||
val response: HttpResponse = client.get("https://raw.githubusercontent.com/vendetta-mod/builds/master/vendetta.js") {
|
||||
headers { if (etag.exists() && bundle.exists()) append(HttpHeaders.IfNoneMatch, etag.readText()) }
|
||||
}
|
||||
|
||||
if (response.status.isSuccess()) {
|
||||
bundle.writeText(response.bodyAsText())
|
||||
if (response.headers.contains("Etag")) etag.writeText(response.headers["Etag"] as String)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("Vendetta", "Failed to download Vendetta")
|
||||
}
|
||||
|
||||
Log.i("Vendetta", "Exfiltrating Metro modules")
|
||||
XposedBridge.invokeOriginalMethod(loadScriptFromAssets,param.thisObject, arrayOf(resources.assets, "assets://js/modules.js", true))
|
||||
Log.i("Vendetta", "Executing identity snippet")
|
||||
|
|
@ -82,8 +81,14 @@ class Main : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
|||
Log.i("Vendetta", "afterHookedMethod called")
|
||||
|
||||
try {
|
||||
Log.i("Vendetta", "Executing Vendetta")
|
||||
XposedBridge.invokeOriginalMethod(loadScriptFromFile, param.thisObject, arrayOf(bundle.absolutePath, bundle.absolutePath, param.args[2]))
|
||||
scope.launch(scope.coroutineContext) {
|
||||
Log.i("Vendetta", "Waiting for HTTP")
|
||||
httpJob.await()
|
||||
delay(500) // Magic hacky bullshit
|
||||
|
||||
Log.i("Vendetta", "Executing Vendetta")
|
||||
XposedBridge.invokeOriginalMethod(loadScriptFromFile, param.thisObject, arrayOf(bundle.absolutePath, bundle.absolutePath, param.args[2]))
|
||||
}
|
||||
} catch(_: Exception) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -91,6 +96,6 @@ class Main : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
|||
XposedBridge.hookMethod(loadScriptFromAssets, hook)
|
||||
XposedBridge.hookMethod(loadScriptFromFile, hook)
|
||||
|
||||
return@with;
|
||||
return@with
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue