mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-15 11:40:36 +03:00
151 lines
4.5 KiB
Go
151 lines
4.5 KiB
Go
package subsonic
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/deluan/navidrome/log"
|
|
"github.com/deluan/navidrome/model"
|
|
"github.com/deluan/navidrome/server/subsonic/engine"
|
|
"github.com/deluan/navidrome/server/subsonic/responses"
|
|
"github.com/deluan/navidrome/utils"
|
|
)
|
|
|
|
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 {
|
|
log.Error(r, err)
|
|
return nil, NewError(responses.ErrorGeneric, "Internal error")
|
|
}
|
|
playlists := make([]responses.Playlist, len(allPls))
|
|
for i, p := range allPls {
|
|
playlists[i].Id = p.ID
|
|
playlists[i].Name = p.Name
|
|
playlists[i].Comment = p.Comment
|
|
playlists[i].SongCount = p.SongCount
|
|
playlists[i].Duration = int(p.Duration)
|
|
playlists[i].Owner = p.Owner
|
|
playlists[i].Public = p.Public
|
|
playlists[i].Created = p.CreatedAt
|
|
playlists[i].Changed = p.UpdatedAt
|
|
}
|
|
response := NewResponse()
|
|
response.Playlists = &responses.Playlists{Playlist: playlists}
|
|
return response, nil
|
|
}
|
|
|
|
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
|
|
}
|
|
pinfo, err := c.pls.Get(r.Context(), id)
|
|
switch {
|
|
case err == model.ErrNotFound:
|
|
log.Error(r, err.Error(), "id", id)
|
|
return nil, NewError(responses.ErrorDataNotFound, "Directory not found")
|
|
case err != nil:
|
|
log.Error(r, err)
|
|
return nil, NewError(responses.ErrorGeneric, "Internal Error")
|
|
}
|
|
|
|
response := NewResponse()
|
|
response.Playlist = c.buildPlaylistWithSongs(r.Context(), pinfo)
|
|
return response, nil
|
|
}
|
|
|
|
func (c *PlaylistsController) CreatePlaylist(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
|
|
songIds := utils.ParamStrings(r, "songId")
|
|
playlistId := utils.ParamString(r, "playlistId")
|
|
name := utils.ParamString(r, "name")
|
|
if playlistId == "" && name == "" {
|
|
return nil, errors.New("Required parameter name is missing")
|
|
}
|
|
err := c.pls.Create(r.Context(), playlistId, name, songIds)
|
|
if err != nil {
|
|
log.Error(r, err)
|
|
return nil, NewError(responses.ErrorGeneric, "Internal Error")
|
|
}
|
|
return NewResponse(), nil
|
|
}
|
|
|
|
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
|
|
}
|
|
err = c.pls.Delete(r.Context(), id)
|
|
if err == model.ErrNotAuthorized {
|
|
return nil, NewError(responses.ErrorAuthorizationFail)
|
|
}
|
|
if err != nil {
|
|
log.Error(r, err)
|
|
return nil, NewError(responses.ErrorGeneric, "Internal Error")
|
|
}
|
|
return NewResponse(), nil
|
|
}
|
|
|
|
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 := utils.ParamStrings(r, "songIdToAdd")
|
|
songIndexesToRemove := utils.ParamInts(r, "songIndexToRemove")
|
|
|
|
var pname *string
|
|
if len(r.URL.Query()["name"]) > 0 {
|
|
s := r.URL.Query()["name"][0]
|
|
pname = &s
|
|
}
|
|
|
|
log.Debug(r, "Updating playlist", "id", playlistId)
|
|
if pname != nil {
|
|
log.Trace(r, fmt.Sprintf("-- New Name: '%s'", *pname))
|
|
}
|
|
log.Trace(r, fmt.Sprintf("-- Adding: '%v'", songsToAdd))
|
|
log.Trace(r, fmt.Sprintf("-- Removing: '%v'", songIndexesToRemove))
|
|
|
|
err = c.pls.Update(r.Context(), playlistId, pname, songsToAdd, songIndexesToRemove)
|
|
if err == model.ErrNotAuthorized {
|
|
return nil, NewError(responses.ErrorAuthorizationFail)
|
|
}
|
|
if err != nil {
|
|
log.Error(r, err)
|
|
return nil, NewError(responses.ErrorGeneric, "Internal Error")
|
|
}
|
|
return NewResponse(), nil
|
|
}
|
|
|
|
func (c *PlaylistsController) buildPlaylistWithSongs(ctx context.Context, d *engine.PlaylistInfo) *responses.PlaylistWithSongs {
|
|
pls := &responses.PlaylistWithSongs{
|
|
Playlist: *c.buildPlaylist(d),
|
|
}
|
|
pls.Entry = ToChildren(ctx, d.Entries)
|
|
return pls
|
|
}
|
|
|
|
func (c *PlaylistsController) buildPlaylist(d *engine.PlaylistInfo) *responses.Playlist {
|
|
pls := &responses.Playlist{}
|
|
pls.Id = d.Id
|
|
pls.Name = d.Name
|
|
pls.Comment = d.Comment
|
|
pls.SongCount = d.SongCount
|
|
pls.Owner = d.Owner
|
|
pls.Duration = d.Duration
|
|
pls.Public = d.Public
|
|
pls.Created = d.Created
|
|
pls.Changed = d.Changed
|
|
return pls
|
|
}
|