rebase
This commit is contained in:
parent
c2ecba402b
commit
d0a809c8a2
28 changed files with 175 additions and 235 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -13,4 +13,3 @@ build
|
|||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
app/release/
|
||||
|
|
|
|||
3
.idea/deploymentTargetSelector.xml
generated
3
.idea/deploymentTargetSelector.xml
generated
|
|
@ -5,6 +5,9 @@
|
|||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
</SelectionState>
|
||||
<SelectionState runConfigName="KettuXposed.app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
||||
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
|
|
@ -6,7 +6,6 @@
|
|||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
|
|
|
|||
3
.idea/misc.xml
generated
3
.idea/misc.xml
generated
|
|
@ -1,8 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="jbr-21" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
|
|
@ -12,8 +12,8 @@ android {
|
|||
applicationId = "cocobo1.pupu.xposed"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 1300
|
||||
versionName = "1.3.0"
|
||||
versionCode = 1310
|
||||
versionName = "1.3.1"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
|
|
|||
BIN
app/release/app-release.apk
Normal file
BIN
app/release/app-release.apk
Normal file
Binary file not shown.
BIN
app/release/baselineProfiles/0/app-release.dm
Normal file
BIN
app/release/baselineProfiles/0/app-release.dm
Normal file
Binary file not shown.
BIN
app/release/baselineProfiles/1/app-release.dm
Normal file
BIN
app/release/baselineProfiles/1/app-release.dm
Normal file
Binary file not shown.
37
app/release/output-metadata.json
Normal file
37
app/release/output-metadata.json
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"version": 3,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "cocobo1.pupu.xposed",
|
||||
"variantName": "release",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 1300,
|
||||
"versionName": "1.3.0",
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
],
|
||||
"elementType": "File",
|
||||
"baselineProfiles": [
|
||||
{
|
||||
"minApi": 28,
|
||||
"maxApi": 30,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/1/app-release.dm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minApi": 31,
|
||||
"maxApi": 2147483647,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/0/app-release.dm"
|
||||
]
|
||||
}
|
||||
],
|
||||
"minSdkVersionForDexing": 24
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
cocobo1.pupu.xposed.Main
|
||||
io.github.revenge.xposed.Main
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cocobo1.pupu.xposed
|
||||
package io.github.revenge.xposed
|
||||
|
||||
class Constants {
|
||||
companion object {
|
||||
|
|
@ -10,7 +10,7 @@ class Constants {
|
|||
const val MAIN_SCRIPT_FILE = "bundle.js"
|
||||
|
||||
|
||||
const val LOG_TAG = "Kettu"
|
||||
const val LOG_TAG = "Revenge"
|
||||
|
||||
const val LOADER_NAME = "KettuXposed"
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cocobo1.pupu.xposed
|
||||
package io.github.revenge.xposed
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
|
|
@ -7,15 +7,15 @@ import android.os.Bundle
|
|||
import de.robv.android.xposed.IXposedHookLoadPackage
|
||||
import de.robv.android.xposed.IXposedHookZygoteInit
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import cocobo1.pupu.xposed.modules.*
|
||||
import cocobo1.pupu.xposed.modules.appearance.FontsModule
|
||||
import cocobo1.pupu.xposed.modules.appearance.SysColorsModule
|
||||
import cocobo1.pupu.xposed.modules.appearance.ThemesModule
|
||||
import cocobo1.pupu.xposed.modules.bridge.AdditionalBridgeMethodsModule
|
||||
import cocobo1.pupu.xposed.modules.bridge.BridgeModule
|
||||
import cocobo1.pupu.xposed.modules.no_track.BlockCrashReportingModule
|
||||
import cocobo1.pupu.xposed.modules.no_track.BlockDeepLinksTrackingModule
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
import io.github.revenge.xposed.modules.*
|
||||
import io.github.revenge.xposed.modules.appearance.FontsModule
|
||||
import io.github.revenge.xposed.modules.appearance.SysColorsModule
|
||||
import io.github.revenge.xposed.modules.appearance.ThemesModule
|
||||
import io.github.revenge.xposed.modules.bridge.AdditionalBridgeMethodsModule
|
||||
import io.github.revenge.xposed.modules.bridge.BridgeModule
|
||||
import io.github.revenge.xposed.modules.no_track.BlockCrashReportingModule
|
||||
import io.github.revenge.xposed.modules.no_track.BlockDeepLinksTrackingModule
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
|
||||
object HookStateHolder {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cocobo1.pupu.xposed
|
||||
package io.github.revenge.xposed
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package cocobo1.pupu.xposed
|
||||
package io.github.revenge.xposed
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.app.AndroidAppHelper
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import cocobo1.pupu.xposed.modules.UpdaterModule
|
||||
import io.github.revenge.xposed.modules.UpdaterModule
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.File
|
||||
import kotlin.system.exitProcess
|
||||
|
|
@ -21,7 +21,7 @@ class Utils {
|
|||
}
|
||||
|
||||
fun showRecoveryAlert(context: Context) {
|
||||
AlertDialog.Builder(context).setTitle("Kettu Recovery Options")
|
||||
AlertDialog.Builder(context).setTitle("Revenge Recovery Options")
|
||||
.setItems(arrayOf("Reload", "Delete Script", "Reset Loader Config")) { _, which ->
|
||||
when (which) {
|
||||
0 -> {
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package cocobo1.pupu.xposed.modules
|
||||
package io.github.revenge.xposed.modules
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AtomicFile
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import cocobo1.pupu.xposed.modules.bridge.BridgeModule
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
import io.github.revenge.xposed.modules.bridge.BridgeModule
|
||||
import java.io.*
|
||||
|
||||
/**
|
||||
|
|
@ -16,18 +16,18 @@ import java.io.*
|
|||
*
|
||||
* ### Modules cache
|
||||
*
|
||||
* - `kettu.caches.modules.read() : { blacklist: number[], finds: { [filter: string]: { [id: string]: number } | null }, version: number } | null`
|
||||
* - `revenge.caches.modules.read() : { blacklist: number[], finds: { [filter: string]: { [id: string]: number } | null }, version: number } | null`
|
||||
* - Reads the modules cache. Returns `null` if the cache file does not exist or is invalid.
|
||||
*
|
||||
* - `kettu.caches.modules.write(blacklist: number[], finds: { [filter: string]: { [id: string]: number } | null }) : void`
|
||||
* - `revenge.caches.modules.write(blacklist: number[], finds: { [filter: string]: { [id: string]: number } | null }) : void`
|
||||
* - Writes the modules cache.
|
||||
*
|
||||
* ### Assets cache
|
||||
*
|
||||
* - `kettu.caches.assets.read() : { data: { [name: string]: { [type: string]: number } }, version: number } | null`
|
||||
* - `revenge.caches.assets.read() : { data: { [name: string]: { [type: string]: number } }, version: number } | null`
|
||||
* - Reads the assets cache. Returns `null` if the cache file does not exist or is invalid.
|
||||
*
|
||||
* - `kettu.caches.assets.write(data: { [name: string]: { [type: string]: number } }) : void`
|
||||
* - `revenge.caches.assets.write(data: { [name: string]: { [type: string]: number } }) : void`
|
||||
* - Writes the assets cache.
|
||||
*
|
||||
* The caches are versioned and tied to the app version code. When the app is updated,
|
||||
|
|
@ -35,7 +35,7 @@ import java.io.*
|
|||
*/
|
||||
object CacheModule : Module() {
|
||||
|
||||
private const val CACHE_DIR = "kettu"
|
||||
private const val CACHE_DIR = "revenge"
|
||||
|
||||
private const val MODULES_CACHE_PREFIX = "modules"
|
||||
private const val ASSETS_CACHE_PREFIX = "assets"
|
||||
|
|
@ -45,18 +45,18 @@ object CacheModule : Module() {
|
|||
private lateinit var assetsCache: AssetsCache
|
||||
|
||||
override fun onContext(context: Context) = with(context) {
|
||||
val kettuCacheDir = File(cacheDir, CACHE_DIR).apply { asDir() }
|
||||
val revengeCacheDir = File(cacheDir, CACHE_DIR).apply { asDir() }
|
||||
val (_, _, _, versionCode) = getAppInfo()
|
||||
|
||||
val modulesCacheFile = File(
|
||||
kettuCacheDir, "$MODULES_CACHE_PREFIX.$versionCode"
|
||||
revengeCacheDir, "$MODULES_CACHE_PREFIX.$versionCode"
|
||||
).apply { asFile() }
|
||||
|
||||
val assetsCacheFile = File(
|
||||
kettuCacheDir, "$ASSETS_CACHE_PREFIX.$versionCode"
|
||||
revengeCacheDir, "$ASSETS_CACHE_PREFIX.$versionCode"
|
||||
).apply { asFile() }
|
||||
|
||||
BridgeModule.registerMethod("kettu.caches.modules.read") {
|
||||
BridgeModule.registerMethod("revenge.caches.modules.read") {
|
||||
if (::modulesCache.isInitialized) modulesCache.toMap() else ModulesCache.loadFromFileOrNull(modulesCacheFile)
|
||||
?.let {
|
||||
modulesCache = it
|
||||
|
|
@ -64,7 +64,7 @@ object CacheModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("kettu.caches.modules.write") {
|
||||
BridgeModule.registerMethod("revenge.caches.modules.write") {
|
||||
val (blacklist, finds) = it
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
modulesCache = ModulesCache(
|
||||
|
|
@ -73,7 +73,7 @@ object CacheModule : Module() {
|
|||
Log.i("Modules cache saved: ${modulesCacheFile.absolutePath} (blacklisted: ${blacklist.size}, finds: ${finds.size})")
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("kettu.caches.assets.read") {
|
||||
BridgeModule.registerMethod("revenge.caches.assets.read") {
|
||||
if (::assetsCache.isInitialized) assetsCache.toMap() else AssetsCache.loadFromFileOrNull(assetsCacheFile)
|
||||
?.let {
|
||||
assetsCache = it
|
||||
|
|
@ -81,7 +81,7 @@ object CacheModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("kettu.caches.assets.write") {
|
||||
BridgeModule.registerMethod("revenge.caches.assets.write") {
|
||||
val (data) = it
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
assetsCache =
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package cocobo1.pupu.xposed.modules
|
||||
package io.github.revenge.xposed.modules
|
||||
|
||||
import android.content.res.Resources
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.Constants.Companion.TARGET_PACKAGE
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import io.github.revenge.xposed.Constants.Companion.TARGET_PACKAGE
|
||||
import io.github.revenge.xposed.Module
|
||||
|
||||
/**
|
||||
* Hooks [Resources.getIdentifier] to fix resource package name mismatch.
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
package cocobo1.pupu.xposed.modules
|
||||
package io.github.revenge.xposed.modules
|
||||
|
||||
import android.content.res.AssetManager
|
||||
import android.content.res.XModuleResources
|
||||
import de.robv.android.xposed.IXposedHookZygoteInit
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.Constants
|
||||
import cocobo1.pupu.xposed.HookStateHolder
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import cocobo1.pupu.xposed.modules.HookScriptLoaderModule.Companion.PRELOADS_DIR
|
||||
import io.github.revenge.xposed.Constants
|
||||
import io.github.revenge.xposed.HookStateHolder
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
import io.github.revenge.xposed.modules.HookScriptLoaderModule.PRELOADS_DIR
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
|
@ -22,7 +22,7 @@ import java.lang.reflect.Method
|
|||
* Preload scripts should be placed in the [PRELOADS_DIR] directory inside the module's files directory.
|
||||
*
|
||||
* The main bundle should be placed in the [Constants.CACHE_DIR] directory named [Constants.MAIN_SCRIPT_FILE].
|
||||
* If the bundle file does not exist, it will attempt to load `assets://kettu.bundle` from the module's assets.
|
||||
* If the bundle file does not exist, it will attempt to load `assets://revenge.bundle` from the module's assets.
|
||||
*/
|
||||
object HookScriptLoaderModule : Module() {
|
||||
private lateinit var preloadsDir: File
|
||||
|
|
@ -111,7 +111,7 @@ object HookScriptLoaderModule : Module() {
|
|||
XposedBridge.invokeOriginalMethod(
|
||||
loadScriptFromAssets,
|
||||
thisObject,
|
||||
arrayOf(resources.assets, "assets://kettu.bundle", loadSynchronously)
|
||||
arrayOf(resources.assets, "assets://revenge.bundle", loadSynchronously)
|
||||
)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
|
|
@ -1,27 +1,14 @@
|
|||
package cocobo1.pupu.xposed.modules
|
||||
package io.github.revenge.xposed.modules
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.widget.EditText
|
||||
import android.widget.Toast
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.BuildConfig
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import de.robv.android.xposed.XposedHelpers
|
||||
import kotlinx.coroutines.*
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import cocobo1.pupu.xposed.Utils.Companion.reloadApp
|
||||
import io.github.revenge.xposed.BuildConfig
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils
|
||||
import io.github.revenge.xposed.Utils.Companion.reloadApp
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
|
||||
class LogBoxModule : Module() {
|
||||
object LogBoxModule : Module() {
|
||||
lateinit var packageParam: XC_LoadPackage.LoadPackageParam
|
||||
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||
|
||||
|
|
@ -109,8 +96,6 @@ class LogBoxModule : Module() {
|
|||
private fun showRecoveryMenu(context: Context) {
|
||||
val options = arrayOf(
|
||||
if (isSafeModeEnabled(context)) "Disable Safe Mode" else "Enable Safe Mode",
|
||||
"Refetch Bundle",
|
||||
"Load Custom Bundle",
|
||||
"Reload App"
|
||||
)
|
||||
|
||||
|
|
@ -126,9 +111,7 @@ class LogBoxModule : Module() {
|
|||
private fun handleMenuSelection(context: Context, index: Int) {
|
||||
when (index) {
|
||||
0 -> toggleSafeMode(context)
|
||||
1 -> confirmAction(context, "refetch the bundle") { refetchBundle(context) }
|
||||
2 -> loadCustomBundle(context)
|
||||
3 -> reloadApp()
|
||||
1 -> reloadApp()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -195,72 +178,6 @@ class LogBoxModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun refetchBundle(context: Context) {
|
||||
try {
|
||||
val pyoncordDir = getPyoncordDirectory(context)
|
||||
val bundleFile = File(pyoncordDir, "bundle.js")
|
||||
val backupFile = File(pyoncordDir, "bundle.js.backup")
|
||||
|
||||
if (bundleFile.exists()) {
|
||||
backupFile.delete()
|
||||
bundleFile.renameTo(backupFile)
|
||||
Log.e("Bundle moved to backup")
|
||||
}
|
||||
|
||||
reloadApp()
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e("Error refetching bundle: ${e.message}")
|
||||
showError(context, "Failed to refetch bundle", e.message)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetBundle(context: Context) {
|
||||
try {
|
||||
val pyoncordDir = getPyoncordDirectory(context)
|
||||
val bundleFile = File(pyoncordDir, "bundle.js")
|
||||
val configFile = File(pyoncordDir, "loader_config.json")
|
||||
|
||||
bundleFile.delete()
|
||||
|
||||
// Reset config
|
||||
if (configFile.exists()) {
|
||||
val config = JSONObject(configFile.readText())
|
||||
config.put("customLoadUrlEnabled", false)
|
||||
config.put("customLoadUrl", "http://localhost:4040/kettu.js")
|
||||
configFile.writeText(config.toString())
|
||||
}
|
||||
|
||||
reloadApp()
|
||||
} catch (e: Exception) {
|
||||
Log.e("Error resetting bundle: ${e.message}")
|
||||
showError(context, "Failed to reset bundle", e.message)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadCustomBundle(context: Context) {
|
||||
val input = EditText(context).apply {
|
||||
hint = "http://localhost:4040/kettu.js"
|
||||
inputType = android.text.InputType.TYPE_TEXT_VARIATION_URI
|
||||
}
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle("Load Custom Bundle")
|
||||
.setMessage("Enter the URL for your custom bundle:")
|
||||
.setView(input)
|
||||
.setPositiveButton("Load") { _, _ ->
|
||||
val urlString = input.text.toString().trim()
|
||||
if (urlString.isEmpty()) {
|
||||
showError(context, "Invalid URL", "Please enter a URL")
|
||||
return@setPositiveButton
|
||||
}
|
||||
|
||||
validateAndLoadBundle(context, urlString)
|
||||
}
|
||||
.setNegativeButton("Cancel", null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun validateAndLoadBundle(context: Context, urlString: String) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
|
|
@ -305,40 +222,6 @@ class LogBoxModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun setCustomBundleURL(context: Context, url: String) {
|
||||
try {
|
||||
val pyoncordDir = getPyoncordDirectory(context)
|
||||
val configFile = File(pyoncordDir, "loader_config.json")
|
||||
|
||||
val config = if (configFile.exists()) {
|
||||
JSONObject(configFile.readText())
|
||||
} else {
|
||||
JSONObject()
|
||||
}
|
||||
|
||||
config.put("customLoadUrlEnabled", true)
|
||||
config.put("customLoadUrl", url)
|
||||
configFile.writeText(config.toString())
|
||||
|
||||
File(pyoncordDir, "bundle.js").delete()
|
||||
|
||||
Toast.makeText(context, "Custom bundle set", Toast.LENGTH_SHORT).show()
|
||||
|
||||
reloadApp()
|
||||
} catch (e: Exception) {
|
||||
Log.e("Error setting custom bundle URL: ${e.message}")
|
||||
showError(context, "Failed to save configuration", e.message)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPyoncordDirectory(context: Context): File {
|
||||
val dir = File(context.filesDir, "pyoncord")
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
}
|
||||
return dir
|
||||
}
|
||||
|
||||
private fun showError(context: Context, title: String, message: String?) {
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(title)
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
package cocobo1.pupu.xposed.modules
|
||||
package io.github.revenge.xposed.modules
|
||||
|
||||
import android.content.res.AssetManager
|
||||
import de.robv.android.xposed.XC_MethodHook
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.BuildConfig
|
||||
import cocobo1.pupu.xposed.Constants
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils.Companion.JSON
|
||||
import cocobo1.pupu.xposed.modules.HookScriptLoaderModule.Companion.PRELOADS_DIR
|
||||
import io.github.revenge.xposed.BuildConfig
|
||||
import io.github.revenge.xposed.Constants
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils.Companion.JSON
|
||||
import io.github.revenge.xposed.modules.HookScriptLoaderModule.PRELOADS_DIR
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.put
|
||||
import java.io.File
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package cocobo1.pupu.xposed.modules
|
||||
package io.github.revenge.xposed.modules
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AtomicFile
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import cocobo1.pupu.xposed.modules.bridge.BridgeModule
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
import io.github.revenge.xposed.modules.bridge.BridgeModule
|
||||
import java.io.*
|
||||
|
||||
/**
|
||||
|
|
@ -12,15 +12,15 @@ import java.io.*
|
|||
*
|
||||
* ## Methods
|
||||
*
|
||||
* - `kettu.plugins.states.read(): { flags: { [pluginId: string]: number } }`
|
||||
* - `revenge.plugins.states.read(): { flags: { [pluginId: string]: number } }`
|
||||
* - Reads the current plugin states from the file and returns them as a map.
|
||||
*
|
||||
* - `kettu.plugins.states.write(flags: { [pluginId: string]: number }): void`
|
||||
* - `revenge.plugins.states.write(flags: { [pluginId: string]: number }): void`
|
||||
* - Writes the provided plugin states to the file.
|
||||
*/
|
||||
class PluginsModule : Module() {
|
||||
private companion object {
|
||||
const val DATA_DIR = "kettu/plugins"
|
||||
const val DATA_DIR = "revenge/plugins"
|
||||
const val STATES_FILE = "states"
|
||||
}
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ class PluginsModule : Module() {
|
|||
dataDir, STATES_FILE
|
||||
).apply { asFile() }
|
||||
|
||||
BridgeModule.registerMethod("kettu.plugins.states.read") {
|
||||
BridgeModule.registerMethod("revenge.plugins.states.read") {
|
||||
if (::states.isInitialized) states.toMap() else
|
||||
PluginStates.loadFromFileOrNull(statesFile)?.let {
|
||||
states = it
|
||||
|
|
@ -41,7 +41,7 @@ class PluginsModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("kettu.plugins.states.write") {
|
||||
BridgeModule.registerMethod("revenge.plugins.states.write") {
|
||||
val (flags) = it
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
states = PluginStates(
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cocobo1.pupu.xposed.modules
|
||||
package io.github.revenge.xposed.modules
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
|
|
@ -7,12 +7,12 @@ import android.util.AtomicFile
|
|||
import android.widget.Toast
|
||||
import androidx.core.util.writeBytes
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.Constants
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils
|
||||
import cocobo1.pupu.xposed.Utils.Companion.JSON
|
||||
import cocobo1.pupu.xposed.Utils.Companion.reloadApp
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import io.github.revenge.xposed.Constants
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils
|
||||
import io.github.revenge.xposed.Utils.Companion.JSON
|
||||
import io.github.revenge.xposed.Utils.Companion.reloadApp
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.engine.cio.*
|
||||
|
|
@ -111,7 +111,7 @@ object UpdaterModule : Module() {
|
|||
// This is a retry, so we show a dialog
|
||||
if (activity != null) {
|
||||
withContext(Dispatchers.Main) {
|
||||
AlertDialog.Builder(activity).setTitle("Kettu Update Successful")
|
||||
AlertDialog.Builder(activity).setTitle("Revenge Update Successful")
|
||||
.setMessage("A reload is required for changes to take effect.")
|
||||
.setPositiveButton("Reload") { dialog, _ ->
|
||||
reloadApp()
|
||||
|
|
@ -142,6 +142,26 @@ object UpdaterModule : Module() {
|
|||
|
||||
fun showErrorDialog(e: Throwable) {
|
||||
val activity = lastActivity?.get() ?: return
|
||||
|
||||
activity.runOnUiThread {
|
||||
AlertDialog.Builder(activity).setTitle("Revenge Update Failed").setMessage(
|
||||
"""
|
||||
Unable to download the latest version of Revenge.
|
||||
This is usually caused by bad network connection.
|
||||
|
||||
Error: ${e.message ?: e.stackTraceToString()}
|
||||
""".trimIndent()
|
||||
).setNegativeButton("Dismiss") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}.setPositiveButton("Retry Update") { dialog, _ ->
|
||||
downloadScript(activity)
|
||||
Toast.makeText(activity, "Retrying download in background...", Toast.LENGTH_SHORT).show()
|
||||
dialog.dismiss()
|
||||
}.setNeutralButton("Recovery") { dialog, _ ->
|
||||
Utils.showRecoveryAlert(activity)
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun resetLoaderConfig(context: Context) {
|
||||
|
|
@ -149,4 +169,4 @@ object UpdaterModule : Module() {
|
|||
val config = File(filesDir, CONFIG_FILE)
|
||||
if (config.exists()) config.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cocobo1.pupu.xposed.modules.appearance
|
||||
package io.github.revenge.xposed.modules.appearance
|
||||
|
||||
import android.content.res.AssetManager
|
||||
import android.graphics.Typeface
|
||||
|
|
@ -9,10 +9,10 @@ import android.os.Build
|
|||
import de.robv.android.xposed.XC_MethodReplacement
|
||||
import de.robv.android.xposed.XposedHelpers
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.Constants
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils.Companion.JSON
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import io.github.revenge.xposed.Constants
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils.Companion.JSON
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.engine.cio.*
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package cocobo1.pupu.xposed.modules.appearance
|
||||
package io.github.revenge.xposed.modules.appearance
|
||||
|
||||
import android.R.color
|
||||
import android.app.AndroidAppHelper
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.core.content.ContextCompat
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import io.github.revenge.xposed.Module
|
||||
import kotlinx.serialization.json.*
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package cocobo1.pupu.xposed.modules.appearance
|
||||
package io.github.revenge.xposed.modules.appearance
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import androidx.core.graphics.toColorInt
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.Constants
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils.Companion.JSON
|
||||
import io.github.revenge.xposed.Constants
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils.Companion.JSON
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cocobo1.pupu.xposed.modules.bridge
|
||||
package io.github.revenge.xposed.modules.bridge
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
|
|
@ -7,13 +7,13 @@ import android.content.ClipboardManager
|
|||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils
|
||||
import java.io.File
|
||||
|
||||
object AdditionalBridgeMethodsModule : Module() {
|
||||
override fun onContext(context: Context) = with(context) {
|
||||
BridgeModule.registerMethod("kettu.fs.getConstants") {
|
||||
BridgeModule.registerMethod("revenge.fs.getConstants") {
|
||||
mapOf(
|
||||
"data" to dataDir.absolutePath,
|
||||
"files" to filesDir.absolutePath,
|
||||
|
|
@ -21,7 +21,7 @@ object AdditionalBridgeMethodsModule : Module() {
|
|||
)
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("kettu.fs.delete") {
|
||||
BridgeModule.registerMethod("revenge.fs.delete") {
|
||||
val (path) = it
|
||||
File(path as String).run {
|
||||
if (this.isDirectory) this.deleteRecursively()
|
||||
|
|
@ -29,19 +29,19 @@ object AdditionalBridgeMethodsModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("kettu.fs.exists") {
|
||||
BridgeModule.registerMethod("revenge.fs.exists") {
|
||||
val (path) = it
|
||||
File(path as String).exists()
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("kettu.fs.read") { it ->
|
||||
BridgeModule.registerMethod("revenge.fs.read") { it ->
|
||||
val (path) = it
|
||||
val file = File(path as String).apply { openFileGuarded() }
|
||||
|
||||
file.bufferedReader().use { it.readText() }
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("kettu.fs.write") {
|
||||
BridgeModule.registerMethod("revenge.fs.write") {
|
||||
val (path, contents) = it
|
||||
val file = File(path as String).apply { openFileGuarded() }
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ object AdditionalBridgeMethodsModule : Module() {
|
|||
}
|
||||
|
||||
override fun onActivity(activity: Activity) = with(activity) {
|
||||
BridgeModule.registerMethod("kettu.alertError") {
|
||||
BridgeModule.registerMethod("revenge.alertError") {
|
||||
val (error, version) = it
|
||||
val app = getAppInfo()
|
||||
val errorString = "$error"
|
||||
|
|
@ -59,10 +59,10 @@ object AdditionalBridgeMethodsModule : Module() {
|
|||
val clip = ClipData.newPlainText("Stack Trace", errorString)
|
||||
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle("Kettu Error")
|
||||
.setTitle("Revenge Error")
|
||||
.setMessage(
|
||||
"""
|
||||
Kettu: $version
|
||||
Revenge: $version
|
||||
${app.name}: ${app.version} (${app.versionCode})
|
||||
Device: ${Build.MANUFACTURER} ${Build.MODEL}
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ object AdditionalBridgeMethodsModule : Module() {
|
|||
null
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("kettu.showRecoveryAlert") {
|
||||
BridgeModule.registerMethod("revenge.showRecoveryAlert") {
|
||||
Utils.showRecoveryAlert(this)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package cocobo1.pupu.xposed.modules.bridge
|
||||
package io.github.revenge.xposed.modules.bridge
|
||||
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.BuildConfig
|
||||
import cocobo1.pupu.xposed.Constants
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import io.github.revenge.xposed.BuildConfig
|
||||
import io.github.revenge.xposed.Constants
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
import java.lang.reflect.Method
|
||||
|
||||
/**
|
||||
|
|
@ -23,7 +23,7 @@ typealias BridgeMethodArgs = ArrayList<Any>
|
|||
* To call a method, pass an object with the following structure to a hooked method:
|
||||
* ```js
|
||||
* {
|
||||
* kettu: {
|
||||
* revenge: {
|
||||
* method: "method.name",
|
||||
* args: [arg1, arg2, ...]
|
||||
* }
|
||||
|
|
@ -50,7 +50,7 @@ object BridgeModule : Module() {
|
|||
private lateinit var readableMapToHashMap: Method
|
||||
private lateinit var argumentsMakeNative: Method
|
||||
|
||||
private const val CALL_DATA_KEY = "kettu"
|
||||
private const val CALL_DATA_KEY = "revenge"
|
||||
private const val METHOD_NAME_KEY = "method"
|
||||
private const val METHOD_ARGS_KEY = "args"
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package cocobo1.pupu.xposed.modules.no_track
|
||||
package io.github.revenge.xposed.modules.no_track
|
||||
|
||||
import android.content.Context
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
|
||||
/**
|
||||
* Hooks Discord's crash reporting to disable Sentry initialization.
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package cocobo1.pupu.xposed.modules.no_track
|
||||
package io.github.revenge.xposed.modules.no_track
|
||||
|
||||
import android.content.Context
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import cocobo1.pupu.xposed.Module
|
||||
import cocobo1.pupu.xposed.Utils.Log
|
||||
import io.github.revenge.xposed.Module
|
||||
import io.github.revenge.xposed.Utils.Log
|
||||
|
||||
/**
|
||||
* Hooks Discord's deep links tracking to disable AppsFlyer initialization.
|
||||
Loading…
Add table
Reference in a new issue