// Package server exposes a read-only HTTP status endpoint for the daemon: // the live encode progress, the pending input queue, and recent log events. package server import ( _ "embed" "encoding/json" "net/http" "path/filepath" "av1dae/internal/logger" "av1dae/internal/status" "av1dae/internal/watcher" ) //go:embed index.html var indexHTML []byte type Server struct { tracker *status.Tracker log *logger.Logger inputDir string } func New(tracker *status.Tracker, log *logger.Logger, inputDir string) *Server { return &Server{tracker: tracker, log: log, inputDir: inputDir} } // Handler returns the mux for all status routes. Phase 3 adds "/" (the HTML // dashboard) to this same mux. func (s *Server) Handler() http.Handler { mux := http.NewServeMux() mux.HandleFunc("/status", s.handleStatus) mux.HandleFunc("/", s.handleIndex) return mux } func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } w.Header().Set("Content-Type", "text/html; charset=utf-8") _, _ = w.Write(indexHTML) } type statusResponse struct { Current status.Snapshot `json:"current"` Queue []string `json:"queue"` Recent []logger.LogEntry `json:"recent"` } func (s *Server) handleStatus(w http.ResponseWriter, r *http.Request) { queue := []string{} for _, f := range watcher.InputFiles(s.inputDir) { queue = append(queue, filepath.Base(f)) } recent, err := s.log.RecentLogs(50) if err != nil { http.Error(w, "reading logs", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(statusResponse{ Current: s.tracker.Snapshot(), Queue: queue, Recent: recent, }) }