Integrate ArtistIndex logic into Artist

This commit is contained in:
Deluan 2020-01-17 20:46:19 -05:00
parent 035fdaeb96
commit c0beaa6377
17 changed files with 110 additions and 427 deletions

View File

@ -50,8 +50,8 @@ func (c *BrowsingController) getArtistIndex(r *http.Request, ifModifiedSince tim
res.Index[i].Name = idx.ID res.Index[i].Name = idx.ID
res.Index[i].Artists = make([]responses.Artist, len(idx.Artists)) res.Index[i].Artists = make([]responses.Artist, len(idx.Artists))
for j, a := range idx.Artists { for j, a := range idx.Artists {
res.Index[i].Artists[j].Id = a.ArtistID res.Index[i].Artists[j].Id = a.ID
res.Index[i].Artists[j].Name = a.Artist res.Index[i].Artists[j].Name = a.Name
res.Index[i].Artists[j].AlbumCount = a.AlbumCount res.Index[i].Artists[j].AlbumCount = a.AlbumCount
} }
} }

View File

@ -23,15 +23,14 @@ type Browser interface {
GetGenres() (model.Genres, error) GetGenres() (model.Genres, error)
} }
func NewBrowser(pr model.PropertyRepository, fr model.MediaFolderRepository, ir model.ArtistIndexRepository, func NewBrowser(pr model.PropertyRepository, fr model.MediaFolderRepository,
ar model.ArtistRepository, alr model.AlbumRepository, mr model.MediaFileRepository, gr model.GenreRepository) Browser { ar model.ArtistRepository, alr model.AlbumRepository, mr model.MediaFileRepository, gr model.GenreRepository) Browser {
return &browser{pr, fr, ir, ar, alr, mr, gr} return &browser{pr, fr, ar, alr, mr, gr}
} }
type browser struct { type browser struct {
propRepo model.PropertyRepository propRepo model.PropertyRepository
folderRepo model.MediaFolderRepository folderRepo model.MediaFolderRepository
indexRepo model.ArtistIndexRepository
artistRepo model.ArtistRepository artistRepo model.ArtistRepository
albumRepo model.AlbumRepository albumRepo model.AlbumRepository
mfileRepo model.MediaFileRepository mfileRepo model.MediaFileRepository
@ -52,7 +51,7 @@ func (b *browser) Indexes(ifModifiedSince time.Time) (model.ArtistIndexes, time.
} }
if lastModified.After(ifModifiedSince) { if lastModified.After(ifModifiedSince) {
indexes, err := b.indexRepo.GetAll() indexes, err := b.artistRepo.GetIndex()
return indexes, lastModified, err return indexes, lastModified, err
} }

View File

@ -5,6 +5,13 @@ type Artist struct {
Name string Name string
AlbumCount int AlbumCount int
} }
type Artists []Artist
type ArtistIndex struct {
ID string
Artists Artists
}
type ArtistIndexes []ArtistIndex
type ArtistRepository interface { type ArtistRepository interface {
CountAll() (int64, error) CountAll() (int64, error)
@ -14,6 +21,5 @@ type ArtistRepository interface {
PurgeInactive(active Artists) error PurgeInactive(active Artists) error
Search(q string, offset int, size int) (Artists, error) Search(q string, offset int, size int) (Artists, error)
Refresh(ids ...string) error Refresh(ids ...string) error
GetIndex() (ArtistIndexes, error)
} }
type Artists []Artist

View File

@ -1,23 +0,0 @@
package model
type ArtistInfo struct {
ArtistID string
Artist string
AlbumCount int
}
type ArtistIndex struct {
ID string
Artists ArtistInfos
}
type ArtistInfos []ArtistInfo
type ArtistIndexes []ArtistIndex
// TODO Combine ArtistIndex with Artist
type ArtistIndexRepository interface {
Put(m *ArtistIndex) error
Refresh() error
GetAll() (ArtistIndexes, error)
DeleteAll() error
}

View File

@ -2,11 +2,14 @@ package persistence
import ( import (
"fmt" "fmt"
"sort"
"strings" "strings"
"github.com/astaxie/beego/orm" "github.com/astaxie/beego/orm"
"github.com/cloudsonic/sonic-server/conf"
"github.com/cloudsonic/sonic-server/log" "github.com/cloudsonic/sonic-server/log"
"github.com/cloudsonic/sonic-server/model" "github.com/cloudsonic/sonic-server/model"
"github.com/cloudsonic/sonic-server/utils"
) )
type Artist struct { type Artist struct {
@ -17,14 +20,27 @@ type Artist struct {
type artistRepository struct { type artistRepository struct {
searchableRepository searchableRepository
indexGroups utils.IndexGroups
} }
func NewArtistRepository() model.ArtistRepository { func NewArtistRepository() model.ArtistRepository {
r := &artistRepository{} r := &artistRepository{}
r.indexGroups = utils.ParseIndexGroups(conf.Sonic.IndexGroups)
r.tableName = "artist" r.tableName = "artist"
return r return r
} }
func (r *artistRepository) getIndexKey(a *Artist) string {
name := strings.ToLower(utils.NoArticle(a.Name))
for k, v := range r.indexGroups {
key := strings.ToLower(k)
if strings.HasPrefix(name, key) {
return v
}
}
return "#"
}
func (r *artistRepository) Put(a *model.Artist) error { func (r *artistRepository) Put(a *model.Artist) error {
ta := Artist(*a) ta := Artist(*a)
return withTx(func(o orm.Ormer) error { return withTx(func(o orm.Ormer) error {
@ -45,6 +61,34 @@ func (r *artistRepository) Get(id string) (*model.Artist, error) {
return &a, nil return &a, nil
} }
// TODO Cache the index (recalculate when there are changes to the DB)
func (r *artistRepository) GetIndex() (model.ArtistIndexes, error) {
var all []Artist
_, err := r.newQuery(Db()).OrderBy("name").All(&all)
if err != nil {
return nil, err
}
fullIdx := make(map[string]*model.ArtistIndex)
for _, a := range all {
ax := r.getIndexKey(&a)
idx, ok := fullIdx[ax]
if !ok {
idx = &model.ArtistIndex{ID: ax}
fullIdx[ax] = idx
}
idx.Artists = append(idx.Artists, model.Artist(a))
}
var result model.ArtistIndexes
for _, idx := range fullIdx {
result = append(result, *idx)
}
sort.Slice(result, func(i, j int) bool {
return result[i].ID < result[j].ID
})
return result, nil
}
func (r *artistRepository) Refresh(ids ...string) error { func (r *artistRepository) Refresh(ids ...string) error {
type refreshArtist struct { type refreshArtist struct {
Artist Artist
@ -71,17 +115,17 @@ where f.artist_id in ('%s') group by f.artist_id order by f.id`, strings.Join(id
var toInsert []Artist var toInsert []Artist
var toUpdate []Artist var toUpdate []Artist
for _, al := range artists { for _, ar := range artists {
if al.Compilation { if ar.Compilation {
al.AlbumArtist = "Various Artists" ar.AlbumArtist = "Various Artists"
} }
if al.AlbumArtist != "" { if ar.AlbumArtist != "" {
al.Name = al.AlbumArtist ar.Name = ar.AlbumArtist
} }
if al.CurrentId != "" { if ar.CurrentId != "" {
toUpdate = append(toUpdate, al.Artist) toUpdate = append(toUpdate, ar.Artist)
} else { } else {
toInsert = append(toInsert, al.Artist) toInsert = append(toInsert, ar.Artist)
} }
} }
if len(toInsert) > 0 { if len(toInsert) > 0 {
@ -93,7 +137,7 @@ where f.artist_id in ('%s') group by f.artist_id order by f.id`, strings.Join(id
} }
if len(toUpdate) > 0 { if len(toUpdate) > 0 {
for _, al := range toUpdate { for _, al := range toUpdate {
_, err := o.Update(&al, "name", "album_count") _, err := o.Update(&al)
if err != nil { if err != nil {
return err return err
} }

View File

@ -13,8 +13,9 @@ var _ = Describe("ArtistRepository", func() {
repo = NewArtistRepository() repo = NewArtistRepository()
}) })
Describe("Put/Get", func() {
It("saves and retrieves data", func() { It("saves and retrieves data", func() {
Expect(repo.Get("1")).To(Equal(&model.Artist{ID: "1", Name: "Saara Saara", AlbumCount: 2})) Expect(repo.Get("1")).To(Equal(&artistSaaraSaara))
}) })
It("overrides data if ID already exists", func() { It("overrides data if ID already exists", func() {
@ -26,6 +27,34 @@ var _ = Describe("ArtistRepository", func() {
_, err := repo.Get("999") _, err := repo.Get("999")
Expect(err).To(MatchError(model.ErrNotFound)) Expect(err).To(MatchError(model.ErrNotFound))
}) })
})
Describe("GetIndex", func() {
It("returns the index", func() {
idx, err := repo.GetIndex()
Expect(err).To(BeNil())
Expect(idx).To(Equal(model.ArtistIndexes{
{
ID: "B",
Artists: model.Artists{
artistBeatles,
},
},
{
ID: "K",
Artists: model.Artists{
artistKraftwerk,
},
},
{
ID: "S",
Artists: model.Artists{
{ID: "1", Name: "Saara Saara is The Best!", AlbumCount: 3},
},
},
}))
})
})
Describe("PurgeInactive", func() { Describe("PurgeInactive", func() {
BeforeEach(func() { BeforeEach(func() {

View File

@ -1,145 +0,0 @@
package persistence
import (
"sort"
"strings"
"github.com/astaxie/beego/orm"
"github.com/cloudsonic/sonic-server/conf"
"github.com/cloudsonic/sonic-server/model"
"github.com/cloudsonic/sonic-server/utils"
)
type ArtistInfo struct {
ID int `orm:"pk;auto;column(id)"`
Idx string
ArtistID string `orm:"column(artist_id)"`
Artist string
AlbumCount int
}
type tempIndex map[string]model.ArtistInfo
type artistIndexRepository struct {
sqlRepository
}
func NewArtistIndexRepository() model.ArtistIndexRepository {
r := &artistIndexRepository{}
r.tableName = "artist_info"
return r
}
func (r *artistIndexRepository) Put(idx *model.ArtistIndex) error {
return withTx(func(o orm.Ormer) error {
_, err := r.newQuery(o).Filter("idx", idx.ID).Delete()
if err != nil {
return err
}
for _, artist := range idx.Artists {
a := ArtistInfo{
Idx: idx.ID,
ArtistID: artist.ArtistID,
Artist: artist.Artist,
AlbumCount: artist.AlbumCount,
}
err := r.insert(o, &a)
if err != nil {
return err
}
}
return nil
})
}
func (r *artistIndexRepository) Refresh() error {
o := Db()
indexGroups := utils.ParseIndexGroups(conf.Sonic.IndexGroups)
artistIndex := make(map[string]tempIndex)
var artists []Artist
_, err := o.QueryTable(&Artist{}).All(&artists)
if err != nil {
return err
}
for _, ar := range artists {
r.collectIndex(indexGroups, &ar, artistIndex)
}
return r.saveIndex(artistIndex)
}
func (r *artistIndexRepository) collectIndex(ig utils.IndexGroups, a *Artist, artistIndex map[string]tempIndex) {
name := a.Name
indexName := strings.ToLower(utils.NoArticle(name))
if indexName == "" {
return
}
group := r.findGroup(ig, indexName)
artists := artistIndex[group]
if artists == nil {
artists = make(tempIndex)
artistIndex[group] = artists
}
artists[indexName] = model.ArtistInfo{ArtistID: a.ID, Artist: a.Name, AlbumCount: a.AlbumCount}
}
func (r *artistIndexRepository) findGroup(ig utils.IndexGroups, name string) string {
for k, v := range ig {
key := strings.ToLower(k)
if strings.HasPrefix(name, key) {
return v
}
}
return "#"
}
func (r *artistIndexRepository) saveIndex(artistIndex map[string]tempIndex) error {
r.DeleteAll()
for k, temp := range artistIndex {
idx := &model.ArtistIndex{ID: k}
for _, v := range temp {
idx.Artists = append(idx.Artists, v)
}
err := r.Put(idx)
if err != nil {
return err
}
}
return nil
}
func (r *artistIndexRepository) GetAll() (model.ArtistIndexes, error) {
var all []ArtistInfo
_, err := r.newQuery(Db()).OrderBy("idx", "artist").All(&all)
if err != nil {
return nil, err
}
fullIdx := make(map[string]*model.ArtistIndex)
for _, a := range all {
idx, ok := fullIdx[a.Idx]
if !ok {
idx = &model.ArtistIndex{ID: a.Idx}
fullIdx[a.Idx] = idx
}
idx.Artists = append(idx.Artists, model.ArtistInfo{
ArtistID: a.ArtistID,
Artist: a.Artist,
AlbumCount: a.AlbumCount,
})
}
var result model.ArtistIndexes
for _, idx := range fullIdx {
result = append(result, *idx)
}
sort.Slice(result, func(i, j int) bool {
return result[i].ID < result[j].ID
})
return result, nil
}
var _ model.ArtistIndexRepository = (*artistIndexRepository)(nil)

View File

@ -1,40 +0,0 @@
package persistence
import (
"github.com/cloudsonic/sonic-server/model"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Artist Index", func() {
var repo model.ArtistIndexRepository
BeforeEach(func() {
repo = NewArtistIndexRepository()
err := repo.DeleteAll()
if err != nil {
panic(err)
}
})
It("successfully persists data", func() {
idx1 := model.ArtistIndex{
ID: "D",
Artists: model.ArtistInfos{
{ArtistID: "4", Artist: "Doobie Brothers", AlbumCount: 2},
{ArtistID: "3", Artist: "The Doors", AlbumCount: 5},
},
}
idx2 := model.ArtistIndex{
ID: "S",
Artists: model.ArtistInfos{
{ArtistID: "1", Artist: "Saara Saara", AlbumCount: 3},
{ArtistID: "2", Artist: "Seu Jorge", AlbumCount: 1},
},
}
Expect(repo.Put(&idx1)).To(BeNil())
Expect(repo.Put(&idx2)).To(BeNil())
Expect(repo.GetAll()).To(Equal(model.ArtistIndexes{idx1, idx2}))
})
})

View File

@ -1,40 +0,0 @@
package persistence
import (
"encoding/json"
"errors"
"fmt"
"github.com/cloudsonic/sonic-server/model"
)
func CreateMockArtistIndexRepo() *MockArtistIndex {
return &MockArtistIndex{}
}
type MockArtistIndex struct {
model.ArtistIndexRepository
data model.ArtistIndexes
err bool
}
func (m *MockArtistIndex) SetError(err bool) {
m.err = err
}
func (m *MockArtistIndex) SetData(j string, length int) {
m.data = make(model.ArtistIndexes, length)
err := json.Unmarshal([]byte(j), &m.data)
if err != nil {
fmt.Println("ERROR: ", err)
}
}
func (m *MockArtistIndex) GetAll() (model.ArtistIndexes, error) {
if m.err {
return nil, errors.New("Error!")
}
return m.data, nil
}
var _ model.ArtistIndexRepository = (*MockArtistIndex)(nil)

View File

@ -74,7 +74,6 @@ func initORM(dbPath string) error {
orm.RegisterModel(new(Artist)) orm.RegisterModel(new(Artist))
orm.RegisterModel(new(Album)) orm.RegisterModel(new(Album))
orm.RegisterModel(new(MediaFile)) orm.RegisterModel(new(MediaFile))
orm.RegisterModel(new(ArtistInfo))
orm.RegisterModel(new(Checksum)) orm.RegisterModel(new(Checksum))
orm.RegisterModel(new(Property)) orm.RegisterModel(new(Property))
orm.RegisterModel(new(Playlist)) orm.RegisterModel(new(Playlist))

View File

@ -8,7 +8,6 @@ var Set = wire.NewSet(
NewArtistRepository, NewArtistRepository,
NewMediaFileRepository, NewMediaFileRepository,
NewAlbumRepository, NewAlbumRepository,
NewArtistIndexRepository,
NewCheckSumRepository, NewCheckSumRepository,
NewPropertyRepository, NewPropertyRepository,
NewPlaylistRepository, NewPlaylistRepository,

View File

@ -21,18 +21,16 @@ type Repositories struct {
mediaFile model.MediaFileRepository mediaFile model.MediaFileRepository
album model.AlbumRepository album model.AlbumRepository
artist model.ArtistRepository artist model.ArtistRepository
index model.ArtistIndexRepository
playlist model.PlaylistRepository playlist model.PlaylistRepository
property model.PropertyRepository property model.PropertyRepository
} }
func New(mfRepo model.MediaFileRepository, albumRepo model.AlbumRepository, artistRepo model.ArtistRepository, idxRepo model.ArtistIndexRepository, plsRepo model.PlaylistRepository, folderRepo model.MediaFolderRepository, property model.PropertyRepository) *Scanner { func New(mfRepo model.MediaFileRepository, albumRepo model.AlbumRepository, artistRepo model.ArtistRepository, plsRepo model.PlaylistRepository, folderRepo model.MediaFolderRepository, property model.PropertyRepository) *Scanner {
repos := Repositories{ repos := Repositories{
folder: folderRepo, folder: folderRepo,
mediaFile: mfRepo, mediaFile: mfRepo,
album: albumRepo, album: albumRepo,
artist: artistRepo, artist: artistRepo,
index: idxRepo,
playlist: plsRepo, playlist: plsRepo,
property: property, property: property,
} }

View File

@ -25,7 +25,6 @@ var _ = XDescribe("TODO: REMOVE", func() {
mediaFile: persistence.NewMediaFileRepository(), mediaFile: persistence.NewMediaFileRepository(),
album: persistence.NewAlbumRepository(), album: persistence.NewAlbumRepository(),
artist: persistence.NewArtistRepository(), artist: persistence.NewArtistRepository(),
index: persistence.NewArtistIndexRepository(),
playlist: nil, playlist: nil,
} }
It("WORKS!", func() { It("WORKS!", func() {

View File

@ -79,11 +79,6 @@ func (s *TagScanner) Scan(ctx context.Context, lastModifiedSince time.Time) erro
return err return err
} }
err = s.repos.index.Refresh()
if err != nil {
return err
}
return nil return nil
} }

View File

@ -4,13 +4,11 @@ import (
"fmt" "fmt"
"os" "os"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/cloudsonic/sonic-server/conf" "github.com/cloudsonic/sonic-server/conf"
"github.com/cloudsonic/sonic-server/log" "github.com/cloudsonic/sonic-server/log"
"github.com/cloudsonic/sonic-server/model" "github.com/cloudsonic/sonic-server/model"
"github.com/cloudsonic/sonic-server/utils"
) )
type Scanner interface { type Scanner interface {
@ -21,29 +19,25 @@ type Scanner interface {
Playlists() map[string]*model.Playlist Playlists() map[string]*model.Playlist
} }
type tempIndex map[string]model.ArtistInfo
type Importer struct { type Importer struct {
scanner Scanner scanner Scanner
mediaFolder string mediaFolder string
mfRepo model.MediaFileRepository mfRepo model.MediaFileRepository
albumRepo model.AlbumRepository albumRepo model.AlbumRepository
artistRepo model.ArtistRepository artistRepo model.ArtistRepository
idxRepo model.ArtistIndexRepository
plsRepo model.PlaylistRepository plsRepo model.PlaylistRepository
propertyRepo model.PropertyRepository propertyRepo model.PropertyRepository
lastScan time.Time lastScan time.Time
lastCheck time.Time lastCheck time.Time
} }
func NewImporter(mediaFolder string, scanner Scanner, mfRepo model.MediaFileRepository, albumRepo model.AlbumRepository, artistRepo model.ArtistRepository, idxRepo model.ArtistIndexRepository, plsRepo model.PlaylistRepository, propertyRepo model.PropertyRepository) *Importer { func NewImporter(mediaFolder string, scanner Scanner, mfRepo model.MediaFileRepository, albumRepo model.AlbumRepository, artistRepo model.ArtistRepository, plsRepo model.PlaylistRepository, propertyRepo model.PropertyRepository) *Importer {
return &Importer{ return &Importer{
scanner: scanner, scanner: scanner,
mediaFolder: mediaFolder, mediaFolder: mediaFolder,
mfRepo: mfRepo, mfRepo: mfRepo,
albumRepo: albumRepo, albumRepo: albumRepo,
artistRepo: artistRepo, artistRepo: artistRepo,
idxRepo: idxRepo,
plsRepo: plsRepo, plsRepo: plsRepo,
propertyRepo: propertyRepo, propertyRepo: propertyRepo,
} }
@ -131,7 +125,6 @@ func (i *Importer) importLibrary() (err error) {
log.Debug("Imported artists", "total", len(ars)) log.Debug("Imported artists", "total", len(ars))
pls := i.importPlaylists() pls := i.importPlaylists()
log.Debug("Imported playlists", "total", len(pls)) log.Debug("Imported playlists", "total", len(pls))
i.importArtistIndex()
log.Debug("Purging old data") log.Debug("Purging old data")
if err := i.mfRepo.PurgeInactive(mfs); err != nil { if err := i.mfRepo.PurgeInactive(mfs); err != nil {
@ -239,19 +232,6 @@ func (i *Importer) importArtists() model.Artists {
return ars return ars
} }
func (i *Importer) importArtistIndex() {
indexGroups := utils.ParseIndexGroups(conf.Sonic.IndexGroups)
artistIndex := make(map[string]tempIndex)
for _, ar := range i.scanner.Artists() {
i.collectIndex(indexGroups, ar, artistIndex)
}
if err := i.saveIndex(artistIndex); err != nil {
log.Error(err)
}
}
func (i *Importer) importPlaylists() model.Playlists { func (i *Importer) importPlaylists() model.Playlists {
pls := make(model.Playlists, len(i.scanner.Playlists())) pls := make(model.Playlists, len(i.scanner.Playlists()))
j := 0 j := 0
@ -267,44 +247,3 @@ func (i *Importer) importPlaylists() model.Playlists {
} }
return pls return pls
} }
func (i *Importer) collectIndex(ig utils.IndexGroups, a *model.Artist, artistIndex map[string]tempIndex) {
name := a.Name
indexName := strings.ToLower(utils.NoArticle(name))
if indexName == "" {
return
}
group := i.findGroup(ig, indexName)
artists := artistIndex[group]
if artists == nil {
artists = make(tempIndex)
artistIndex[group] = artists
}
artists[indexName] = model.ArtistInfo{ArtistID: a.ID, Artist: a.Name, AlbumCount: a.AlbumCount}
}
func (i *Importer) findGroup(ig utils.IndexGroups, name string) string {
for k, v := range ig {
key := strings.ToLower(k)
if strings.HasPrefix(name, key) {
return v
}
}
return "#"
}
func (i *Importer) saveIndex(artistIndex map[string]tempIndex) error {
i.idxRepo.DeleteAll()
for k, temp := range artistIndex {
idx := &model.ArtistIndex{ID: k}
for _, v := range temp {
idx.Artists = append(idx.Artists, v)
}
err := i.idxRepo.Put(idx)
if err != nil {
return err
}
}
return nil
}

View File

@ -1,74 +0,0 @@
package scanner_legacy
import (
"testing"
"github.com/cloudsonic/sonic-server/model"
"github.com/cloudsonic/sonic-server/tests"
"github.com/cloudsonic/sonic-server/utils"
. "github.com/smartystreets/goconvey/convey"
)
func TestCollectIndex(t *testing.T) {
tests.Init(t, false)
ig := utils.IndexGroups{"A": "A", "B": "B", "Tom": "Tom", "X": "X-Z"}
importer := &Importer{}
Convey("Simple Name", t, func() {
a := &model.Artist{Name: "Björk"}
artistIndex := make(map[string]tempIndex)
importer.collectIndex(ig, a, artistIndex)
So(artistIndex, ShouldContainKey, "B")
So(artistIndex["B"], ShouldContainKey, "björk")
for _, k := range []string{"A", "Tom", "X-Z", "#"} {
So(artistIndex, ShouldNotContainKey, k)
}
})
Convey("Name not in the index", t, func() {
a := &model.Artist{Name: "Kraftwerk"}
artistIndex := make(map[string]tempIndex)
importer.collectIndex(ig, a, artistIndex)
So(artistIndex, ShouldContainKey, "#")
So(artistIndex["#"], ShouldContainKey, "kraftwerk")
for _, k := range []string{"A", "B", "Tom", "X-Z"} {
So(artistIndex, ShouldNotContainKey, k)
}
})
Convey("Name starts with an article", t, func() {
a := &model.Artist{Name: "The The"}
artistIndex := make(map[string]tempIndex)
importer.collectIndex(ig, a, artistIndex)
So(artistIndex, ShouldContainKey, "#")
So(artistIndex["#"], ShouldContainKey, "the")
for _, k := range []string{"A", "B", "Tom", "X-Z"} {
So(artistIndex, ShouldNotContainKey, k)
}
})
Convey("Name match a multichar entry", t, func() {
a := &model.Artist{Name: "Tom Waits"}
artistIndex := make(map[string]tempIndex)
importer.collectIndex(ig, a, artistIndex)
So(artistIndex, ShouldContainKey, "Tom")
So(artistIndex["Tom"], ShouldContainKey, "tom waits")
for _, k := range []string{"A", "B", "X-Z", "#"} {
So(artistIndex, ShouldNotContainKey, k)
}
})
}

View File

@ -24,12 +24,11 @@ func CreateApp(musicFolder string) *server.Server {
mediaFileRepository := persistence.NewMediaFileRepository() mediaFileRepository := persistence.NewMediaFileRepository()
albumRepository := persistence.NewAlbumRepository() albumRepository := persistence.NewAlbumRepository()
artistRepository := persistence.NewArtistRepository() artistRepository := persistence.NewArtistRepository()
artistIndexRepository := persistence.NewArtistIndexRepository()
playlistRepository := persistence.NewPlaylistRepository() playlistRepository := persistence.NewPlaylistRepository()
propertyRepository := persistence.NewPropertyRepository() propertyRepository := persistence.NewPropertyRepository()
importer := scanner_legacy.NewImporter(musicFolder, itunesScanner, mediaFileRepository, albumRepository, artistRepository, artistIndexRepository, playlistRepository, propertyRepository) importer := scanner_legacy.NewImporter(musicFolder, itunesScanner, mediaFileRepository, albumRepository, artistRepository, playlistRepository, propertyRepository)
mediaFolderRepository := persistence.NewMediaFolderRepository() mediaFolderRepository := persistence.NewMediaFolderRepository()
scannerScanner := scanner.New(mediaFileRepository, albumRepository, artistRepository, artistIndexRepository, playlistRepository, mediaFolderRepository, propertyRepository) scannerScanner := scanner.New(mediaFileRepository, albumRepository, artistRepository, playlistRepository, mediaFolderRepository, propertyRepository)
serverServer := server.New(importer, scannerScanner) serverServer := server.New(importer, scannerScanner)
return serverServer return serverServer
} }
@ -37,12 +36,11 @@ func CreateApp(musicFolder string) *server.Server {
func CreateSubsonicAPIRouter() *api.Router { func CreateSubsonicAPIRouter() *api.Router {
propertyRepository := persistence.NewPropertyRepository() propertyRepository := persistence.NewPropertyRepository()
mediaFolderRepository := persistence.NewMediaFolderRepository() mediaFolderRepository := persistence.NewMediaFolderRepository()
artistIndexRepository := persistence.NewArtistIndexRepository()
artistRepository := persistence.NewArtistRepository() artistRepository := persistence.NewArtistRepository()
albumRepository := persistence.NewAlbumRepository() albumRepository := persistence.NewAlbumRepository()
mediaFileRepository := persistence.NewMediaFileRepository() mediaFileRepository := persistence.NewMediaFileRepository()
genreRepository := persistence.NewGenreRepository() genreRepository := persistence.NewGenreRepository()
browser := engine.NewBrowser(propertyRepository, mediaFolderRepository, artistIndexRepository, artistRepository, albumRepository, mediaFileRepository, genreRepository) browser := engine.NewBrowser(propertyRepository, mediaFolderRepository, artistRepository, albumRepository, mediaFileRepository, genreRepository)
cover := engine.NewCover(mediaFileRepository, albumRepository) cover := engine.NewCover(mediaFileRepository, albumRepository)
nowPlayingRepository := persistence.NewNowPlayingRepository() nowPlayingRepository := persistence.NewNowPlayingRepository()
listGenerator := engine.NewListGenerator(albumRepository, mediaFileRepository, nowPlayingRepository) listGenerator := engine.NewListGenerator(albumRepository, mediaFileRepository, nowPlayingRepository)