moving some code around to show a "(reply)" on opengraph subscripts.

This commit is contained in:
fiatjaf
2024-01-08 16:39:03 -03:00
parent 87c2f25646
commit f1472b90a6
6 changed files with 87 additions and 84 deletions

17
data.go
View File

@@ -8,15 +8,13 @@ import (
"strings" "strings"
"time" "time"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19" "github.com/nbd-wtf/go-nostr/nip19"
sdk "github.com/nbd-wtf/nostr-sdk" sdk "github.com/nbd-wtf/nostr-sdk"
) )
type Data struct { type Data struct {
templateId TemplateID templateId TemplateID
event *nostr.Event event EnhancedEvent
relays []string
nprofile string nprofile string
nevent string nevent string
neventNaked string neventNaked string
@@ -28,7 +26,6 @@ type Data struct {
metadata Metadata metadata Metadata
authorRelays []string authorRelays []string
authorLong string authorLong string
authorShort string
renderableLastNotes []EnhancedEvent renderableLastNotes []EnhancedEvent
kindDescription string kindDescription string
kindNIP string kindNIP string
@@ -64,14 +61,15 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
} }
data := &Data{ data := &Data{
event: event, event: EnhancedEvent{
Event: event,
relays: relays, relays: relays,
},
} }
npub, _ := nip19.EncodePublicKey(event.PubKey) npub, _ := nip19.EncodePublicKey(event.PubKey)
npubShort := npub[:8] + "…" + npub[len(npub)-4:] npubShort := npub[:8] + "…" + npub[len(npub)-4:]
data.authorLong = npub // hopefully will be replaced later data.authorLong = npub // hopefully will be replaced later
data.authorShort = npubShort // hopefully will be replaced later
data.nevent, _ = nip19.EncodeEvent(event.ID, relaysForNip19, event.PubKey) data.nevent, _ = nip19.EncodeEvent(event.ID, relaysForNip19, event.PubKey)
data.neventNaked, _ = nip19.EncodeEvent(event.ID, nil, event.PubKey) data.neventNaked, _ = nip19.EncodeEvent(event.ID, nil, event.PubKey)
data.naddr = "" data.naddr = ""
@@ -193,7 +191,7 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
pTags := event.Tags.GetAll([]string{"p", ""}) pTags := event.Tags.GetAll([]string{"p", ""})
for _, p := range pTags { for _, p := range pTags {
if p[3] == "host" { if p[3] == "host" {
data.kind30311Metadata.Host = sdk.FetchProfileMetadata(ctx, pool, p[1], data.relays...) data.kind30311Metadata.Host = sdk.FetchProfileMetadata(ctx, pool, p[1], data.event.relays...)
data.kind30311Metadata.HostNpub = data.kind30311Metadata.Host.Npub() data.kind30311Metadata.HostNpub = data.kind30311Metadata.Host.Npub()
} }
} }
@@ -208,7 +206,7 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
if atag := event.Tags.GetFirst([]string{"a", ""}); atag != nil { if atag := event.Tags.GetFirst([]string{"a", ""}); atag != nil {
parts := strings.Split((*atag)[1], ":") parts := strings.Split((*atag)[1], ":")
kind, _ := strconv.Atoi(parts[0]) kind, _ := strconv.Atoi(parts[0])
parentNevent, _ := nip19.EncodeEntity(parts[1], kind, parts[2], data.relays) parentNevent, _ := nip19.EncodeEntity(parts[1], kind, parts[2], data.event.relays)
data.parentLink = template.HTML(replaceNostrURLsWithTags(nostrEveryMatcher, "nostr:"+parentNevent)) data.parentLink = template.HTML(replaceNostrURLsWithTags(nostrEveryMatcher, "nostr:"+parentNevent))
} }
default: default:
@@ -229,8 +227,7 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
spm, _ := sdk.ParseMetadata(author) spm, _ := sdk.ParseMetadata(author)
data.metadata = Metadata{spm} data.metadata = Metadata{spm}
if data.metadata.Name != "" { if data.metadata.Name != "" {
data.authorLong = fmt.Sprintf("%s (%s)", data.metadata.Name, npub) data.authorLong = fmt.Sprintf("%s (%s)", data.metadata.Name, npubShort)
data.authorShort = fmt.Sprintf("%s (%s)", data.metadata.Name, npubShort)
} }
} }
data.nprofile, _ = nip19.EncodeProfile(event.PubKey, limitAt(relays, 2)) data.nprofile, _ = nip19.EncodeProfile(event.PubKey, limitAt(relays, 2))

