diff --git a/engine/list_generator.go b/engine/list_generator.go index ab231a466..b82861d8a 100644 --- a/engine/list_generator.go +++ b/engine/list_generator.go @@ -8,6 +8,31 @@ import ( "github.com/deluan/navidrome/model" ) +type AlbumFilter model.QueryOptions + +func ByGenre(genre string) AlbumFilter { + return AlbumFilter{ + Sort: "genre asc, name asc", + Filters: squirrel.Eq{"genre": genre}, + } +} + +func ByYear(fromYear, toYear int) AlbumFilter { + return AlbumFilter{ + Sort: "max_year", + Filters: squirrel.Or{ + squirrel.And{ + squirrel.LtOrEq{"min_year": toYear}, + squirrel.GtOrEq{"max_year": toYear}, + }, + squirrel.And{ + squirrel.LtOrEq{"min_year": fromYear}, + squirrel.GtOrEq{"max_year": fromYear}, + }, + }, + } +} + type ListGenerator interface { GetNewest(ctx context.Context, offset int, size int) (Entries, error) GetRecent(ctx context.Context, offset int, size int) (Entries, error) @@ -20,6 +45,7 @@ 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 { @@ -98,6 +124,18 @@ func (g *listGenerator) GetRandomSongs(ctx context.Context, size int, genre stri return FromMediaFiles(mediaFiles), nil } +func (g *listGenerator) GetAlbums(ctx context.Context, offset, size int, filter AlbumFilter) (Entries, error) { + qo := model.QueryOptions(filter) + qo.Offset = offset + qo.Max = size + albums, err := g.ds.Album(ctx).GetAll(qo) + if err != nil { + return nil, err + } + + return FromAlbums(albums), nil +} + func (g *listGenerator) GetStarred(ctx context.Context, offset int, size int) (Entries, error) { qo := model.QueryOptions{Offset: offset, Max: size, Sort: "starred_at", Order: "desc"} albums, err := g.ds.Album(ctx).GetStarred(qo) diff --git a/server/subsonic/album_lists.go b/server/subsonic/album_lists.go index 51d256dbb..2100be437 100644 --- a/server/subsonic/album_lists.go +++ b/server/subsonic/album_lists.go @@ -59,8 +59,36 @@ func (c *AlbumListController) getAlbumList(r *http.Request) (engine.Entries, err 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 { + return nil, err + } + + var filter engine.AlbumFilter + switch typ { + 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) + } + + offset := utils.ParamInt(r, "offset", 0) + size := utils.MinInt(utils.ParamInt(r, "size", 10), 500) + + albums, err := c.listGen.GetAlbums(r.Context(), offset, size, filter) + if err != nil { + log.Error(r, "Error retrieving albums", "error", err) + return nil, errors.New("Internal Error") + } + + return albums, nil +} + func (c *AlbumListController) GetAlbumList(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) { - albums, err := c.getAlbumList(r) + albums, err := c.getNewAlbumList(r) if err != nil { return nil, NewError(responses.ErrorGeneric, err.Error()) } @@ -71,7 +99,7 @@ func (c *AlbumListController) GetAlbumList(w http.ResponseWriter, r *http.Reques } func (c *AlbumListController) GetAlbumList2(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) { - albums, err := c.getAlbumList(r) + albums, err := c.getNewAlbumList(r) if err != nil { return nil, NewError(responses.ErrorGeneric, err.Error()) } diff --git a/server/subsonic/api.go b/server/subsonic/api.go index 0e73b8ad4..833aca891 100644 --- a/server/subsonic/api.go +++ b/server/subsonic/api.go @@ -13,7 +13,7 @@ import ( "github.com/go-chi/chi" ) -const Version = "1.8.0" +const Version = "1.10.1" type Handler = func(http.ResponseWriter, *http.Request) (*responses.Subsonic, error)