Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rhunk committed May 14, 2023
0 parents commit 0650686
Show file tree
Hide file tree
Showing 110 changed files with 6,056 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*.iml
.gradle
/local.properties
/.idea/
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# SnapEnhance
A xposed mod to enhance the Snapchat experience
The project is currently in development, so expect bugs and crashes. Feel free to open an issue if you find any bug.

## build
1. make sure you have the latest version of [LSPosed](https://github.com/LSPosed/LSPosed)
2. clone this repo using ``git clone``
3. run ``./gradlew assembleDebug``
4. install the apk using adb ``adb install -r app/build/outputs/apk/debug/app-debug.apk``

## features
- media downloader (+ overlay merging)
- message auto save
- message in notifications
- message logger
- snapchat plus features
- anonymous story viewing
- stealth mode
- screenshot detection bypass
- conversation preview
- prevent status notifications
- UI tweaks (remove call button, record button, ...)
- ad blocker

## todo
- [] localization
- [] ui improvements
- [] snap splitting
16 changes: 16 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
/.idea/
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
74 changes: 74 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}

def appVersionName = "0.0.1"
def appVersionCode = 1

android {
compileSdk 32

defaultConfig {
applicationId "me.rhunk.snapenhance"
minSdk 29
targetSdk 32
versionCode appVersionCode
versionName appVersionName
multiDexEnabled true
}

buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

//keep arm64-v8a native libs
packagingOptions {
exclude "META-INF/**"
exclude 'lib/x86/**'
exclude 'lib/x86_64/**'
exclude 'lib/armeabi-v7a/**'
}

kotlinOptions {
jvmTarget = '1.8'
}
}

afterEvaluate {
//auto install for debug purpose
getTasks().getByPath(":app:assembleDebug").doLast {
try {
println "Killing Snapchat"
exec {
commandLine "adb", "shell", "am", "force-stop", "com.snapchat.android"
}
println "Installing debug build"
exec() {
commandLine "adb", "install", "-r", "-d", "${buildDir}/outputs/apk/debug/app-debug.apk"
}
println "Starting Snapchat"
exec {
commandLine "adb", "shell", "am", "start", "com.snapchat.android"
}
} catch (Throwable t) {
println "Failed to install debug build"
t.printStackTrace()
}
}
}

dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
compileOnly files('libs/LSPosed-api-1.0-SNAPSHOT.jar')
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.arthenica:ffmpeg-kit-min-gpl:5.1'
}
Binary file added app/libs/LSPosed-api-1.0-SNAPSHOT-javadoc.jar
Binary file not shown.
Binary file added app/libs/LSPosed-api-1.0-SNAPSHOT-sources.jar
Binary file not shown.
Binary file added app/libs/LSPosed-api-1.0-SNAPSHOT.jar
Binary file not shown.
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
47 changes: 47 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="me.rhunk.snapenhance">

<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<application
android:usesCleartextTraffic="true"
android:label="@string/app_name"
tools:targetApi="31">
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="Enhanced Snapchat" />
<meta-data
android:name="xposedminversion"
android:value="53" />
<meta-data
android:name="xposedscope"
android:resource="@array/sc_scope" />

<service
android:name=".bridge.service.BridgeService"
android:exported="true">
</service>

<activity
android:theme="@android:style/Theme.NoDisplay"
android:name=".bridge.service.MainActivity"
android:exported="true"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>

</manifest>
1 change: 1 addition & 0 deletions app/src/main/assets/xposed_init
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
me.rhunk.snapenhance.XposedLoader
14 changes: 14 additions & 0 deletions app/src/main/java/me/rhunk/snapenhance/XposedLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package me.rhunk.snapenhance;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class XposedLoader implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam packageParam) throws Throwable {
if (!packageParam.packageName.equals(Constants.SNAPCHAT_PACKAGE_NAME)) return;
new SnapEnhance();
}
}
21 changes: 21 additions & 0 deletions app/src/main/kotlin/me/rhunk/snapenhance/Constants.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package me.rhunk.snapenhance

