mirror of
https://github.com/fiatjaf/khatru.git
synced 2025-03-29 11:12:03 +01:00
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:
parent
d7aba0b21f
commit
d69479974c
57
add-event.go
Normal file
57
add-event.go
Normal 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, ""
|
||||
}
|
56
handlers.go
56
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 <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)
|
||||
|
28
interface.go
28
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
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package relayer
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/fiatjaf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
)
|
||||
|
||||
type Listener struct {
|
||||
|
Loading…
x
Reference in New Issue
Block a user