From 1ca10e12fbd5892b3670ddaaac85b61e96303c8d Mon Sep 17 00:00:00 2001 From: dtonon Date: Wed, 2 Apr 2025 00:44:53 +0200 Subject: [PATCH] Add support for Highlight (kind:9802) --- clients.go | 6 +++++ data.go | 55 +++++++++++++++++++++++++++++++++++++ highlight.templ | 69 +++++++++++++++++++++++++++++++++++++++++++++++ pages.go | 1 + render_event.go | 19 +++++++++++++ template_types.go | 10 +++++++ utils.go | 8 ++++++ 7 files changed, 168 insertions(+) create mode 100644 highlight.templ diff --git a/clients.go b/clients.go index 0395c11..6d7efb8 100644 --- a/clients.go +++ b/clients.go @@ -110,6 +110,12 @@ func generateClientList( amethyst, snort, coracle, nostrudel, } + case 9802: + clients = []ClientReference{ + highlighter, + coracle, + nostrudel, + } case 30311: clients = []ClientReference{ native, diff --git a/data.go b/data.go index f7767ae..8c3ba89 100644 --- a/data.go +++ b/data.go @@ -3,7 +3,9 @@ package main import ( "context" "fmt" + "html" "html/template" + "strconv" "strings" "time" @@ -37,6 +39,7 @@ type Data struct { kind30311Metadata *Kind30311Metadata kind31922Or31923Metadata *Kind31922Or31923Metadata Kind30818Metadata Kind30818Metadata + Kind9802Metadata Kind9802Metadata } func grabData(ctx context.Context, code string, withRelays bool) (Data, error) { @@ -129,6 +132,58 @@ func grabData(ctx context.Context, code string, withRelays bool) (Data, error) { return "" }() data.content = event.Content + case 9802: + data.templateId = Highlight + data.content = event.Content + if author := event.Tags.Find("p"); author != nil { + ctx, cancel := context.WithTimeout(ctx, time.Second*3) + defer cancel() + data.Kind9802Metadata.Author = sys.FetchProfileMetadata(ctx, author[1]) + } + if sourceEvent := event.Tags.Find("e"); sourceEvent != nil { + data.Kind9802Metadata.SourceEvent = sourceEvent[1] + data.Kind9802Metadata.SourceName = "#" + shortenString(sourceEvent[1], 8, 4) + } else if sourceEvent := event.Tags.Find("a"); sourceEvent != nil { + spl := strings.Split(sourceEvent[1], ":") + kind, _ := strconv.Atoi(spl[0]) + var relayHints []string + if len(sourceEvent) > 2 { + relayHints = []string{sourceEvent[2]} + } + naddr, _ := nip19.EncodeEntity(spl[1], kind, spl[2], relayHints) + data.Kind9802Metadata.SourceEvent = naddr + + sourceEvent, _, _ := getEvent(ctx, naddr, withRelays) + if title := sourceEvent.Tags.Find("title"); title != nil { + data.Kind9802Metadata.SourceName = title[1] + } else { + data.Kind9802Metadata.SourceName = "#" + shortenString(naddr, 8, 4) + } + } else if sourceUrl := event.Tags.Find("r"); sourceUrl != nil { + data.Kind9802Metadata.SourceURL = sourceUrl[1] + data.Kind9802Metadata.SourceName = sourceUrl[1] + } + if context := event.Tags.Find("context"); context != nil { + data.Kind9802Metadata.Context = context[1] + + escapedContext := html.EscapeString(context[1]) + escapedCitation := html.EscapeString(data.content) + + // Some clients mistakenly put the highlight in the context + if escapedContext != escapedCitation { + // Replace the citation with the marked version + data.Kind9802Metadata.MarkedContext = strings.Replace( + escapedContext, + escapedCitation, + fmt.Sprintf("%s", escapedCitation), + -1, // Replace all occurrences + ) + } + } + if comment := event.Tags.Find("comment"); comment != nil { + data.Kind9802Metadata.Comment = basicFormatting(comment[1], false, false, false) + } + default: data.templateId = Other } diff --git a/highlight.templ b/highlight.templ new file mode 100644 index 0000000..7e816f6 --- /dev/null +++ b/highlight.templ @@ -0,0 +1,69 @@ +package main + +import "html/template" + +type HighlightPageParams struct { + BaseEventPageParams + OpenGraphParams + HeadParams + + Details DetailsParams + Content template.HTML + HighlightEvent Kind9802Metadata + Clients []ClientReference +} + +templ highlightInnerBlock(params HighlightPageParams) { +

Highlight

+
+ if params.HighlightEvent.Comment != "" { +
+ @templ.Raw(params.HighlightEvent.Comment) +
+ } +
+ if params.HighlightEvent.MarkedContext != "" { + @templ.Raw(params.HighlightEvent.MarkedContext) + } else { + @templ.Raw(params.Content) + } + +
+
+} + +templ highlightTemplate(params HighlightPageParams, isEmbed bool) { + + if isEmbed { + @embeddedPageTemplate( + params.Event, + params.NeventNaked, + ) { + @highlightInnerBlock(params) + } + } else { + @eventPageTemplate( + "Highlight", + params.OpenGraphParams, + params.HeadParams, + params.Clients, + params.Details, + params.Event, + ) { + @highlightInnerBlock(params) + } + } +} diff --git a/pages.go b/pages.go index 4997d1a..cff5983 100644 --- a/pages.go +++ b/pages.go @@ -24,6 +24,7 @@ const ( LiveEventMessage CalendarEvent WikiEvent + Highlight Other ) diff --git a/render_event.go b/render_event.go index 234482a..a290f0a 100644 --- a/render_event.go +++ b/render_event.go @@ -564,6 +564,25 @@ func renderEvent(w http.ResponseWriter, r *http.Request) { component = wikiEventTemplate(params, isEmbed) + case Highlight: + content := data.content + + params := HighlightPageParams{ + BaseEventPageParams: baseEventPageParams, + OpenGraphParams: opengraph, + HeadParams: HeadParams{ + IsProfile: false, + NaddrNaked: data.naddrNaked, + NeventNaked: data.neventNaked, + }, + Content: template.HTML(content), + HighlightEvent: data.Kind9802Metadata, + Details: detailsData, + Clients: generateClientList(data.event.Kind, data.nevent), + } + + component = highlightTemplate(params, isEmbed) + case Other: detailsData.HideDetails = false // always open this since we know nothing else about the event diff --git a/template_types.go b/template_types.go index 446f6eb..6324fce 100644 --- a/template_types.go +++ b/template_types.go @@ -35,3 +35,13 @@ type Kind30818Metadata struct { Summary string PublishedAt time.Time } + +type Kind9802Metadata struct { + Author sdk.ProfileMetadata + SourceEvent string + SourceURL string + SourceName string + Context string + MarkedContext string + Comment string +} diff --git a/utils.go b/utils.go index 7f4e1c6..c2f89ba 100644 --- a/utils.go +++ b/utils.go @@ -67,6 +67,7 @@ var kindNames = map[int]string{ 1984: "Reporting", 9734: "Zap Request", 9735: "Zap", + 9802: "Highlight", 10000: "Mute List", 10001: "Pin List", 10002: "Relay List Metadata", @@ -107,6 +108,7 @@ var kindNIPs = map[int]string{ 1984: "56", 9734: "57", 9735: "57", + 9802: "84", 10000: "51", 10001: "51", 10002: "65", @@ -254,6 +256,12 @@ func shortenNostrURLs(input string) string { }) } +func shortenString(input string, before int, after int) string { + firstChars := input[:before] + lastChars := input[len(input)-after:] + return firstChars + "…" + lastChars +} + func getNameFromNip19(ctx context.Context, nip19code string) (string, bool) { metadata, _ := sys.FetchProfileFromInput(ctx, nip19code) if metadata.Name == "" {