278 lines
6.8 KiB
Go
278 lines
6.8 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/fujin/music-agregator/internal/services"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func (h *Handlers) ListQueue(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
var status *string
|
|
if s := r.URL.Query().Get("status"); s != "" {
|
|
status = &s
|
|
}
|
|
|
|
items, err := h.DB.ListDownloadQueue(r.Context(), status)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]any{
|
|
"items": items,
|
|
"total": len(items),
|
|
})
|
|
}
|
|
|
|
func (h *Handlers) GetQueueItem(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := parseUUID(idStr)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid ID")
|
|
return
|
|
}
|
|
|
|
item, err := h.DB.GetDownloadQueueItem(r.Context(), id)
|
|
if err != nil {
|
|
writeError(w, http.StatusNotFound, "queue item not found")
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, item)
|
|
}
|
|
|
|
func (h *Handlers) AddToQueue(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
Title string `json:"title"`
|
|
TorrentHash *string `json:"torrent_hash"`
|
|
Size int64 `json:"size"`
|
|
Indexer *string `json:"indexer"`
|
|
AlbumID *string `json:"album_id"`
|
|
ArtistID *string `json:"artist_id"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid request body")
|
|
return
|
|
}
|
|
|
|
var albumID, artistID *uuid.UUID
|
|
if req.AlbumID != nil {
|
|
if id, err := parseUUID(*req.AlbumID); err == nil {
|
|
albumID = &id
|
|
}
|
|
}
|
|
if req.ArtistID != nil {
|
|
if id, err := parseUUID(*req.ArtistID); err == nil {
|
|
artistID = &id
|
|
}
|
|
}
|
|
|
|
id, err := h.DB.AddToDownloadQueue(r.Context(), req.Title, req.Size, req.TorrentHash, req.Indexer, albumID, artistID)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
item, _ := h.DB.GetDownloadQueueItem(r.Context(), id)
|
|
writeJSON(w, http.StatusOK, item)
|
|
}
|
|
|
|
func (h *Handlers) UpdateQueueItem(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := parseUUID(idStr)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid ID")
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
Status *string `json:"status"`
|
|
ErrorMessage *string `json:"error_message"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid request body")
|
|
return
|
|
}
|
|
|
|
if req.Status != nil {
|
|
if *req.Status == "failed" && req.ErrorMessage != nil {
|
|
services.HandleFailedDownload(r.Context(), h.DB, id, *req.ErrorMessage)
|
|
} else {
|
|
if err := h.DB.UpdateDownloadQueueStatus(r.Context(), id, *req.Status, req.ErrorMessage); err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
if *req.Status == "completed" {
|
|
item, _ := h.DB.GetDownloadQueueItem(r.Context(), id)
|
|
if item != nil && item.AlbumID != nil {
|
|
h.DB.RemoveFromWantedAlbums(r.Context(), *item.AlbumID)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
item, err := h.DB.GetDownloadQueueItem(r.Context(), id)
|
|
if err != nil {
|
|
writeError(w, http.StatusNotFound, "queue item not found")
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, item)
|
|
}
|
|
|
|
func (h *Handlers) DeleteQueueItem(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := parseUUID(idStr)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid ID")
|
|
return
|
|
}
|
|
|
|
item, err := h.DB.GetDownloadQueueItem(r.Context(), id)
|
|
if err != nil {
|
|
writeError(w, http.StatusNotFound, "queue item not found")
|
|
return
|
|
}
|
|
|
|
if item.TorrentHash != nil && h.TorrentService.IsConfigured() {
|
|
h.TorrentService.RemoveTorrent(r.Context(), *item.TorrentHash, false)
|
|
}
|
|
|
|
if err := h.DB.DeleteDownloadQueueItem(r.Context(), id); err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]any{"deleted": true})
|
|
}
|
|
|
|
func (h *Handlers) SyncQueue(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
result, err := services.SyncDownloadQueue(r.Context(), h.DB, h.TorrentService)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, result)
|
|
}
|
|
|
|
func (h *Handlers) BlocklistQueueItem(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := parseUUID(idStr)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid ID")
|
|
return
|
|
}
|
|
|
|
result, err := services.BlocklistAndRemove(r.Context(), h.DB, h.TorrentService, id)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, result)
|
|
}
|
|
|
|
func (h *Handlers) QueueStats(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
stats, err := h.DB.GetDownloadQueueStats(r.Context())
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, stats)
|
|
}
|
|
|
|
func (h *Handlers) GetJobStatus(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := parseUUID(idStr)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid job ID")
|
|
return
|
|
}
|
|
|
|
status, err := services.GetJobStatus(r.Context(), h.DB, h.TorrentService, id)
|
|
if err != nil {
|
|
writeError(w, http.StatusNotFound, "job not found")
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, status)
|
|
}
|
|
|
|
func (h *Handlers) ImportQueueItem(w http.ResponseWriter, r *http.Request) {
|
|
if h.DB == nil {
|
|
writeError(w, http.StatusServiceUnavailable, "database not connected")
|
|
return
|
|
}
|
|
|
|
if h.StorageBasePath == "" {
|
|
writeError(w, http.StatusServiceUnavailable, "storage not configured")
|
|
return
|
|
}
|
|
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := parseUUID(idStr)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid ID")
|
|
return
|
|
}
|
|
|
|
result, err := services.ImportCompletedDownload(r.Context(), id, h.StorageBasePath, h.DB, h.TorrentService)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, result)
|
|
}
|