mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-11-18 18:16:50 +01:00
move ExternalPointer to nip73 and write nip27.Parse() that gets all the parts of the text including URLs, Nostr URIs and just raw text.
This commit is contained in:
152
nip27/blocks.go
Normal file
152
nip27/blocks.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package nip27
|
||||
|
||||
import (
|
||||
"iter"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
"github.com/nbd-wtf/go-nostr/nip73"
|
||||
)
|
||||
|
||||
type Block struct {
|
||||
Text string
|
||||
Start int
|
||||
Pointer nostr.Pointer
|
||||
}
|
||||
|
||||
var (
|
||||
noCharacter = regexp.MustCompile(`(?m)\W`)
|
||||
noURLCharacter = regexp.MustCompile(`(?m)\W |\W$|$|,| `)
|
||||
)
|
||||
|
||||
func Parse(content string) iter.Seq[Block] {
|
||||
return func(yield func(Block) bool) {
|
||||
max := len(content)
|
||||
index := 0
|
||||
prevIndex := 0
|
||||
|
||||
for index < max {
|
||||
pu := strings.IndexRune(content[index:], ':')
|
||||
if pu == -1 {
|
||||
// reached end
|
||||
break
|
||||
}
|
||||
u := pu + index
|
||||
|
||||
switch {
|
||||
case u >= 5 && content[u-5:u] == "nostr" && u+60 < max:
|
||||
m := noCharacter.FindStringIndex(content[u+60:])
|
||||
end := max
|
||||
if m != nil {
|
||||
end = u + 60 + m[0]
|
||||
}
|
||||
|
||||
prefix, data, err := nip19.Decode(content[u+1 : end])
|
||||
if err != nil {
|
||||
// ignore this, not a valid nostr uri
|
||||
index = u + 1
|
||||
continue
|
||||
}
|
||||
|
||||
var pointer nostr.Pointer
|
||||
switch prefix {
|
||||
case "npub":
|
||||
pointer = nostr.ProfilePointer{PublicKey: data.(string)}
|
||||
case "nprofile", "nevent", "naddr":
|
||||
pointer = data.(nostr.Pointer)
|
||||
case "note", "nsec":
|
||||
fallthrough // I'm so cool
|
||||
default:
|
||||
// ignore this, treat it as not a valid uri
|
||||
index = end + 1
|
||||
continue
|
||||
}
|
||||
|
||||
if prevIndex != u-5 {
|
||||
if !yield(Block{Text: content[prevIndex : u-5], Start: prevIndex}) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !yield(Block{Pointer: pointer, Text: content[u-5 : end], Start: u - 5}) {
|
||||
return
|
||||
}
|
||||
|
||||
index = end
|
||||
prevIndex = index
|
||||
continue
|
||||
case (u >= 5 && content[u-5:u] == "https") || (u >= 4 && content[u-4:u] == "http"):
|
||||
m := noURLCharacter.FindStringIndex(content[u+4:])
|
||||
end := max
|
||||
if m != nil {
|
||||
end = u + 4 + m[0]
|
||||
}
|
||||
prefixLen := 4
|
||||
if content[u-1] == 's' {
|
||||
prefixLen = 5
|
||||
}
|
||||
parsed, err := url.Parse(content[u-prefixLen : end])
|
||||
if err != nil || !strings.Contains(parsed.Host, ".") {
|
||||
// ignore this, not a valid url
|
||||
index = end + 1
|
||||
continue
|
||||
}
|
||||
|
||||
if prevIndex != u-prefixLen {
|
||||
if !yield(Block{Text: content[prevIndex : u-prefixLen], Start: prevIndex}) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !yield(Block{Pointer: nip73.ExternalPointer{Thing: content[u-prefixLen : end]}, Text: content[u-prefixLen : end], Start: u - prefixLen}) {
|
||||
return
|
||||
}
|
||||
|
||||
index = end
|
||||
prevIndex = index
|
||||
continue
|
||||
case (u >= 3 && content[u-3:u] == "wss") || (u >= 2 && content[u-2:u] == "ws"):
|
||||
m := noURLCharacter.FindStringIndex(content[u+4:])
|
||||
end := max
|
||||
if m != nil {
|
||||
end = u + 4 + m[0]
|
||||
}
|
||||
prefixLen := 2
|
||||
if content[u-1] == 's' {
|
||||
prefixLen = 3
|
||||
}
|
||||
parsed, err := url.Parse(content[u-prefixLen : end])
|
||||
if err != nil || !strings.Contains(parsed.Host, ".") {
|
||||
// ignore this, not a valid url
|
||||
index = end + 1
|
||||
continue
|
||||
}
|
||||
|
||||
if prevIndex != u-prefixLen {
|
||||
if !yield(Block{Text: content[prevIndex : u-prefixLen], Start: prevIndex}) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !yield(Block{Pointer: nip73.ExternalPointer{Thing: content[u-prefixLen : end]}, Text: content[u-prefixLen : end], Start: u - prefixLen}) {
|
||||
return
|
||||
}
|
||||
|
||||
index = end
|
||||
prevIndex = index
|
||||
continue
|
||||
default:
|
||||
// ignore this, it is nothing
|
||||
index = u + 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if prevIndex != max {
|
||||
yield(Block{Text: content[prevIndex:], Start: prevIndex})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user