2016-03-09 06:09:15 -09:00
|
|
|
package engine
|
|
|
|
|
|
|
|
|
|
import (
|
2020-01-08 16:45:07 -09:00
|
|
|
"context"
|
2016-03-24 08:06:39 -08:00
|
|
|
|
2020-01-23 15:44:08 -09:00
|
|
|
"github.com/deluan/navidrome/model"
|
|
|
|
|
"github.com/deluan/navidrome/utils"
|
2016-03-09 06:09:15 -09:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Playlists interface {
|
2020-01-22 04:32:31 -09:00
|
|
|
GetAll(ctx context.Context) (model.Playlists, error)
|
2020-01-21 19:01:43 -09:00
|
|
|
Get(ctx context.Context, id string) (*PlaylistInfo, error)
|
2020-01-21 12:35:57 -09:00
|
|
|
Create(ctx context.Context, playlistId, name string, ids []string) error
|
2020-01-08 16:45:07 -09:00
|
|
|
Delete(ctx context.Context, playlistId string) error
|
2020-01-21 12:35:57 -09:00
|
|
|
Update(ctx context.Context, playlistId string, name *string, idsToAdd []string, idxToRemove []int) error
|
2016-03-09 06:09:15 -09:00
|
|
|
}
|
|
|
|
|
|
2020-01-19 11:37:41 -09:00
|
|
|
func NewPlaylists(ds model.DataStore) Playlists {
|
|
|
|
|
return &playlists{ds}
|
2016-03-09 06:09:15 -09:00
|
|
|
}
|
|
|
|
|
|
2016-03-09 14:28:11 -09:00
|
|
|
type playlists struct {
|
2020-01-19 11:37:41 -09:00
|
|
|
ds model.DataStore
|
2016-03-09 06:09:15 -09:00
|
|
|
}
|
|
|
|
|
|
2020-01-21 12:35:57 -09:00
|
|
|
func (p *playlists) Create(ctx context.Context, playlistId, name string, ids []string) error {
|
2020-01-21 13:18:46 -09:00
|
|
|
owner := p.getUser(ctx)
|
2020-01-21 12:35:57 -09:00
|
|
|
var pls *model.Playlist
|
|
|
|
|
var err error
|
|
|
|
|
// If playlistID is present, override tracks
|
|
|
|
|
if playlistId != "" {
|
2020-01-27 05:41:33 -09:00
|
|
|
pls, err = p.ds.Playlist(ctx).Get(playlistId)
|
2020-01-21 12:35:57 -09:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2020-01-21 13:18:46 -09:00
|
|
|
if owner != pls.Owner {
|
|
|
|
|
return model.ErrNotAuthorized
|
|
|
|
|
}
|
2020-01-21 12:35:57 -09:00
|
|
|
pls.Tracks = nil
|
|
|
|
|
} else {
|
|
|
|
|
pls = &model.Playlist{
|
|
|
|
|
Name: name,
|
|
|
|
|
Owner: owner,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for _, id := range ids {
|
|
|
|
|
pls.Tracks = append(pls.Tracks, model.MediaFile{ID: id})
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-27 05:41:33 -09:00
|
|
|
return p.ds.Playlist(ctx).Put(pls)
|
2020-01-21 12:35:57 -09:00
|
|
|
}
|
|
|
|
|
|
2020-01-21 13:18:46 -09:00
|
|
|
func (p *playlists) getUser(ctx context.Context) string {
|
2020-02-29 16:01:09 -09:00
|
|
|
user, ok := ctx.Value("user").(model.User)
|
2020-01-21 13:18:46 -09:00
|
|
|
if ok {
|
2020-01-30 10:43:24 -09:00
|
|
|
return user.UserName
|
2020-01-21 13:18:46 -09:00
|
|
|
}
|
2020-01-30 10:43:24 -09:00
|
|
|
return ""
|
2020-01-21 13:18:46 -09:00
|
|
|
}
|
|
|
|
|
|
2020-01-21 12:35:57 -09:00
|
|
|
func (p *playlists) Delete(ctx context.Context, playlistId string) error {
|
2020-01-27 05:41:33 -09:00
|
|
|
pls, err := p.ds.Playlist(ctx).Get(playlistId)
|
2020-01-21 13:18:46 -09:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
owner := p.getUser(ctx)
|
|
|
|
|
if owner != pls.Owner {
|
|
|
|
|
return model.ErrNotAuthorized
|
|
|
|
|
}
|
2020-01-27 05:41:33 -09:00
|
|
|
return p.ds.Playlist(nil).Delete(playlistId)
|
2020-01-21 12:35:57 -09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *playlists) Update(ctx context.Context, playlistId string, name *string, idsToAdd []string, idxToRemove []int) error {
|
2020-01-27 05:41:33 -09:00
|
|
|
pls, err := p.ds.Playlist(ctx).Get(playlistId)
|
2020-03-19 20:02:31 -08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2020-01-21 13:18:46 -09:00
|
|
|
|
|
|
|
|
owner := p.getUser(ctx)
|
|
|
|
|
if owner != pls.Owner {
|
|
|
|
|
return model.ErrNotAuthorized
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-21 12:35:57 -09:00
|
|
|
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
|
|
|
|
|
|
2020-01-27 05:41:33 -09:00
|
|
|
return p.ds.Playlist(ctx).Put(pls)
|
2020-01-21 12:35:57 -09:00
|
|
|
}
|
|
|
|
|
|
2020-01-22 04:32:31 -09:00
|
|
|
func (p *playlists) GetAll(ctx context.Context) (model.Playlists, error) {
|
2020-02-22 20:10:05 -09:00
|
|
|
all, err := p.ds.Playlist(ctx).GetAll(model.QueryOptions{})
|
|
|
|
|
for i := range all {
|
|
|
|
|
all[i].Public = true
|
|
|
|
|
}
|
|
|
|
|
return all, err
|
2016-03-09 06:09:15 -09:00
|
|
|
}
|
2016-03-09 14:28:11 -09:00
|
|
|
|
|
|
|
|
type PlaylistInfo struct {
|
2016-03-21 08:26:55 -08:00
|
|
|
Id string
|
|
|
|
|
Name string
|
|
|
|
|
Entries Entries
|
|
|
|
|
SongCount int
|
|
|
|
|
Duration int
|
|
|
|
|
Public bool
|
|
|
|
|
Owner string
|
2016-03-24 09:28:20 -08:00
|
|
|
Comment string
|
2016-03-09 14:28:11 -09:00
|
|
|
}
|
|
|
|
|
|
2020-01-21 19:01:43 -09:00
|
|
|
func (p *playlists) Get(ctx context.Context, id string) (*PlaylistInfo, error) {
|
2020-01-27 05:41:33 -09:00
|
|
|
pl, err := p.ds.Playlist(ctx).GetWithTracks(id)
|
2016-03-09 14:28:11 -09:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-21 14:10:29 -09:00
|
|
|
// TODO Use model.Playlist when got rid of Entries
|
2020-01-30 18:07:02 -09:00
|
|
|
plsInfo := &PlaylistInfo{
|
2020-01-09 19:33:01 -09:00
|
|
|
Id: pl.ID,
|
2016-03-21 08:26:55 -08:00
|
|
|
Name: pl.Name,
|
2020-01-21 14:10:29 -09:00
|
|
|
SongCount: len(pl.Tracks),
|
2020-02-20 13:00:56 -09:00
|
|
|
Duration: int(pl.Duration),
|
2016-03-21 08:26:55 -08:00
|
|
|
Public: pl.Public,
|
|
|
|
|
Owner: pl.Owner,
|
2016-03-24 09:28:20 -08:00
|
|
|
Comment: pl.Comment,
|
2016-03-21 08:26:55 -08:00
|
|
|
}
|
2016-03-09 14:28:11 -09:00
|
|
|
|
2020-01-30 18:07:02 -09:00
|
|
|
plsInfo.Entries = FromMediaFiles(pl.Tracks)
|
|
|
|
|
return plsInfo, nil
|
2016-03-09 14:28:11 -09:00
|
|
|
}
|