View File

@@ -141,7 +141,7 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
useTextImage = false useTextImage = false
} }
title := "" subscript := ""
if data.event.Kind >= 30000 && data.event.Kind < 40000 { if data.event.Kind >= 30000 && data.event.Kind < 40000 {
tValue := "~" tValue := "~"
for _, tag := range data.event.Tags { for _, tag := range data.event.Tags {
@@ -150,20 +150,23 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
break break
} }
} }
title = fmt.Sprintf("%s: %s", kindNames[data.event.Kind], tValue) subscript = fmt.Sprintf("%s: %s", kindNames[data.event.Kind], tValue)
} else if kindName, ok := kindNames[data.event.Kind]; ok { } else if kindName, ok := kindNames[data.event.Kind]; ok {
title = kindName subscript = kindName
} else { } else {
title = fmt.Sprintf("kind:%d event", data.event.Kind) subscript = fmt.Sprintf("kind:%d event", data.event.Kind)
} }
if subject != "" { if subject != "" {
title += " (" + subject + ")" subscript += " (" + subject + ")"
}
subscript += " by " + data.metadata.ShortName()
if data.event.IsReply() {
subscript += " (reply)"
} }
title += " by " + data.authorShort
seenOnRelays := "" seenOnRelays := ""
if len(data.relays) > 0 { if len(data.event.relays) > 0 {
seenOnRelays = fmt.Sprintf("seen on %s", strings.Join(data.relays, ", ")) seenOnRelays = fmt.Sprintf("seen on %s", strings.Join(data.event.relays, ", "))
} }
textImageURL := "" textImageURL := ""
@@ -212,7 +215,7 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
titleizedContent = urlRegex.ReplaceAllString(titleizedContent, "") titleizedContent = urlRegex.ReplaceAllString(titleizedContent, "")
if titleizedContent == "" { if titleizedContent == "" {
titleizedContent = title titleizedContent = subscript
} }
if len(titleizedContent) > 85 { if len(titleizedContent) > 85 {
@@ -283,9 +286,9 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
CreatedAt: data.createdAt, CreatedAt: data.createdAt,
KindDescription: data.kindDescription, KindDescription: data.kindDescription,
KindNIP: data.kindNIP, KindNIP: data.kindNIP,
EventJSON: eventToHTML(data.event), EventJSON: data.event.ToJSONHTML(),
Kind: data.event.Kind, Kind: data.event.Kind,
SeenOn: data.relays, SeenOn: data.event.relays,
Metadata: data.metadata, Metadata: data.metadata,
// kind-specific stuff // kind-specific stuff
@@ -301,7 +304,7 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
ProxiedImage: "https://" + host + "/njump/proxy?src=" + data.image, ProxiedImage: "https://" + host + "/njump/proxy?src=" + data.image,
Superscript: data.authorLong, Superscript: data.authorLong,
Subscript: title, Subscript: subscript,
Text: strings.TrimSpace(description), Text: strings.TrimSpace(description),
} }

View File

@@ -71,7 +71,7 @@ func renderProfile(w http.ResponseWriter, r *http.Request, code string) {
CreatedAt: data.createdAt, CreatedAt: data.createdAt,
KindDescription: data.kindDescription, KindDescription: data.kindDescription,
KindNIP: data.kindNIP, KindNIP: data.kindNIP,
EventJSON: eventToHTML(data.event), EventJSON: data.event.ToJSONHTML(),
Kind: data.event.Kind, Kind: data.event.Kind,
Metadata: data.metadata, Metadata: data.metadata,
}, },

View File

@@ -32,12 +32,16 @@ templ telegramInstantViewTemplate(params TelegramInstantViewParams) {
} else { } else {
<a href={ templ.URL("/" + params.Metadata.Npub()) }> <a href={ templ.URL("/" + params.Metadata.Npub()) }>
{ params.Metadata.ShortName() } { params.Metadata.ShortName() }
</a> on Nostr: </a> on Nostr
if params.ParentLink != "" {
(reply)
}
:
} }
</h1> </h1>
if params.ParentLink != "" { if params.ParentLink != "" {
<aside> <aside>
in reply to in reply to{ " " }
@templ.Raw(params.ParentLink) @templ.Raw(params.ParentLink)
</aside> </aside>
} }

View File

