mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-03-17 13:22:56 +01:00
breaking pointer mess
- ExternalPointer (?) - nip27, nip22 and nip10 functions to return pointers - get rid of sdk/thread helpers that were just a thin layer over nip10 and nip22
This commit is contained in:
parent
f575f63f6c
commit
7e04bbb4b8
@ -36,11 +36,12 @@ func GetImmediateParent(tags nostr.Tags) *nostr.EventPointer {
|
||||
|
||||
if len(tag) >= 4 {
|
||||
if tag[3] == "reply" {
|
||||
return &tag
|
||||
parent = tag
|
||||
break
|
||||
}
|
||||
if tag[3] == "root" {
|
||||
if tag[3] == "parent" {
|
||||
// will be used as our first fallback
|
||||
root = &tag
|
||||
parent = tag
|
||||
continue
|
||||
}
|
||||
if tag[3] == "mention" {
|
||||
@ -49,15 +50,23 @@ func GetImmediateParent(tags nostr.Tags) *nostr.EventPointer {
|
||||
}
|
||||
}
|
||||
|
||||
lastE = &tag // will be used as our second fallback (clients that don't add markers)
|
||||
lastE = tag // will be used as our second fallback (clients that don't add markers)
|
||||
}
|
||||
|
||||
// if we reached this point we don't have a "reply", but if we have a "root"
|
||||
// that means this event is a direct reply to the root
|
||||
if root != nil {
|
||||
return root
|
||||
// if we reached this point we don't have a "reply", but if we have a "parent"
|
||||
// that means this event is a direct reply to the parent
|
||||
if parent != nil {
|
||||
p, _ := nostr.EventPointerFromTag(parent)
|
||||
return &p
|
||||
}
|
||||
|
||||
// if we reached this point and we have at least one "e" we'll use that (the last)
|
||||
return lastE
|
||||
if lastE != nil {
|
||||
// if we reached this point and we have at least one "e" we'll use that (the last)
|
||||
// (we don't bother looking for relay or author hints because these clients don't add these anyway)
|
||||
return &nostr.EventPointer{
|
||||
ID: lastE[1],
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -9,8 +9,13 @@ import (
|
||||
func EncodePointer(pointer nostr.Pointer) string {
|
||||
switch v := pointer.(type) {
|
||||
case nostr.ProfilePointer:
|
||||
res, _ := EncodeProfile(v.PublicKey, v.Relays)
|
||||
return res
|
||||
if v.Relays == nil {
|
||||
res, _ := EncodePublicKey(v.PublicKey)
|
||||
return res
|
||||
} else {
|
||||
res, _ := EncodeProfile(v.PublicKey, v.Relays)
|
||||
return res
|
||||
}
|
||||
case nostr.EventPointer:
|
||||
res, _ := EncodeEvent(v.ID, v.Relays, v.Author)
|
||||
return res
|
||||
|
@ -2,25 +2,41 @@ package nip22
|
||||
|
||||
import "github.com/nbd-wtf/go-nostr"
|
||||
|
||||
func GetThreadRoot(tags nostr.Tags) *nostr.Tag {
|
||||
func GetThreadRoot(tags nostr.Tags) nostr.Pointer {
|
||||
for _, tag := range tags {
|
||||
if len(tag) < 2 {
|
||||
continue
|
||||
}
|
||||
if tag[0] == "E" || tag[0] == "A" || tag[0] == "I" {
|
||||
return &tag
|
||||
switch tag[0] {
|
||||
case "E":
|
||||
ep, _ := nostr.EventPointerFromTag(tag)
|
||||
return ep
|
||||
case "A":
|
||||
ep, _ := nostr.EntityPointerFromTag(tag)
|
||||
return ep
|
||||
case "I":
|
||||
ep, _ := nostr.ExternalPointerFromTag(tag)
|
||||
return ep
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetImmediateReply(tags nostr.Tags) *nostr.Tag {
|
||||
func GetImmediateParent(tags nostr.Tags) nostr.Pointer {
|
||||
for _, tag := range tags {
|
||||
if len(tag) < 2 {
|
||||
continue
|
||||
}
|
||||
if tag[0] == "e" || tag[0] == "a" || tag[0] == "i" {
|
||||
return &tag
|
||||
switch tag[0] {
|
||||
case "e":
|
||||
ep, _ := nostr.EventPointerFromTag(tag)
|
||||
return ep
|
||||
case "a":
|
||||
ep, _ := nostr.EntityPointerFromTag(tag)
|
||||
return ep
|
||||
case "i":
|
||||
ep, _ := nostr.ExternalPointerFromTag(tag)
|
||||
return ep
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -12,9 +12,7 @@ type Reference struct {
|
||||
Text string
|
||||
Start int
|
||||
End int
|
||||
Profile *nostr.ProfilePointer
|
||||
Event *nostr.EventPointer
|
||||
Entity *nostr.EntityPointer
|
||||
Pointer nostr.Pointer
|
||||
}
|
||||
|
||||
var mentionRegex = regexp.MustCompile(`\bnostr:((note|npub|naddr|nevent|nprofile)1\w+)\b`)
|
||||
@ -33,40 +31,45 @@ func ParseReferences(evt nostr.Event) iter.Seq[Reference] {
|
||||
if prefix, data, err := nip19.Decode(nip19code); err == nil {
|
||||
switch prefix {
|
||||
case "npub":
|
||||
reference.Profile = &nostr.ProfilePointer{
|
||||
pointer := &nostr.ProfilePointer{
|
||||
PublicKey: data.(string), Relays: []string{},
|
||||
}
|
||||
tag := evt.Tags.GetFirst([]string{"p", reference.Profile.PublicKey})
|
||||
if tag != nil && len(*tag) >= 3 {
|
||||
reference.Profile.Relays = []string{(*tag)[2]}
|
||||
tag := evt.Tags.FindWithValue("p", pointer.PublicKey)
|
||||
if tag != nil && len(tag) >= 3 {
|
||||
pointer.Relays = []string{tag[2]}
|
||||
}
|
||||
if nostr.IsValidPublicKey(pointer.PublicKey) {
|
||||
reference.Pointer = pointer
|
||||
}
|
||||
case "nprofile":
|
||||
pp := data.(nostr.ProfilePointer)
|
||||
reference.Profile = &pp
|
||||
tag := evt.Tags.GetFirst([]string{"p", reference.Profile.PublicKey})
|
||||
if tag != nil && len(*tag) >= 3 {
|
||||
reference.Profile.Relays = append(reference.Profile.Relays, (*tag)[2])
|
||||
pointer := data.(nostr.ProfilePointer)
|
||||
tag := evt.Tags.FindWithValue("p", pointer.PublicKey)
|
||||
if tag != nil && len(tag) >= 3 {
|
||||
pointer.Relays = append(pointer.Relays, tag[2])
|
||||
}
|
||||
if nostr.IsValidPublicKey(pointer.PublicKey) {
|
||||
reference.Pointer = pointer
|
||||
}
|
||||
case "note":
|
||||
// we don't even bother here because people using note1 codes aren't including relay hints anyway
|
||||
reference.Event = &nostr.EventPointer{ID: data.(string), Relays: []string{}}
|
||||
reference.Pointer = &nostr.EventPointer{ID: data.(string), Relays: nil}
|
||||
case "nevent":
|
||||
evp := data.(nostr.EventPointer)
|
||||
reference.Event = &evp
|
||||
tag := evt.Tags.GetFirst([]string{"e", reference.Event.ID})
|
||||
if tag != nil && len(*tag) >= 3 {
|
||||
reference.Event.Relays = append(reference.Event.Relays, (*tag)[2])
|
||||
if reference.Event.Author == "" && len(*tag) >= 5 {
|
||||
reference.Event.Author = (*tag)[4]
|
||||
pointer := data.(nostr.EventPointer)
|
||||
tag := evt.Tags.FindWithValue("e", pointer.ID)
|
||||
if tag != nil && len(tag) >= 3 {
|
||||
pointer.Relays = append(pointer.Relays, tag[2])
|
||||
if pointer.Author == "" && len(tag) >= 5 && nostr.IsValidPublicKey(tag[4]) {
|
||||
pointer.Author = tag[4]
|
||||
}
|
||||
}
|
||||
reference.Pointer = pointer
|
||||
case "naddr":
|
||||
addr := data.(nostr.EntityPointer)
|
||||
reference.Entity = &addr
|
||||
tag := evt.Tags.GetFirst([]string{"a", reference.Entity.AsTagReference()})
|
||||
if tag != nil && len(*tag) >= 3 {
|
||||
reference.Entity.Relays = append(reference.Entity.Relays, (*tag)[2])
|
||||
pointer := data.(nostr.EntityPointer)
|
||||
tag := evt.Tags.FindWithValue("a", pointer.AsTagReference())
|
||||
if tag != nil && len(tag) >= 3 {
|
||||
pointer.Relays = append(pointer.Relays, tag[2])
|
||||
}
|
||||
reference.Pointer = pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ func TestParseReferences(t *testing.T) {
|
||||
Text: "nostr:nprofile1qqsvc6ulagpn7kwrcwdqgp797xl7usumqa6s3kgcelwq6m75x8fe8yc5usxdg",
|
||||
Start: 7,
|
||||
End: 83,
|
||||
Profile: &nostr.ProfilePointer{
|
||||
Pointer: nostr.ProfilePointer{
|
||||
PublicKey: "cc6b9fea033f59c3c39a0407c5f1bfee439b077508d918cfdc0d6fd431d39393",
|
||||
Relays: []string{"wss://xawr.com"},
|
||||
},
|
||||
@ -32,7 +32,7 @@ func TestParseReferences(t *testing.T) {
|
||||
Text: "nostr:nevent1qqsvc6ulagpn7kwrcwdqgp797xl7usumqa6s3kgcelwq6m75x8fe8ychxp5v4",
|
||||
Start: 90,
|
||||
End: 164,
|
||||
Event: &nostr.EventPointer{
|
||||
Pointer: nostr.EventPointer{
|
||||
ID: "cc6b9fea033f59c3c39a0407c5f1bfee439b077508d918cfdc0d6fd431d39393",
|
||||
Relays: []string{"wss://nasdj.com"},
|
||||
Author: "",
|
||||
|
27
pointers.go
27
pointers.go
@ -26,6 +26,7 @@ var (
|
||||
_ Pointer = (*ProfilePointer)(nil)
|
||||
_ Pointer = (*EventPointer)(nil)
|
||||
_ Pointer = (*EntityPointer)(nil)
|
||||
_ Pointer = (*ExternalPointer)(nil)
|
||||
)
|
||||
|
||||
// ProfilePointer represents a pointer to a Nostr profile.
|
||||
@ -36,7 +37,7 @@ type ProfilePointer struct {
|
||||
|
||||
// ProfilePointerFromTag creates a ProfilePointer from a "p" tag (but it doesn't have to be necessarily a "p" tag, could be something else).
|
||||
func ProfilePointerFromTag(refTag Tag) (ProfilePointer, error) {
|
||||
pk := (refTag)[1]
|
||||
pk := refTag[1]
|
||||
if !IsValidPublicKey(pk) {
|
||||
return ProfilePointer{}, fmt.Errorf("invalid pubkey '%s'", pk)
|
||||
}
|
||||
@ -74,7 +75,7 @@ type EventPointer struct {
|
||||
|
||||
// EventPointerFromTag creates an EventPointer from an "e" tag (but it could be other tag name, it isn't checked).
|
||||
func EventPointerFromTag(refTag Tag) (EventPointer, error) {
|
||||
id := (refTag)[1]
|
||||
id := refTag[1]
|
||||
if !IsValid32ByteHex(id) {
|
||||
return EventPointer{}, fmt.Errorf("invalid id '%s'", id)
|
||||
}
|
||||
@ -86,8 +87,10 @@ func EventPointerFromTag(refTag Tag) (EventPointer, error) {
|
||||
if relay := (refTag)[2]; IsValidRelayURL(relay) {
|
||||
pointer.Relays = []string{relay}
|
||||
}
|
||||
if len(refTag) > 3 && IsValidPublicKey((refTag)[3]) {
|
||||
if len(refTag) > 3 && IsValidPublicKey(refTag[3]) {
|
||||
pointer.Author = (refTag)[3]
|
||||
} else if len(refTag) > 4 && IsValidPublicKey(refTag[4]) {
|
||||
pointer.Author = (refTag)[4]
|
||||
}
|
||||
}
|
||||
return pointer, nil
|
||||
@ -171,3 +174,21 @@ func (ep EntityPointer) AsTag() Tag {
|
||||
}
|
||||
return Tag{"a", ep.AsTagReference()}
|
||||
}
|
||||
|
||||
// ExternalPointer represents a pointer to a Nostr profile.
|
||||
type ExternalPointer struct {
|
||||
Thing string
|
||||
}
|
||||
|
||||
// ExternalPointerFromTag creates a ExternalPointer from an "i" tag
|
||||
func ExternalPointerFromTag(refTag Tag) (ExternalPointer, error) {
|
||||
return ExternalPointer{refTag[1]}, nil
|
||||
}
|
||||
|
||||
func (ep ExternalPointer) MatchesEvent(_ Event) bool { return false }
|
||||
func (ep ExternalPointer) AsTagReference() string { return ep.Thing }
|
||||
func (ep ExternalPointer) AsFilter() Filter { return Filter{} }
|
||||
|
||||
func (ep ExternalPointer) AsTag() Tag {
|
||||
return Tag{"i", ep.Thing}
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip10"
|
||||
"github.com/nbd-wtf/go-nostr/nip22"
|
||||
)
|
||||
|
||||
func GetThreadRoot(evt *nostr.Event) *nostr.Tag {
|
||||
if evt.Kind == nostr.KindComment {
|
||||
return nip22.GetThreadRoot(evt.Tags)
|
||||
} else {
|
||||
return nip10.GetThreadRoot(evt.Tags)
|
||||
}
|
||||
}
|
||||
|
||||
func GetImmediateReply(evt *nostr.Event) *nostr.Tag {
|
||||
if evt.Kind == nostr.KindComment {
|
||||
return nip22.GetImmediateReply(evt.Tags)
|
||||
} else {
|
||||
return nip10.GetImmediateReply(evt.Tags)
|
||||
}
|
||||
}
|
@ -106,27 +106,36 @@ func (sys *System) trackEventHints(ie nostr.RelayEvent) {
|
||||
}
|
||||
|
||||
for ref := range nip27.ParseReferences(*ie.Event) {
|
||||
if ref.Profile != nil {
|
||||
for _, relay := range ref.Profile.Relays {
|
||||
switch pointer := ref.Pointer.(type) {
|
||||
case nostr.ProfilePointer:
|
||||
for _, relay := range pointer.Relays {
|
||||
if IsVirtualRelay(relay) {
|
||||
continue
|
||||
}
|
||||
if p, err := url.Parse(relay); err != nil || (p.Scheme != "wss" && p.Scheme != "ws") {
|
||||
continue
|
||||
}
|
||||
if nostr.IsValidPublicKey(ref.Profile.PublicKey) {
|
||||
sys.Hints.Save(ref.Profile.PublicKey, nostr.NormalizeURL(relay), hints.LastInHint, ie.CreatedAt)
|
||||
}
|
||||
sys.Hints.Save(pointer.PublicKey, nostr.NormalizeURL(relay), hints.LastInHint, ie.CreatedAt)
|
||||
}
|
||||
} else if ref.Event != nil && nostr.IsValidPublicKey(ref.Event.Author) {
|
||||
for _, relay := range ref.Event.Relays {
|
||||
case nostr.EventPointer:
|
||||
for _, relay := range pointer.Relays {
|
||||
if IsVirtualRelay(relay) {
|
||||
continue
|
||||
}
|
||||
if p, err := url.Parse(relay); err != nil || (p.Scheme != "wss" && p.Scheme != "ws") {
|
||||
continue
|
||||
}
|
||||
sys.Hints.Save(ref.Event.Author, nostr.NormalizeURL(relay), hints.LastInHint, ie.CreatedAt)
|
||||
sys.Hints.Save(pointer.Author, nostr.NormalizeURL(relay), hints.LastInHint, ie.CreatedAt)
|
||||
}
|
||||
case nostr.EntityPointer:
|
||||
for _, relay := range pointer.Relays {
|
||||
if IsVirtualRelay(relay) {
|
||||
continue
|
||||
}
|
||||
if p, err := url.Parse(relay); err != nil || (p.Scheme != "wss" && p.Scheme != "ws") {
|
||||
continue
|
||||
}
|
||||
sys.Hints.Save(pointer.PublicKey, nostr.NormalizeURL(relay), hints.LastInHint, ie.CreatedAt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user