From a698e434fdd0e0bde65790204739f80b26064d8c Mon Sep 17 00:00:00 2001 From: Deluan Date: Fri, 17 Apr 2020 20:29:10 -0400 Subject: [PATCH] Refactor list_generator to use new filters --- engine/list_generator.go | 106 ++++++++++++---------------- server/subsonic/album_lists.go | 59 +++++----------- server/subsonic/album_lists_test.go | 2 +- 3 files changed, 64 insertions(+), 103 deletions(-) diff --git a/engine/list_generator.go b/engine/list_generator.go index b82861d8a..95c4df04b 100644 --- a/engine/list_generator.go +++ b/engine/list_generator.go @@ -8,8 +8,51 @@ import ( "github.com/deluan/navidrome/model" ) +type ListGenerator interface { + GetAllStarred(ctx context.Context) (artists Entries, albums Entries, mediaFiles Entries, err error) + GetNowPlaying(ctx context.Context) (Entries, error) + GetRandomSongs(ctx context.Context, size int, genre string) (Entries, error) + GetAlbums(ctx context.Context, offset, size int, filter AlbumFilter) (Entries, error) +} + +func NewListGenerator(ds model.DataStore, npRepo NowPlayingRepository) ListGenerator { + return &listGenerator{ds, npRepo} +} + type AlbumFilter model.QueryOptions +func ByNewest() AlbumFilter { + return AlbumFilter{Sort: "createdAt", Order: "desc"} +} + +func ByRecent() AlbumFilter { + return AlbumFilter{Sort: "playDate", Order: "desc", Filters: squirrel.Gt{"play_date": time.Time{}}} +} + +func ByFrequent() AlbumFilter { + return AlbumFilter{Sort: "playCount", Order: "desc", Filters: squirrel.Gt{"play_count": 0}} +} + +func ByRandom() AlbumFilter { + return AlbumFilter{Sort: "random()"} +} + +func ByName() AlbumFilter { + return AlbumFilter{Sort: "name"} +} + +func ByArtist() AlbumFilter { + return AlbumFilter{Sort: "artist"} +} + +func ByStarred() AlbumFilter { + return AlbumFilter{Sort: "starred_at", Order: "desc", Filters: squirrel.Eq{"starred": true}} +} + +func ByRating() AlbumFilter { + return AlbumFilter{Sort: "Rating", Order: "desc", Filters: squirrel.Gt{"rating": 0}} +} + func ByGenre(genre string) AlbumFilter { return AlbumFilter{ Sort: "genre asc, name asc", @@ -19,7 +62,7 @@ func ByGenre(genre string) AlbumFilter { func ByYear(fromYear, toYear int) AlbumFilter { return AlbumFilter{ - Sort: "max_year", + Sort: "max_year, name", Filters: squirrel.Or{ squirrel.And{ squirrel.LtOrEq{"min_year": toYear}, @@ -33,25 +76,6 @@ func ByYear(fromYear, toYear int) AlbumFilter { } } -type ListGenerator interface { - GetNewest(ctx context.Context, offset int, size int) (Entries, error) - GetRecent(ctx context.Context, offset int, size int) (Entries, error) - GetFrequent(ctx context.Context, offset int, size int) (Entries, error) - GetHighest(ctx context.Context, offset int, size int) (Entries, error) - GetRandom(ctx context.Context, offset int, size int) (Entries, error) - GetByName(ctx context.Context, offset int, size int) (Entries, error) - GetByArtist(ctx context.Context, offset int, size int) (Entries, error) - GetStarred(ctx context.Context, offset int, size int) (Entries, error) - GetAllStarred(ctx context.Context) (artists Entries, albums Entries, mediaFiles Entries, err error) - GetNowPlaying(ctx context.Context) (Entries, error) - GetRandomSongs(ctx context.Context, size int, genre string) (Entries, error) - GetAlbums(ctx context.Context, offset, size int, filter AlbumFilter) (Entries, error) -} - -func NewListGenerator(ds model.DataStore, npRepo NowPlayingRepository) ListGenerator { - return &listGenerator{ds, npRepo} -} - type listGenerator struct { ds model.DataStore npRepo NowPlayingRepository @@ -69,48 +93,6 @@ func (g *listGenerator) query(ctx context.Context, qo model.QueryOptions) (Entri return FromAlbums(albums), err } -func (g *listGenerator) GetNewest(ctx context.Context, offset int, size int) (Entries, error) { - qo := model.QueryOptions{Sort: "CreatedAt", Order: "desc", Offset: offset, Max: size} - return g.query(ctx, qo) -} - -func (g *listGenerator) GetRecent(ctx context.Context, offset int, size int) (Entries, error) { - qo := model.QueryOptions{Sort: "PlayDate", Order: "desc", Offset: offset, Max: size, - Filters: squirrel.Gt{"play_date": time.Time{}}} - return g.query(ctx, qo) -} - -func (g *listGenerator) GetFrequent(ctx context.Context, offset int, size int) (Entries, error) { - qo := model.QueryOptions{Sort: "PlayCount", Order: "desc", Offset: offset, Max: size, - Filters: squirrel.Gt{"play_count": 0}} - return g.query(ctx, qo) -} - -func (g *listGenerator) GetHighest(ctx context.Context, offset int, size int) (Entries, error) { - qo := model.QueryOptions{Sort: "Rating", Order: "desc", Offset: offset, Max: size, - Filters: squirrel.Gt{"rating": 0}} - return g.query(ctx, qo) -} - -func (g *listGenerator) GetByName(ctx context.Context, offset int, size int) (Entries, error) { - qo := model.QueryOptions{Sort: "Name", Offset: offset, Max: size} - return g.query(ctx, qo) -} - -func (g *listGenerator) GetByArtist(ctx context.Context, offset int, size int) (Entries, error) { - qo := model.QueryOptions{Sort: "Artist", Offset: offset, Max: size} - return g.query(ctx, qo) -} - -func (g *listGenerator) GetRandom(ctx context.Context, offset int, size int) (Entries, error) { - albums, err := g.ds.Album(ctx).GetRandom(model.QueryOptions{Max: size, Offset: offset}) - if err != nil { - return nil, err - } - - return FromAlbums(albums), nil -} - func (g *listGenerator) GetRandomSongs(ctx context.Context, size int, genre string) (Entries, error) { options := model.QueryOptions{Max: size} if genre != "" { diff --git a/server/subsonic/album_lists.go b/server/subsonic/album_lists.go index 2100be437..cb67ad550 100644 --- a/server/subsonic/album_lists.go +++ b/server/subsonic/album_lists.go @@ -1,7 +1,6 @@ package subsonic import ( - "context" "errors" "net/http" @@ -12,53 +11,16 @@ import ( ) type AlbumListController struct { - listGen engine.ListGenerator - listFunctions map[string]strategy + listGen engine.ListGenerator } func NewAlbumListController(listGen engine.ListGenerator) *AlbumListController { c := &AlbumListController{ listGen: listGen, } - c.listFunctions = map[string]strategy{ - "random": c.listGen.GetRandom, - "newest": c.listGen.GetNewest, - "recent": c.listGen.GetRecent, - "frequent": c.listGen.GetFrequent, - "highest": c.listGen.GetHighest, - "alphabeticalByName": c.listGen.GetByName, - "alphabeticalByArtist": c.listGen.GetByArtist, - "starred": c.listGen.GetStarred, - } return c } -type strategy func(ctx context.Context, offset int, size int) (engine.Entries, error) - -func (c *AlbumListController) getAlbumList(r *http.Request) (engine.Entries, error) { - typ, err := RequiredParamString(r, "type", "Required string parameter 'type' is not present") - if err != nil { - return nil, err - } - listFunc, found := c.listFunctions[typ] - - if !found { - log.Error(r, "albumList type not implemented", "type", typ) - return nil, errors.New("Not implemented!") - } - - offset := utils.ParamInt(r, "offset", 0) - size := utils.MinInt(utils.ParamInt(r, "size", 10), 500) - - albums, err := listFunc(r.Context(), offset, size) - if err != nil { - log.Error(r, "Error retrieving albums", "error", err) - return nil, errors.New("Internal Error") - } - - return albums, nil -} - func (c *AlbumListController) getNewAlbumList(r *http.Request) (engine.Entries, error) { typ, err := RequiredParamString(r, "type", "Required string parameter 'type' is not present") if err != nil { @@ -67,12 +29,29 @@ func (c *AlbumListController) getNewAlbumList(r *http.Request) (engine.Entries, var filter engine.AlbumFilter switch typ { + case "newest": + filter = engine.ByNewest() + case "recent": + filter = engine.ByRecent() + case "random": + filter = engine.ByRandom() + case "alphabeticalByName": + filter = engine.ByName() + case "alphabeticalByArtist": + filter = engine.ByArtist() + case "frequent": + filter = engine.ByFrequent() + case "starred": + filter = engine.ByStarred() + case "highest": + filter = engine.ByRating() case "byGenre": filter = engine.ByGenre(utils.ParamString(r, "genre")) case "byYear": filter = engine.ByYear(utils.ParamInt(r, "fromYear", 0), utils.ParamInt(r, "toYear", 0)) default: - return c.getAlbumList(r) + log.Error(r, "albumList type not implemented", "type", typ) + return nil, errors.New("Not implemented!") } offset := utils.ParamInt(r, "offset", 0) diff --git a/server/subsonic/album_lists_test.go b/server/subsonic/album_lists_test.go index 8b5fa8342..f29a267ef 100644 --- a/server/subsonic/album_lists_test.go +++ b/server/subsonic/album_lists_test.go @@ -18,7 +18,7 @@ type fakeListGen struct { recvSize int } -func (lg *fakeListGen) GetNewest(ctx context.Context, offset int, size int) (engine.Entries, error) { +func (lg *fakeListGen) GetAlbums(ctx context.Context, offset int, size int, filter engine.AlbumFilter) (engine.Entries, error) { if lg.err != nil { return nil, lg.err }