sdk: return start and end on references for replacement.

This commit is contained in:
fiatjaf
2023-05-26 18:04:36 -03:00
parent 5c0f8bff83
commit b269dd9ce9
2 changed files with 66 additions and 58 deletions

View File

@@ -11,6 +11,8 @@ import (
type Reference struct {
Text string
Start int
End int
Profile *nostr.ProfilePointer
Event *nostr.EventPointer
Entity *nostr.EntityPointer
@@ -21,95 +23,85 @@ var mentionRegex = regexp.MustCompile(`\bnostr:((note|npub|naddr|nevent|nprofile
// 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 {
content := evt.Content
for _, ref := range mentionRegex.FindAllStringSubmatchIndex(evt.Content, -1) {
reference := &Reference{
Text: content[ref[0]:ref[1]],
Start: ref[0],
End: ref[1],
}
if ref[6] == -1 {
// didn't find a NIP-10 #[0] reference, so it's it's a NIP-27 mention
nip19code := content[ref[2]:ref[3]]
if prefix, data, err := nip19.Decode(nip19code); err == nil {
switch prefix {
case "npub":
references = append(references, &Reference{
Text: ref[0],
Profile: &nostr.ProfilePointer{
PublicKey: data.(string), Relays: []string{},
},
})
reference.Profile = &nostr.ProfilePointer{
PublicKey: data.(string), Relays: []string{},
}
case "nprofile":
pp := data.(nostr.ProfilePointer)
references = append(references, &Reference{
Text: ref[0],
Profile: &pp,
})
reference.Profile = &pp
case "note":
references = append(references, &Reference{
Text: ref[0],
Event: &nostr.EventPointer{ID: data.(string), Relays: []string{}},
})
reference.Event = &nostr.EventPointer{ID: data.(string), Relays: []string{}}
case "nevent":
evp := data.(nostr.EventPointer)
references = append(references, &Reference{
Text: ref[0],
Event: &evp,
})
reference.Event = &evp
case "naddr":
addr := data.(nostr.EntityPointer)
references = append(references, &Reference{
Text: ref[0],
Entity: &addr,
})
reference.Entity = &addr
}
}
} else if ref[3] != "" {
// it's a NIP-10 mention
idx, err := strconv.Atoi(ref[3])
} else {
// it's a NIP-10 mention.
// parse the number, get data from event tags.
n := content[ref[6]:ref[7]]
idx, err := strconv.Atoi(n)
if err != nil || len(evt.Tags) <= idx {
continue
}
if tag := evt.Tags[idx]; tag != nil {
if tag := evt.Tags[idx]; tag != nil && len(tag) >= 2 {
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,
},
})
reference.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,
},
})
reference.Event = &nostr.EventPointer{
ID: tag[1],
Relays: relays,
}
case "a":
if parts := strings.Split(ref[1], ":"); len(parts) == 3 {
if parts := strings.Split(tag[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,
},
})
reference.Entity = &nostr.EntityPointer{
Identifier: parts[2],
PublicKey: parts[1],
Kind: kind,
Relays: relays,
}
}
}
}
}
references = append(references, reference)
}
return references

View File

@@ -19,28 +19,36 @@ func TestParseReferences(t *testing.T) {
expected := []Reference{
{
Text: "#[0]",
Text: "#[0]",
Start: 6,
End: 10,
Profile: &nostr.ProfilePointer{
PublicKey: "c9d556c6d3978d112d30616d0d20aaa81410e3653911dd67787b5aaf9b36ade8",
Relays: []string{"wss://nostr.com"},
},
},
{
Text: "#[2]",
Text: "#[2]",
Start: 26,
End: 30,
Event: &nostr.EventPointer{
ID: "31d7c2875b5fc8e6f9c8f9dc1f84de1b6b91d1947ea4c59225e55c325d330fa8",
Relays: []string{},
},
},
{
Text: "nostr:nprofile1qqsvc6ulagpn7kwrcwdqgp797xl7usumqa6s3kgcelwq6m75x8fe8yc5usxdg",
Text: "nostr:nprofile1qqsvc6ulagpn7kwrcwdqgp797xl7usumqa6s3kgcelwq6m75x8fe8yc5usxdg",
Start: 47,
End: 123,
Profile: &nostr.ProfilePointer{
PublicKey: "cc6b9fea033f59c3c39a0407c5f1bfee439b077508d918cfdc0d6fd431d39393",
Relays: []string{},
},
},
{
Text: "nostr:nevent1qqsvc6ulagpn7kwrcwdqgp797xl7usumqa6s3kgcelwq6m75x8fe8ychxp5v4",
Text: "nostr:nevent1qqsvc6ulagpn7kwrcwdqgp797xl7usumqa6s3kgcelwq6m75x8fe8ychxp5v4",
Start: 127,
End: 201,
Event: &nostr.EventPointer{
ID: "cc6b9fea033f59c3c39a0407c5f1bfee439b077508d918cfdc0d6fd431d39393",
Relays: []string{},
@@ -61,6 +69,14 @@ func TestParseReferences(t *testing.T) {
t.Errorf("%d: got text %s, expected %s", i, g.Text, e.Text)
}
if g.Start != e.Start {
t.Errorf("%d: got start %d, expected %d", i, g.Start, e.Start)
}
if g.End != e.End {
t.Errorf("%d: got end %d, expected %d", i, g.End, e.End)
}
if (g.Entity == nil && e.Entity != nil) ||
(g.Event == nil && e.Event != nil) ||
(g.Profile == nil && e.Profile != nil) {