repos
/ orchard main

orchard

mirror

Every site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.

blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics

1.7 KB · 59 lines · Go Raw History
 1package main
 2
 3import (
 4	"encoding/json"
 5	"net/http"
 6	"strconv"
 7
 8	"chat.bythewood.me/tools"
 9)
10
11// The page fetches a widget's readings here rather than being handed them with
12// the turn. That is what lets a chart change range without asking the model
13// anything, and what makes a conversation opened a week later draw today's
14// price instead of the one that was on screen when the question was asked.
15
16// Widget is the subject of a chart, recorded on the message that produced it.
17type Widget = tools.Widget
18
19func (s *site) widgetTicker(w http.ResponseWriter, r *http.Request) {
20	sym := r.URL.Query().Get("symbol")
21	if sym == "" {
22		http.Error(w, "symbol is required", 400)
23		return
24	}
25	series, err := tools.Ticker(r.Context(), s.engine.Deps(), sym, r.URL.Query().Get("range"))
26	if err != nil {
27		widgetErr(w, err)
28		return
29	}
30	writeJSON(w, series)
31}
32
33func (s *site) widgetWeather(w http.ResponseWriter, r *http.Request) {
34	q := r.URL.Query()
35	lat, err1 := strconv.ParseFloat(q.Get("lat"), 64)
36	lon, err2 := strconv.ParseFloat(q.Get("lon"), 64)
37	if err1 != nil || err2 != nil {
38		http.Error(w, "lat and lon are required", 400)
39		return
40	}
41	days, _ := strconv.Atoi(q.Get("days"))
42	rep, err := tools.Forecast(r.Context(), s.engine.Deps(), lat, lon,
43		q.Get("place"), q.Get("zip"), q.Get("country"), days)
44	if err != nil {
45		widgetErr(w, err)
46		return
47	}
48	writeJSON(w, rep)
49}
50
51// widgetErr answers with the reason rather than a bare status, because the
52// panel prints it: a rate limited host and a symbol that does not exist read
53// identically as a blank chart otherwise.
54func widgetErr(w http.ResponseWriter, err error) {
55	w.Header().Set("Content-Type", "application/json")
56	w.WriteHeader(http.StatusBadGateway)
57	_ = json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
58}