diff --git a/badger/count.go b/badger/count.go index c2d79e2..3012437 100644 --- a/badger/count.go +++ b/badger/count.go @@ -10,7 +10,7 @@ import ( "github.com/nbd-wtf/go-nostr" ) -func (b BadgerBackend) CountEvents(ctx context.Context, filter nostr.Filter) (int64, error) { +func (b *BadgerBackend) CountEvents(ctx context.Context, filter nostr.Filter) (int64, error) { var count int64 = 0 queries, extraFilter, since, err := prepareQueries(filter) diff --git a/badger/helpers.go b/badger/helpers.go index b77f641..a5f0fef 100644 --- a/badger/helpers.go +++ b/badger/helpers.go @@ -43,7 +43,7 @@ func getTagIndexPrefix(tagValue string) ([]byte, int) { return k, offset } -func (b BadgerBackend) getIndexKeysForEvent(evt *nostr.Event, idx []byte) iter.Seq[[]byte] { +func (b *BadgerBackend) getIndexKeysForEvent(evt *nostr.Event, idx []byte) iter.Seq[[]byte] { return func(yield func([]byte) bool) { { // ~ by id diff --git a/badger/query.go b/badger/query.go index 8aa45b9..5fc2346 100644 --- a/badger/query.go +++ b/badger/query.go @@ -21,7 +21,7 @@ type iterEvent struct { var BatchFilled = errors.New("batch-filled") -func (b BadgerBackend) QueryEvents(ctx context.Context, filter nostr.Filter) (chan *nostr.Event, error) { +func (b *BadgerBackend) QueryEvents(ctx context.Context, filter nostr.Filter) (chan *nostr.Event, error) { ch := make(chan *nostr.Event) if filter.Search != "" { diff --git a/badger/replace.go.bak b/badger/replace.go.bak new file mode 100644 index 0000000..a5d3300 --- /dev/null +++ b/badger/replace.go.bak @@ -0,0 +1,68 @@ +package badger + +import ( + "context" + "fmt" + + "github.com/nbd-wtf/go-nostr" +) + +func (b *BadgerBackend) ReplaceEvent(ctx context.Context, matcher nostr.Filter, newEvent *nostr.Event) error { + if 20000 <= evt.Kind && evt.Kind < 30000 { + // do not store ephemeral events + return nil + } else if evt.Kind == 0 || evt.Kind == 3 || (10000 <= evt.Kind && evt.Kind < 20000) { + // replaceable event, delete before storing + ch, err := w.Store.QueryEvents(ctx, nostr.Filter{Authors: []string{evt.PubKey}, Kinds: []int{evt.Kind}}) + if err != nil { + return fmt.Errorf("failed to query before replacing: %w", err) + } + isNewer := true + for previous := range ch { + if previous == nil { + continue + } + if isOlder(previous, &evt) { + if err := w.Store.DeleteEvent(ctx, previous); err != nil { + return fmt.Errorf("failed to delete event for replacing: %w", err) + } + } else { + // already, newer event is stored. + isNewer = false + break + } + } + if !isNewer { + return nil + } + } else if 30000 <= evt.Kind && evt.Kind < 40000 { + // parameterized replaceable event, delete before storing + d := evt.Tags.GetFirst([]string{"d", ""}) + if d == nil { + return fmt.Errorf("failed to add event missing d tag for parameterized replacing") + } + ch, err := w.Store.QueryEvents(ctx, nostr.Filter{Authors: []string{evt.PubKey}, Kinds: []int{evt.Kind}, Tags: nostr.TagMap{"d": []string{d.Value()}}}) + if err != nil { + return fmt.Errorf("failed to query before parameterized replacing: %w", err) + } + isNewer := true + for previous := range ch { + if previous == nil { + continue + } + + if !isOlder(previous, &evt) { + if err := w.Store.DeleteEvent(ctx, previous); err != nil { + return fmt.Errorf("failed to delete event for parameterized replacing: %w", err) + } + } else { + // already, newer event is stored. + isNewer = false + break + } + } + if !isNewer { + return nil + } + } +}