commit 2d7b69f7e30bb173a0b8c1ea5098de1971136746 parent 073f81526c99b52d5c323d48d2bf22c5979d00c8 Author: rhunk <101876869+rhunk@users.noreply.github.com> Date: Wed, 17 May 2023 00:13:32 +0200 external media as snap feature Diffstat:
8 files changed, 69 insertions(+), 18 deletions(-)
diff --git a/app/src/main/assets/lang/en.json b/app/src/main/assets/lang/en.json @@ -30,6 +30,7 @@ "hide_typing_notification": "Hide Typing Notification", "menu_slot_id": "Friend Menu Slot ID", "message_preview_length": "Message Preview Length", + "external_media_as_snap": "External Media As Snap", "auto_save": "Auto Save", "snapchat_plus": "Snapchat Plus", "remove_voice_record_button": "Remove Voice Record Button", diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/BridgeClient.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/BridgeClient.kt @@ -7,7 +7,6 @@ import android.content.Intent import android.content.ServiceConnection import android.os.* import me.rhunk.snapenhance.BuildConfig -import me.rhunk.snapenhance.Logger.log import me.rhunk.snapenhance.Logger.xposedLog import me.rhunk.snapenhance.ModContext import me.rhunk.snapenhance.bridge.common.BridgeMessage diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt b/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt @@ -114,6 +114,12 @@ enum class ConfigProperty( 20 ), + EXTERNAL_MEDIA_AS_SNAP( + "property.external_media_as_snap", + "description.external_media_as_snap", + ConfigCategory.EXTRAS, + false + ), AUTO_SAVE("property.auto_save", "description.auto_save", ConfigCategory.EXTRAS, false), SNAPCHAT_PLUS("property.snapchat_plus", "description.snapchat_plus", ConfigCategory.EXTRAS, false), diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt @@ -6,10 +6,9 @@ import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.util.setObjectField import java.lang.reflect.Field import java.lang.reflect.Modifier -import java.util.concurrent.atomic.AtomicReference class ConfigEnumKeys : Feature("Config enum keys", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) { - private fun hookAllEnums(enumClass: Class<*>, callback: (String, AtomicReference<Any>) -> Unit) { + private fun hookAllEnums(enumClass: Class<*>, callback: (String, (Any) -> Unit) -> Unit) { //Enum(String, int, ?) //or Enum(?) val enumDataClass = enumClass.constructors[0].parameterTypes.first { clazz: Class<*> -> clazz != String::class.java && !clazz.isPrimitive } @@ -27,39 +26,39 @@ class ConfigEnumKeys : Feature("Config enum keys", loadParams = FeatureLoadParam enumClass.enumConstants.forEach { enum -> enumDataField.get(enum)?.let { enumData -> val key = enum.toString() - val value = AtomicReference(objectDataField.get(enumData)) - callback(key, value) - enumData.setObjectField(objectDataField.name, value.get()) + callback(key) { newValue -> + enumData.setObjectField(objectDataField.name, newValue) + } } } } override fun onActivityCreate() { if (context.config.bool(ConfigProperty.NEW_MAP_UI)) { - hookAllEnums(context.mappings.getMappedClass("enums", "PLUS")) { key, atomicValue -> - if (key == "REDUCE_MY_PROFILE_UI_COMPLEXITY") atomicValue.set(true) + hookAllEnums(context.mappings.getMappedClass("enums", "PLUS")) { key, set -> + if (key == "REDUCE_MY_PROFILE_UI_COMPLEXITY") set(true) } } - if (context.config.bool(ConfigProperty.LONG_SNAP_SENDING)) { - hookAllEnums(context.mappings.getMappedClass("enums", "ARROYO")) { key, atomicValue -> - if (key == "ENABLE_LONG_SNAP_SENDING") atomicValue.set(true) + hookAllEnums(context.mappings.getMappedClass("enums", "ARROYO")) { key, set -> + if (key == "ENABLE_LONG_SNAP_SENDING") { + if (context.config.bool(ConfigProperty.LONG_SNAP_SENDING)) set(true) } } if (context.config.bool(ConfigProperty.STREAK_EXPIRATION_INFO)) { - hookAllEnums(context.mappings.getMappedClass("enums", "FRIENDS_FEED")) { key, atomicValue -> - if (key == "STREAK_EXPIRATION_INFO") atomicValue.set(true) + hookAllEnums(context.mappings.getMappedClass("enums", "FRIENDS_FEED")) { key, set -> + if (key == "STREAK_EXPIRATION_INFO") set(true) } } if (context.config.bool(ConfigProperty.BLOCK_ADS)) { - hookAllEnums(context.mappings.getMappedClass("enums", "SNAPADS")) { key, atomicValue -> + hookAllEnums(context.mappings.getMappedClass("enums", "SNAPADS")) { key, set -> if (key == "BYPASS_AD_FEATURE_GATE") { - atomicValue.set(true) + set(true) } if (key == "CUSTOM_AD_SERVER_URL" || key == "CUSTOM_AD_INIT_SERVER_URL" || key == "CUSTOM_AD_TRACKER_URL") { - atomicValue.set("http://127.0.0.1") + set("http://127.0.0.1") } } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt @@ -9,7 +9,6 @@ import android.widget.ImageView import com.arthenica.ffmpegkit.FFmpegKit import me.rhunk.snapenhance.Constants import me.rhunk.snapenhance.Constants.ARROYO_URL_KEY_PROTO_PATH -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.Logger.xposedLog import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.ContentType diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/extras/ExternalMediaAsSnap.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/extras/ExternalMediaAsSnap.kt @@ -0,0 +1,44 @@ +package me.rhunk.snapenhance.features.impl.extras + +import me.rhunk.snapenhance.config.ConfigProperty +import me.rhunk.snapenhance.data.ContentType +import me.rhunk.snapenhance.data.wrapper.impl.MessageContent +import me.rhunk.snapenhance.features.Feature +import me.rhunk.snapenhance.features.FeatureLoadParams +import me.rhunk.snapenhance.hook.HookStage +import me.rhunk.snapenhance.hook.Hooker +import me.rhunk.snapenhance.util.protobuf.ProtoWriter + +class ExternalMediaAsSnap : Feature("External Media As Snap", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) { + private val redSnapProto: ByteArray by lazy { + ProtoWriter().apply { + write(11, 5) { + write(1) { + write(1) { + writeConstant(2, 0) + writeConstant(12, 0) + writeConstant(15, 0) + } + writeConstant(6, 0) + } + write(2) { + writeConstant(5, 0) + writeBuffer(6, byteArrayOf()) + } + } + }.toByteArray() + } + + override fun onActivityCreate() { + Hooker.hook(context.classCache.conversationManager, "sendMessageWithContent", HookStage.BEFORE, { + context.config.bool(ConfigProperty.EXTERNAL_MEDIA_AS_SNAP) + }) { param -> + val localMessageContent = MessageContent(param.arg(1)) + + if (localMessageContent.contentType != ContentType.EXTERNAL_MEDIA) return@hook + + localMessageContent.contentType = ContentType.SNAP + localMessageContent.content = redSnapProto + } + } +}+ \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt @@ -9,6 +9,7 @@ import me.rhunk.snapenhance.features.impl.Messaging import me.rhunk.snapenhance.features.impl.downloader.AntiAutoDownload import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader import me.rhunk.snapenhance.features.impl.extras.AutoSave +import me.rhunk.snapenhance.features.impl.extras.ExternalMediaAsSnap import me.rhunk.snapenhance.features.impl.extras.Notifications import me.rhunk.snapenhance.features.impl.extras.SnapchatPlus import me.rhunk.snapenhance.features.impl.privacy.DisableMetrics @@ -58,6 +59,7 @@ class FeatureManager(private val context: ModContext) : Manager { register(UITweaks::class) register(ConfigEnumKeys::class) register(AntiAutoDownload::class) + register(ExternalMediaAsSnap::class) initializeFeatures() } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/util/XposedHelperMacros.kt b/app/src/main/kotlin/me/rhunk/snapenhance/util/XposedHelperMacros.kt @@ -6,7 +6,7 @@ fun Any.getObjectField(fieldName: String): Any? { return XposedHelpers.getObjectField(this, fieldName) } -fun Any.setObjectField(fieldName: String, value: Any) { +fun Any.setObjectField(fieldName: String, value: Any?) { XposedHelpers.setObjectField(this, fieldName, value) }