mirror of
https://github.com/navidrome/navidrome.git
synced 2025-08-10 00:52:20 +00:00
* Add migration converting playqueue current to index * refactor Signed-off-by: Deluan <deluan@navidrome.org> * fix(queue): ensure valid current index and improve test coverage Signed-off-by: Deluan <deluan@navidrome.org> --------- Signed-off-by: Deluan <deluan@navidrome.org>
77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package nativeapi
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
|
|
"github.com/navidrome/navidrome/log"
|
|
"github.com/navidrome/navidrome/model"
|
|
"github.com/navidrome/navidrome/model/request"
|
|
"github.com/navidrome/navidrome/utils/slice"
|
|
)
|
|
|
|
type queuePayload struct {
|
|
Ids []string `json:"ids"`
|
|
Current int `json:"current"`
|
|
Position int64 `json:"position"`
|
|
}
|
|
|
|
func getQueue(ds model.DataStore) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
user, _ := request.UserFrom(ctx)
|
|
repo := ds.PlayQueue(ctx)
|
|
pq, err := repo.Retrieve(user.ID)
|
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
|
log.Error(ctx, "Error retrieving queue", err)
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if pq == nil {
|
|
pq = &model.PlayQueue{}
|
|
}
|
|
resp, err := json.Marshal(pq)
|
|
if err != nil {
|
|
log.Error(ctx, "Error marshalling queue", err)
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write(resp)
|
|
}
|
|
}
|
|
|
|
func saveQueue(ds model.DataStore) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
var payload queuePayload
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
user, _ := request.UserFrom(ctx)
|
|
client, _ := request.ClientFrom(ctx)
|
|
items := slice.Map(payload.Ids, func(id string) model.MediaFile {
|
|
return model.MediaFile{ID: id}
|
|
})
|
|
if len(payload.Ids) > 0 && (payload.Current < 0 || payload.Current >= len(payload.Ids)) {
|
|
http.Error(w, "current index out of bounds", http.StatusBadRequest)
|
|
return
|
|
}
|
|
pq := &model.PlayQueue{
|
|
UserID: user.ID,
|
|
Current: payload.Current,
|
|
Position: max(payload.Position, 0),
|
|
ChangedBy: client,
|
|
Items: items,
|
|
}
|
|
if err := ds.PlayQueue(ctx).Store(pq); err != nil {
|
|
log.Error(ctx, "Error saving queue", err)
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
}
|