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, ` + + + The Watcher + + +
+	`)
+	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, "
") + 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, ` +
+
+
+
+ + + +
+ +
+
+ %s +
+ +
+ %s +
+
+
+ +
+
%s
+
%s
+
+
+
+
%M
+
+ +
+ `, "/?uri="+twter.URI, "https://txt.sour.is/user/xuu/avatar", + "/?uri="+twter.URI, twter.Nick, + twter.URI, uri.Host, + "/conv/"+twt.Hash(), fmt.Sprintf("", 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, "
") + output += int64(i) + + return output, err +} + +func mkValue(v string) string { + if strings.HasPrefix(v, "http") { + return fmt.Sprintf(`%s`, v, v) + } + return v +}