chore: add twt html formatting
This commit is contained in:
parent
ef65b115b7
commit
a7009dcb56
16
http-api.go
16
http-api.go
@ -194,16 +194,24 @@ func add(preamble lextwt.Comments, text string, v ...any) lextwt.Comments {
|
|||||||
}
|
}
|
||||||
return append(preamble, lextwt.NewComment("# "+text))
|
return append(preamble, lextwt.NewComment("# "+text))
|
||||||
}
|
}
|
||||||
|
func addKey(preamble lextwt.Comments, key, value string, v ...any) lextwt.Comments {
|
||||||
|
if len(v) > 0 {
|
||||||
|
value = fmt.Sprintf(value, v...)
|
||||||
|
}
|
||||||
|
comment := fmt.Sprintf("# %s = %s", key, value)
|
||||||
|
return append(preamble, lextwt.NewCommentValue(comment, key, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func mkPreamble(hostname, uri, path string, limit int, length, offset, end int64) lextwt.Comments {
|
func mkPreamble(hostname, uri, path string, limit int, length, offset, end int64) lextwt.Comments {
|
||||||
uri += path
|
uri += path
|
||||||
preamble := add(mkPreambleDocs(hostname), "twt range = 1 %d", end)
|
preamble := addKey(mkPreambleDocs(hostname), "twt range", "1 %d", end)
|
||||||
preamble = add(preamble, "self = %s%s", hostname, mkqry(uri, limit, offset))
|
preamble = addKey(preamble, "self", "%s%s", hostname, mkqry(uri, limit, offset))
|
||||||
if next := offset + length; next < end {
|
if next := offset + length; next < end {
|
||||||
preamble = add(preamble, "next = %s%s", hostname, mkqry(uri, limit, next))
|
preamble = addKey(preamble, "next", "%s%s", hostname, mkqry(uri, limit, next))
|
||||||
}
|
}
|
||||||
if prev := offset - int64(limit); prev > 0 {
|
if prev := offset - int64(limit); prev > 0 {
|
||||||
preamble = add(preamble, "prev = %s%s", hostname, mkqry(uri, limit, prev))
|
preamble = addKey(preamble, "prev", "%s%s", hostname, mkqry(uri, limit, prev))
|
||||||
}
|
}
|
||||||
return preamble
|
return preamble
|
||||||
}
|
}
|
||||||
|
160
http-html.go
160
http-html.go
@ -1,9 +1,17 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"go.sour.is/xt/internal/otel"
|
"go.sour.is/xt/internal/otel"
|
||||||
|
"go.yarn.social/lextwt"
|
||||||
|
"go.yarn.social/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HTML struct {
|
type HTML struct {
|
||||||
@ -21,10 +29,156 @@ func (a *HTML) healthcheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *HTML) home(w http.ResponseWriter, r *http.Request) {
|
func (a *HTML) home(w http.ResponseWriter, r *http.Request) {
|
||||||
_, span := otel.Span(r.Context())
|
ctx, span := otel.Span(r.Context())
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
w.Write([]byte("ok"))
|
|
||||||
|
uri := r.URL.Query().Get("uri")
|
||||||
|
|
||||||
|
limit := 100
|
||||||
|
if v, ok := strconv.Atoi(r.URL.Query().Get("limit")); ok == nil {
|
||||||
|
limit = v
|
||||||
|
}
|
||||||
|
limit = min(100, max(1, limit))
|
||||||
|
|
||||||
|
var offset int64 = 0
|
||||||
|
if v, ok := strconv.ParseInt(r.URL.Query().Get("offset"), 10, 64); ok == nil {
|
||||||
|
offset = v
|
||||||
|
}
|
||||||
|
|
||||||
|
twts, offset, end, err := fetchTwts(ctx, a.db, uri, limit, offset)
|
||||||
|
span.RecordError(err)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "ERR", 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
preamble := mkPreamble(a.hostname, uri, "", limit, int64(len(twts)), offset, end)
|
||||||
|
|
||||||
|
reg := &HTWriter{
|
||||||
|
lextwt.NewTwtRegistry(preamble, twts),
|
||||||
|
}
|
||||||
|
|
||||||
|
reg.WriteTo(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type reg interface {
|
||||||
|
Preamble() lextwt.Comments
|
||||||
|
Twts() types.Twts
|
||||||
|
}
|
||||||
|
|
||||||
|
type HTWriter struct {
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *HTWriter) WriteTo(w io.Writer) (int64, error) {
|
||||||
|
var output int64
|
||||||
|
i, err := fmt.Fprintln(w, `<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>The Watcher</title>
|
||||||
|
<style>
|
||||||
|
body { width: 70%; margin: auto; background: black; color: white; }
|
||||||
|
a { color: cornflowerblue; text-decoration: none; }
|
||||||
|
main { }
|
||||||
|
pre.preamble { color: green; }
|
||||||
|
article { border: 1px solid green; border-radius: 4px; padding: 4px; margin: 2px; }
|
||||||
|
.h-card { columns: 2; }
|
||||||
|
.h-card .author { display: flex; }
|
||||||
|
.h-card .icon { width: 36px; margin: 4px; }
|
||||||
|
.h-card .u-photo { width: 32px; }
|
||||||
|
.h-card .date { text-align: right;}
|
||||||
|
section { overflow: scroll; }
|
||||||
|
</style
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre class='preamble'>
|
||||||
|
`)
|
||||||
|
output += int64(i)
|
||||||
|
if err != nil {
|
||||||
|
return output, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range r.Preamble() {
|
||||||
|
if key := c.Key(); key != "" {
|
||||||
|
value := mkValue(c.Value())
|
||||||
|
i, err = fmt.Fprintf(w, "# %s = %s\n", key, value)
|
||||||
|
} else {
|
||||||
|
i, err = fmt.Fprintln(w, c.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
output += int64(i)
|
||||||
|
if err != nil {
|
||||||
|
return output, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i, err = fmt.Fprintln(w, "</pre><main>")
|
||||||
|
output += int64(i)
|
||||||
|
|
||||||
|
for _, twt := range r.Twts() {
|
||||||
|
twter := twt.Twter()
|
||||||
|
uri, err := url.Parse(twter.URI)
|
||||||
|
if err != nil {
|
||||||
|
uri = &url.URL{
|
||||||
|
Scheme: "HTTPS",
|
||||||
|
Host: "unknown.txt",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i, err = fmt.Fprintf(w, `
|
||||||
|
<article>
|
||||||
|
<header class="u-author h-card">
|
||||||
|
<div class="author">
|
||||||
|
<div class="icon">
|
||||||
|
<a href="%s" class="u-url">
|
||||||
|
<img class="avatar u-photo" src="%s" alt="" loading="lazy">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="author-name">
|
||||||
|
<div class="p-name">
|
||||||
|
<a href="%s">%s</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-org">
|
||||||
|
<a target="_blank" href="%s">%s</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="date">
|
||||||
|
<div><a class="u-url" href="%s">%s</a></div>
|
||||||
|
<div><small>%s</small></div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<section>
|
||||||
|
<pre>%M</pre>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
`, "/?uri="+twter.URI, "https://txt.sour.is/user/xuu/avatar",
|
||||||
|
"/?uri="+twter.URI, twter.Nick,
|
||||||
|
twter.URI, uri.Host,
|
||||||
|
"/conv/"+twt.Hash(), fmt.Sprintf("<time datetime='%s'>%s</time>", twt.Created().Format(time.RFC3339), twt.Created().Format(time.RFC822)),
|
||||||
|
time.Since(twt.Created()).Round(time.Second).String(), twt,
|
||||||
|
)
|
||||||
|
output += int64(i)
|
||||||
|
if err != nil {
|
||||||
|
return output, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
i, err = fmt.Fprintln(w, "</main></body>")
|
||||||
|
output += int64(i)
|
||||||
|
|
||||||
|
return output, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func mkValue(v string) string {
|
||||||
|
if strings.HasPrefix(v, "http") {
|
||||||
|
return fmt.Sprintf(`<a href="%s">%s</a>`, v, v)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user