package api import ( "encoding/json" "net/http" "time" "jukebox_maker/internal/disk" ) func (s *Server) handleDiskStatus(w http.ResponseWriter, r *http.Request) { type response struct { State disk.DiskState `json:"state"` DiskID string `json:"disk_id"` TotalBytes int64 `json:"total_bytes"` FreeBytes int64 `json:"free_bytes"` MountPath string `json:"mount_path"` LastCopiedAt string `json:"last_copied_at,omitempty"` ActiveTaskID string `json:"active_task_id,omitempty"` } disks := s.deps.Watcher.ListDisks() resp := make([]response, 0, len(disks)) for _, info := range disks { item := response{ State: info.State, DiskID: info.DiskID, TotalBytes: info.TotalBytes, FreeBytes: info.FreeBytes, MountPath: info.MountPath, } if info.DiskID != "" { if lastCopiedAt, ok, err := s.deps.Copier.LastCopiedAt(info.DiskID); err == nil && ok { item.LastCopiedAt = lastCopiedAt.Format(time.RFC3339) } if t, ok := s.deps.Tasks.ActiveTaskByDisk(info.DiskID); ok { item.ActiveTaskID = t.ID } } resp = append(resp, item) } jsonOK(w, map[string]any{"items": resp}) } func (s *Server) handleDiskInit(w http.ResponseWriter, r *http.Request) { var req struct { MountPath string `json:"mount_path"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { jsonErr(w, http.StatusBadRequest, "invalid JSON: "+err.Error()) return } info, ok := s.deps.Watcher.DiskByMountPath(req.MountPath) if !ok { jsonErr(w, http.StatusNotFound, "disk not found") return } if info.State == disk.DiskAbsent { jsonErr(w, http.StatusUnprocessableEntity, "no disk connected") return } if info.State == disk.DiskKnown { jsonErr(w, http.StatusConflict, "disk already initialized") return } diskID, err := disk.InitDisk(info.MountPath) if err != nil { jsonErr(w, http.StatusInternalServerError, "init disk: "+err.Error()) return } s.deps.OnDiskInit(info.MountPath, diskID) s.deps.Watcher.ProbeNow() jsonOK(w, map[string]string{"disk_id": diskID}) }