2023-08-10 14:32:11 -03:00
|
|
|
package khatru
|
2022-11-11 09:48:04 -03:00
|
|
|
|
|
|
|
import (
|
2023-05-01 19:21:09 -03:00
|
|
|
"context"
|
2022-11-11 09:48:04 -03:00
|
|
|
"fmt"
|
|
|
|
|
2023-11-07 14:36:13 -03:00
|
|
|
"github.com/fiatjaf/eventstore"
|
2022-11-11 09:48:04 -03:00
|
|
|
"github.com/nbd-wtf/go-nostr"
|
|
|
|
)
|
|
|
|
|
2023-08-10 14:32:11 -03:00
|
|
|
func (rl *Relay) AddEvent(ctx context.Context, evt *nostr.Event) error {
|
2023-06-12 08:19:07 -03:00
|
|
|
if evt == nil {
|
2023-08-10 14:32:11 -03:00
|
|
|
return fmt.Errorf("event is nil")
|
2023-06-12 08:19:07 -03:00
|
|
|
}
|
|
|
|
|
2023-08-10 14:32:11 -03:00
|
|
|
msg := ""
|
|
|
|
rejecting := false
|
|
|
|
for _, reject := range rl.RejectEvent {
|
|
|
|
rejecting, msg = reject(ctx, evt)
|
|
|
|
if rejecting {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2022-11-11 09:48:04 -03:00
|
|
|
|
2023-08-10 14:32:11 -03:00
|
|
|
if rejecting {
|
|
|
|
if msg == "" {
|
|
|
|
msg = "no reason"
|
|
|
|
}
|
|
|
|
return fmt.Errorf(msg)
|
2022-11-11 09:48:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
if 20000 <= evt.Kind && evt.Kind < 30000 {
|
|
|
|
// do not store ephemeral events
|
|
|
|
} else {
|
2023-08-10 14:32:11 -03:00
|
|
|
if evt.Kind == 0 || evt.Kind == 3 || (10000 <= evt.Kind && evt.Kind < 20000) {
|
|
|
|
// replaceable event, delete before storing
|
|
|
|
for _, query := range rl.QueryEvents {
|
|
|
|
ch, err := query(ctx, nostr.Filter{Authors: []string{evt.PubKey}, Kinds: []int{evt.Kind}})
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
2023-11-07 14:14:53 -03:00
|
|
|
if previous := <-ch; previous != nil && isOlder(previous, evt) {
|
2023-08-10 14:32:11 -03:00
|
|
|
for _, del := range rl.DeleteEvent {
|
|
|
|
del(ctx, previous)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if 30000 <= evt.Kind && evt.Kind < 40000 {
|
|
|
|
// parameterized replaceable event, delete before storing
|
|
|
|
d := evt.Tags.GetFirst([]string{"d", ""})
|
|
|
|
if d != nil {
|
|
|
|
for _, query := range rl.QueryEvents {
|
|
|
|
ch, err := query(ctx, nostr.Filter{Authors: []string{evt.PubKey}, Kinds: []int{evt.Kind}, Tags: nostr.TagMap{"d": []string{d.Value()}}})
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
2023-11-07 14:14:53 -03:00
|
|
|
if previous := <-ch; previous != nil && isOlder(previous, evt) {
|
2023-08-10 14:32:11 -03:00
|
|
|
for _, del := range rl.DeleteEvent {
|
|
|
|
del(ctx, previous)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-11-11 09:48:04 -03:00
|
|
|
}
|
|
|
|
|
2023-08-10 14:32:11 -03:00
|
|
|
// store
|
|
|
|
for _, store := range rl.StoreEvent {
|
|
|
|
if saveErr := store(ctx, evt); saveErr != nil {
|
|
|
|
switch saveErr {
|
2023-11-07 14:36:13 -03:00
|
|
|
case eventstore.ErrDupEvent:
|
2023-08-10 14:32:11 -03:00
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
errmsg := saveErr.Error()
|
|
|
|
if nip20prefixmatcher.MatchString(errmsg) {
|
|
|
|
return saveErr
|
|
|
|
} else {
|
|
|
|
return fmt.Errorf("error: failed to save (%s)", errmsg)
|
|
|
|
}
|
2023-06-26 20:47:33 -03:00
|
|
|
}
|
2022-12-23 15:55:52 +01:00
|
|
|
}
|
2022-11-11 09:48:04 -03:00
|
|
|
}
|
|
|
|
|
2023-08-10 14:32:11 -03:00
|
|
|
for _, ons := range rl.OnEventSaved {
|
|
|
|
ons(ctx, evt)
|
2022-11-11 09:48:04 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-04 17:35:47 -03:00
|
|
|
for _, ovw := range rl.OverwriteResponseEvent {
|
|
|
|
ovw(ctx, evt)
|
|
|
|
}
|
2023-06-12 08:19:07 -03:00
|
|
|
notifyListeners(evt)
|
2023-11-04 17:35:47 -03:00
|
|
|
|
2023-08-10 14:32:11 -03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rl *Relay) handleDeleteRequest(ctx context.Context, evt *nostr.Event) error {
|
|
|
|
// event deletion -- nip09
|
|
|
|
for _, tag := range evt.Tags {
|
|
|
|
if len(tag) >= 2 && tag[0] == "e" {
|
|
|
|
// first we fetch the event
|
|
|
|
for _, query := range rl.QueryEvents {
|
|
|
|
ch, err := query(ctx, nostr.Filter{IDs: []string{tag[1]}})
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
target := <-ch
|
|
|
|
if target == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// got the event, now check if the user can delete it
|
|
|
|
acceptDeletion := target.PubKey == evt.PubKey
|
|
|
|
var msg string
|
|
|
|
if acceptDeletion == false {
|
|
|
|
msg = "you are not the author of this event"
|
|
|
|
}
|
|
|
|
// but if we have a function to overwrite this outcome, use that instead
|
|
|
|
for _, odo := range rl.OverwriteDeletionOutcome {
|
|
|
|
acceptDeletion, msg = odo(ctx, target, evt)
|
|
|
|
}
|
|
|
|
if acceptDeletion {
|
|
|
|
// delete it
|
|
|
|
for _, del := range rl.DeleteEvent {
|
|
|
|
del(ctx, target)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// fail and stop here
|
|
|
|
return fmt.Errorf("blocked: %s", msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
// don't try to query this same event again
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-11-11 09:48:04 -03:00
|
|
|
|
2023-08-10 14:32:11 -03:00
|
|
|
return nil
|
2022-11-11 09:48:04 -03:00
|
|
|
}
|