commit 4a7c7d71bc6a7b66396899625661ac86c0543ee0
parent 4b49d669b7ec8ee0599f621b64b3e8ad674a5dfe
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sun, 15 Oct 2023 19:53:48 +0200

feat: hide from friend feed

Diffstat:
Mcommon/src/main/assets/lang/en_US.json | 8++++++--
Mcommon/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/UserInterfaceTweaks.kt | 1+
Mcommon/src/main/kotlin/me/rhunk/snapenhance/common/data/MessagingCoreObjects.kt | 2+-
Acore/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideFriendFeedEntry.kt | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/FeatureManager.kt | 1+
5 files changed, 81 insertions(+), 3 deletions(-)

diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json @@ -97,8 +97,8 @@ "whitelist": "Auto save" } }, - "hide_chat_feed": { - "name": "Hide from Chat feed" + "hide_friend_feed": { + "name": "Hide from Friend Feed" }, "e2e_encryption": { "name": "Use E2E Encryption" @@ -254,6 +254,10 @@ "name": "Show Streak Expiration Info", "description": "Shows a Streak Expiration timer next to the Streaks counter" }, + "hide_friend_feed_entry": { + "name": "Hide Friend Feed Entry", + "description": "Hides a specific friend from the Friend Feed\nUse the social tab to manage this feature" + }, "hide_streak_restore": { "name": "Hide Streak Restore", "description": "Hides the Restore button in the friend feed" diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/UserInterfaceTweaks.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/UserInterfaceTweaks.kt @@ -29,6 +29,7 @@ class UserInterfaceTweaks : ConfigContainer() { val bootstrapOverride = container("bootstrap_override", BootstrapOverride()) { requireRestart() } val mapFriendNameTags = boolean("map_friend_nametags") { requireRestart() } val streakExpirationInfo = boolean("streak_expiration_info") { requireRestart() } + val hideFriendFeedEntry = boolean("hide_friend_feed_entry") { requireRestart() } val hideStreakRestore = boolean("hide_streak_restore") { requireRestart() } val hideStorySections = multiple("hide_story_sections", "hide_friend_suggestions", "hide_friends", "hide_suggested", "hide_for_you") { requireRestart() } diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/MessagingCoreObjects.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/data/MessagingCoreObjects.kt @@ -34,7 +34,7 @@ enum class MessagingRuleType( AUTO_DOWNLOAD("auto_download", true), STEALTH("stealth", true), AUTO_SAVE("auto_save", true), - HIDE_CHAT_FEED("hide_chat_feed", false, showInFriendMenu = false), + HIDE_FRIEND_FEED("hide_friend_feed", false, showInFriendMenu = false), E2E_ENCRYPTION("e2e_encryption", false), PIN_CONVERSATION("pin_conversation", false, showInFriendMenu = false); diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideFriendFeedEntry.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideFriendFeedEntry.kt @@ -0,0 +1,71 @@ +package me.rhunk.snapenhance.core.features.impl.ui + +import me.rhunk.snapenhance.common.data.MessagingRuleType +import me.rhunk.snapenhance.common.data.RuleState +import me.rhunk.snapenhance.core.features.FeatureLoadParams +import me.rhunk.snapenhance.core.features.MessagingRuleFeature +import me.rhunk.snapenhance.core.util.hook.HookStage +import me.rhunk.snapenhance.core.util.hook.hook +import me.rhunk.snapenhance.core.util.ktx.getObjectField +import me.rhunk.snapenhance.core.util.ktx.setObjectField +import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID + +class HideFriendFeedEntry : MessagingRuleFeature("HideFriendFeedEntry", ruleType = MessagingRuleType.HIDE_FRIEND_FEED, loadParams = FeatureLoadParams.INIT_SYNC) { + private fun createDeletedFeedEntry(conversationId: String) = context.gson.fromJson( + """ + { + "mFeedEntryIdentifier": { + "mConversationId": null + }, + "mReason": "CLEAR_CONVERSATION" + } + """.trimIndent(), + findClass("com.snapchat.client.messaging.DeletedFeedEntry") + ).also { + it.getObjectField("mFeedEntryIdentifier")?.setObjectField("mConversationId", SnapUUID.fromString(conversationId).instanceNonNull()) + } + + private fun filterFriendFeed(entries: ArrayList<Any>, deletedEntries: ArrayList<Any>? = null) { + entries.removeIf { feedEntry -> + val conversationId = SnapUUID(feedEntry.getObjectField("mConversationId")).toString() + + if (canUseRule(conversationId)) { + deletedEntries?.add(createDeletedFeedEntry(conversationId)) + true + } else { + false + } + } + } + + override fun init() { + if (!context.config.userInterface.hideFriendFeedEntry.get()) return + + arrayOf( + "QueryFeedCallback" to "onQueryFeedComplete", + "FeedManagerDelegate" to "onFeedEntriesUpdated", + "FeedManagerDelegate" to "onInternalSyncFeed", + "SyncFeedCallback" to "onSyncFeedComplete", + ).forEach { (callbackName, methodName) -> + context.mappings.getMappedClass("callbacks", callbackName) + .hook(methodName, HookStage.BEFORE) { param -> + filterFriendFeed(param.arg(0)) + } + } + + context.mappings.getMappedClass("callbacks", "FetchAndSyncFeedCallback") + .hook("onFetchAndSyncFeedComplete", HookStage.BEFORE) { param -> + val deletedConversations: ArrayList<Any> = param.arg(2) + filterFriendFeed(param.arg(0), deletedConversations) + + if (deletedConversations.any { + val uuid = SnapUUID(it.getObjectField("mFeedEntryIdentifier")?.getObjectField("mConversationId")).toString() + context.database.getFeedEntryByConversationId(uuid) != null + }) { + param.setArg(4, true) + } + } + } + + override fun getRuleState() = RuleState.WHITELIST +}+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/FeatureManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/FeatureManager.kt @@ -99,6 +99,7 @@ class FeatureManager( SnapToChatMedia::class, FriendFeedMessagePreview::class, HideStreakRestore::class, + HideFriendFeedEntry::class, ) initializeFeatures()