mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-04 13:07:36 +03:00
162 lines
4 KiB
Go
162 lines
4 KiB
Go
package persistence
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
. "github.com/Masterminds/squirrel"
|
|
"github.com/astaxie/beego/orm"
|
|
"github.com/deluan/navidrome/log"
|
|
"github.com/deluan/navidrome/model"
|
|
"github.com/deluan/rest"
|
|
)
|
|
|
|
type playlistRepository struct {
|
|
sqlRepository
|
|
sqlRestful
|
|
}
|
|
|
|
func NewPlaylistRepository(ctx context.Context, o orm.Ormer) model.PlaylistRepository {
|
|
r := &playlistRepository{}
|
|
r.ctx = ctx
|
|
r.ormer = o
|
|
r.tableName = "playlist"
|
|
return r
|
|
}
|
|
|
|
func (r *playlistRepository) CountAll(options ...model.QueryOptions) (int64, error) {
|
|
return r.count(Select(), options...)
|
|
}
|
|
|
|
func (r *playlistRepository) Exists(id string) (bool, error) {
|
|
return r.exists(Select().Where(Eq{"id": id}))
|
|
}
|
|
|
|
func (r *playlistRepository) Delete(id string) error {
|
|
del := Delete("playlist_tracks").Where(Eq{"playlist_id": id})
|
|
_, err := r.executeSQL(del)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return r.delete(Eq{"id": id})
|
|
}
|
|
|
|
func (r *playlistRepository) Put(p *model.Playlist) error {
|
|
if p.ID == "" {
|
|
p.CreatedAt = time.Now()
|
|
}
|
|
p.UpdatedAt = time.Now()
|
|
|
|
// Save tracks for later and set it to nil, to avoid trying to save it to the DB
|
|
tracks := p.Tracks
|
|
p.Tracks = nil
|
|
|
|
id, err := r.put(p.ID, p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = r.updateTracks(id, tracks)
|
|
return err
|
|
}
|
|
|
|
func (r *playlistRepository) Get(id string) (*model.Playlist, error) {
|
|
sel := r.newSelect().Columns("*").Where(Eq{"id": id})
|
|
var pls model.Playlist
|
|
err := r.queryOne(sel, &pls)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = r.loadTracks(&pls)
|
|
return &pls, err
|
|
}
|
|
|
|
func (r *playlistRepository) GetAll(options ...model.QueryOptions) (model.Playlists, error) {
|
|
sel := r.newSelect(options...).Columns("*")
|
|
var res model.Playlists
|
|
err := r.queryAll(sel, &res)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = r.loadAllTracks(res)
|
|
return res, err
|
|
}
|
|
|
|
func (r *playlistRepository) updateTracks(id string, tracks model.MediaFiles) error {
|
|
// Remove old tracks
|
|
del := Delete("playlist_tracks").Where(Eq{"playlist_id": id})
|
|
_, err := r.executeSQL(del)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Add new tracks
|
|
for i, t := range tracks {
|
|
ins := Insert("playlist_tracks").Columns("playlist_id", "media_file_id", "id").
|
|
Values(id, t.ID, i)
|
|
_, err = r.executeSQL(ins)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Get total playlist duration and count
|
|
statsSql := Select("sum(duration) as duration", "count(*) as count").From("media_file").
|
|
Join("playlist_tracks f on f.media_file_id = media_file.id").
|
|
Where(Eq{"playlist_id": id})
|
|
var res struct{ Duration, Count float32 }
|
|
err = r.queryOne(statsSql, &res)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Update total playlist duration and count
|
|
upd := Update(r.tableName).
|
|
Set("duration", res.Duration).
|
|
Set("song_count", res.Count).
|
|
Where(Eq{"id": id})
|
|
_, err = r.executeSQL(upd)
|
|
return err
|
|
}
|
|
|
|
func (r *playlistRepository) loadAllTracks(all model.Playlists) error {
|
|
for i := range all {
|
|
if err := r.loadTracks(&all[i]); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *playlistRepository) loadTracks(pls *model.Playlist) (err error) {
|
|
tracksQuery := Select("media_file.*").From("media_file").
|
|
Join("playlist_tracks f on f.media_file_id = media_file.id").
|
|
Where(Eq{"f.playlist_id": pls.ID}).OrderBy("f.id")
|
|
err = r.queryAll(tracksQuery, &pls.Tracks)
|
|
if err != nil {
|
|
log.Error("Error loading playlist tracks", "playlist", pls.Name, "id", pls.ID)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (r *playlistRepository) Count(options ...rest.QueryOptions) (int64, error) {
|
|
return r.CountAll(r.parseRestOptions(options...))
|
|
}
|
|
|
|
func (r *playlistRepository) Read(id string) (interface{}, error) {
|
|
return r.Get(id)
|
|
}
|
|
|
|
func (r *playlistRepository) ReadAll(options ...rest.QueryOptions) (interface{}, error) {
|
|
return r.GetAll(r.parseRestOptions(options...))
|
|
}
|
|
|
|
func (r *playlistRepository) EntityName() string {
|
|
return "playlist"
|
|
}
|
|
|
|
func (r *playlistRepository) NewInstance() interface{} {
|
|
return &model.Playlist{}
|
|
}
|
|
|
|
var _ model.PlaylistRepository = (*playlistRepository)(nil)
|
|
var _ model.ResourceRepository = (*playlistRepository)(nil)
|