navidrome/server/subsonic/playlists.go

138 lines
4.0 KiB
Go
Raw Normal View History

package subsonic
import (
"errors"
2016-03-24 18:28:20 +01:00
"fmt"
"net/http"
2016-03-24 18:28:20 +01:00
2017-04-01 15:47:14 +02:00
"github.com/cloudsonic/sonic-server/engine"
2020-01-09 02:45:07 +01:00
"github.com/cloudsonic/sonic-server/log"
2020-01-15 04:22:34 +01:00
"github.com/cloudsonic/sonic-server/model"
"github.com/cloudsonic/sonic-server/server/subsonic/responses"
)
type PlaylistsController struct {
pls engine.Playlists
}
func NewPlaylistsController(pls engine.Playlists) *PlaylistsController {
return &PlaylistsController{pls: pls}
}
func (c *PlaylistsController) GetPlaylists(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
allPls, err := c.pls.GetAll(r.Context())
if err != nil {
2020-01-09 02:45:07 +01:00
log.Error(r, err)
return nil, NewError(responses.ErrorGeneric, "Internal error")
}
playlists := make([]responses.Playlist, len(allPls))
2016-03-21 17:26:55 +01:00
for i, p := range allPls {
playlists[i].Id = p.ID
2016-03-21 17:26:55 +01:00
playlists[i].Name = p.Name
2016-03-24 18:28:20 +01:00
playlists[i].Comment = p.Comment
2016-03-21 17:26:55 +01:00
playlists[i].SongCount = len(p.Tracks)
playlists[i].Duration = p.Duration
playlists[i].Owner = p.Owner
playlists[i].Public = p.Public
}
2020-01-11 23:18:20 +01:00
response := NewResponse()
response.Playlists = &responses.Playlists{Playlist: playlists}
return response, nil
}
2016-03-10 00:28:11 +01:00
func (c *PlaylistsController) GetPlaylist(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
id, err := RequiredParamString(r, "id", "id parameter required")
if err != nil {
return nil, err
}
2020-01-22 05:01:43 +01:00
pinfo, err := c.pls.Get(r.Context(), id)
2016-03-10 00:28:11 +01:00
switch {
2020-01-15 04:22:34 +01:00
case err == model.ErrNotFound:
2020-01-09 02:45:07 +01:00
log.Error(r, err.Error(), "id", id)
return nil, NewError(responses.ErrorDataNotFound, "Directory not found")
2016-03-10 00:28:11 +01:00
case err != nil:
2020-01-09 02:45:07 +01:00
log.Error(r, err)
return nil, NewError(responses.ErrorGeneric, "Internal Error")
2016-03-10 00:28:11 +01:00
}
2020-01-11 23:18:20 +01:00
response := NewResponse()
2016-03-10 00:28:11 +01:00
response.Playlist = c.buildPlaylist(pinfo)
return response, nil
2016-03-10 00:28:11 +01:00
}
func (c *PlaylistsController) CreatePlaylist(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
songIds := ParamStrings(r, "songId")
playlistId := ParamString(r, "playlistId")
name := ParamString(r, "name")
if playlistId == "" && name == "" {
return nil, errors.New("Required parameter name is missing")
}
err := c.pls.Create(r.Context(), playlistId, name, songIds)
2016-03-24 17:06:39 +01:00
if err != nil {
2020-01-09 02:45:07 +01:00
log.Error(r, err)
return nil, NewError(responses.ErrorGeneric, "Internal Error")
2016-03-24 17:06:39 +01:00
}
2020-01-11 23:18:20 +01:00
return NewResponse(), nil
2016-03-24 17:06:39 +01:00
}
func (c *PlaylistsController) DeletePlaylist(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
id, err := RequiredParamString(r, "id", "Required parameter id is missing")
if err != nil {
return nil, err
}
2020-01-09 02:45:07 +01:00
err = c.pls.Delete(r.Context(), id)
if err == model.ErrNotAuthorized {
return nil, NewError(responses.ErrorAuthorizationFail)
}
2016-03-24 17:17:35 +01:00
if err != nil {
2020-01-09 02:45:07 +01:00
log.Error(r, err)
return nil, NewError(responses.ErrorGeneric, "Internal Error")
2016-03-24 17:17:35 +01:00
}
2020-01-11 23:18:20 +01:00
return NewResponse(), nil
2016-03-24 17:17:35 +01:00
}
func (c *PlaylistsController) UpdatePlaylist(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
playlistId, err := RequiredParamString(r, "playlistId", "Required parameter playlistId is missing")
if err != nil {
return nil, err
}
songsToAdd := ParamStrings(r, "songIdToAdd")
songIndexesToRemove := ParamInts(r, "songIndexToRemove")
2016-03-24 18:28:20 +01:00
var pname *string
if len(r.URL.Query()["name"]) > 0 {
s := r.URL.Query()["name"][0]
2016-03-24 18:28:20 +01:00
pname = &s
}
2020-01-09 02:45:07 +01:00
log.Info(r, "Updating playlist", "id", playlistId)
2016-03-24 18:28:20 +01:00
if pname != nil {
2020-01-09 02:45:07 +01:00
log.Debug(r, fmt.Sprintf("-- New Name: '%s'", *pname))
2016-03-24 18:28:20 +01:00
}
2020-01-09 02:45:07 +01:00
log.Debug(r, fmt.Sprintf("-- Adding: '%v'", songsToAdd))
log.Debug(r, fmt.Sprintf("-- Removing: '%v'", songIndexesToRemove))
2016-03-24 18:28:20 +01:00
err = c.pls.Update(r.Context(), playlistId, pname, songsToAdd, songIndexesToRemove)
if err == model.ErrNotAuthorized {
return nil, NewError(responses.ErrorAuthorizationFail)
}
2016-03-24 18:28:20 +01:00
if err != nil {
2020-01-09 02:45:07 +01:00
log.Error(r, err)
return nil, NewError(responses.ErrorGeneric, "Internal Error")
2016-03-24 18:28:20 +01:00
}
2020-01-11 23:18:20 +01:00
return NewResponse(), nil
2016-03-24 18:28:20 +01:00
}
2016-03-10 00:28:11 +01:00
func (c *PlaylistsController) buildPlaylist(d *engine.PlaylistInfo) *responses.PlaylistWithSongs {
pls := &responses.PlaylistWithSongs{}
pls.Id = d.Id
pls.Name = d.Name
2016-03-21 17:26:55 +01:00
pls.SongCount = d.SongCount
pls.Owner = d.Owner
pls.Duration = d.Duration
pls.Public = d.Public
2016-03-10 00:28:11 +01:00
pls.Entry = ToChildren(d.Entries)
2016-03-10 00:28:11 +01:00
return pls
}