object Constants {
const val TAG = "SnapEnhance"
const val SNAPCHAT_PACKAGE_NAME = "com.snapchat.android"

const val VIEW_INJECTED_CODE = 0x7FFFFF02
const val VIEW_DRAWER = 0x7FFFFF03

val ARROYO_NOTE_ENCRYPTION_PROTO_PATH = intArrayOf(4, 4, 6, 1, 1)
val ARROYO_SNAP_ENCRYPTION_PROTO_PATH = intArrayOf(4, 4, 11, 5, 1, 1)
val MESSAGE_SNAP_ENCRYPTION_PROTO_PATH = intArrayOf(11, 5, 1, 1)
val ARROYO_EXTERNAL_MEDIA_ENCRYPTION_PROTO_PATH = intArrayOf(4, 4, 3, 3, 5, 1, 1)
val ARROYO_STRING_CHAT_MESSAGE_PROTO = intArrayOf(4, 4, 2, 1)
val ARROYO_URL_KEY_PROTO_PATH = intArrayOf(4, 5, 1, 3, 2, 2)

const val ARROYO_ENCRYPTION_PROTO_INDEX = 19
const val ARROYO_ENCRYPTION_PROTO_INDEX_V2 = 4

const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
42 changes: 42 additions & 0 deletions app/src/main/kotlin/me/rhunk/snapenhance/Logger.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package me.rhunk.snapenhance

import android.util.Log
import de.robv.android.xposed.XposedBridge

object Logger {
private const val TAG = "SnapEnhance"

fun log(message: Any?) {
Log.i(TAG, message.toString())
}

fun debug(message: Any?) {
if (!BuildConfig.DEBUG) return
Log.d(TAG, message.toString())
}

fun error(throwable: Throwable) {
Log.e(TAG, "",throwable)
}

fun error(message: Any?) {
Log.e(TAG, message.toString())
}

fun error(message: Any?, throwable: Throwable) {
Log.e(TAG, message.toString(), throwable)
}

fun xposedLog(message: Any?) {
XposedBridge.log(message.toString())
}

fun xposedLog(message: Any?, throwable: Throwable?) {
XposedBridge.log(message.toString())
XposedBridge.log(throwable)
}

fun xposedLog(throwable: Throwable) {
XposedBridge.log(throwable)
}
}
96 changes: 96 additions & 0 deletions app/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package me.rhunk.snapenhance

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.os.Handler
import android.os.Looper
import android.os.Process
import android.widget.Toast
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import me.rhunk.snapenhance.bridge.client.BridgeClient
import me.rhunk.snapenhance.database.DatabaseAccess
import me.rhunk.snapenhance.features.Feature
import me.rhunk.snapenhance.manager.impl.ConfigManager
import me.rhunk.snapenhance.manager.impl.FeatureManager
import me.rhunk.snapenhance.manager.impl.MappingManager
import me.rhunk.snapenhance.manager.impl.TranslationManager
import me.rhunk.snapenhance.util.download.DownloadServer
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import kotlin.reflect.KClass
import kotlin.system.exitProcess

class ModContext {
private val executorService: ExecutorService = Executors.newCachedThreadPool()

lateinit var androidContext: Context
var mainActivity: Activity? = null

val gson: Gson = GsonBuilder().create()

val bridgeClient = BridgeClient(this)
val translation = TranslationManager(this)
val features = FeatureManager(this)
val mappings = MappingManager(this)
val config = ConfigManager(this)
val database = DatabaseAccess(this)
val downloadServer = DownloadServer(this)
val classCache get() = SnapEnhance.classCache
val resources: Resources get() = androidContext.resources

fun <T : Feature> feature(featureClass: KClass<T>): T {
return features.get(featureClass)!!
}

fun runOnUiThread(runnable: () -> Unit) {
Handler(Looper.getMainLooper()).post {
runCatching(runnable).onFailure {
Logger.xposedLog("UI thread runnable failed", it)
}
}
}

fun executeAsync(runnable: () -> Unit) {
executorService.submit {
runCatching {
runnable()
}.onFailure {
Logger.xposedLog("Async task failed", it)
}
}
}

fun shortToast(message: Any) {
runOnUiThread {
Toast.makeText(androidContext, message.toString(), Toast.LENGTH_SHORT).show()
}
}

fun longToast(message: Any) {
runOnUiThread {
Toast.makeText(androidContext, message.toString(), Toast.LENGTH_LONG).show()
}
}

fun restartApp() {
androidContext.packageManager.getLaunchIntentForPackage(
Constants.SNAPCHAT_PACKAGE_NAME
)?.let {
val intent = Intent.makeRestartActivityTask(it.component)
androidContext.startActivity(intent)
Runtime.getRuntime().exit(0)
}
}

fun softRestartApp() {
exitProcess(0)
}

fun forceCloseApp() {
Process.killProcess(Process.myPid())
exitProcess(1)
}
}
Loading

0 comments on commit 0650686

Please sign in to comment.