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