%M+
diff --git a/http-api.go b/http-api.go index 401a9c3..7f3335e 100644 --- a/http-api.go +++ b/http-api.go @@ -194,16 +194,24 @@ func add(preamble lextwt.Comments, text string, v ...any) lextwt.Comments { } 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 { uri += path - preamble := add(mkPreambleDocs(hostname), "twt range = 1 %d", end) - preamble = add(preamble, "self = %s%s", hostname, mkqry(uri, limit, offset)) + preamble := addKey(mkPreambleDocs(hostname), "twt range", "1 %d", end) + preamble = addKey(preamble, "self", "%s%s", hostname, mkqry(uri, limit, offset)) 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 { - preamble = add(preamble, "prev = %s%s", hostname, mkqry(uri, limit, prev)) + preamble = addKey(preamble, "prev", "%s%s", hostname, mkqry(uri, limit, prev)) } return preamble } diff --git a/http-html.go b/http-html.go index 3a4929f..dbe5bc3 100644 --- a/http-html.go +++ b/http-html.go @@ -1,9 +1,17 @@ package main import ( + "fmt" + "io" "net/http" + "net/url" + "strconv" + "strings" + "time" "go.sour.is/xt/internal/otel" + "go.yarn.social/lextwt" + "go.yarn.social/types" ) 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) { - _, span := otel.Span(r.Context()) + ctx, span := otel.Span(r.Context()) defer span.End() - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - w.Write([]byte("ok")) + w.Header().Set("Content-Type", "text/html; charset=utf-8") + + 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, ` + +
++ `) + 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, "
%M+