mirror of
https://github.com/aljazceru/njump.git
synced 2025-12-17 14:24:27 +01:00
tmpl migration: profile.html
This commit is contained in:
57
data.go
57
data.go
@@ -4,21 +4,38 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip10"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
Npub string
|
||||
NpubShort string
|
||||
Nevent string
|
||||
Content string
|
||||
CreatedAt string
|
||||
ModifiedAt string
|
||||
ParentNevent string
|
||||
type LastNotesItem struct {
|
||||
Npub string
|
||||
NpubShort string
|
||||
Nevent string
|
||||
Content string
|
||||
CreatedAt string
|
||||
ModifiedAt string
|
||||
IsReply bool
|
||||
}
|
||||
|
||||
func (i LastNotesItem) Preview() template.HTML {
|
||||
lines := strings.Split(html.EscapeString(i.Content), "\n")
|
||||
var processedLines []string
|
||||
for _, line := range lines {
|
||||
if strings.TrimSpace(line) == "" {
|
||||
continue
|
||||
}
|
||||
processedLine := shortenNostrURLs(line)
|
||||
processedLines = append(processedLines, processedLine)
|
||||
}
|
||||
|
||||
return template.HTML(strings.Join(processedLines, "<br/>"))
|
||||
}
|
||||
|
||||
type Data struct {
|
||||
@@ -37,7 +54,7 @@ type Data struct {
|
||||
authorRelays []string
|
||||
authorLong string
|
||||
authorShort string
|
||||
renderableLastNotes []*Event
|
||||
renderableLastNotes []LastNotesItem
|
||||
kindDescription string
|
||||
kindNIP string
|
||||
video string
|
||||
@@ -69,7 +86,7 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
|
||||
modifiedAt := time.Unix(int64(event.CreatedAt), 0).Format("2006-01-02T15:04:05Z07:00")
|
||||
|
||||
author := event
|
||||
var renderableLastNotes []*Event
|
||||
var renderableLastNotes []LastNotesItem
|
||||
parentNevent := ""
|
||||
authorRelays := []string{}
|
||||
var content string
|
||||
@@ -98,7 +115,7 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
|
||||
key = "lns:" + event.PubKey
|
||||
eventsToFetch = 50000
|
||||
} else {
|
||||
typ = "profile"
|
||||
templateId = Profile
|
||||
key = "ln:" + event.PubKey
|
||||
}
|
||||
|
||||
@@ -131,15 +148,15 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
|
||||
}
|
||||
}
|
||||
|
||||
renderableLastNotes = make([]*Event, len(lastNotes))
|
||||
for i, n := range lastNotes {
|
||||
nevent, _ := nip19.EncodeEvent(n.ID, []string{}, n.PubKey)
|
||||
renderableLastNotes[i] = &Event{
|
||||
Nevent: nevent,
|
||||
Content: n.Content,
|
||||
CreatedAt: time.Unix(int64(n.CreatedAt), 0).Format("2006-01-02 15:04:05"),
|
||||
ModifiedAt: time.Unix(int64(n.CreatedAt), 0).Format("2006-01-02T15:04:05Z07:00"),
|
||||
ParentNevent: getParentNevent(n),
|
||||
renderableLastNotes = make([]LastNotesItem, len(lastNotes))
|
||||
for i, levt := range lastNotes {
|
||||
nevent, _ := nip19.EncodeEvent(levt.ID, []string{}, levt.PubKey)
|
||||
renderableLastNotes[i] = LastNotesItem{
|
||||
Nevent: nevent,
|
||||
Content: levt.Content,
|
||||
CreatedAt: time.Unix(int64(levt.CreatedAt), 0).Format("2006-01-02 15:04:05"),
|
||||
ModifiedAt: time.Unix(int64(levt.CreatedAt), 0).Format("2006-01-02T15:04:05Z07:00"),
|
||||
IsReply: nip10.GetImmediateReply(levt.Tags) != nil,
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
|
||||
1
main.go
1
main.go
@@ -70,7 +70,6 @@ func main() {
|
||||
// initialize templates
|
||||
// use a mapping to expressly link the templates and share them between more kinds/types
|
||||
templateMapping = map[string]string{
|
||||
"profile": "profile.html",
|
||||
"profile_sitemap": "sitemap.xml",
|
||||
"relay": "relay.html",
|
||||
"relay_sitemap": "sitemap.xml",
|
||||
|
||||
32
pages.go
32
pages.go
@@ -226,3 +226,35 @@ type NotePage struct {
|
||||
func (*NotePage) TemplateText() string {
|
||||
return tmplNote
|
||||
}
|
||||
|
||||
var (
|
||||
//go:embed templates/profile.html
|
||||
tmplProfile string
|
||||
ProfileTemplate = tmpl.MustCompile(&ProfilePage{})
|
||||
)
|
||||
|
||||
type ProfilePage struct {
|
||||
HeadCommonPartial `tmpl:"head_common"`
|
||||
TopPartial `tmpl:"top"`
|
||||
DetailsPartial `tmpl:"details"`
|
||||
ClientsPartial `tmpl:"clients"`
|
||||
FooterPartial `tmpl:"footer"`
|
||||
|
||||
AuthorRelays []string
|
||||
Content string
|
||||
CreatedAt string
|
||||
Domain string
|
||||
LastNotes []LastNotesItem
|
||||
Metadata nostr.ProfileMetadata
|
||||
NormalizedAuthorWebsiteURL string
|
||||
RenderedAuthorAboutText template.HTML
|
||||
Nevent string
|
||||
Npub string
|
||||
IsReply string
|
||||
Proxy string
|
||||
Title string
|
||||
}
|
||||
|
||||
func (*ProfilePage) TemplateText() string {
|
||||
return tmplProfile
|
||||
}
|
||||
|
||||
22
render.go
22
render.go
@@ -328,6 +328,28 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
Video: data.video,
|
||||
VideoType: data.videoType,
|
||||
})
|
||||
case Profile:
|
||||
err = ProfileTemplate.Render(w, &ProfilePage{
|
||||
HeadCommonPartial: HeadCommonPartial{IsProfile: true},
|
||||
DetailsPartial: DetailsPartial{
|
||||
HideDetails: true,
|
||||
CreatedAt: data.createdAt,
|
||||
KindDescription: data.kindDescription,
|
||||
KindNIP: data.kindNIP,
|
||||
EventJSON: string(eventJSON),
|
||||
Kind: data.event.Kind,
|
||||
},
|
||||
ClientsPartial: ClientsPartial{
|
||||
Clients: generateClientList(code, data.event),
|
||||
},
|
||||
|
||||
Metadata: data.metadata,
|
||||
NormalizedAuthorWebsiteURL: normalizeWebsiteURL(data.metadata.Website),
|
||||
RenderedAuthorAboutText: template.HTML(basicFormatting(html.EscapeString(data.metadata.About), false, false)),
|
||||
Npub: data.npub,
|
||||
AuthorRelays: data.authorRelays,
|
||||
LastNotes: data.renderableLastNotes,
|
||||
})
|
||||
case Other:
|
||||
err = OtherTemplate.Render(w, &OtherPage{
|
||||
HeadCommonPartial: HeadCommonPartial{IsProfile: false},
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip10"
|
||||
"github.com/nbd-wtf/go-nostr/nip11"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
)
|
||||
@@ -43,24 +44,24 @@ func renderRelayPage(w http.ResponseWriter, r *http.Request) {
|
||||
Limit: events_num,
|
||||
})
|
||||
}
|
||||
renderableLastNotes := make([]*Event, len(lastNotes))
|
||||
renderableLastNotes := make([]LastNotesItem, len(lastNotes))
|
||||
lastEventAt := time.Now()
|
||||
relay := []string{"wss://" + hostname}
|
||||
for i, n := range lastNotes {
|
||||
nevent, _ := nip19.EncodeEvent(n.ID, relay, n.PubKey)
|
||||
npub, _ := nip19.EncodePublicKey(n.PubKey)
|
||||
for i, levt := range lastNotes {
|
||||
nevent, _ := nip19.EncodeEvent(levt.ID, relay, levt.PubKey)
|
||||
npub, _ := nip19.EncodePublicKey(levt.PubKey)
|
||||
npubShort := npub[:8] + "…" + npub[len(npub)-4:]
|
||||
renderableLastNotes[i] = &Event{
|
||||
Npub: npub,
|
||||
NpubShort: npubShort,
|
||||
Nevent: nevent,
|
||||
Content: n.Content,
|
||||
CreatedAt: time.Unix(int64(n.CreatedAt), 0).Format("2006-01-02 15:04:05"),
|
||||
ModifiedAt: time.Unix(int64(n.CreatedAt), 0).Format("2006-01-02T15:04:05Z07:00"),
|
||||
ParentNevent: getParentNevent(n),
|
||||
renderableLastNotes[i] = LastNotesItem{
|
||||
Npub: npub,
|
||||
NpubShort: npubShort,
|
||||
Nevent: nevent,
|
||||
Content: levt.Content,
|
||||
CreatedAt: time.Unix(int64(levt.CreatedAt), 0).Format("2006-01-02 15:04:05"),
|
||||
ModifiedAt: time.Unix(int64(levt.CreatedAt), 0).Format("2006-01-02T15:04:05Z07:00"),
|
||||
IsReply: nip10.GetImmediateReply(levt.Tags) != nil,
|
||||
}
|
||||
if i == 0 {
|
||||
lastEventAt = time.Unix(int64(n.CreatedAt), 0)
|
||||
lastEventAt = time.Unix(int64(levt.CreatedAt), 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,113 +1,92 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html class="theme--default">
|
||||
<meta charset="UTF-8" />
|
||||
<head>
|
||||
<title>
|
||||
{{.metadata.Name | escapeString}} / {{.metadata.DisplayName |
|
||||
escapeString}} is on nostr
|
||||
</title>
|
||||
<title>{{.Metadata.Name}} / {{.Metadata.DisplayName}} is on nostr</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="{{.npub | escapeString}} is {{.metadata.Name | escapeString}} / {{.metadata.DisplayName | escapeString}} public key on nostr"
|
||||
/>
|
||||
<meta property="og:title" content="{{.title | escapeString}}" />
|
||||
<meta property="og:site_name" content="{{.npub | escapeString}}" />
|
||||
{{ if .metadata.Picture }}
|
||||
<meta property="og:image" content="{{.metadata.Picture | escapeString}}" />
|
||||
<meta
|
||||
property="twitter:image"
|
||||
content="{{.proxy}}{{.metadata.Picture | escapeString}}"
|
||||
/>
|
||||
{{end}} {{ if .metadata.About }}
|
||||
<meta
|
||||
property="og:description"
|
||||
content="{{.metadata.About | escapeString}}"
|
||||
content="{{.Npub}} is {{.Metadata.Name}} / {{.Metadata.DisplayName}} public key on nostr"
|
||||
/>
|
||||
<meta property="og:title" content="{{.Title}}" />
|
||||
<meta property="og:site_name" content="{{.Npub}}" />
|
||||
{{ if not (eq "" .Metadata.Picture) }}
|
||||
<meta property="og:image" content="{{.Metadata.Picture}}" />
|
||||
<meta property="twitter:image" content="{{.Proxy}}{{.Metadata.Picture}}" />
|
||||
{{end}} {{ if not (eq "" .Metadata.About) }}
|
||||
<meta property="og:description" content="{{.Metadata.About}}" />
|
||||
{{end}}
|
||||
<meta property="twitter:card" content="summary" />
|
||||
|
||||
<link
|
||||
rel="canonical"
|
||||
href="https://{{s.Domain}}/{{.npub | escapeString }}"
|
||||
/>
|
||||
<link rel="canonical" href="https://njump.me/{{.Npub}}" />
|
||||
<link
|
||||
rel="sitemap"
|
||||
type="application/xml"
|
||||
title="Sitemap for {{.npub | escapeString}}"
|
||||
href="/{{.npub | escapeString}}.xml"
|
||||
title="Sitemap for {{.Npub}}"
|
||||
href="/{{.Npub}}.Xml"
|
||||
/>
|
||||
|
||||
{{template "head_common.html" .}}
|
||||
{{template "head_common" .}}
|
||||
</head>
|
||||
|
||||
<body class="profile">
|
||||
{{template "top.html" .}}
|
||||
{{template "top" .}}
|
||||
|
||||
<div class="container_wrapper">
|
||||
<div class="container">
|
||||
<header class="column columnA">
|
||||
<div class="info-wrapper">
|
||||
<div class="name">
|
||||
{{.metadata.Name | escapeString}} {{if not (eq .metadata.Name
|
||||
.metadata.DisplayName)}}
|
||||
<span class="display"
|
||||
>{{.metadata.DisplayName | escapeString}}</span
|
||||
>
|
||||
{{.Metadata.Name}} {{if not (eq .Metadata.Name
|
||||
.Metadata.DisplayName)}}
|
||||
<span class="display">{{.Metadata.DisplayName}}</span>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="pic-wrapper">
|
||||
<img class="pic" src="{{.metadata.Picture | escapeString}}" />
|
||||
<img class="pic" src="{{.Metadata.Picture}}" />
|
||||
</div>
|
||||
<div class="last_update">
|
||||
Last update:<br />
|
||||
{{.createdAt | escapeString}}
|
||||
{{.CreatedAt}}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="column column_content">
|
||||
<header class="field info-wrapper">
|
||||
<h1 id="profile_name" class="name">
|
||||
{{.metadata.Name | escapeString}} {{if not (eq .metadata.Name
|
||||
.metadata.DisplayName)}}
|
||||
<span class="display"
|
||||
>{{.metadata.DisplayName | escapeString}}</span
|
||||
>
|
||||
{{.Metadata.Name}} {{if not (eq .Metadata.Name
|
||||
.Metadata.DisplayName)}}
|
||||
<span class="display">{{.Metadata.DisplayName}}</span>
|
||||
{{end}}
|
||||
</h1>
|
||||
</header>
|
||||
<div class="field separator long"></div>
|
||||
<div class="field">
|
||||
<a href="{{.metadata.Website | normalizeWebsiteURL | escapeString}}"
|
||||
>{{.metadata.Website | escapeString}}</a
|
||||
>
|
||||
</div>
|
||||
<div class="field about">
|
||||
{{.metadata.About | escapeString | basicFormatting}}
|
||||
<a href="{{.NormalizedAuthorWebsiteURL}}">{{.Metadata.Website}}</a>
|
||||
</div>
|
||||
<div class="field about">{{.RenderedAuthorAboutText}}</div>
|
||||
<div class="field separator"></div>
|
||||
<div class="field">
|
||||
<div class="label">Public key</div>
|
||||
{{.npub | escapeString}}
|
||||
{{.Npub}}
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">NIP-05</div>
|
||||
{{.metadata.NIP05 | escapeString}}
|
||||
{{.Metadata.NIP05}}
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">LN Address</div>
|
||||
{{.metadata.LUD16 | escapeString}}
|
||||
{{.Metadata.LUD16}}
|
||||
</div>
|
||||
|
||||
{{ if not (eq 0 (len .AuthorRelays)) }}
|
||||
<div class="field">
|
||||
<div class="label">Posting on these relays</div>
|
||||
{{if .authorRelays}} {{range $index, $element := .authorRelays}}
|
||||
<a href="/r/{{$element | escapeString}}" class="button"
|
||||
>{{$element}}</a
|
||||
>
|
||||
{{end}} {{else}} No relays found, sorry! Try to reload to search
|
||||
again. {{end}}
|
||||
{{range $index, $element := .AuthorRelays}}
|
||||
<a href="/r/{{$element}}" class="button">{{$element}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="field advanced-switch-wrapper">
|
||||
<input
|
||||
@@ -119,29 +98,26 @@
|
||||
<label for="advanced-switch">Show more details</label>
|
||||
</div>
|
||||
|
||||
{{template "details.html" .}}
|
||||
{{template "details" .}}
|
||||
|
||||
<div class="field last_update">
|
||||
Last update:<br />
|
||||
{{.createdAt | escapeString}}
|
||||
{{.CreatedAt}}
|
||||
</div>
|
||||
|
||||
{{if not (eq 0 (len .LastNotes))}}
|
||||
<div class="field separator"></div>
|
||||
|
||||
{{if .lastNotes}}
|
||||
<nav class="field last_notes">
|
||||
<h2>Last Notes</h2>
|
||||
{{range .lastNotes}}
|
||||
<a href="/{{.Nevent | escapeString}}" class="note">
|
||||
{{range $i, $element := .LastNotes}}
|
||||
<a href="/{{.Nevent}}" class="note">
|
||||
<div class="header">
|
||||
<div class="published_at">{{.CreatedAt | escapeString}}</div>
|
||||
{{if not (eq .ParentNevent "")}}
|
||||
<div class="published_at">{{$element.CreatedAt}}</div>
|
||||
{{if $element.IsReply}}
|
||||
<div class="is_reply">- reply</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="content">
|
||||
{{.Content | escapeString | previewNotesFormatting}}
|
||||
</div>
|
||||
<div class="content">{{$element.Preview}}</div>
|
||||
</a>
|
||||
{{end}}
|
||||
</nav>
|
||||
@@ -150,14 +126,12 @@
|
||||
<div class="field separator"></div>
|
||||
</div>
|
||||
|
||||
{{template "column_clients.html" .}}
|
||||
{{template "clients" .ClientsPartial}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "footer.html"}}
|
||||
{{template "footer" .}}
|
||||
|
||||
<script>
|
||||
{{template "scripts.js"}}
|
||||
</script>
|
||||
<script src="/njump/static/scripts.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user