clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

main
tinyrelay / tinyclient / social_mentions.go
social_mentions.go 1.9K
1package tinyclient23import (4 "encoding/hex"5 "html"6 "net/url"7 "regexp"8 "strings"9)1011var socialNostrAnchor = regexp.MustCompile(`<a href="/open\?target=([^"&]+)">((?:nostr:|web\+nostr:)[^<]+)</a>`)1213// socialNostrLinks gives NIP-27 references useful labels after autolinking.14// It only accepts the exact anchors emitted by autolinkOutsideTags.15func socialNostrLinks(rendered string) string {16 return socialNostrAnchor.ReplaceAllStringFunc(rendered, func(anchor string) string {17 match := socialNostrAnchor.FindStringSubmatch(anchor)18 target, err := url.QueryUnescape(html.UnescapeString(match[1]))19 if err != nil || !strings.EqualFold(target, html.UnescapeString(match[2])) {20 return anchor21 }22 path, label, ok := socialNostrDestination(target)23 if !ok {24 return anchor25 }26 return `<a href="` + html.EscapeString(path) + `">` + label + `</a>`27 })28}2930func socialNostrDestination(target string) (string, string, bool) {31 value := strings.Trim(strings.TrimSpace(target), "/")32 for _, prefix := range []string{"web+nostr:", "nostr:"} {33 if strings.HasPrefix(strings.ToLower(value), prefix) {34 value = value[len(prefix):]35 break36 }37 }38 hrp, data, ok := bech32Decode(strings.ToLower(value))39 if !ok {40 return "", "", false41 }42 switch hrp {43 case "npub", "nprofile":44 fields := data45 if hrp == "nprofile" {46 fields = tlvFields(data)[0]47 }48 if len(fields) != 32 {49 return "", "", false50 }51 pubkey := hex.EncodeToString(fields)52 return "/social/profile?author=" + pubkey, `<nostr-name pubkey="` + pubkey + `">` + shortID(pubkey) + `</nostr-name>`, true53 case "note", "nevent":54 id := data55 if hrp == "nevent" {56 id = tlvFields(data)[0]57 }58 if len(id) != 32 {59 return "", "", false60 }61 return "/e/" + hex.EncodeToString(id), "Quoted post", true62 case "naddr":63 path, ok := nostrTargetPath(target)64 label := "View post"65 if strings.HasPrefix(path, "/a/30023:") {66 label = "Article"67 }68 return path, label, ok69 default:70 return "", "", false71 }72}