@@ -2,6 +2,8 @@ package main
import ( import (
"context" "context"
"encoding/json"
"fmt"
"html" "html"
"html/template" "html/template"
"regexp" "regexp"
@@ -30,20 +32,20 @@ func (m Metadata) NpubShort() string {
} }
type EnhancedEvent struct { type EnhancedEvent struct {
event *nostr.Event *nostr.Event
relays []string relays []string
} }
func (ee EnhancedEvent) IsReply() bool { func (ee EnhancedEvent) IsReply() bool {
return nip10.GetImmediateReply(ee.event.Tags) != nil return nip10.GetImmediateReply(ee.Event.Tags) != nil
} }
func (ee EnhancedEvent) Reply() *nostr.Tag { func (ee EnhancedEvent) Reply() *nostr.Tag {
return nip10.GetImmediateReply(ee.event.Tags) return nip10.GetImmediateReply(ee.Event.Tags)
} }
func (ee EnhancedEvent) Preview() template.HTML { func (ee EnhancedEvent) Preview() template.HTML {
lines := strings.Split(html.EscapeString(ee.event.Content), "\n") lines := strings.Split(html.EscapeString(ee.Event.Content), "\n")
var processedLines []string var processedLines []string
for _, line := range lines { for _, line := range lines {
if strings.TrimSpace(line) == "" { if strings.TrimSpace(line) == "" {
@@ -88,11 +90,11 @@ func (ee EnhancedEvent) RssTitle() string {
} }
func (ee EnhancedEvent) RssContent() string { func (ee EnhancedEvent) RssContent() string {
content := ee.event.Content content := ee.Event.Content
content = basicFormatting(html.EscapeString(content), true, false, false) content = basicFormatting(html.EscapeString(content), true, false, false)
content = renderQuotesAsHTML(context.Background(), content, false) content = renderQuotesAsHTML(context.Background(), content, false)
if ee.IsReply() { if ee.IsReply() {
nevent, _ := nip19.EncodeEvent(ee.Reply().Value(), ee.relays, ee.event.PubKey) nevent, _ := nip19.EncodeEvent(ee.Reply().Value(), ee.relays, ee.Event.PubKey)
neventShort := nevent[:8] + "…" + nevent[len(nevent)-4:] neventShort := nevent[:8] + "…" + nevent[len(nevent)-4:]
content = "In reply to <a href='/" + nevent + "'>" + neventShort + "</a><br/>_________________________<br/><br/>" + content content = "In reply to <a href='/" + nevent + "'>" + neventShort + "</a><br/>_________________________<br/><br/>" + content
} }
@@ -101,7 +103,7 @@ func (ee EnhancedEvent) RssContent() string {
func (ee EnhancedEvent) Thumb() string { func (ee EnhancedEvent) Thumb() string {
imgRegex := regexp.MustCompile(`(https?://[^\s]+\.(?:png|jpe?g|gif|bmp|svg)(?:/[^\s]*)?)`) imgRegex := regexp.MustCompile(`(https?://[^\s]+\.(?:png|jpe?g|gif|bmp|svg)(?:/[^\s]*)?)`)
matches := imgRegex.FindAllStringSubmatch(ee.event.Content, -1) matches := imgRegex.FindAllStringSubmatch(ee.Event.Content, -1)
if len(matches) > 0 { if len(matches) > 0 {
// The first match group captures the image URL // The first match group captures the image URL
return matches[0][1] return matches[0][1]
@@ -110,7 +112,7 @@ func (ee EnhancedEvent) Thumb() string {
} }
func (ee EnhancedEvent) Npub() string { func (ee EnhancedEvent) Npub() string {
npub, _ := nip19.EncodePublicKey(ee.event.PubKey) npub, _ := nip19.EncodePublicKey(ee.Event.PubKey)
return npub return npub
} }
@@ -120,16 +122,59 @@ func (ee EnhancedEvent) NpubShort() string {
} }
func (ee EnhancedEvent) Nevent() string { func (ee EnhancedEvent) Nevent() string {
nevent, _ := nip19.EncodeEvent(ee.event.ID, ee.relays, ee.event.PubKey) nevent, _ := nip19.EncodeEvent(ee.Event.ID, ee.relays, ee.Event.PubKey)
return nevent return nevent
} }
func (ee EnhancedEvent) CreatedAtStr() string { func (ee EnhancedEvent) CreatedAtStr() string {
return time.Unix(int64(ee.event.CreatedAt), 0).Format("2006-01-02 15:04:05") return time.Unix(int64(ee.Event.CreatedAt), 0).Format("2006-01-02 15:04:05")
} }
func (ee EnhancedEvent) ModifiedAtStr() string { func (ee EnhancedEvent) ModifiedAtStr() string {
return time.Unix(int64(ee.event.CreatedAt), 0).Format("2006-01-02T15:04:05Z07:00") return time.Unix(int64(ee.Event.CreatedAt), 0).Format("2006-01-02T15:04:05Z07:00")
}
func (ee EnhancedEvent) ToJSONHTML() template.HTML {
tagsHTML := "["
for t, tag := range ee.Tags {
tagsHTML += "\n ["
for i, item := range tag {
cls := `"text-zinc-500 dark:text-zinc-50"`
if i == 0 {
cls = `"text-amber-500 dark:text-amber-200"`
}
itemJSON, _ := json.Marshal(item)
tagsHTML += "\n <span class=" + cls + ">" + html.EscapeString(string(itemJSON))
if i < len(tag)-1 {
tagsHTML += ","
} else {
tagsHTML += "\n "
}
}
tagsHTML += "]"
if t < len(ee.Tags)-1 {
tagsHTML += ","
} else {
tagsHTML += "\n "
}
}
tagsHTML += "]"
contentJSON, _ := json.Marshal(ee.Content)
keyCls := "text-purple-700 dark:text-purple-300"
return template.HTML(fmt.Sprintf(
`{
<span class="`+keyCls+`">"id":</span> <span class="text-zinc-500 dark:text-zinc-50">"%s"</span>,
<span class="`+keyCls+`">"pubkey":</span> <span class="text-zinc-500 dark:text-zinc-50">"%s"</span>,
<span class="`+keyCls+`">"created_at":</span> <span class="text-green-600">%d</span>,
<span class="`+keyCls+`">"kind":</span> <span class="text-amber-500 dark:text-amber-200">%d</span>,
<span class="`+keyCls+`">"tags":</span> %s,
<span class="`+keyCls+`">"content":</span> <span class="text-zinc-500 dark:text-zinc-50">%s</span>,
<span class="`+keyCls+`">"sig":</span> <span class="text-zinc-500 dark:text-zinc-50 content">"%s"</span>
}`, ee.ID, ee.PubKey, ee.CreatedAt, ee.Kind, tagsHTML, html.EscapeString(string(contentJSON)), ee.Sig),
)
} }
type Kind1063Metadata struct { type Kind1063Metadata struct {

View File

@@ -3,10 +3,7 @@ package main
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/json"
"fmt" "fmt"
"html"
"html/template"
"math/rand" "math/rand"
"net/http" "net/http"
"regexp" "regexp"
@@ -431,49 +428,6 @@ func normalizeWebsiteURL(u string) string {
return "https://" + u return "https://" + u
} }
func eventToHTML(evt *nostr.Event) template.HTML {
tagsHTML := "["
for t, tag := range evt.Tags {
tagsHTML += "\n ["
for i, item := range tag {
cls := `"text-zinc-500 dark:text-zinc-50"`
if i == 0 {
cls = `"text-amber-500 dark:text-amber-200"`
}
itemJSON, _ := json.Marshal(item)
tagsHTML += "\n <span class=" + cls + ">" + html.EscapeString(string(itemJSON))
if i < len(tag)-1 {
tagsHTML += ","
} else {
tagsHTML += "\n "
}
}
tagsHTML += "]"
if t < len(evt.Tags)-1 {
tagsHTML += ","
} else {
tagsHTML += "\n "
}
}
tagsHTML += "]"
contentJSON, _ := json.Marshal(evt.Content)
keyCls := "text-purple-700 dark:text-purple-300"
return template.HTML(fmt.Sprintf(
`{
<span class="`+keyCls+`">"id":</span> <span class="text-zinc-500 dark:text-zinc-50">"%s"</span>,
<span class="`+keyCls+`">"pubkey":</span> <span class="text-zinc-500 dark:text-zinc-50">"%s"</span>,
<span class="`+keyCls+`">"created_at":</span> <span class="text-green-600">%d</span>,
<span class="`+keyCls+`">"kind":</span> <span class="text-amber-500 dark:text-amber-200">%d</span>,
<span class="`+keyCls+`">"tags":</span> %s,
<span class="`+keyCls+`">"content":</span> <span class="text-zinc-500 dark:text-zinc-50">%s</span>,
<span class="`+keyCls+`">"sig":</span> <span class="text-zinc-500 dark:text-zinc-50 content">"%s"</span>
}`, evt.ID, evt.PubKey, evt.CreatedAt, evt.Kind, tagsHTML, html.EscapeString(string(contentJSON)), evt.Sig),
)
}
func limitAt[V any](list []V, n int) []V { func limitAt[V any](list []V, n int) []V {
if len(list) < n { if len(list) < n {
return list return list