mirror of
https://github.com/fiatjaf/khatru.git
synced 2026-04-07 14:06:51 +02:00
Compare commits
7 Commits
v0.0.10
...
author-nam
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86d2fec964 | ||
|
|
dcdf86c4e4 | ||
|
|
0a62169e14 | ||
|
|
8fd6436ac8 | ||
|
|
d2544d0f4d | ||
|
|
7a3eb6fb08 | ||
|
|
1abeab4851 |
10
README.md
10
README.md
@@ -1,5 +1,7 @@
|
||||
# khatru, a relay framework [](https://pkg.go.dev/github.com/fiatjaf/khatru#Relay)
|
||||
|
||||
`author: pablof7z`
|
||||
|
||||
[](https://github.com/fiatjaf/khatru/actions/workflows/test.yml)
|
||||
[](https://pkg.go.dev/github.com/fiatjaf/khatru)
|
||||
[](https://goreportcard.com/report/github.com/fiatjaf/khatru)
|
||||
@@ -31,10 +33,10 @@ func main() {
|
||||
relay := khatru.NewRelay()
|
||||
|
||||
// set up some basic properties (will be returned on the NIP-11 endpoint)
|
||||
relay.Name = "my relay"
|
||||
relay.PubKey = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
|
||||
relay.Description = "this is my custom relay"
|
||||
relay.IconURL = "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fliquipedia.net%2Fcommons%2Fimages%2F3%2F35%2FSCProbe.jpg&f=1&nofb=1&ipt=0cbbfef25bce41da63d910e86c3c343e6c3b9d63194ca9755351bb7c2efa3359&ipo=images"
|
||||
relay.Info.Name = "my relay"
|
||||
relay.Info.PubKey = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
|
||||
relay.Info.Description = "this is my custom relay"
|
||||
relay.Info.IconURL = "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fliquipedia.net%2Fcommons%2Fimages%2F3%2F35%2FSCProbe.jpg&f=1&nofb=1&ipt=0cbbfef25bce41da63d910e86c3c343e6c3b9d63194ca9755351bb7c2efa3359&ipo=images"
|
||||
|
||||
// you must bring your own storage scheme -- if you want to have any
|
||||
store := make(map[string]*nostr.Event, 120)
|
||||
|
||||
@@ -15,10 +15,10 @@ func main() {
|
||||
relay := khatru.NewRelay()
|
||||
|
||||
// set up some basic properties (will be returned on the NIP-11 endpoint)
|
||||
relay.Name = "my relay"
|
||||
relay.PubKey = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
|
||||
relay.Description = "this is my custom relay"
|
||||
relay.IconURL = "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fliquipedia.net%2Fcommons%2Fimages%2F3%2F35%2FSCProbe.jpg&f=1&nofb=1&ipt=0cbbfef25bce41da63d910e86c3c343e6c3b9d63194ca9755351bb7c2efa3359&ipo=images"
|
||||
relay.Info.Name = "my relay"
|
||||
relay.Info.PubKey = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
|
||||
relay.Info.Description = "this is my custom relay"
|
||||
relay.Info.Icon = "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fliquipedia.net%2Fcommons%2Fimages%2F3%2F35%2FSCProbe.jpg&f=1&nofb=1&ipt=0cbbfef25bce41da63d910e86c3c343e6c3b9d63194ca9755351bb7c2efa3359&ipo=images"
|
||||
|
||||
// you must bring your own storage scheme -- if you want to have any
|
||||
store := make(map[string]*nostr.Event, 120)
|
||||
|
||||
4
go.mod
4
go.mod
@@ -5,8 +5,7 @@ go 1.21.0
|
||||
require (
|
||||
github.com/fasthttp/websocket v1.5.3
|
||||
github.com/fiatjaf/eventstore v0.1.0
|
||||
github.com/gobwas/ws v1.2.0
|
||||
github.com/nbd-wtf/go-nostr v0.25.1
|
||||
github.com/nbd-wtf/go-nostr v0.25.7
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1
|
||||
github.com/rs/cors v1.7.0
|
||||
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53
|
||||
@@ -30,6 +29,7 @@ require (
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.2.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@@ -90,8 +90,8 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/nbd-wtf/go-nostr v0.25.1 h1:YTLTDUgngfzd3qQ0fWmQmq20flwnGtHH0g0Q8S3HlW4=
|
||||
github.com/nbd-wtf/go-nostr v0.25.1/go.mod h1:bkffJI+x914sPQWum9ZRUn66D7NpDnAoWo1yICvj3/0=
|
||||
github.com/nbd-wtf/go-nostr v0.25.7 h1:DcGOSgKVr/L6w62tRtKeV2t46sRyFcq9pWcyIFkh0eM=
|
||||
github.com/nbd-wtf/go-nostr v0.25.7/go.mod h1:bkffJI+x914sPQWum9ZRUn66D7NpDnAoWo1yICvj3/0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
|
||||
27
handlers.go
27
handlers.go
@@ -13,7 +13,6 @@ import (
|
||||
|
||||
"github.com/fasthttp/websocket"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip11"
|
||||
"github.com/nbd-wtf/go-nostr/nip42"
|
||||
)
|
||||
|
||||
@@ -252,29 +251,5 @@ func (rl *Relay) HandleWebsocket(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (rl *Relay) HandleNIP11(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/nostr+json")
|
||||
|
||||
supportedNIPs := []int{9, 11, 12, 15, 16, 20, 33}
|
||||
if rl.ServiceURL != "" {
|
||||
supportedNIPs = append(supportedNIPs, 42)
|
||||
}
|
||||
if rl.CountEvents != nil {
|
||||
supportedNIPs = append(supportedNIPs, 45)
|
||||
}
|
||||
|
||||
info := nip11.RelayInformationDocument{
|
||||
Name: rl.Name,
|
||||
Description: rl.Description,
|
||||
PubKey: rl.PubKey,
|
||||
Contact: rl.Contact,
|
||||
Icon: rl.IconURL,
|
||||
SupportedNIPs: supportedNIPs,
|
||||
Software: "https://github.com/trailriver/khatru",
|
||||
Version: "n/a",
|
||||
}
|
||||
|
||||
for _, edit := range rl.EditInformation {
|
||||
edit(r.Context(), &info)
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(info)
|
||||
json.NewEncoder(w).Encode(rl.Info)
|
||||
}
|
||||
|
||||
@@ -4,12 +4,34 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// PreventTooManyIndexableTags returns a function that can be used as a RejectFilter that will reject
|
||||
// events with more indexable (single-character) tags than the specified number.
|
||||
func PreventTooManyIndexableTags(max int) func(context.Context, *nostr.Event) (bool, string) {
|
||||
//
|
||||
// If ignoreKinds is given this restriction will not apply to these kinds (useful for allowing a bigger).
|
||||
// If onlyKinds is given then all other kinds will be ignored.
|
||||
func PreventTooManyIndexableTags(max int, ignoreKinds []int, onlyKinds []int) func(context.Context, *nostr.Event) (bool, string) {
|
||||
ignore := func(kind int) bool { return false }
|
||||
if len(ignoreKinds) > 0 {
|
||||
ignore = func(kind int) bool {
|
||||
_, isIgnored := slices.BinarySearch(ignoreKinds, kind)
|
||||
return isIgnored
|
||||
}
|
||||
}
|
||||
if len(onlyKinds) > 0 {
|
||||
ignore = func(kind int) bool {
|
||||
_, isApplicable := slices.BinarySearch(onlyKinds, kind)
|
||||
return !isApplicable
|
||||
}
|
||||
}
|
||||
|
||||
return func(ctx context.Context, event *nostr.Event) (reject bool, msg string) {
|
||||
if ignore(event.Kind) {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
ntags := 0
|
||||
for _, tag := range event.Tags {
|
||||
if len(tag) > 0 && len(tag[0]) == 1 {
|
||||
@@ -23,6 +45,20 @@ func PreventTooManyIndexableTags(max int) func(context.Context, *nostr.Event) (b
|
||||
}
|
||||
}
|
||||
|
||||
// PreventLargeTags rejects events that have indexable tag values greater than maxTagValueLen.
|
||||
func PreventLargeTags(maxTagValueLen int) func(context.Context, *nostr.Event) (bool, string) {
|
||||
return func(ctx context.Context, event *nostr.Event) (reject bool, msg string) {
|
||||
for _, tag := range event.Tags {
|
||||
if len(tag) > 1 && len(tag[0]) == 1 {
|
||||
if len(tag[1]) > maxTagValueLen {
|
||||
return true, "event contains too large tags"
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, ""
|
||||
}
|
||||
}
|
||||
|
||||
// RestrictToSpecifiedKinds returns a function that can be used as a RejectFilter that will reject
|
||||
// any events with kinds different than the specified ones.
|
||||
func RestrictToSpecifiedKinds(kinds ...uint16) func(context.Context, *nostr.Event) (bool, string) {
|
||||
|
||||
16
relay.go
16
relay.go
@@ -17,6 +17,11 @@ func NewRelay() *Relay {
|
||||
return &Relay{
|
||||
Log: log.New(os.Stderr, "[khatru-relay] ", log.LstdFlags),
|
||||
|
||||
Info: &nip11.RelayInformationDocument{
|
||||
Software: "https://github.com/fiatjaf/khatru",
|
||||
Version: "n/a",
|
||||
},
|
||||
|
||||
upgrader: websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
@@ -34,12 +39,7 @@ func NewRelay() *Relay {
|
||||
}
|
||||
|
||||
type Relay struct {
|
||||
Name string
|
||||
Description string
|
||||
PubKey string
|
||||
Contact string
|
||||
ServiceURL string // required for nip-42
|
||||
IconURL string
|
||||
ServiceURL string // required for nip-42
|
||||
|
||||
RejectEvent []func(ctx context.Context, event *nostr.Event) (reject bool, msg string)
|
||||
RejectFilter []func(ctx context.Context, filter nostr.Filter) (reject bool, msg string)
|
||||
@@ -52,11 +52,13 @@ type Relay struct {
|
||||
DeleteEvent []func(ctx context.Context, event *nostr.Event) error
|
||||
QueryEvents []func(ctx context.Context, filter nostr.Filter) (chan *nostr.Event, error)
|
||||
CountEvents []func(ctx context.Context, filter nostr.Filter) (int64, error)
|
||||
EditInformation []func(ctx context.Context, info *nip11.RelayInformationDocument)
|
||||
OnAuth []func(ctx context.Context, pubkey string)
|
||||
OnConnect []func(ctx context.Context)
|
||||
OnEventSaved []func(ctx context.Context, event *nostr.Event)
|
||||
|
||||
// editing info will affect
|
||||
Info *nip11.RelayInformationDocument
|
||||
|
||||
// Default logger, as set by NewServer, is a stdlib logger prefixed with "[khatru-relay] ",
|
||||
// outputting to stderr.
|
||||
Log *log.Logger
|
||||
|
||||
@@ -16,7 +16,7 @@ func (rl *Relay) handleRequest(ctx context.Context, id string, eose *sync.WaitGr
|
||||
ovw(ctx, &filter)
|
||||
}
|
||||
|
||||
if filter.Limit == 0 {
|
||||
if filter.Limit < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user