package main
import (
"context"
"fmt"
"html/template"
"strings"
"time"
"github.com/nbd-wtf/go-nostr/nip19"
"github.com/nbd-wtf/go-nostr/nip31"
"github.com/nbd-wtf/go-nostr/nip52"
"github.com/nbd-wtf/go-nostr/nip53"
"github.com/nbd-wtf/go-nostr/nip92"
"github.com/nbd-wtf/go-nostr/nip94"
"github.com/nbd-wtf/go-nostr/sdk"
)
type Data struct {
templateId TemplateID
event EnhancedEvent
nevent string
neventNaked string
naddr string
naddrNaked string
createdAt string
parentLink template.HTML
kindDescription string
kindNIP string
video string
videoType string
image string
cover string
content string
alt string
kind1063Metadata *Kind1063Metadata
kind30311Metadata *Kind30311Metadata
kind31922Or31923Metadata *Kind31922Or31923Metadata
Kind30818Metadata Kind30818Metadata
}
func grabData(ctx context.Context, code string, withRelays bool) (Data, error) {
// code can be a nevent or naddr, in which case we try to fetch the associated event
event, relays, err := getEvent(ctx, code, withRelays)
if err != nil {
return Data{}, fmt.Errorf("error fetching event: %w", err)
}
relaysForNip19 := make([]string, 0, 3)
c := 0
for _, relayUrl := range relays {
if sdk.IsVirtualRelay(relayUrl) {
continue
}
relaysForNip19 = append(relaysForNip19, relayUrl)
if c == 2 {
break
}
}
ee := NewEnhancedEvent(ctx, event)
ee.relays = relays
data := Data{
event: ee,
}
data.nevent, _ = nip19.EncodeEvent(event.ID, relaysForNip19, event.PubKey)
data.neventNaked, _ = nip19.EncodeEvent(event.ID, nil, event.PubKey)
data.naddr = ""
data.naddrNaked = ""
data.createdAt = time.Unix(int64(event.CreatedAt), 0).Format("2006-01-02 15:04:05 MST")
if event.Kind >= 30000 && event.Kind < 40000 {
if dTag := event.Tags.Find("d"); dTag != nil {
data.naddr, _ = nip19.EncodeEntity(event.PubKey, event.Kind, dTag[1], relaysForNip19)
data.naddrNaked, _ = nip19.EncodeEntity(event.PubKey, event.Kind, dTag[1], nil)
}
}
data.alt = nip31.GetAlt(*event)
switch event.Kind {
case 1, 7:
data.templateId = Note
data.content = event.Content
case 30023, 30024:
data.templateId = LongForm
data.content = event.Content
case 20:
data.templateId = Note
data.content = event.Content
case 6:
data.templateId = Note
if reposted := event.Tags.Find("e"); reposted != nil {
originalNevent, _ := nip19.EncodeEvent(reposted[1], []string{}, "")
data.content = "Repost of nostr:" + originalNevent
}
case 1063:
data.templateId = FileMetadata
data.kind1063Metadata = &Kind1063Metadata{nip94.ParseFileMetadata(*event)}
case 30311:
data.templateId = LiveEvent
data.kind30311Metadata = &Kind30311Metadata{LiveEvent: nip53.ParseLiveEvent(*event)}
host := data.kind30311Metadata.GetHost()
if host != nil {
hostProfile := sys.FetchProfileMetadata(ctx, host.PubKey)
data.kind30311Metadata.Host = &hostProfile
}
case 1311:
data.templateId = LiveEventMessage
data.content = event.Content
case 31922, 31923:
data.templateId = CalendarEvent
data.kind31922Or31923Metadata = &Kind31922Or31923Metadata{CalendarEvent: nip52.ParseCalendarEvent(*event)}
data.content = event.Content
case 30818:
data.templateId = WikiEvent
data.Kind30818Metadata.Handle = event.Tags.GetD()
data.Kind30818Metadata.Title = data.Kind30818Metadata.Handle
if titleTag := event.Tags.Find("title"); titleTag != nil {
data.Kind30818Metadata.Title = titleTag[1]
}
data.Kind30818Metadata.Summary = func() string {
if tag := event.Tags.Find("summary"); tag != nil {
value := tag[1]
return value
}
return ""
}()
data.content = event.Content
default:
data.templateId = Other
}
data.kindDescription = kindNames[event.Kind]
if data.kindDescription == "" {
data.kindDescription = fmt.Sprintf("Kind %d", event.Kind)
}
data.kindNIP = kindNIPs[event.Kind]
image := event.Tags.Find("image")
if event.Kind == 30023 && image != nil {
data.cover = image[1]
} else if event.Kind == 1063 {
if data.kind1063Metadata.IsImage() {
data.image = data.kind1063Metadata.URL
} else if data.kind1063Metadata.IsVideo() {
data.video = data.kind1063Metadata.URL
data.videoType = strings.Split(data.kind1063Metadata.M, "/")[1]
}
} else if event.Kind == 20 {
imeta := nip92.ParseTags(event.Tags)
if len(imeta) > 0 {
data.image = imeta[0].URL
content := strings.Builder{}
content.Grow(110*len(imeta) + len(data.content))
for _, entry := range imeta {
content.WriteString(entry.URL)
content.WriteString(" ")
}
content.WriteString(data.content)
data.content = content.String()
}
if tag := data.event.Tags.Find("title"); tag != nil {
data.event.subject = tag[1]
}
} else {
urls := urlMatcher.FindAllString(event.Content, -1)
for _, url := range urls {
switch {
case imageExtensionMatcher.MatchString(url):
if data.image == "" {
data.image = url
}
case videoExtensionMatcher.MatchString(url):
if data.video == "" {
data.video = url
if strings.HasSuffix(data.video, "mp4") {
data.videoType = "mp4"
} else if strings.HasSuffix(data.video, "mov") {
data.videoType = "mov"
} else {
data.videoType = "webm"
}
}
}
}
}
return data, nil
}