expose AddEvent() method, allow implementations to deal with unknown websocket messages, remove opinionated validations from core lib, implement NIP-20 ("OK" message).

This commit is contained in:
fiatjaf 2022-11-11 09:48:04 -03:00
parent d7aba0b21f
commit d69479974c
No known key found for this signature in database
GPG Key ID: BAD43C4BE5C1A3A1
4 changed files with 90 additions and 53 deletions

57
add-event.go Normal file
View File

@ -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, ""
}

View File

@ -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 <id>"
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)

View File

@ -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
}

View File

@ -3,7 +3,7 @@ package relayer
import (
"sync"
"github.com/fiatjaf/go-nostr"
"github.com/nbd-wtf/go-nostr"
)
type Listener struct {