go-nostr/sdk/references.go
2023-03-27 08:47:59 -03:00

117 lines
2.9 KiB
Go

package sdk
import (
"regexp"
"strconv"
"strings"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
)
type Reference struct {
Text string
Profile *nostr.ProfilePointer
Event *nostr.EventPointer
Entity *nostr.EntityPointer
}
var mentionRegex = regexp.MustCompile(`\bnostr:((note|npub|naddr|nevent|nprofile)1\w+)\b|#\[(\d+)\]`)
// ParseReferences parses both NIP-08 and NIP-27 references in a single unifying interface.
func ParseReferences(evt *nostr.Event) []*Reference {
var references []*Reference
for _, ref := range mentionRegex.FindAllStringSubmatch(evt.Content, -1) {
if ref[2] != "" {
// it's a NIP-27 mention
if prefix, data, err := nip19.Decode(ref[1]); err == nil {
switch prefix {
case "npub":
references = append(references, &Reference{
Text: ref[0],
Profile: &nostr.ProfilePointer{
PublicKey: data.(string), Relays: []string{},
},
})
case "nprofile":
pp := data.(nostr.ProfilePointer)
references = append(references, &Reference{
Text: ref[0],
Profile: &pp,
})
case "note":
references = append(references, &Reference{
Text: ref[0],
Event: &nostr.EventPointer{ID: data.(string), Relays: []string{}},
})
case "nevent":
evp := data.(nostr.EventPointer)
references = append(references, &Reference{
Text: ref[0],
Event: &evp,
})
case "naddr":
addr := data.(nostr.EntityPointer)
references = append(references, &Reference{
Text: ref[0],
Entity: &addr,
})
}
}
} else if ref[3] != "" {
// it's a NIP-10 mention
idx, err := strconv.Atoi(ref[3])
if err != nil || len(evt.Tags) <= idx {
continue
}
if tag := evt.Tags[idx]; tag != nil {
switch tag[0] {
case "p":
relays := make([]string, 0, 1)
if len(tag) > 2 && tag[2] != "" {
relays = append(relays, tag[2])
}
references = append(references, &Reference{
Text: ref[0],
Profile: &nostr.ProfilePointer{
PublicKey: tag[1],
Relays: relays,
},
})
case "e":
relays := make([]string, 0, 1)
if len(tag) > 2 && tag[2] != "" {
relays = append(relays, tag[2])
}
references = append(references, &Reference{
Text: ref[0],
Event: &nostr.EventPointer{
ID: tag[1],
Relays: relays,
},
})
case "a":
if parts := strings.Split(ref[1], ":"); len(parts) == 3 {
kind, _ := strconv.Atoi(parts[0])
relays := make([]string, 0, 1)
if len(tag) > 2 && tag[2] != "" {
relays = append(relays, tag[2])
}
references = append(references, &Reference{
Text: ref[0],
Entity: &nostr.EntityPointer{
Identifier: parts[2],
PublicKey: parts[1],
Kind: kind,
Relays: relays,
},
})
}
}
}
}
}
return references
}