mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-06-12 13:17:42 +02:00
feat: disable hold to replay in FF
- add setEnumField ktx - refactor AbstractWrapper delegate (nullable getValue)
This commit is contained in:
@ -233,6 +233,10 @@
|
||||
"name": "Unlimited Snap View Time",
|
||||
"description": "Removes the time limit for viewing Snaps"
|
||||
},
|
||||
"disable_replay_in_ff": {
|
||||
"name": "Disable Replay in FF",
|
||||
"description": "Disables the ability to replay with a long press from the friend feed"
|
||||
},
|
||||
"prevent_message_sending": {
|
||||
"name": "Prevent Message Sending",
|
||||
"description": "Prevents sending certain types of messages"
|
||||
|
@ -35,13 +35,15 @@ class EventDispatcher(
|
||||
}
|
||||
|
||||
context.classCache.snapManager.hook("onSnapInteraction", HookStage.BEFORE) { param ->
|
||||
val interactionType = param.arg<Any>(0).toString()
|
||||
val conversationId = SnapUUID(param.arg(1))
|
||||
val messageId = param.arg<Long>(2)
|
||||
context.event.post(
|
||||
OnSnapInteractionEvent(
|
||||
conversationId = conversationId,
|
||||
messageId = messageId
|
||||
)
|
||||
interactionType = interactionType,
|
||||
conversationId = conversationId,
|
||||
messageId = messageId
|
||||
)
|
||||
)?.also {
|
||||
if (it.canceled) {
|
||||
param.setResult(null)
|
||||
|
@ -9,6 +9,7 @@ class MessagingTweaks : ConfigContainer() {
|
||||
val hideBitmojiPresence = boolean("hide_bitmoji_presence")
|
||||
val hideTypingNotifications = boolean("hide_typing_notifications")
|
||||
val unlimitedSnapViewTime = boolean("unlimited_snap_view_time")
|
||||
val disableReplayInFF = boolean("disable_replay_in_ff")
|
||||
val autoSaveMessagesInConversations = multiple("auto_save_messages_in_conversations",
|
||||
"CHAT",
|
||||
"SNAP",
|
||||
|
@ -4,6 +4,7 @@ import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent
|
||||
import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID
|
||||
|
||||
class OnSnapInteractionEvent(
|
||||
val interactionType: String,
|
||||
val conversationId: SnapUUID,
|
||||
val messageId: Long
|
||||
) : AbstractHookEvent()
|
@ -9,8 +9,8 @@ abstract class AbstractWrapper(
|
||||
) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inner class EnumAccessor<T>(private val fieldName: String, private val defaultValue: T) {
|
||||
operator fun getValue(obj: Any, property: KProperty<*>): T = getEnumValue(fieldName, defaultValue as Enum<*>) as T
|
||||
operator fun setValue(obj: Any, property: KProperty<*>, value: Any) = setEnumValue(fieldName, value as Enum<*>)
|
||||
operator fun getValue(obj: Any, property: KProperty<*>): T? = getEnumValue(fieldName, defaultValue as Enum<*>) as? T
|
||||
operator fun setValue(obj: Any, property: KProperty<*>, value: Any?) = setEnumValue(fieldName, value as Enum<*>)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@ -32,9 +32,10 @@ abstract class AbstractWrapper(
|
||||
|
||||
protected fun <T> enum(fieldName: String, defaultValue: T) = EnumAccessor(fieldName, defaultValue)
|
||||
|
||||
fun <T : Enum<*>> getEnumValue(fieldName: String, defaultValue: T): T {
|
||||
fun <T : Enum<*>> getEnumValue(fieldName: String, defaultValue: T?): T? {
|
||||
if (defaultValue == null) return null
|
||||
val mContentType = XposedHelpers.getObjectField(instance, fieldName) as Enum<*>
|
||||
return java.lang.Enum.valueOf(defaultValue::class.java, mContentType.name) as T
|
||||
return java.lang.Enum.valueOf(defaultValue::class.java, mContentType.name)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -24,7 +24,7 @@ class PreventMessageSending : Feature("Prevent message sending", loadParams = Fe
|
||||
|
||||
context.event.subscribe(SendMessageWithContentEvent::class) { event ->
|
||||
val contentType = event.messageContent.contentType
|
||||
val associatedType = NotificationType.fromContentType(contentType) ?: return@subscribe
|
||||
val associatedType = NotificationType.fromContentType(contentType ?: return@subscribe) ?: return@subscribe
|
||||
|
||||
if (preventMessageSending.contains(associatedType.key)) {
|
||||
context.log.verbose("Preventing message sending for $associatedType")
|
||||
|
@ -0,0 +1,22 @@
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import me.rhunk.snapenhance.features.Feature
|
||||
import me.rhunk.snapenhance.features.FeatureLoadParams
|
||||
import me.rhunk.snapenhance.hook.HookStage
|
||||
import me.rhunk.snapenhance.hook.hookConstructor
|
||||
import me.rhunk.snapenhance.util.ktx.getObjectField
|
||||
import me.rhunk.snapenhance.util.ktx.setEnumField
|
||||
|
||||
class DisableReplayInFF : Feature("DisableReplayInFF", loadParams = FeatureLoadParams.ACTIVITY_CREATE_ASYNC) {
|
||||
override fun asyncOnActivityCreate() {
|
||||
val state by context.config.messaging.disableReplayInFF
|
||||
|
||||
findClass("com.snapchat.client.messaging.InteractionInfo")
|
||||
.hookConstructor(HookStage.AFTER, { state }) { param ->
|
||||
val instance = param.thisObject<Any>()
|
||||
if (instance.getObjectField("mLongPressActionState").toString() == "REQUEST_SNAP_REPLAY") {
|
||||
instance.setEnumField("mLongPressActionState", "SHOW_CONVERSATION_ACTION_MENU")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -221,7 +221,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
|
||||
}
|
||||
}
|
||||
|
||||
val contentType = snapMessage.messageContent.contentType
|
||||
val contentType = snapMessage.messageContent.contentType ?: return@onEach
|
||||
val contentData = snapMessage.messageContent.content
|
||||
|
||||
val formatUsername: (String) -> String = { "$senderUsername: $it" }
|
||||
|
@ -25,6 +25,7 @@ import me.rhunk.snapenhance.features.impl.spying.PreventReadReceipts
|
||||
import me.rhunk.snapenhance.features.impl.spying.StealthMode
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.AutoSave
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.CameraTweaks
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.DisableReplayInFF
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.DisableVideoLengthRestriction
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.GalleryMediaSendOverride
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.GooglePlayServicesDialogs
|
||||
@ -95,6 +96,7 @@ class FeatureManager(private val context: ModContext) : Manager {
|
||||
register(NoFriendScoreDelay::class)
|
||||
register(ProfilePictureDownloader::class)
|
||||
register(AddFriendSourceSpoof::class)
|
||||
register(DisableReplayInFF::class)
|
||||
|
||||
initializeFeatures()
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ class MessageExporter(
|
||||
val sender = conversationParticipants[message.senderId.toString()]
|
||||
val senderUsername = sender?.usernameForSorting ?: message.senderId.toString()
|
||||
val senderDisplayName = sender?.displayName ?: message.senderId.toString()
|
||||
val messageContent = serializeMessageContent(message) ?: message.messageContent.contentType.name
|
||||
val messageContent = serializeMessageContent(message) ?: message.messageContent.contentType?.name
|
||||
val date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).format(Date(message.messageMetadata.createdAt))
|
||||
writer.write("[$date] - $senderDisplayName (${senderUsername}): $messageContent\n")
|
||||
}
|
||||
@ -118,7 +118,7 @@ class MessageExporter(
|
||||
|
||||
runCatching {
|
||||
val downloadedMedia = MediaDownloaderHelper.downloadMediaFromReference(protoMediaReference) {
|
||||
EncryptionHelper.decryptInputStream(it, message.messageContent.contentType, ProtoReader(message.messageContent.content), isArroyo = false)
|
||||
EncryptionHelper.decryptInputStream(it, message.messageContent.contentType!!, ProtoReader(message.messageContent.content), isArroyo = false)
|
||||
}
|
||||
|
||||
printLog("downloaded media ${message.orderKey}")
|
||||
@ -276,7 +276,7 @@ class MessageExporter(
|
||||
addProperty("serializedContent", serializeMessageContent(message))
|
||||
addProperty("rawContent", Base64.getUrlEncoder().encodeToString(message.messageContent.content))
|
||||
|
||||
val messageContentType = message.messageContent.contentType
|
||||
val messageContentType = message.messageContent.contentType ?: ContentType.CHAT
|
||||
|
||||
EncryptionHelper.getEncryptionKeys(messageContentType, ProtoReader(message.messageContent.content), isArroyo = false)?.let { encryptionKeyPair ->
|
||||
add("encryption", JsonObject().apply encryption@{
|
||||
|
@ -6,6 +6,13 @@ fun Any.getObjectField(fieldName: String): Any? {
|
||||
return XposedHelpers.getObjectField(this, fieldName)
|
||||
}
|
||||
|
||||
fun Any.setEnumField(fieldName: String, value: String) {
|
||||
this::class.java.getDeclaredField(fieldName)
|
||||
.type.enumConstants?.firstOrNull { it.toString() == value }?.let { enum ->
|
||||
setObjectField(fieldName, enum)
|
||||
}
|
||||
}
|
||||
|
||||
fun Any.setObjectField(fieldName: String, value: Any?) {
|
||||
XposedHelpers.setObjectField(this, fieldName, value)
|
||||
}
|
||||
|
Reference in New Issue
Block a user