mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-08 23:54:39 +00:00
feat(buzz): auto-invite mentioned non-members into a workspace channel
Mentioning someone who isn't yet a member of a Buzz workspace channel now adds them (kind-9000 put-user) before the message is published, so the `@`-mention resolves to a real member — mirroring Buzz's own composer, which is how you pull a bot into a channel by naming it. Gated on the sender being able to moderate (only a moderator can issue kind-9000; it's a silent no-op otherwise), skips self and already-present members, and is best-effort so a failed add never blocks the message. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8KBSw6smQRyXLiWHeDsZ8
This commit is contained in:
+35
@@ -39,6 +39,7 @@ import com.vitorpamplona.amethyst.commons.model.emphChat.EphemeralChatChannel
|
||||
import com.vitorpamplona.amethyst.commons.model.geohashChat.GeohashChatChannel
|
||||
import com.vitorpamplona.amethyst.commons.model.nip28PublicChats.PublicChatChannel
|
||||
import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupChannel
|
||||
import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupMembership
|
||||
import com.vitorpamplona.amethyst.commons.model.nip30CustomEmojis.EmojiPackState
|
||||
import com.vitorpamplona.amethyst.commons.model.nip30CustomEmojis.EmojiSuggestionState
|
||||
import com.vitorpamplona.amethyst.commons.model.nip53LiveActivities.LiveActivitiesChannel
|
||||
@@ -126,6 +127,7 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
@Stable
|
||||
open class ChannelNewMessageViewModel :
|
||||
@@ -530,6 +532,37 @@ open class ChannelNewMessageViewModel :
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Buzz auto-invite: mentioning someone who isn't yet a member of a Buzz workspace channel adds
|
||||
* them (kind-9000 put-user) before the message goes out, so the `@`-mention resolves to a real
|
||||
* member — mirroring Buzz's own composer, which is how you pull a bot into a channel by naming it.
|
||||
*
|
||||
* Only a moderator can issue kind-9000, so this is a no-op for a plain member (the relay would
|
||||
* reject it anyway); self and already-present members are skipped. Best-effort — a failed add
|
||||
* must never block the message, so each is guarded.
|
||||
*/
|
||||
private suspend fun autoInviteMentionedBuzzMembers(
|
||||
channel: Channel,
|
||||
mentioned: List<User>?,
|
||||
) {
|
||||
if (mentioned.isNullOrEmpty()) return
|
||||
if (channel !is RelayGroupChannel || !BuzzRelayDialect.isBuzz(channel.groupId.relayUrl)) return
|
||||
val me = accountViewModel.account.userProfile().pubkeyHex
|
||||
if (!channel.membershipOf(me).canModerate()) return
|
||||
|
||||
mentioned.forEach { user ->
|
||||
val pk = user.pubkeyHex
|
||||
if (pk != me && channel.membershipOf(pk) == RelayGroupMembership.NONE) {
|
||||
try {
|
||||
accountViewModel.account.putRelayGroupUser(channel, pk, emptyList())
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.w("BuzzAutoInvite", "Failed to add mentioned member ${pk.take(8)}: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// `protected open` so a specialized composer (e.g. the Buzz forum reply) can reuse this whole
|
||||
// rich EditFieldRow but swap only the event it builds for the composed text.
|
||||
protected open suspend fun createTemplate(): EventTemplate<out Event>? {
|
||||
@@ -545,6 +578,8 @@ open class ChannelNewMessageViewModel :
|
||||
)
|
||||
tagger.run()
|
||||
|
||||
autoInviteMentionedBuzzMembers(channel, tagger.pTags)
|
||||
|
||||
val urls = findURLs(messageText)
|
||||
val usedAttachments = iMetaAttachments.filterIsIn(urls.toSet())
|
||||
val emojis = accountViewModel.account.emoji.findEmojiTags(messageText)
|
||||
|
||||
Reference in New Issue
Block a user