111 lines
3.1 KiB
Go
111 lines
3.1 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"html/template"
|
|
"net/http"
|
|
|
|
webui "jukebox_maker/web"
|
|
|
|
"jukebox_maker/internal/config"
|
|
"jukebox_maker/internal/copier"
|
|
"jukebox_maker/internal/task"
|
|
"jukebox_maker/internal/watcher"
|
|
)
|
|
|
|
type Deps struct {
|
|
Config *config.Config
|
|
ConfigPath string
|
|
Version string
|
|
Watcher *watcher.Watcher
|
|
Copier *copier.Copier
|
|
Tasks *task.Store
|
|
MediaPath string
|
|
MountPath string
|
|
// OnDiskInit вызывается при ручной инициализации диска через UI.
|
|
OnDiskInit func(mountPath, diskID string)
|
|
}
|
|
|
|
type Server struct {
|
|
deps Deps
|
|
dashboard *template.Template
|
|
settings *template.Template
|
|
mux *http.ServeMux
|
|
}
|
|
|
|
func New(deps Deps) (*Server, error) {
|
|
dash, err := template.ParseFS(webui.FS, "templates/layout.html", "templates/dashboard.html")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sett, err := template.ParseFS(webui.FS, "templates/layout.html", "templates/settings.html")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s := &Server{deps: deps, dashboard: dash, settings: sett, mux: http.NewServeMux()}
|
|
s.routes()
|
|
return s, nil
|
|
}
|
|
|
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
s.mux.ServeHTTP(w, r)
|
|
}
|
|
|
|
func (s *Server) routes() {
|
|
s.mux.Handle("GET /static/", http.FileServerFS(webui.FS))
|
|
|
|
s.mux.HandleFunc("GET /", s.handleDashboard)
|
|
s.mux.HandleFunc("GET /settings", s.handleSettings)
|
|
|
|
s.mux.HandleFunc("GET /health", s.handleHealth)
|
|
s.mux.HandleFunc("GET /api/disks", s.handleDiskStatus)
|
|
s.mux.HandleFunc("POST /api/disks/init", s.handleDiskInit)
|
|
s.mux.HandleFunc("GET /api/sources", s.handleSources)
|
|
s.mux.HandleFunc("GET /api/config", s.handleGetConfig)
|
|
s.mux.HandleFunc("PUT /api/config", s.handlePutConfig)
|
|
s.mux.HandleFunc("POST /api/disks/{diskID}/copy/start", s.handleCopyStart)
|
|
s.mux.HandleFunc("POST /api/disks/{diskID}/copy/cancel", s.handleCopyCancel)
|
|
s.mux.HandleFunc("GET /api/tasks/{id}", s.handleTaskGet)
|
|
}
|
|
|
|
func (s *Server) handleDashboard(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/" {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
s.render(w, s.dashboard, map[string]any{"Title": "Dashboard", "Page": "dashboard"})
|
|
}
|
|
|
|
func (s *Server) handleSettings(w http.ResponseWriter, r *http.Request) {
|
|
s.render(w, s.settings, map[string]any{"Title": "Settings", "Page": "settings"})
|
|
}
|
|
|
|
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
|
|
jsonOK(w, map[string]string{"status": "ok"})
|
|
}
|
|
|
|
func (s *Server) render(w http.ResponseWriter, tmpl *template.Template, data any) {
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
payload := map[string]any{"Version": s.deps.Version}
|
|
if incoming, ok := data.(map[string]any); ok {
|
|
for k, v := range incoming {
|
|
payload[k] = v
|
|
}
|
|
}
|
|
if err := tmpl.ExecuteTemplate(w, "layout", payload); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
func jsonOK(w http.ResponseWriter, v any) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(v)
|
|
}
|
|
|
|
func jsonErr(w http.ResponseWriter, code int, msg string) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(code)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": msg})
|
|
}
|