navidrome/server/api/includes.go
2023-06-07 10:49:56 -04:00

123 lines
2.9 KiB
Go

package api
import (
"context"
"sort"
"github.com/Masterminds/squirrel"
"github.com/navidrome/navidrome/model"
"golang.org/x/exp/slices"
)
type includedResources struct {
ctx context.Context
ds model.DataStore
includes *includeSlice
resources []IncludedResource
ids map[ResourceType][]string
}
func newIncludedResources(ctx context.Context, ds model.DataStore, includes *includeSlice) *includedResources {
i := &includedResources{
ctx: ctx,
ds: ds,
includes: includes,
}
if includes != nil {
i.ids = make(map[ResourceType][]string)
for _, inc := range *includes {
i.ids[ResourceType(inc)] = []string{}
}
}
return i
}
func (i *includedResources) Tracks(trackIds ...string) {
if i.ids == nil || i.ids[ResourceTypeTrack] == nil {
return
}
i.ids[ResourceTypeTrack] = append(i.ids[ResourceTypeTrack], trackIds...)
}
func (i *includedResources) Albums(albumIds ...string) {
if i.ids == nil || i.ids[ResourceTypeAlbum] == nil {
return
}
i.ids[ResourceTypeAlbum] = append(i.ids[ResourceTypeAlbum], albumIds...)
}
func (i *includedResources) Artists(artistIds ...string) {
if i.ids == nil || i.ids[ResourceTypeArtist] == nil {
return
}
i.ids[ResourceTypeArtist] = append(i.ids[ResourceTypeArtist], artistIds...)
}
func (i *includedResources) addTracks(albumIds []string) error {
tracks, err := i.ds.MediaFile(i.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"album_id": albumIds}})
if err != nil {
return err
}
for _, tr := range tracks {
inc := &IncludedResource{}
_ = inc.FromTrack(toAPITrack(tr))
i.resources = append(i.resources, *inc)
}
return nil
}
func (i *includedResources) addAlbums(albumIds []string) error {
albums, err := i.ds.Album(i.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"id": albumIds}})
if err != nil {
return err
}
for _, al := range albums {
inc := &IncludedResource{}
_ = inc.FromAlbum(toAPIAlbum(al))
i.resources = append(i.resources, *inc)
}
return nil
}
func (i *includedResources) addArtists(artistIds []string) error {
artists, err := i.ds.Artist(i.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"artist.id": artistIds}})
if err != nil {
return err
}
for _, ar := range artists {
inc := &IncludedResource{}
_ = inc.FromArtist(toAPIArtist(ar))
i.resources = append(i.resources, *inc)
}
return nil
}
func (i *includedResources) Build() (*[]IncludedResource, error) {
if i.includes == nil {
return nil, nil
}
for _, typ := range *i.includes {
ids := i.ids[ResourceType(typ)]
sort.Strings(ids)
slices.Compact(ids)
if len(ids) == 0 {
continue
}
switch ResourceType(typ) {
case ResourceTypeAlbum:
if err := i.addAlbums(ids); err != nil {
return nil, err
}
case ResourceTypeArtist:
if err := i.addArtists(ids); err != nil {
return nil, err
}
case ResourceTypeTrack:
if err := i.addTracks(ids); err != nil {
return nil, err
}
}
}
return &i.resources, nil
}