Correctly adding relays to the filters so that the Global feed can filter only events that came from the relays listed in the Global filter.

This commit is contained in:
Vitor Pamplona
2025-11-13 10:50:13 -05:00
parent 19846e7ff3
commit e6a10e07c4
12 changed files with 32 additions and 24 deletions
@@ -67,14 +67,14 @@ class FilterByListParams(
fun match( fun match(
noteEvent: Event, noteEvent: Event,
comingFrom: List<NormalizedRelayUrl> = emptyList(), comingFrom: List<NormalizedRelayUrl>,
) = ((isGlobal(comingFrom)) || isEventInList(noteEvent)) && ) = ((isGlobal(comingFrom)) || isEventInList(noteEvent)) &&
(isHiddenList || isNotHidden(noteEvent.pubKey)) && (isHiddenList || isNotHidden(noteEvent.pubKey)) &&
isNotInTheFuture(noteEvent) isNotInTheFuture(noteEvent)
fun match( fun match(
address: Address?, address: Address?,
comingFrom: List<NormalizedRelayUrl> = emptyList(), comingFrom: List<NormalizedRelayUrl>,
) = address != null && ) = address != null &&
(isGlobal(comingFrom) || isAuthorInFollows(address)) && (isGlobal(comingFrom) || isAuthorInFollows(address)) &&
(isHiddenList || isNotHidden(address.pubKeyHex)) (isHiddenList || isNotHidden(address.pubKeyHex))
@@ -49,7 +49,7 @@ open class DiscoverLongFormFeedFilter(
val notes = val notes =
LocalCache.addressables.filterIntoSet(LongTextNoteEvent.KIND) { _, it -> LocalCache.addressables.filterIntoSet(LongTextNoteEvent.KIND) { _, it ->
val noteEvent = it.event val noteEvent = it.event
noteEvent is LongTextNoteEvent && params.match(noteEvent) noteEvent is LongTextNoteEvent && params.match(noteEvent, it.relays)
} }
return sort(notes) return sort(notes)
} }
@@ -67,7 +67,7 @@ open class DiscoverLongFormFeedFilter(
return collection.filterTo(HashSet()) { return collection.filterTo(HashSet()) {
val noteEvent = it.event val noteEvent = it.event
noteEvent is LongTextNoteEvent && params.match(noteEvent) noteEvent is LongTextNoteEvent && params.match(noteEvent, it.relays)
} }
} }
@@ -51,7 +51,7 @@ open class DiscoverChatFeedFilter(
val note = LocalCache.getNoteIfExists(channel.idHex) val note = LocalCache.getNoteIfExists(channel.idHex)
val noteEvent = note?.event val noteEvent = note?.event
if (noteEvent == null || params.match(noteEvent)) { if (noteEvent == null || params.match(noteEvent, note.relays)) {
note note
} else { } else {
null null
@@ -75,7 +75,7 @@ open class DiscoverChatFeedFilter(
return collection.mapNotNullTo(HashSet()) { note -> return collection.mapNotNullTo(HashSet()) { note ->
// note event here will never be null // note event here will never be null
val noteEvent = note.event val noteEvent = note.event
if (noteEvent is ChannelCreateEvent && params.match(noteEvent)) { if (noteEvent is ChannelCreateEvent && params.match(noteEvent, note.relays)) {
if ((LocalCache.getPublicChatChannelIfExists(noteEvent.id)?.notes?.size() ?: 0) > 0) { if ((LocalCache.getPublicChatChannelIfExists(noteEvent.id)?.notes?.size() ?: 0) > 0) {
note note
} else { } else {
@@ -86,7 +86,7 @@ open class DiscoverChatFeedFilter(
val channelEvent = channel?.event val channelEvent = channel?.event
if (channel != null && if (channel != null &&
(channelEvent == null || (channelEvent is ChannelCreateEvent && params.match(channelEvent))) (channelEvent == null || (channelEvent is ChannelCreateEvent && params.match(channelEvent, note.relays)))
) { ) {
if ((LocalCache.getPublicChatChannelIfExists(channel.idHex)?.notes?.size() ?: 0) > 0) { if ((LocalCache.getPublicChatChannelIfExists(channel.idHex)?.notes?.size() ?: 0) > 0) {
channel channel
@@ -48,7 +48,7 @@ open class DiscoverFollowSetsFeedFilter(
val notes = val notes =
LocalCache.addressables.filterIntoSet(FollowListEvent.KIND) { _, it -> LocalCache.addressables.filterIntoSet(FollowListEvent.KIND) { _, it ->
val noteEvent = it.event val noteEvent = it.event
noteEvent is FollowListEvent && params.match(noteEvent) noteEvent is FollowListEvent && params.match(noteEvent, it.relays)
} }
return sort(notes) return sort(notes)
@@ -67,7 +67,7 @@ open class DiscoverFollowSetsFeedFilter(
return collection.filterTo(HashSet()) { return collection.filterTo(HashSet()) {
val noteEvent = it.event val noteEvent = it.event
noteEvent is FollowListEvent && params.match(noteEvent) noteEvent is FollowListEvent && params.match(noteEvent, it.relays)
} }
} }
@@ -72,7 +72,7 @@ open class DiscoverLiveFeedFilter(
return collection.filterTo(HashSet()) { return collection.filterTo(HashSet()) {
val noteEvent = it.event val noteEvent = it.event
noteEvent is LiveActivitiesEvent && filterParams.match(noteEvent) noteEvent is LiveActivitiesEvent && filterParams.match(noteEvent, it.relays)
} }
} }
@@ -60,7 +60,7 @@ open class DiscoverCommunityFeedFilter(
if (noteEvent == null && shouldInclude(key, filterParams, note.relays)) { if (noteEvent == null && shouldInclude(key, filterParams, note.relays)) {
// send unloaded communities to the screen // send unloaded communities to the screen
note note
} else if (noteEvent is CommunityDefinitionEvent && filterParams.match(noteEvent)) { } else if (noteEvent is CommunityDefinitionEvent && filterParams.match(noteEvent, note.relays)) {
note note
} else { } else {
null null
@@ -84,7 +84,7 @@ open class DiscoverCommunityFeedFilter(
.mapNotNull { note -> .mapNotNull { note ->
// note event here will never be null // note event here will never be null
val noteEvent = note.event val noteEvent = note.event
if (noteEvent is CommunityDefinitionEvent && filterParams.match(noteEvent)) { if (noteEvent is CommunityDefinitionEvent && filterParams.match(noteEvent, note.relays)) {
listOf(note) listOf(note)
} else if (noteEvent is CommunityPostApprovalEvent) { } else if (noteEvent is CommunityPostApprovalEvent) {
noteEvent.communityAddresses().mapNotNull { noteEvent.communityAddresses().mapNotNull {
@@ -93,7 +93,7 @@ open class DiscoverCommunityFeedFilter(
if (definitionEvent == null && shouldInclude(it, filterParams, definitionNote.relays)) { if (definitionEvent == null && shouldInclude(it, filterParams, definitionNote.relays)) {
definitionNote definitionNote
} else if (definitionEvent is CommunityDefinitionEvent && filterParams.match(definitionEvent)) { } else if (definitionEvent is CommunityDefinitionEvent && filterParams.match(definitionEvent, definitionNote.relays)) {
definitionNote definitionNote
} else { } else {
null null
@@ -34,6 +34,7 @@ import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthors
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
import com.vitorpamplona.quartz.nip89AppHandlers.definition.AppDefinitionEvent import com.vitorpamplona.quartz.nip89AppHandlers.definition.AppDefinitionEvent
@@ -74,16 +75,19 @@ open class DiscoverNIP89FeedFilter(
fun acceptDVM(note: Note): Boolean { fun acceptDVM(note: Note): Boolean {
val noteEvent = note.event val noteEvent = note.event
return if (noteEvent is AppDefinitionEvent) { return if (noteEvent is AppDefinitionEvent) {
acceptDVM(noteEvent) acceptDVM(noteEvent, note.relays)
} else { } else {
false false
} }
} }
fun acceptDVM(noteEvent: AppDefinitionEvent): Boolean { fun acceptDVM(
noteEvent: AppDefinitionEvent,
relays: List<NormalizedRelayUrl>,
): Boolean {
val filterParams = buildFilterParams(account) val filterParams = buildFilterParams(account)
return noteEvent.appMetaData()?.subscription != true && return noteEvent.appMetaData()?.subscription != true &&
filterParams.match(noteEvent) && filterParams.match(noteEvent, relays) &&
noteEvent.includeKind(5300) && noteEvent.includeKind(5300) &&
noteEvent.createdAt > lastAnnounced // && params.match(noteEvent) noteEvent.createdAt > lastAnnounced // && params.match(noteEvent)
} }
@@ -49,7 +49,7 @@ open class DiscoverMarketplaceFeedFilter(
val notes = val notes =
LocalCache.addressables.filterIntoSet(ClassifiedsEvent.KIND) { _, it -> LocalCache.addressables.filterIntoSet(ClassifiedsEvent.KIND) { _, it ->
val noteEvent = it.event val noteEvent = it.event
noteEvent is ClassifiedsEvent && noteEvent.isWellFormed() && params.match(noteEvent) noteEvent is ClassifiedsEvent && noteEvent.isWellFormed() && params.match(noteEvent, it.relays)
} }
return sort(notes) return sort(notes)
@@ -68,7 +68,7 @@ open class DiscoverMarketplaceFeedFilter(
return collection.filterTo(HashSet()) { return collection.filterTo(HashSet()) {
val noteEvent = it.event val noteEvent = it.event
noteEvent is ClassifiedsEvent && noteEvent.isWellFormed() && params.match(noteEvent) noteEvent is ClassifiedsEvent && noteEvent.isWellFormed() && params.match(noteEvent, it.relays)
} }
} }
@@ -34,6 +34,7 @@ import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
import com.vitorpamplona.quartz.nip22Comments.CommentEvent import com.vitorpamplona.quartz.nip22Comments.CommentEvent
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
@@ -96,6 +97,7 @@ class FollowPackFeedConversationsFeedFilter(
fun acceptableEvent( fun acceptableEvent(
event: Event?, event: Event?,
relays: List<NormalizedRelayUrl>,
filterParams: FilterByListParams, filterParams: FilterByListParams,
): Boolean = ): Boolean =
( (
@@ -107,12 +109,12 @@ class FollowPackFeedConversationsFeedFilter(
event is PublicMessageEvent || event is PublicMessageEvent ||
event is LiveActivitiesChatMessageEvent event is LiveActivitiesChatMessageEvent
) && ) &&
filterParams.match(event) filterParams.match(event, relays)
fun acceptableEvent( fun acceptableEvent(
note: Note, note: Note,
filterParams: FilterByListParams, filterParams: FilterByListParams,
): Boolean = acceptableEvent(note.event, filterParams) && !note.isNewThread() ): Boolean = acceptableEvent(note.event, note.relays, filterParams) && !note.isNewThread()
override fun sort(items: Set<Note>): List<Note> = items.sortedWith(DefaultFeedOrder) override fun sort(items: Set<Note>): List<Note> = items.sortedWith(DefaultFeedOrder)
} }
@@ -31,6 +31,7 @@ import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
import com.vitorpamplona.quartz.nip22Comments.CommentEvent import com.vitorpamplona.quartz.nip22Comments.CommentEvent
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
@@ -74,6 +75,7 @@ class HomeConversationsFeedFilter(
fun acceptableEvent( fun acceptableEvent(
event: Event?, event: Event?,
relays: List<NormalizedRelayUrl>,
filterParams: FilterByListParams, filterParams: FilterByListParams,
): Boolean = ): Boolean =
( (
@@ -85,12 +87,12 @@ class HomeConversationsFeedFilter(
event is PublicMessageEvent || event is PublicMessageEvent ||
event is LiveActivitiesChatMessageEvent event is LiveActivitiesChatMessageEvent
) && ) &&
filterParams.match(event) filterParams.match(event, relays)
fun acceptableEvent( fun acceptableEvent(
note: Note, note: Note,
filterParams: FilterByListParams, filterParams: FilterByListParams,
): Boolean = acceptableEvent(note.event, filterParams) && !note.isNewThread() ): Boolean = acceptableEvent(note.event, note.relays, filterParams) && !note.isNewThread()
override fun sort(items: Set<Note>): List<Note> = items.sortedWith(DefaultFeedOrder) override fun sort(items: Set<Note>): List<Note> = items.sortedWith(DefaultFeedOrder)
} }
@@ -72,7 +72,7 @@ class UserProfileGalleryFeedFilter(
return ( return (
(it.event?.pubKey == user.pubkeyHex && (noteEvent is PictureEvent || noteEvent is VideoEvent || (noteEvent is ProfileGalleryEntryEvent) && noteEvent.hasUrl() && noteEvent.hasFromEvent())) // && noteEvent.isOneOf(SUPPORTED_VIDEO_FEED_MIME_TYPES_SET)) (it.event?.pubKey == user.pubkeyHex && (noteEvent is PictureEvent || noteEvent is VideoEvent || (noteEvent is ProfileGalleryEntryEvent) && noteEvent.hasUrl() && noteEvent.hasFromEvent())) // && noteEvent.isOneOf(SUPPORTED_VIDEO_FEED_MIME_TYPES_SET))
) && ) &&
params.match(noteEvent) && params.match(noteEvent, it.relays) &&
account.isAcceptable(it) account.isAcceptable(it)
} }
@@ -126,7 +126,7 @@ class VideoFeedFilter(
(noteEvent is FileStorageHeaderEvent && noteEvent.isOneOf(SUPPORTED_VIDEO_FEED_MIME_TYPES_SET)) || (noteEvent is FileStorageHeaderEvent && noteEvent.isOneOf(SUPPORTED_VIDEO_FEED_MIME_TYPES_SET)) ||
(noteEvent is PictureEvent && acceptanceEvent(noteEvent)) (noteEvent is PictureEvent && acceptanceEvent(noteEvent))
) && ) &&
params.match(noteEvent) && params.match(noteEvent, note.relays) &&
(params.isHiddenList || account.isAcceptable(note)) (params.isHiddenList || account.isAcceptable(note))
} }