feat: hide from friend feed

This commit is contained in:
rhunk
2023-10-15 19:53:48 +02:00
parent 4b49d669b7
commit 4a7c7d71bc
5 changed files with 80 additions and 3 deletions

View File

@ -97,8 +97,8 @@
"whitelist": "Auto save" "whitelist": "Auto save"
} }
}, },
"hide_chat_feed": { "hide_friend_feed": {
"name": "Hide from Chat feed" "name": "Hide from Friend Feed"
}, },
"e2e_encryption": { "e2e_encryption": {
"name": "Use E2E Encryption" "name": "Use E2E Encryption"
@ -254,6 +254,10 @@
"name": "Show Streak Expiration Info", "name": "Show Streak Expiration Info",
"description": "Shows a Streak Expiration timer next to the Streaks counter" "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": { "hide_streak_restore": {
"name": "Hide Streak Restore", "name": "Hide Streak Restore",
"description": "Hides the Restore button in the friend feed" "description": "Hides the Restore button in the friend feed"

View File

@ -29,6 +29,7 @@ class UserInterfaceTweaks : ConfigContainer() {
val bootstrapOverride = container("bootstrap_override", BootstrapOverride()) { requireRestart() } val bootstrapOverride = container("bootstrap_override", BootstrapOverride()) { requireRestart() }
val mapFriendNameTags = boolean("map_friend_nametags") { requireRestart() } val mapFriendNameTags = boolean("map_friend_nametags") { requireRestart() }
val streakExpirationInfo = boolean("streak_expiration_info") { requireRestart() } val streakExpirationInfo = boolean("streak_expiration_info") { requireRestart() }
val hideFriendFeedEntry = boolean("hide_friend_feed_entry") { requireRestart() }
val hideStreakRestore = boolean("hide_streak_restore") { requireRestart() } val hideStreakRestore = boolean("hide_streak_restore") { requireRestart() }
val hideStorySections = multiple("hide_story_sections", val hideStorySections = multiple("hide_story_sections",
"hide_friend_suggestions", "hide_friends", "hide_suggested", "hide_for_you") { requireRestart() } "hide_friend_suggestions", "hide_friends", "hide_suggested", "hide_for_you") { requireRestart() }

View File

@ -34,7 +34,7 @@ enum class MessagingRuleType(
AUTO_DOWNLOAD("auto_download", true), AUTO_DOWNLOAD("auto_download", true),
STEALTH("stealth", true), STEALTH("stealth", true),
AUTO_SAVE("auto_save", 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), E2E_ENCRYPTION("e2e_encryption", false),
PIN_CONVERSATION("pin_conversation", false, showInFriendMenu = false); PIN_CONVERSATION("pin_conversation", false, showInFriendMenu = false);

View File

@ -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
}

View File

@ -99,6 +99,7 @@ class FeatureManager(
SnapToChatMedia::class, SnapToChatMedia::class,
FriendFeedMessagePreview::class, FriendFeedMessagePreview::class,
HideStreakRestore::class, HideStreakRestore::class,
HideFriendFeedEntry::class,
) )
initializeFeatures() initializeFeatures()