diff --git a/filter.go b/filter.go index 044deeb..c8cf1db 100644 --- a/filter.go +++ b/filter.go @@ -2,7 +2,6 @@ package nostr import ( "encoding/json" - "slices" "github.com/mailru/easyjson" @@ -19,6 +18,9 @@ type Filter struct { Until *Timestamp `json:"until,omitempty"` Limit int `json:"limit,omitempty"` Search string `json:"search,omitempty"` + + // LimitZero is or must be set when there is a "limit":0 in the filter, and not when "limit" is just omitted + LimitZero bool `json:"-"` } type TagMap map[string][]string @@ -115,16 +117,21 @@ func FilterEqual(a Filter, b Filter) bool { return false } + if a.LimitZero != b.LimitZero { + return false + } + return true } func (ef Filter) Clone() Filter { clone := Filter{ - IDs: slices.Clone(ef.IDs), - Authors: slices.Clone(ef.Authors), - Kinds: slices.Clone(ef.Kinds), - Limit: ef.Limit, - Search: ef.Search, + IDs: slices.Clone(ef.IDs), + Authors: slices.Clone(ef.Authors), + Kinds: slices.Clone(ef.Kinds), + Limit: ef.Limit, + Search: ef.Search, + LimitZero: ef.LimitZero, } if ef.Tags != nil { diff --git a/filter_easyjson.go b/filter_easyjson.go index a89c360..791b507 100644 --- a/filter_easyjson.go +++ b/filter_easyjson.go @@ -129,6 +129,9 @@ func easyjson4d398eaaDecodeGithubComNbdWtfGoNostr(in *jlexer.Lexer, out *Filter) } case "limit": out.Limit = int(in.Int()) + if out.Limit == 0 { + out.LimitZero = true + } case "search": out.Search = string(in.String()) default: @@ -243,7 +246,7 @@ func easyjson4d398eaaEncodeGithubComNbdWtfGoNostr(out *jwriter.Writer, in Filter } out.Int64(int64(*in.Until)) } - if in.Limit != 0 { + if in.Limit != 0 || in.LimitZero { const prefix string = ",\"limit\":" if first { first = false diff --git a/filter_test.go b/filter_test.go index 6fb9ef6..9422ede 100644 --- a/filter_test.go +++ b/filter_test.go @@ -2,9 +2,8 @@ package nostr import ( "encoding/json" - "testing" - "slices" + "testing" ) func TestFilterUnmarshal(t *testing.T) { @@ -39,6 +38,41 @@ func TestFilterMarshal(t *testing.T) { } } +func TestFilterUnmarshalWithLimitZero(t *testing.T) { + raw := `{"ids": ["abc"],"#e":["zzz"],"limit":0,"#something":["nothing","bab"],"since":1644254609,"search":"test"}` + var f Filter + if err := json.Unmarshal([]byte(raw), &f); err != nil { + t.Errorf("failed to parse filter json: %v", err) + } + + if f.Since == nil || + f.Since.Time().UTC().Format("2006-01-02") != "2022-02-07" || + f.Until != nil || + f.Tags == nil || len(f.Tags) != 2 || !slices.Contains(f.Tags["something"], "bab") || + f.Search != "test" || + f.LimitZero == false { + t.Error("failed to parse filter correctly") + } +} + +func TestFilterMarshalWithLimitZero(t *testing.T) { + until := Timestamp(12345678) + filterj, err := json.Marshal(Filter{ + Kinds: []int{KindTextNote, KindRecommendServer, KindEncryptedDirectMessage}, + Tags: TagMap{"fruit": {"banana", "mango"}}, + Until: &until, + LimitZero: true, + }) + if err != nil { + t.Errorf("failed to marshal filter json: %v", err) + } + + expected := `{"kinds":[1,2,4],"until":12345678,"limit":0,"#fruit":["banana","mango"]}` + if string(filterj) != expected { + t.Errorf("filter json was wrong: %s != %s", string(filterj), expected) + } +} + func TestFilterMatchingLive(t *testing.T) { var filter Filter var event Event