diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 7b4a8ca73..72c216274 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -196,7 +196,9 @@ import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Request import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Response import com.vitorpamplona.quartz.nip51Lists.bookmarkList.BookmarkListEvent +import com.vitorpamplona.quartz.nip51Lists.bookmarkList.OldBookmarkListEvent import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.AddressBookmark +import com.vitorpamplona.quartz.nip51Lists.labeledBookmarkList.LabeledBookmarkListEvent import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingRoomEvent import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent @@ -235,6 +237,7 @@ import com.vitorpamplona.quartz.nip72ModCommunities.rules.CommunityRulesEvent import com.vitorpamplona.quartz.nip72ModCommunities.rules.tags.KindRuleTag import com.vitorpamplona.quartz.nip72ModCommunities.rules.tags.PubkeyRuleTag import com.vitorpamplona.quartz.nip72ModCommunities.rules.tags.WotTag +import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent import com.vitorpamplona.quartz.nip88Polls.response.PollResponseEvent import com.vitorpamplona.quartz.nip90Dvms.contentDiscoveryRequest.NIP90ContentDiscoveryRequestEvent @@ -937,11 +940,32 @@ class Account( private fun computeRelaysForChannels(event: Event): Set = cache.getAnyChannel(event)?.relays() ?: emptySet() - fun computeRelayListToBroadcast(event: Event): Set { - if (event is MetadataEvent || event is AdvertisedRelayListEvent) { - // everywhere - return followPlusAllMineWithIndex.flow.value + client.availableRelaysFlow().value + // Personal events the user stores just for themselves — drafts, app settings, bookmark + // lists — and channel/community events that already declare their own home relays + // should not be replicated to the user's broadcasting relays. Channel/community events + // that don't define any home relays fall through to broadcast, since there's nowhere + // else for them to land. + private fun wantsBroadcastRelays(event: Event): Boolean { + if (event is DraftWrapEvent || + event is AppSpecificDataEvent || + event is BookmarkListEvent || + event is OldBookmarkListEvent || + event is LabeledBookmarkListEvent + ) { + return false } + if (event is PollEvent && event.relays().isNotEmpty()) return false + if (event is MeetingSpaceEvent && event.allRelayUrls().isNotEmpty()) return false + if (event is MeetingRoomEvent && event.allRelayUrls().isNotEmpty()) return false + if (event is LiveActivitiesEvent && event.allRelayUrls().isNotEmpty()) return false + + val channelRelays = cache.getAnyChannel(event)?.relays() + if (channelRelays != null && channelRelays.isNotEmpty()) return false + + return true + } + + fun computeRelayListToBroadcast(event: Event): Set { if (event is GiftWrapEvent) { val receiver = event.recipientPubKey() return if (receiver != null) { @@ -960,13 +984,30 @@ class Account( return emptySet() } + val includeBroadcast = wantsBroadcastRelays(event) + val broadcastRelays = if (includeBroadcast) broadcastRelayList.flow.value else emptySet() + + if (event is MetadataEvent || event is AdvertisedRelayListEvent) { + // everywhere + return followPlusAllMineWithIndex.flow.value + client.availableRelaysFlow().value + broadcastRelays + } + val relayList = mutableSetOf() + relayList.addAll(broadcastRelays) val author = cache.getUserIfExists(event.pubKey) if (author != null) { if (author == userProfile()) { - relayList.addAll(outboxRelays.flow.value) + if (includeBroadcast) { + relayList.addAll(outboxRelays.flow.value) + } else { + // outboxRelays mixes in the broadcast list; for personal/channel events + // we want the user's NIP-65 / private / local outbox without it. + relayList.addAll(nip65RelayList.outboxFlow.value) + relayList.addAll(privateStorageRelayList.flow.value) + relayList.addAll(localRelayList.flow.value) + } } else { val relays = author.outboxRelays()?.ifEmpty { null }