diff --git a/database/query/query_where_builder.go b/database/query/query_where_builder.go index 5f05907f..4da5802e 100644 --- a/database/query/query_where_builder.go +++ b/database/query/query_where_builder.go @@ -15,7 +15,8 @@ import ( ) const ( - whereBuilderDefaultWhere = "e.hidden=0" + whereBuilderDefaultWhere = "e.hidden=0" + whereBuilderCommunityFilter = "iif(e.kind in (1, 30023, 30175), NOT EXISTS (select true from event_tags where event_id = e.id AND event_tag_key = 'h'), true)" ) const ( @@ -407,6 +408,11 @@ func (w *whereBuilder) applyFilter(idx int, filter *databaseFilterSearch) error w.applyFilterTags(name, filter.Tags) w.applyFilterTagMarkers(name, filter.TagMarkers) + if _, ok := filter.Tags[model.CustomIONTagCommunity]; !ok { + w.maybeAND() + w.WriteString(whereBuilderCommunityFilter) + } + w.WriteRune(')') // End the filter section. return nil @@ -780,6 +786,12 @@ func (w *whereBuilder) Build(filters ...model.Filter) (sql string, params map[st w.WriteString(" events_search MATCH :search") w.Params["search"] = strings.Join(searchKeywords, " OR ") } + if len(filters) == 0 { + if w.Len() > 0 { + w.WriteString(" AND ") + } + w.WriteString(whereBuilderCommunityFilter) + } if w.Prefix == "" { if w.Len() > 0 { w.WriteString(" AND ") diff --git a/database/query/query_where_builder_db_test.go b/database/query/query_where_builder_db_test.go index 8942f5e6..8cd82e53 100644 --- a/database/query/query_where_builder_db_test.go +++ b/database/query/query_where_builder_db_test.go @@ -1000,3 +1000,32 @@ func TestGetReplyTypeFromValues(t *testing.T) { require.Equal(t, "root", getReplyTypeFromValues([]model.TagValues{{nil, nil, model.PointerOf("root")}})) require.Equal(t, "reply", getReplyTypeFromValues([]model.TagValues{{nil, nil, model.PointerOf("reply")}})) } + +func TestCommunityEventsLookup(t *testing.T) { + t.Parallel() + + db := helperNewDatabase(t) + defer db.Close() + + var event, event2 model.Event + event.Kind = nostr.KindTextNote + event.ID = "1" + event.PubKey = "1" + + event2.Kind = nostr.KindTextNote + event2.ID = "2" + event2.PubKey = "2" + event2.Tags = model.Tags{{model.CustomIONTagCommunity, "foo"}} + + require.NoError(t, db.AcceptEvents(context.TODO(), &event, &event2)) + eventsNoFilter := helperSelectEvents(t, db) + require.Len(t, eventsNoFilter, 1) + + events := helperSelectEvents(t, db, model.Filter{IDs: []string{"1", "2"}, Limit: 3}) + require.Equal(t, 1, len(events)) // Only one event with ID 1. + require.Equal(t, "1", events[0].ID) + + eventsWithCommunity := helperSelectEvents(t, db, model.Filter{Tags: model.TagMap{}.Set(model.CustomIONTagCommunity), Limit: 3}) + require.Equal(t, 1, len(eventsWithCommunity)) // Only one event with tag "h". + require.Equal(t, "2", eventsWithCommunity[0].ID) +} diff --git a/database/query/query_where_builder_stmt_test.go b/database/query/query_where_builder_stmt_test.go index eacb732d..14ff389b 100644 --- a/database/query/query_where_builder_stmt_test.go +++ b/database/query/query_where_builder_stmt_test.go @@ -24,16 +24,6 @@ func TestIsFilterEmpty(t *testing.T) { require.False(t, isFilterEmpty(dbFilter)) } -func TestWhereBuilderEmpty(t *testing.T) { - t.Parallel() - - builder := newWhereBuilder() - q, params, err := builder.Build() - require.NoError(t, err) - require.Equal(t, whereBuilderDefaultWhere, q) - require.Empty(t, params) -} - func helperEnsureParams(t *testing.T, stmt string, params map[string]any) { t.Helper() @@ -49,7 +39,7 @@ func TestWhereBuilderSingleNoTags(t *testing.T) { q, params, err := newWhereBuilder().Build() require.NoError(t, err) require.Empty(t, params) - require.Equal(t, whereBuilderDefaultWhere, q) + require.Contains(t, q, whereBuilderDefaultWhere) }) t.Run("WithID", func(t *testing.T) { q, params, err := newWhereBuilder().Build(model.Filter{ diff --git a/go.mod b/go.mod index b8945361..6015e22b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ice-blockchain/subzero -go 1.23.5 +go 1.23.6 replace ( filippo.io/mkcert => github.com/kixelated/mkcert v1.4.4-days @@ -26,7 +26,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.24 github.com/mitchellh/mapstructure v1.5.0 github.com/mxschmitt/golang-combinations v1.2.0 - github.com/nbd-wtf/go-nostr v0.49.3 + github.com/nbd-wtf/go-nostr v0.49.4 github.com/puzpuzpuz/xsync/v3 v3.5.0 github.com/quic-go/quic-go v0.49.0 github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 diff --git a/server/ws/subscriptions_auth_test.go b/server/ws/subscriptions_auth_test.go index a2bbf66e..8ee7cd87 100644 --- a/server/ws/subscriptions_auth_test.go +++ b/server/ws/subscriptions_auth_test.go @@ -400,11 +400,12 @@ func TestSubscriptionPrivateCommunity(t *testing.T) { }) t.Run("select data by authorized user that is in the community now", func(t *testing.T) { - events, err := relay.QuerySync(ctx, model.Filter{Kinds: []int{nostr.KindTextNote}}) + events, err := relay.QuerySync(ctx, model.Filter{ + Kinds: []int{communityPostEvent.Kind}, + Tags: model.TagMap{}.SetLiterals(model.CustomIONTagCommunity, communityPostEvent.GetHTag()), + }) require.NoError(t, err) - require.Len(t, events, 2) - - require.Contains(t, events, &nonCommunityEvent.Event) + require.Len(t, events, 1) require.Contains(t, events, &communityPostEvent.Event) })