Refactor `getMusicDirectory`
This commit is contained in:
parent
15c8f4c0ef
commit
f16dc5f8f8
|
@ -105,7 +105,9 @@ func (c *BrowsingController) GetArtists(w http.ResponseWriter, r *http.Request)
|
|||
|
||||
func (c *BrowsingController) GetMusicDirectory(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
|
||||
id := utils.ParamString(r, "id")
|
||||
dir, err := c.browser.Directory(r.Context(), id)
|
||||
ctx := r.Context()
|
||||
|
||||
entity, err := getEntityByID(ctx, c.ds, id)
|
||||
switch {
|
||||
case err == model.ErrNotFound:
|
||||
log.Error(r, "Requested ID not found ", "id", id)
|
||||
|
@ -115,8 +117,25 @@ func (c *BrowsingController) GetMusicDirectory(w http.ResponseWriter, r *http.Re
|
|||
return nil, NewError(responses.ErrorGeneric, "Internal Error")
|
||||
}
|
||||
|
||||
var dir *responses.Directory
|
||||
|
||||
switch v := entity.(type) {
|
||||
case *model.Artist:
|
||||
dir, err = c.buildArtistDirectory(ctx, v)
|
||||
case *model.Album:
|
||||
dir, err = c.buildAlbumDirectory(ctx, v)
|
||||
default:
|
||||
log.Error(r, "Requested ID of invalid type", "id", id, "entity", v)
|
||||
return nil, NewError(responses.ErrorDataNotFound, "Directory not found")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, NewError(responses.ErrorGeneric, "Internal Error")
|
||||
}
|
||||
|
||||
response := NewResponse()
|
||||
response.Directory = c.buildDirectory(r.Context(), dir)
|
||||
response.Directory = dir
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
@ -233,21 +252,24 @@ func (c *BrowsingController) GetTopSongs(w http.ResponseWriter, r *http.Request)
|
|||
return response, nil
|
||||
}
|
||||
|
||||
func (c *BrowsingController) buildDirectory(ctx context.Context, d *engine.DirectoryInfo) *responses.Directory {
|
||||
dir := &responses.Directory{
|
||||
Id: d.Id,
|
||||
Name: d.Name,
|
||||
Parent: d.Parent,
|
||||
PlayCount: d.PlayCount,
|
||||
AlbumCount: d.AlbumCount,
|
||||
UserRating: d.UserRating,
|
||||
}
|
||||
if !d.Starred.IsZero() {
|
||||
dir.Starred = &d.Starred
|
||||
func (c *BrowsingController) buildArtistDirectory(ctx context.Context, artist *model.Artist) (*responses.Directory, error) {
|
||||
dir := &responses.Directory{}
|
||||
dir.Id = artist.ID
|
||||
dir.Name = artist.Name
|
||||
dir.PlayCount = artist.PlayCount
|
||||
dir.AlbumCount = artist.AlbumCount
|
||||
dir.UserRating = artist.Rating
|
||||
if artist.Starred {
|
||||
dir.Starred = &artist.StarredAt
|
||||
}
|
||||
|
||||
dir.Child = ToChildren(ctx, d.Entries)
|
||||
return dir
|
||||
albums, err := c.ds.Album(ctx).FindByArtist(artist.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dir.Child = ChildrenFromAlbums(ctx, albums)
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
func (c *BrowsingController) buildArtist(ctx context.Context, artist *model.Artist, albums model.Albums) *responses.ArtistWithAlbumsID3 {
|
||||
|
@ -263,6 +285,28 @@ func (c *BrowsingController) buildArtist(ctx context.Context, artist *model.Arti
|
|||
return dir
|
||||
}
|
||||
|
||||
func (c *BrowsingController) buildAlbumDirectory(ctx context.Context, album *model.Album) (*responses.Directory, error) {
|
||||
dir := &responses.Directory{}
|
||||
dir.Id = album.ID
|
||||
dir.Name = album.Name
|
||||
dir.Parent = album.AlbumArtistID
|
||||
dir.PlayCount = album.PlayCount
|
||||
dir.UserRating = album.Rating
|
||||
dir.SongCount = album.SongCount
|
||||
dir.CoverArt = album.CoverArtId
|
||||
if album.Starred {
|
||||
dir.Starred = &album.StarredAt
|
||||
}
|
||||
|
||||
mfs, err := c.ds.MediaFile(ctx).FindByAlbum(album.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dir.Child = ChildrenFromMediaFiles(ctx, mfs)
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
func (c *BrowsingController) buildAlbum(ctx context.Context, album *model.Album, mfs model.MediaFiles) *responses.AlbumWithSongsID3 {
|
||||
dir := &responses.AlbumWithSongsID3{}
|
||||
dir.Id = album.ID
|
||||
|
|
|
@ -2,18 +2,13 @@ package engine
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/deluan/navidrome/log"
|
||||
"github.com/deluan/navidrome/model"
|
||||
)
|
||||
|
||||
type Browser interface {
|
||||
Directory(ctx context.Context, id string) (*DirectoryInfo, error)
|
||||
Album(ctx context.Context, id string) (*DirectoryInfo, error)
|
||||
GetSong(ctx context.Context, id string) (*Entry, error)
|
||||
GetGenres(ctx context.Context) (model.Genres, error)
|
||||
}
|
||||
|
@ -26,55 +21,6 @@ type browser struct {
|
|||
ds model.DataStore
|
||||
}
|
||||
|
||||
type DirectoryInfo struct {
|
||||
Id string
|
||||
Name string
|
||||
Entries Entries
|
||||
Parent string
|
||||
Starred time.Time
|
||||
PlayCount int64
|
||||
UserRating int
|
||||
AlbumCount int
|
||||
CoverArt string
|
||||
Artist string
|
||||
ArtistId string
|
||||
SongCount int
|
||||
Duration int
|
||||
Created time.Time
|
||||
Year int
|
||||
Genre string
|
||||
}
|
||||
|
||||
func (b *browser) Artist(ctx context.Context, id string) (*DirectoryInfo, error) {
|
||||
a, albums, err := b.retrieveArtist(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debug(ctx, "Found Artist", "id", id, "name", a.Name)
|
||||
return b.buildArtistDir(a, albums), nil
|
||||
}
|
||||
|
||||
func (b *browser) Album(ctx context.Context, id string) (*DirectoryInfo, error) {
|
||||
al, tracks, err := b.retrieveAlbum(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debug(ctx, "Found Album", "id", id, "name", al.Name)
|
||||
return b.buildAlbumDir(al, tracks), nil
|
||||
}
|
||||
|
||||
func (b *browser) Directory(ctx context.Context, id string) (*DirectoryInfo, error) {
|
||||
switch {
|
||||
case b.isArtist(ctx, id):
|
||||
return b.Artist(ctx, id)
|
||||
case b.isAlbum(ctx, id):
|
||||
return b.Album(ctx, id)
|
||||
default:
|
||||
log.Debug(ctx, "Directory not found", "id", id)
|
||||
return nil, model.ErrNotFound
|
||||
}
|
||||
}
|
||||
|
||||
func (b *browser) GetSong(ctx context.Context, id string) (*Entry, error) {
|
||||
mf, err := b.ds.MediaFile(ctx).Get(id)
|
||||
if err != nil {
|
||||
|
@ -97,88 +43,3 @@ func (b *browser) GetGenres(ctx context.Context) (model.Genres, error) {
|
|||
})
|
||||
return genres, err
|
||||
}
|
||||
|
||||
func (b *browser) buildArtistDir(a *model.Artist, albums model.Albums) *DirectoryInfo {
|
||||
dir := &DirectoryInfo{
|
||||
Id: a.ID,
|
||||
Name: a.Name,
|
||||
AlbumCount: a.AlbumCount,
|
||||
}
|
||||
|
||||
dir.Entries = make(Entries, len(albums))
|
||||
for i := range albums {
|
||||
al := albums[i]
|
||||
dir.Entries[i] = FromAlbum(&al)
|
||||
dir.PlayCount += al.PlayCount
|
||||
}
|
||||
return dir
|
||||
}
|
||||
|
||||
func (b *browser) buildAlbumDir(al *model.Album, tracks model.MediaFiles) *DirectoryInfo {
|
||||
dir := &DirectoryInfo{
|
||||
Id: al.ID,
|
||||
Name: al.Name,
|
||||
Parent: al.AlbumArtistID,
|
||||
Artist: al.AlbumArtist,
|
||||
ArtistId: al.AlbumArtistID,
|
||||
SongCount: al.SongCount,
|
||||
Duration: int(al.Duration),
|
||||
Created: al.CreatedAt,
|
||||
Year: al.MaxYear,
|
||||
Genre: al.Genre,
|
||||
CoverArt: al.CoverArtId,
|
||||
PlayCount: al.PlayCount,
|
||||
UserRating: al.Rating,
|
||||
}
|
||||
|
||||
if al.Starred {
|
||||
dir.Starred = al.StarredAt
|
||||
}
|
||||
|
||||
dir.Entries = FromMediaFiles(tracks)
|
||||
return dir
|
||||
}
|
||||
|
||||
func (b *browser) isArtist(ctx context.Context, id string) bool {
|
||||
found, err := b.ds.Artist(ctx).Exists(id)
|
||||
if err != nil {
|
||||
log.Debug(ctx, "Error searching for Artist", "id", id, err)
|
||||
return false
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func (b *browser) isAlbum(ctx context.Context, id string) bool {
|
||||
found, err := b.ds.Album(ctx).Exists(id)
|
||||
if err != nil {
|
||||
log.Debug(ctx, "Error searching for Album", "id", id, err)
|
||||
return false
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func (b *browser) retrieveArtist(ctx context.Context, id string) (a *model.Artist, as model.Albums, err error) {
|
||||
a, err = b.ds.Artist(ctx).Get(id)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error reading Artist %s from DB: %v", id, err)
|
||||
return
|
||||
}
|
||||
|
||||
if as, err = b.ds.Album(ctx).FindByArtist(id); err != nil {
|
||||
err = fmt.Errorf("Error reading %s's albums from DB: %v", a.Name, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *browser) retrieveAlbum(ctx context.Context, id string) (al *model.Album, mfs model.MediaFiles, err error) {
|
||||
al, err = b.ds.Album(ctx).Get(id)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error reading Album %s from DB: %v", id, err)
|
||||
return
|
||||
}
|
||||
|
||||
if mfs, err = b.ds.MediaFile(ctx).FindByAlbum(id); err != nil {
|
||||
err = fmt.Errorf("Error reading %s's tracks from DB: %v", al.Name, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -255,3 +255,20 @@ func ChildrenFromAlbums(ctx context.Context, als model.Albums) []responses.Child
|
|||
}
|
||||
return children
|
||||
}
|
||||
|
||||
// TODO: Should the type be encoded in the ID?
|
||||
func getEntityByID(ctx context.Context, ds model.DataStore, id string) (interface{}, error) {
|
||||
ar, err := ds.Artist(ctx).Get(id)
|
||||
if err == nil {
|
||||
return ar, nil
|
||||
}
|
||||
al, err := ds.Album(ctx).Get(id)
|
||||
if err == nil {
|
||||
return al, nil
|
||||
}
|
||||
mf, err := ds.MediaFile(ctx).Get(id)
|
||||
if err == nil {
|
||||
return mf, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue