-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- a way to handle custom messages from Relay (NEG-whatever etc) - negentropy implementation (adapted from that other one) - nip77 nostr negentropy extension - QueryEvents method for RelayStore that returns a channel (makes negentropy syncing work more seamlessly)
- Loading branch information
Showing
14 changed files
with
1,329 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
package nip77 | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
|
||
"github.com/mailru/easyjson" | ||
jwriter "github.com/mailru/easyjson/jwriter" | ||
"github.com/nbd-wtf/go-nostr" | ||
"github.com/tidwall/gjson" | ||
) | ||
|
||
func ParseNegMessage(message []byte) nostr.Envelope { | ||
firstComma := bytes.Index(message, []byte{','}) | ||
if firstComma == -1 { | ||
return nil | ||
} | ||
label := message[0:firstComma] | ||
|
||
var v nostr.Envelope | ||
switch { | ||
case bytes.Contains(label, []byte("NEG-MSG")): | ||
v = &MessageEnvelope{} | ||
case bytes.Contains(label, []byte("NEG-OPEN")): | ||
v = &OpenEnvelope{} | ||
case bytes.Contains(label, []byte("NEG-ERR")): | ||
v = &ErrorEnvelope{} | ||
case bytes.Contains(label, []byte("NEG-CLOSE")): | ||
v = &CloseEnvelope{} | ||
default: | ||
return nil | ||
} | ||
|
||
if err := v.UnmarshalJSON(message); err != nil { | ||
return nil | ||
} | ||
return v | ||
} | ||
|
||
var ( | ||
_ nostr.Envelope = (*OpenEnvelope)(nil) | ||
_ nostr.Envelope = (*MessageEnvelope)(nil) | ||
_ nostr.Envelope = (*CloseEnvelope)(nil) | ||
_ nostr.Envelope = (*ErrorEnvelope)(nil) | ||
) | ||
|
||
type OpenEnvelope struct { | ||
SubscriptionID string | ||
Filter nostr.Filter | ||
Message string | ||
} | ||
|
||
func (_ OpenEnvelope) Label() string { return "NEG-OPEN" } | ||
func (v OpenEnvelope) String() string { | ||
b, _ := v.MarshalJSON() | ||
return string(b) | ||
} | ||
|
||
func (v *OpenEnvelope) UnmarshalJSON(data []byte) error { | ||
r := gjson.ParseBytes(data) | ||
arr := r.Array() | ||
if len(arr) != 4 { | ||
return fmt.Errorf("failed to decode NEG-OPEN envelope") | ||
} | ||
|
||
v.SubscriptionID = arr[1].Str | ||
v.Message = arr[3].Str | ||
return easyjson.Unmarshal([]byte(arr[2].Raw), &v.Filter) | ||
} | ||
|
||
func (v OpenEnvelope) MarshalJSON() ([]byte, error) { | ||
res := bytes.NewBuffer(make([]byte, 0, 17+len(v.SubscriptionID)+len(v.Message)+500)) | ||
|
||
res.WriteString(`["NEG-OPEN","`) | ||
res.WriteString(v.SubscriptionID) | ||
res.WriteString(`",`) | ||
|
||
w := jwriter.Writer{} | ||
v.Filter.MarshalEasyJSON(&w) | ||
w.Buffer.DumpTo(res) | ||
|
||
res.WriteString(`,"`) | ||
res.WriteString(v.Message) | ||
res.WriteString(`"]`) | ||
|
||
return res.Bytes(), nil | ||
} | ||
|
||
type MessageEnvelope struct { | ||
SubscriptionID string | ||
Message string | ||
} | ||
|
||
func (_ MessageEnvelope) Label() string { return "NEG-MSG" } | ||
func (v MessageEnvelope) String() string { | ||
b, _ := v.MarshalJSON() | ||
return string(b) | ||
} | ||
|
||
func (v *MessageEnvelope) UnmarshalJSON(data []byte) error { | ||
r := gjson.ParseBytes(data) | ||
arr := r.Array() | ||
if len(arr) < 3 { | ||
return fmt.Errorf("failed to decode NEG-MSG envelope") | ||
} | ||
v.SubscriptionID = arr[1].Str | ||
v.Message = arr[2].Str | ||
return nil | ||
} | ||
|
||
func (v MessageEnvelope) MarshalJSON() ([]byte, error) { | ||
res := bytes.NewBuffer(make([]byte, 0, 17+len(v.SubscriptionID)+len(v.Message))) | ||
|
||
res.WriteString(`["NEG-MSG","`) | ||
res.WriteString(v.SubscriptionID) | ||
res.WriteString(`","`) | ||
res.WriteString(v.Message) | ||
res.WriteString(`"]`) | ||
|
||
return res.Bytes(), nil | ||
} | ||
|
||
type CloseEnvelope struct { | ||
SubscriptionID string | ||
} | ||
|
||
func (_ CloseEnvelope) Label() string { return "NEG-CLOSE" } | ||
func (v CloseEnvelope) String() string { | ||
b, _ := v.MarshalJSON() | ||
return string(b) | ||
} | ||
|
||
func (v *CloseEnvelope) UnmarshalJSON(data []byte) error { | ||
r := gjson.ParseBytes(data) | ||
arr := r.Array() | ||
if len(arr) < 2 { | ||
return fmt.Errorf("failed to decode NEG-CLOSE envelope") | ||
} | ||
v.SubscriptionID = arr[1].Str | ||
return nil | ||
} | ||
|
||
func (v CloseEnvelope) MarshalJSON() ([]byte, error) { | ||
res := bytes.NewBuffer(make([]byte, 0, 14+len(v.SubscriptionID))) | ||
res.WriteString(`["NEG-CLOSE","`) | ||
res.WriteString(v.SubscriptionID) | ||
res.WriteString(`"]`) | ||
return res.Bytes(), nil | ||
} | ||
|
||
type ErrorEnvelope struct { | ||
SubscriptionID string | ||
Reason string | ||
} | ||
|
||
func (_ ErrorEnvelope) Label() string { return "NEG-ERROR" } | ||
func (v ErrorEnvelope) String() string { | ||
b, _ := v.MarshalJSON() | ||
return string(b) | ||
} | ||
|
||
func (v *ErrorEnvelope) UnmarshalJSON(data []byte) error { | ||
r := gjson.ParseBytes(data) | ||
arr := r.Array() | ||
if len(arr) < 3 { | ||
return fmt.Errorf("failed to decode NEG-ERROR envelope") | ||
} | ||
v.SubscriptionID = arr[1].Str | ||
v.Reason = arr[2].Str | ||
return nil | ||
} | ||
|
||
func (v ErrorEnvelope) MarshalJSON() ([]byte, error) { | ||
res := bytes.NewBuffer(make([]byte, 0, 19+len(v.SubscriptionID)+len(v.Reason))) | ||
res.WriteString(`["NEG-ERROR","`) | ||
res.WriteString(v.SubscriptionID) | ||
res.WriteString(`","`) | ||
res.WriteString(v.Reason) | ||
res.WriteString(`"]`) | ||
return res.Bytes(), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/fiatjaf/eventstore" | ||
Check failure on line 8 in nip77/example/example.go GitHub Actions / test
|
||
"github.com/fiatjaf/eventstore/slicestore" | ||
Check failure on line 9 in nip77/example/example.go GitHub Actions / test
|
||
"github.com/nbd-wtf/go-nostr" | ||
"github.com/nbd-wtf/go-nostr/nip77" | ||
) | ||
|
||
func main() { | ||
ctx := context.Background() | ||
db := &slicestore.SliceStore{} | ||
db.Init() | ||
|
||
sk := nostr.GeneratePrivateKey() | ||
local := eventstore.RelayWrapper{Store: db} | ||
|
||
for { | ||
for i := 0; i < 20; i++ { | ||
{ | ||
evt := nostr.Event{ | ||
Kind: 1, | ||
Content: fmt.Sprintf("same old hello %d", i), | ||
CreatedAt: nostr.Timestamp(i), | ||
Tags: nostr.Tags{}, | ||
} | ||
evt.Sign(sk) | ||
db.SaveEvent(ctx, &evt) | ||
} | ||
|
||
{ | ||
evt := nostr.Event{ | ||
Kind: 1, | ||
Content: fmt.Sprintf("custom hello %d", i), | ||
CreatedAt: nostr.Now(), | ||
Tags: nostr.Tags{}, | ||
} | ||
evt.Sign(sk) | ||
db.SaveEvent(ctx, &evt) | ||
} | ||
} | ||
|
||
err := nip77.NegentropySync(ctx, | ||
local, "ws://localhost:7777", nostr.Filter{}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
data, err := local.QuerySync(ctx, nostr.Filter{}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
fmt.Println("total local events:", len(data)) | ||
time.Sleep(time.Second * 10) | ||
} | ||
} |
Oops, something went wrong.