mirror of
https://github.com/aljazceru/njump.git
synced 2025-12-17 14:24:27 +01:00
initial broken draft of relays page.
This commit is contained in:
38
main.go
38
main.go
@@ -1,16 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"html"
|
||||
"net/http"
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var log = zerolog.New(os.Stderr).Output(zerolog.ConsoleWriter{Out: os.Stdout}).
|
||||
With().Timestamp().Logger()
|
||||
//go:embed static/*
|
||||
var static embed.FS
|
||||
|
||||
//go:embed templates/*
|
||||
var templates embed.FS
|
||||
|
||||
var (
|
||||
tmpl *template.Template
|
||||
templateMapping = make(map[string]string)
|
||||
|
||||
log = zerolog.New(os.Stderr).Output(zerolog.ConsoleWriter{Out: os.Stdout}).With().Timestamp().Logger()
|
||||
)
|
||||
|
||||
func main() {
|
||||
// initialize templates
|
||||
// use a mapping to expressly link the templates and share them between more kinds/types
|
||||
templateMapping["profile"] = "profile.html"
|
||||
templateMapping["note"] = "note.html"
|
||||
templateMapping["address"] = "other.html"
|
||||
templateMapping["relay"] = "relay.html"
|
||||
|
||||
funcMap := template.FuncMap{
|
||||
"basicFormatting": basicFormatting,
|
||||
"mdToHTML": mdToHTML,
|
||||
"escapeString": html.EscapeString,
|
||||
"sanitizeXSS": sanitizeXSS,
|
||||
}
|
||||
|
||||
tmpl = template.Must(
|
||||
template.New("tmpl").
|
||||
Funcs(funcMap).
|
||||
ParseFS(templates, "templates/*"),
|
||||
)
|
||||
|
||||
// routes
|
||||
http.HandleFunc("/njump/image/", generate)
|
||||
http.HandleFunc("/njump/proxy/", proxy)
|
||||
http.Handle("/njump/static/", http.StripPrefix("/njump/", http.FileServer(http.FS(static))))
|
||||
|
||||
37
render.go
37
render.go
@@ -2,27 +2,18 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
)
|
||||
|
||||
//go:embed static/*
|
||||
var static embed.FS
|
||||
|
||||
//go:embed templates/*
|
||||
var templates embed.FS
|
||||
|
||||
type Event struct {
|
||||
Nevent string
|
||||
Content string
|
||||
@@ -50,8 +41,15 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
hostname := r.Header.Get("X-Forwarded-Host")
|
||||
style := getPreviewStyle(r)
|
||||
|
||||
// code can be a nevent, nprofile, npub or nip05 identifier, in which case we try to fetch the associated event
|
||||
event, err := getEvent(r.Context(), code)
|
||||
if err != nil {
|
||||
// this will fail if code is a relay URL, in which case we will handle it differently
|
||||
if urlMatcher.MatchString(code) {
|
||||
renderRelayPage(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
http.Error(w, "error fetching event: "+err.Error(), 404)
|
||||
return
|
||||
}
|
||||
@@ -275,30 +273,11 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
"parentNevent": parentNevent,
|
||||
}
|
||||
|
||||
// Use a mapping to expressly link the templates and share them between more kinds/types
|
||||
templateMapping := make(map[string]string)
|
||||
templateMapping["profile"] = "profile.html"
|
||||
templateMapping["note"] = "note.html"
|
||||
templateMapping["address"] = "other.html"
|
||||
|
||||
// If a mapping is not found fallback to raw
|
||||
// if a mapping is not found fallback to raw
|
||||
if templateMapping[typ] == "" {
|
||||
templateMapping[typ] = "other.html"
|
||||
}
|
||||
|
||||
funcMap := template.FuncMap{
|
||||
"basicFormatting": basicFormatting,
|
||||
"mdToHTML": mdToHTML,
|
||||
"escapeString": html.EscapeString,
|
||||
"sanitizeXSS": sanitizeXSS,
|
||||
}
|
||||
|
||||
tmpl := template.Must(
|
||||
template.New("tmpl").
|
||||
Funcs(funcMap).
|
||||
ParseFS(templates, "templates/*"),
|
||||
)
|
||||
|
||||
w.Header().Set("Cache-Control", "max-age=604800")
|
||||
if err := tmpl.ExecuteTemplate(w, templateMapping[typ], params); err != nil {
|
||||
log.Error().Err(err).Msg("error rendering")
|
||||
|
||||
75
render_relay.go
Normal file
75
render_relay.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip11"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
)
|
||||
|
||||
func renderRelayPage(w http.ResponseWriter, r *http.Request) {
|
||||
code := r.URL.Path[1:]
|
||||
|
||||
hostname := code
|
||||
if strings.HasPrefix(code, "wss://") {
|
||||
hostname = code[6:]
|
||||
}
|
||||
if strings.HasPrefix(code, "ws://") {
|
||||
hostname = code[5:]
|
||||
}
|
||||
|
||||
fmt.Println("hostname", hostname)
|
||||
|
||||
ctx, cancel := context.WithTimeout(r.Context(), time.Second*5)
|
||||
defer cancel()
|
||||
|
||||
// relay metadata
|
||||
info, _ := nip11.Fetch(r.Context(), code)
|
||||
if info == nil {
|
||||
info = &nip11.RelayInformationDocument{
|
||||
Name: hostname,
|
||||
}
|
||||
}
|
||||
|
||||
// last notes
|
||||
var lastNotes []*nostr.Event
|
||||
if relay, err := pool.EnsureRelay(code); err == nil {
|
||||
lastNotes, _ = relay.QuerySync(ctx, nostr.Filter{
|
||||
Kinds: []int{1},
|
||||
Limit: 50,
|
||||
})
|
||||
}
|
||||
renderableLastNotes := make([]*Event, len(lastNotes))
|
||||
for i, n := range lastNotes {
|
||||
nevent, _ := nip19.EncodeEvent(n.ID, []string{}, n.PubKey)
|
||||
date := time.Unix(int64(n.CreatedAt), 0).Format("2006-01-02 15:04:05")
|
||||
renderableLastNotes[i] = &Event{
|
||||
Nevent: nevent,
|
||||
Content: n.Content,
|
||||
CreatedAt: date,
|
||||
ParentNevent: getParentNevent(n),
|
||||
}
|
||||
}
|
||||
|
||||
params := map[string]any{
|
||||
"clients": []ClientReference{
|
||||
{Name: "Coracle", URL: "https://coracle.social/relays/" + hostname},
|
||||
},
|
||||
"type": "relay",
|
||||
"info": info,
|
||||
"hostname": hostname,
|
||||
"proxy": "https://" + hostname + "/njump/proxy?src=",
|
||||
"lastNotes": renderableLastNotes,
|
||||
}
|
||||
|
||||
w.Header().Set("Cache-Control", "max-age=604800")
|
||||
if err := tmpl.ExecuteTemplate(w, templateMapping["relay"], params); err != nil {
|
||||
log.Error().Err(err).Msg("error rendering")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -55,8 +55,12 @@
|
||||
<title>Nostr Address {{.naddr | escapeString }}</title>
|
||||
{{end}}
|
||||
<!----------->
|
||||
{{ if eq .type "relay" }}
|
||||
<title>Nostr Relay {{.hostname}}</title>
|
||||
{{end}}
|
||||
<!----------->
|
||||
{{ if eq .type "other" }}
|
||||
<title>Nostr Event {{.kindID }} - {{.kindDescription | escapeString }}</title>
|
||||
<title>Nostr Event {{.kindID}} - {{.kindDescription | escapeString }}</title>
|
||||
{{end}}
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
|
||||
<div class="field separator"></div>
|
||||
|
||||
{{if .lastNotes}}
|
||||
<div class="field last_notes">
|
||||
<h2>Last Notes</h2>
|
||||
{{range .lastNotes}}
|
||||
@@ -75,8 +76,8 @@
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="field separator"></div>
|
||||
{{end}}
|
||||
|
||||
<div class="field advanced-switch-wrapper">
|
||||
<input
|
||||
|
||||
46
templates/relay.html
Normal file
46
templates/relay.html
Normal file
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="theme--default">
|
||||
<meta charset="UTF-8" />
|
||||
{{template "head.html" .}}
|
||||
|
||||
<body class="profile">
|
||||
{{template "top.html" .}}
|
||||
|
||||
<div class="container_wrapper">
|
||||
<div class="container">
|
||||
<div class="column columnA">
|
||||
<div class="info-wrapper">
|
||||
{{.info.Name | escapeString}}
|
||||
<span class="display">{{.info.Description | escapeString}}</span>
|
||||
</div>
|
||||
<div class="pic-wrapper">
|
||||
<img class="pic" src="{{.info.Icon | escapeString}}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column column_content">
|
||||
<div class="field last_notes">
|
||||
<h2>Last Notes</h2>
|
||||
{{range .lastNotes}}
|
||||
<a href="/{{.Nevent | escapeString}}" class="note">
|
||||
<div class="published_at">{{.CreatedAt | escapeString}}</div>
|
||||
{{if not (eq .ParentNevent "")}}
|
||||
<div class="is_reply">- reply</div>
|
||||
{{end}}
|
||||
<div class="content">{{.Content | escapeString}}</div>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "column_clients.html" .}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "footer.html"}}
|
||||
|
||||
<script>
|
||||
{{template "scripts.js"}}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user