Files
realy/realy/add-event.go

87 lines
2.2 KiB
Go

package realy
import (
"fmt"
"net/http"
"regexp"
"strings"
"realy.lol/event"
"realy.lol/normalize"
"realy.lol/relay"
"realy.lol/relay/wrapper"
"realy.lol/store"
)
var nip20prefixmatcher = regexp.MustCompile(`^\w+: `)
// AddEvent has a business rule to add an event to the event store
func AddEvent(c Ctx, rl relay.I, ev *event.T, hr *http.Request, origin S,
authedPubkey B) (accepted bool, message B) {
if ev == nil {
return false, normalize.Invalid.F("empty event")
}
sto := rl.Storage(c)
wrapper := &wrapper.RelayWrapper{I: sto}
advancedSaver, _ := sto.(relay.AdvancedSaver)
accept, notice, after := rl.AcceptEvent(c, ev, hr, origin, authedPubkey)
if !accept {
return false, normalize.Blocked.F(notice)
}
if ev.Tags.ContainsProtectedMarker() {
if len(authedPubkey) == 0 || !equals(ev.PubKey, authedPubkey) {
return false, B(fmt.Sprintf(
"event with relay marker tag '-' may only be published by matching npub: %0x is not %0x",
authedPubkey, ev.PubKey))
}
}
if ev.Kind.IsEphemeral() {
// do not store ephemeral events
} else {
if advancedSaver != nil {
advancedSaver.BeforeSave(c, ev)
}
if saveErr := wrapper.Publish(c, ev); chk.E(saveErr) {
switch saveErr {
case store.ErrDupEvent:
return false, normalize.Error.F(saveErr.Error())
default:
errmsg := saveErr.Error()
if nip20prefixmatcher.MatchString(errmsg) {
if strings.Contains(errmsg, "tombstone") {
return false, normalize.Blocked.F(
"event was deleted, not storing it again")
}
return false, normalize.Error.F(errmsg)
} else {
return false, normalize.Error.F("failed to save (%s)", errmsg)
}
}
// } else {
// log.D.F("saved event %s", ev.Serialize())
}
if advancedSaver != nil {
advancedSaver.AfterSave(ev)
}
}
var authRequired bool
if ar, ok := rl.(relay.Authenticator); ok {
authRequired = ar.AuthEnabled()
}
// if the AcceptEvent function returned a closure we run it after the publish
// has been done because at least for now this means it is an updated follow
// list of an owner or their follows
if after != nil {
after()
}
notifyListeners(authRequired, ev)
accepted = true
return
}