Completely removed engine package, fewer abstraction layers \o/
This commit is contained in:
+107
-37
@@ -8,36 +8,28 @@ import (
|
||||
|
||||
"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
|
||||
ds model.DataStore
|
||||
}
|
||||
|
||||
func NewPlaylistsController(pls engine.Playlists) *PlaylistsController {
|
||||
return &PlaylistsController{pls: pls}
|
||||
func NewPlaylistsController(ds model.DataStore) *PlaylistsController {
|
||||
return &PlaylistsController{ds: ds}
|
||||
}
|
||||
|
||||
func (c *PlaylistsController) GetPlaylists(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
|
||||
allPls, err := c.pls.GetAll(r.Context())
|
||||
ctx := r.Context()
|
||||
allPls, err := c.ds.Playlist(ctx).GetAll()
|
||||
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
|
||||
playlists[i] = *c.buildPlaylist(p)
|
||||
}
|
||||
response := newResponse()
|
||||
response.Playlists = &responses.Playlists{Playlist: playlists}
|
||||
@@ -45,11 +37,12 @@ func (c *PlaylistsController) GetPlaylists(w http.ResponseWriter, r *http.Reques
|
||||
}
|
||||
|
||||
func (c *PlaylistsController) GetPlaylist(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
|
||||
ctx := r.Context()
|
||||
id, err := requiredParamString(r, "id", "id parameter required")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pinfo, err := c.pls.Get(r.Context(), id)
|
||||
pls, err := c.ds.Playlist(ctx).Get(id)
|
||||
switch {
|
||||
case err == model.ErrNotFound:
|
||||
log.Error(r, err.Error(), "id", id)
|
||||
@@ -60,18 +53,48 @@ func (c *PlaylistsController) GetPlaylist(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
|
||||
response := newResponse()
|
||||
response.Playlist = c.buildPlaylistWithSongs(r.Context(), pinfo)
|
||||
response.Playlist = c.buildPlaylistWithSongs(ctx, pls)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *PlaylistsController) create(ctx context.Context, playlistId, name string, ids []string) error {
|
||||
return c.ds.WithTx(func(tx model.DataStore) error {
|
||||
owner := getUser(ctx)
|
||||
var pls *model.Playlist
|
||||
var err error
|
||||
|
||||
// If playlistID is present, override tracks
|
||||
if playlistId != "" {
|
||||
pls, err = tx.Playlist(ctx).Get(playlistId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if owner != pls.Owner {
|
||||
return model.ErrNotAuthorized
|
||||
}
|
||||
pls.Tracks = nil
|
||||
} else {
|
||||
pls = &model.Playlist{
|
||||
Name: name,
|
||||
Owner: owner,
|
||||
}
|
||||
}
|
||||
for _, id := range ids {
|
||||
pls.Tracks = append(pls.Tracks, model.MediaFile{ID: id})
|
||||
}
|
||||
|
||||
return tx.Playlist(ctx).Put(pls)
|
||||
})
|
||||
}
|
||||
|
||||
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")
|
||||
return nil, errors.New("required parameter name is missing")
|
||||
}
|
||||
err := c.pls.Create(r.Context(), playlistId, name, songIds)
|
||||
err := c.create(r.Context(), playlistId, name, songIds)
|
||||
if err != nil {
|
||||
log.Error(r, err)
|
||||
return nil, newError(responses.ErrorGeneric, "Internal Error")
|
||||
@@ -79,12 +102,27 @@ func (c *PlaylistsController) CreatePlaylist(w http.ResponseWriter, r *http.Requ
|
||||
return newResponse(), nil
|
||||
}
|
||||
|
||||
func (c *PlaylistsController) delete(ctx context.Context, playlistId string) error {
|
||||
return c.ds.WithTx(func(tx model.DataStore) error {
|
||||
pls, err := tx.Playlist(ctx).Get(playlistId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
owner := getUser(ctx)
|
||||
if owner != pls.Owner {
|
||||
return model.ErrNotAuthorized
|
||||
}
|
||||
return tx.Playlist(ctx).Delete(playlistId)
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
err = c.delete(r.Context(), id)
|
||||
if err == model.ErrNotAuthorized {
|
||||
return nil, newError(responses.ErrorAuthorizationFail)
|
||||
}
|
||||
@@ -95,6 +133,38 @@ func (c *PlaylistsController) DeletePlaylist(w http.ResponseWriter, r *http.Requ
|
||||
return newResponse(), nil
|
||||
}
|
||||
|
||||
func (p *PlaylistsController) update(ctx context.Context, playlistId string, name *string, idsToAdd []string, idxToRemove []int) error {
|
||||
return p.ds.WithTx(func(tx model.DataStore) error {
|
||||
pls, err := tx.Playlist(ctx).Get(playlistId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
owner := getUser(ctx)
|
||||
if owner != pls.Owner {
|
||||
return model.ErrNotAuthorized
|
||||
}
|
||||
|
||||
if name != nil {
|
||||
pls.Name = *name
|
||||
}
|
||||
newTracks := model.MediaFiles{}
|
||||
for i, t := range pls.Tracks {
|
||||
if utils.IntInSlice(i, idxToRemove) {
|
||||
continue
|
||||
}
|
||||
newTracks = append(newTracks, t)
|
||||
}
|
||||
|
||||
for _, id := range idsToAdd {
|
||||
newTracks = append(newTracks, model.MediaFile{ID: id})
|
||||
}
|
||||
pls.Tracks = newTracks
|
||||
|
||||
return tx.Playlist(ctx).Put(pls)
|
||||
})
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -103,20 +173,20 @@ func (c *PlaylistsController) UpdatePlaylist(w http.ResponseWriter, r *http.Requ
|
||||
songsToAdd := utils.ParamStrings(r, "songIdToAdd")
|
||||
songIndexesToRemove := utils.ParamInts(r, "songIndexToRemove")
|
||||
|
||||
var pname *string
|
||||
var plsName *string
|
||||
if len(r.URL.Query()["name"]) > 0 {
|
||||
s := r.URL.Query()["name"][0]
|
||||
pname = &s
|
||||
plsName = &s
|
||||
}
|
||||
|
||||
log.Debug(r, "Updating playlist", "id", playlistId)
|
||||
if pname != nil {
|
||||
log.Trace(r, fmt.Sprintf("-- New Name: '%s'", *pname))
|
||||
if plsName != nil {
|
||||
log.Trace(r, fmt.Sprintf("-- New Name: '%s'", *plsName))
|
||||
}
|
||||
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)
|
||||
err = c.update(r.Context(), playlistId, plsName, songsToAdd, songIndexesToRemove)
|
||||
if err == model.ErrNotAuthorized {
|
||||
return nil, newError(responses.ErrorAuthorizationFail)
|
||||
}
|
||||
@@ -127,24 +197,24 @@ func (c *PlaylistsController) UpdatePlaylist(w http.ResponseWriter, r *http.Requ
|
||||
return newResponse(), nil
|
||||
}
|
||||
|
||||
func (c *PlaylistsController) buildPlaylistWithSongs(ctx context.Context, d *engine.PlaylistInfo) *responses.PlaylistWithSongs {
|
||||
func (c *PlaylistsController) buildPlaylistWithSongs(ctx context.Context, p *model.Playlist) *responses.PlaylistWithSongs {
|
||||
pls := &responses.PlaylistWithSongs{
|
||||
Playlist: *c.buildPlaylist(d),
|
||||
Playlist: *c.buildPlaylist(*p),
|
||||
}
|
||||
pls.Entry = toChildren(ctx, d.Entries)
|
||||
pls.Entry = childrenFromMediaFiles(ctx, p.Tracks)
|
||||
return pls
|
||||
}
|
||||
|
||||
func (c *PlaylistsController) buildPlaylist(d *engine.PlaylistInfo) *responses.Playlist {
|
||||
func (c *PlaylistsController) buildPlaylist(p model.Playlist) *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
|
||||
pls.Id = p.ID
|
||||
pls.Name = p.Name
|
||||
pls.Comment = p.Comment
|
||||
pls.SongCount = p.SongCount
|
||||
pls.Owner = p.Owner
|
||||
pls.Duration = int(p.Duration)
|
||||
pls.Public = p.Public
|
||||
pls.Created = p.CreatedAt
|
||||
pls.Changed = p.UpdatedAt
|
||||
return pls
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user