package api import ( "context" "encoding/json" "log/slog" "net/http" "nonsense-time/util" "os" "strconv" "time" "github.com/docker/docker/pkg/stdcopy" ) type ServerStatus struct { Online bool `json:"online"` Site string `json:"url"` Timestamp time.Time `json:"timestamp"` } var Logger *slog.Logger const VTT_URL string = "https://dnd.jpappel.xyz/foundry" func remoteOnline(ctx context.Context, url string) ServerStatus { status := ServerStatus{Site: url, Timestamp: time.Now()} req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { panic(err) } _, err = http.DefaultClient.Do(req) if err != nil { status.Online = false } else { status.Online = true } return status } func respondOnline(w http.ResponseWriter, status ServerStatus) { jsonData, err := json.Marshal(status) if err != nil { http.Error(w, "Error constructing response", http.StatusInternalServerError) Logger.Error("Error marshalling site status data", slog.Any("err", err)) return } w.Header().Set("Content-Type", "application/json") w.Write(jsonData) } func VttOnline(w http.ResponseWriter, req *http.Request) { status := vttStatus(req.Context()) if !status.Online { Logger.DebugContext(req.Context(), "Foundry VTT is offline") } respondOnline(w, status) } func VttRedirect(w http.ResponseWriter, req *http.Request) { http.Redirect(w, req, VTT_URL, http.StatusMovedPermanently) } func VttLogs(w http.ResponseWriter, req *http.Request) { var lines uint = 0 linesParam := req.URL.Query().Get("lines") if linesParam != "" { lines_64, err := strconv.ParseUint(linesParam, 10, 0) if err != nil { Logger.ErrorContext(req.Context(), "Invalid line count in vtt logs request", slog.Any("err", err)) http.Error(w, "Invalid line count in request", http.StatusBadRequest) return } lines = uint(lines_64) } logReader, err := vttLogs(req.Context(), lines) if err != nil { http.Error(w, "Error occured while getting logs", http.StatusInternalServerError) return } defer logReader.Close() filteredWriter := util.NewAnsiFilterWriter(w) n, err := stdcopy.StdCopy(filteredWriter, filteredWriter, logReader) if err != nil { Logger.Error("Error occured while writting logs to response", slog.Any("err", err), slog.Any("request", req)) Logger.Error("", slog.Int64("written", n)) http.Error(w, "Error occured while writting logs", http.StatusInternalServerError) return } } func init() { Logger = slog.New(slog.NewTextHandler(os.Stdout, nil)) }