From d69479974c26d95dd4b626d9deea8e47653fa73f Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Fri, 11 Nov 2022 09:48:04 -0300 Subject: [PATCH] expose AddEvent() method, allow implementations to deal with unknown websocket messages, remove opinionated validations from core lib, implement NIP-20 ("OK" message). --- add-event.go | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ handlers.go | 56 +++++++++++++-------------------------------------- interface.go | 28 +++++++++++++++++--------- listener.go | 2 +- 4 files changed, 90 insertions(+), 53 deletions(-) create mode 100644 add-event.go diff --git a/add-event.go b/add-event.go new file mode 100644 index 0000000..8037e76 --- /dev/null +++ b/add-event.go @@ -0,0 +1,57 @@ +package relayer + +import ( + "fmt" + + "github.com/nbd-wtf/go-nostr" +) + +func AddEvent(relay Relay, evt nostr.Event) (accepted bool, message string) { + store := relay.Storage() + advancedDeleter, _ := store.(AdvancedDeleter) + advancedSaver, _ := store.(AdvancedSaver) + + if evt.Kind == 5 { + // event deletion -- nip09 + for _, tag := range evt.Tags { + if len(tag) >= 2 && tag[0] == "e" { + if advancedDeleter != nil { + advancedDeleter.BeforeDelete(tag[1], evt.PubKey) + } + + if err := store.DeleteEvent(tag[1], evt.PubKey); err != nil { + return false, fmt.Sprintf("error: failed to delete: %s", err.Error()) + } + + if advancedDeleter != nil { + advancedDeleter.AfterDelete(tag[1], evt.PubKey) + } + } + } + return true, "" + } + + if !relay.AcceptEvent(&evt) { + return false, "blocked" + } + + if 20000 <= evt.Kind && evt.Kind < 30000 { + // do not store ephemeral events + } else { + if advancedSaver != nil { + advancedSaver.BeforeSave(&evt) + } + + if err := store.SaveEvent(&evt); err != nil { + return false, fmt.Sprintf("error: failed to save: %s", err.Error()) + } + + if advancedSaver != nil { + advancedSaver.AfterSave(&evt) + } + } + + notifyListeners(&evt) + + return true, "" +} diff --git a/handlers.go b/handlers.go index b785d1f..f053122 100644 --- a/handlers.go +++ b/handlers.go @@ -8,9 +8,9 @@ import ( "net/http" "time" - "github.com/fiatjaf/go-nostr" - "github.com/fiatjaf/go-nostr/nip11" "github.com/gorilla/websocket" + "github.com/nbd-wtf/go-nostr" + "github.com/nbd-wtf/go-nostr/nip11" ) const ( @@ -36,9 +36,8 @@ var upgrader = websocket.Upgrader{ func handleWebsocket(relay Relay) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { store := relay.Storage() - advancedQuerier, _ := store.(AdvancedQuerier) advancedDeleter, _ := store.(AdvancedDeleter) - advancedSaver, _ := store.(AdvancedSaver) + advancedQuerier, _ := store.(AdvancedQuerier) conn, err := upgrader.Upgrade(w, r, nil) if err != nil { @@ -116,24 +115,12 @@ func handleWebsocket(relay Relay) func(http.ResponseWriter, *http.Request) { hash := sha256.Sum256(serialized) evt.ID = hex.EncodeToString(hash[:]) - // block too many indexable tags - t := 0 - for _, tag := range evt.Tags { - if len(tag[0]) == 1 { - t++ - } - } - if t > 3 { - notice = "too many indexable tags" - return - } - // check signature (requires the ID to be set) if ok, err := evt.CheckSignature(); err != nil { - notice = "signature verification error" + ws.WriteJSON([]interface{}{"OK", evt.ID, false, "error: failed to verify signature"}) return } else if !ok { - notice = "signature invalid" + ws.WriteJSON([]interface{}{"OK", evt.ID, false, "invalid: signature is invalid"}) return } @@ -146,7 +133,7 @@ func handleWebsocket(relay Relay) func(http.ResponseWriter, *http.Request) { } if err := store.DeleteEvent(tag[1], evt.PubKey); err != nil { - notice = fmt.Sprintf("failed to delete: %s", err.Error()) + ws.WriteJSON([]interface{}{"OK", evt.ID, false, fmt.Sprintf("error: %s", err.Error())}) return } @@ -158,28 +145,9 @@ func handleWebsocket(relay Relay) func(http.ResponseWriter, *http.Request) { return } - if !relay.AcceptEvent(&evt) { - return - } + ok, message := AddEvent(relay, evt) + ws.WriteJSON([]interface{}{"OK", evt.ID, ok, message}) - if 20000 <= evt.Kind && evt.Kind < 30000 { - // do not store ephemeral events - } else { - if advancedSaver != nil { - advancedSaver.BeforeSave(&evt) - } - - if err := store.SaveEvent(&evt); err != nil { - notice = err.Error() - return - } - - if advancedSaver != nil { - advancedSaver.AfterSave(&evt) - } - } - - notifyListeners(&evt) break case "REQ": var id string @@ -227,7 +195,7 @@ func handleWebsocket(relay Relay) func(http.ResponseWriter, *http.Request) { break case "CLOSE": var id string - json.Unmarshal(request[0], &id) + json.Unmarshal(request[1], &id) if id == "" { notice = "CLOSE has no " return @@ -236,7 +204,11 @@ func handleWebsocket(relay Relay) func(http.ResponseWriter, *http.Request) { removeListener(ws, id) break default: - notice = "unknown message type " + typ + if cwh, ok := relay.(CustomWebSocketHandler); ok { + cwh.HandleUnknownType(ws, typ, request) + } else { + notice = "unknown message type " + typ + } return } }(message) diff --git a/interface.go b/interface.go index 7678166..e77d01b 100644 --- a/interface.go +++ b/interface.go @@ -1,12 +1,15 @@ package relayer import ( - "github.com/fiatjaf/go-nostr" - "github.com/fiatjaf/go-nostr/nip11" + "encoding/json" + + "github.com/nbd-wtf/go-nostr" + "github.com/nbd-wtf/go-nostr/nip11" ) var Log = log +// relay type Relay interface { Name() string Init() error @@ -23,6 +26,19 @@ type Informationer interface { GetNIP11InformationDocument() nip11.RelayInformationDocument } +type CustomWebSocketHandler interface { + HandleUnknownType(ws *WebSocket, typ string, request []json.RawMessage) +} + +// storage +type Storage interface { + Init() error + + QueryEvents(filter *nostr.Filter) (events []nostr.Event, err error) + DeleteEvent(id string, pubkey string) error + SaveEvent(event *nostr.Event) error +} + type AdvancedQuerier interface { BeforeQuery(*nostr.Filter) AfterQuery([]nostr.Event, *nostr.Filter) @@ -37,11 +53,3 @@ type AdvancedSaver interface { BeforeSave(*nostr.Event) AfterSave(*nostr.Event) } - -type Storage interface { - Init() error - - QueryEvents(filter *nostr.Filter) (events []nostr.Event, err error) - DeleteEvent(id string, pubkey string) error - SaveEvent(event *nostr.Event) error -} diff --git a/listener.go b/listener.go index 4247a22..3c20ca5 100644 --- a/listener.go +++ b/listener.go @@ -3,7 +3,7 @@ package relayer import ( "sync" - "github.com/fiatjaf/go-nostr" + "github.com/nbd-wtf/go-nostr" ) type Listener struct {