htdocs/main.go
2025-04-27 15:13:18 +02:00

279 lines
7.2 KiB
Go

package main
import (
"context"
"fmt"
"log"
"net/http"
"strings"
"time"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
)
// --- Your FetchNotesHTML() from earlier ---
func FetchNotesHTML(relayURL, npub string) (string, error) {
ctx := context.Background()
relay, err := nostr.RelayConnect(ctx, relayURL)
if err != nil {
return "", fmt.Errorf("relay connection failed: %w", err)
}
defer relay.Close()
var filters nostr.Filters
if _, v, err := nip19.Decode(npub); err == nil {
pub := v.(string)
filters = []nostr.Filter{{
Kinds: []int{nostr.KindTextNote},
Authors: []string{pub},
Limit: 3,
}}
} else {
return "", fmt.Errorf("npub decode failed: %w", err)
}
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
sub, err := relay.Subscribe(ctx, filters)
if err != nil {
return "", fmt.Errorf("subscribe failed: %w", err)
}
var builder strings.Builder
for ev := range sub.Events {
id, _ := nip19.EncodeNote(ev.ID)
pub, _ := nip19.EncodePublicKey(ev.PubKey)
t := time.Unix(int64(ev.CreatedAt), 0).UTC()
rfc3339 := t.Format(time.RFC3339)
content := ev.Content
builder.WriteString("<li>")
builder.WriteString("<div>")
builder.WriteString(fmt.Sprintf("<p><strong>ID:</strong> %s</p>", id))
builder.WriteString(fmt.Sprintf("<p><strong>Author:</strong> %s</p>", pub))
builder.WriteString(fmt.Sprintf("<p><strong>Created:</strong> %s</p>", rfc3339))
builder.WriteString(fmt.Sprintf("<p><strong>Content:</strong> %s</p>", content))
builder.WriteString("</div>")
builder.WriteString("</li>")
builder.WriteString("<hr>")
}
return builder.String(), nil
}
// --- Your static HTML template with a placeholder ---
const htmlTemplate = `
<!DOCTYPE html>
<html>
<head>
<title>despera.space</title>
<style>
html, body {
margin: 0;
padding: 0;
min-height: 100%;
}
body {
background-color: #000000; /* Black background */
color: #39ff14; /* Phosphor green text */
font-family: monospace;
overflow-y: auto; /* <-- Add this line */
}
a {
color: #39ff14; /* Match phosphor green */
text-decoration: none;
}
a:hover {
color: #80ff80; /* Slightly lighter green on hover */
text-decoration: underline;
}
h1 {
color: #39ff14;
margin-top: 30px;
font-size: 1.5em;
border-bottom: 1px solid #39ff14;
padding-bottom: 5px;
}
ul {
list-style-type: none;
padding-left: 0;
}
li {
margin-bottom: 10px;
}
hr {
border: 0;
height: 1px;
background-color: #39ff14;
margin: 20px 0;
}
/* Navigation Bar */
nav {
background-color: #000000;
border-bottom: 1px solid #39ff14;
padding: 10px;
display: flex;
justify-content: center;
gap: 20px;
position: sticky;
top: 0;
z-index: 9999;
}
nav a {
color: #39ff14;
font-weight: bold;
padding: 5px 10px;
border: 1px solid #39ff14;
border-radius: 2px;
transition: background 0.3s, color 0.3s;
}
nav a:hover {
background-color: #39ff14;
color: #000000;
}
/* Scanline overlay effect */
.scanlines {
position: relative;
}
.scanlines:before {
content: "";
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 2px;
z-index: 2147483649;
background: rgba(0, 255, 0, 0.3); /* Subtle green line */
opacity: 0.75;
pointer-events: none;
animation: scanline 2s linear infinite;
}
.scanlines:after {
content: "";
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 2147483648;
pointer-events: none;
background: linear-gradient(
to bottom,
transparent 50%,
rgba(0, 255, 0, 0.05) 51%
);
background-size: 100% 4px;
animation: scanlines 1s steps(60) infinite;
}
@keyframes scanline {
0% {
transform: translateY(-2px);
}
100% {
transform: translateY(100vh);
}
}
@keyframes scanlines {
0% {
background-position: 0 50%;
}
}
/* Main content padding */
.content {
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
</style>
</head>
<body class="scanlines">
<nav>
<a href="#ids">IDs</a>
<a href="#notes">Long Form Notes</a>
<a href="#other">Other Stuff</a>
<a href="#posts">Posts</a>
</nav>
<div class="content">
<h1 id="ids">IDs</h1>
<ul>
<li>NPUB: npub1nmk2399jazpsup0vsm6dzxw7gydzm5atedj4yhdkn3yx7jh7tzpq842975</li>
<li>NIP06: iru@ this domain</li>
<li>LNURL: iru@ this domain</li>
<li>GPG: 0DE8AAA9F5DA9CCB3F3F3B8E14566DCEC81EF576</li>
<li>Github: irusensei</li>
</ul>
<h1 id="notes">Long Form Notes</h1>
<ul>
<li>
Running popular AI software on Linux and AMD GPUs:
<a href="https://habla.news/a/naddr1qqxnzd3ex56rwvfexvurxwfjqgsfam9gjjew3qcwqhkgdax3r80yzx3d6w4uke2jtkmfcjr0ftl93qsrqsqqqa28vfwv5f">note</a>,
<a href="https://code.despera.space/iru/htdocs/src/branch/main/notes/AMD-AGI.md">local</a>
</li>
<li>
How I put NixOS on my UDM (trashcan model) router:
<a href="https://habla.news/a/naddr1qvzqqqr4gupzp8hv4z2t96yrpcz7eph56yvausg69hf6hjm92fwmd8zgda90ukyzqqxnzde3xccnyd3sxver2dfk5j9lzf">note</a>,
<a href="https://code.despera.space/iru/htdocs/src/branch/main/notes/UDM-NIXOS.md">local</a>
</li>
</ul>
<h1 id="other">Other Stuff</h1>
<ul>
<li>
<a href="https://code.despera.space/mirrors">I keep mirrors of repos I use or feel like having preserved</a>.
</li>
</ul>
<h1 id="posts">Posts</h1>
<ul>
{{POSTS}}
</ul>
</div>
</body>
</html>
`
// --- HTTP Handler ---
func handler(w http.ResponseWriter, r *http.Request) {
relayURL := "wss://relay.despera.space"
npub := "npub1nmk2399jazpsup0vsm6dzxw7gydzm5atedj4yhdkn3yx7jh7tzpq842975"
notesHTML, err := FetchNotesHTML(relayURL, npub)
if err != nil {
http.Error(w, fmt.Sprintf("failed to fetch notes: %v", err), http.StatusInternalServerError)
return
}
page := strings.Replace(htmlTemplate, "{{POSTS}}", notesHTML, 1)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, page)
}
// --- Main ---
func main() {
http.HandleFunc("/", handler)
fmt.Println("Serving on http://localhost:8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}