From 03dd09e9578983961e2de6a0fec26892883b8e13 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Sun, 19 Feb 2023 16:38:59 -0500 Subject: [PATCH] Adds a second list of filtered Users that were automatically added and are not saved with the person's key --- .../vitorpamplona/amethyst/model/Account.kt | 17 +++++++++++++- .../amethyst/model/LocalCache.kt | 23 +++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 78bdccd04..4de61d476 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -58,6 +58,8 @@ class Account( var dontTranslateFrom: Set = getLanguagesSpokenByUser(), var translateTo: String = Locale.getDefault().language ) { + var transientHiddenUsers: Set = setOf() + fun userProfile(): User { return LocalCache.getOrCreateUser(loggedIn.pubKey.toHexKey()) } @@ -67,7 +69,7 @@ class Account( } fun hiddenUsers(): List { - return hiddenUsers.map { LocalCache.getOrCreateUser(it) } + return (hiddenUsers + transientHiddenUsers).map { LocalCache.getOrCreateUser(it) } } fun isWriteable(): Boolean { @@ -321,6 +323,7 @@ class Account( fun showUser(pubkeyHex: String) { hiddenUsers = hiddenUsers - pubkeyHex + transientHiddenUsers = transientHiddenUsers - pubkeyHex invalidateData(live) } @@ -411,6 +414,18 @@ class Account( reconnectIfRelaysHaveChanged() } } + LocalCache.liveSpam.observeForever { + GlobalScope.launch(Dispatchers.IO) { + LocalCache.spamMessages.snapshot().values.forEach { + if (it !in hiddenUsers) { + val userToBlock = LocalCache.getOrCreateUser(it) + if (userToBlock != userProfile() && userToBlock !in userProfile().follows) { + transientHiddenUsers = transientHiddenUsers + it + } + } + } + } + } } // Observers line up here. diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 1a446d3ae..914058f18 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -52,8 +52,8 @@ object LocalCache { val notes = ConcurrentHashMap() val channels = ConcurrentHashMap() - val recentMessages = LruCache(1000) - val spamMessages = LruCache(1000) + val recentMessages = LruCache(1000) + val spamMessages = LruCache(1000) fun checkGetOrCreateUser(key: HexKey): User? { return try { @@ -120,16 +120,24 @@ object LocalCache { .format(DateTimeFormatter.ofPattern("uuuu MMM d hh:mm a")) } + @Synchronized fun isRepeatedMessageSpam(event: Event): Boolean { + val idHex = event.id.toHexKey() + // if already processed, return + if (notes[idHex] != null) return false + // double list strategy: // if duplicated, it goes into spam. 1000 spam messages are saved into the spam list. - - val hash = event.content.hashCode() - if (event.content.length > 50 && (recentMessages[hash] != null || spamMessages[hash] != null)) { - spamMessages.put(hash, hash) + val hash = (event.content + event.tags.flatten().joinToString(",")).hashCode() + if (event.content.length > 50 && ((recentMessages[hash] != null && recentMessages[hash] != idHex) || spamMessages[hash] != null)) { + Log.w("Potential SPAM Message", "${event.id.toHex()} ${recentMessages[hash]} ${spamMessages[hash] != null} ${event.content.replace("\n", " | ")}") + if (spamMessages.get(hash) == null) { + spamMessages.put(hash, event.pubKey.toHexKey()) + liveSpam.invalidateData() + } return true } - recentMessages.put(hash, hash) + recentMessages.put(hash, idHex) return false } @@ -639,6 +647,7 @@ object LocalCache { // Observers line up here. val live: LocalCacheLiveData = LocalCacheLiveData(this) + val liveSpam: LocalCacheLiveData = LocalCacheLiveData(this) private fun refreshObservers() { live.invalidateData()