From 757e1992d75156b5425b1a872d0562b6022e22d4 Mon Sep 17 00:00:00 2001 From: Deluan Date: Wed, 2 Mar 2016 23:15:17 -0500 Subject: [PATCH] Bare bones getMusicDirectory for albums! --- api/get_music_directory.go | 69 +++++++++++++++---- api/get_music_directory_test.go | 15 ++++ conf/inject_definitions.go | 1 + domain/{media_file.go => mediafile.go} | 2 + domain/{media_folder.go => mediafolder.go} | 0 persistence/album_repository.go | 2 +- ..._repository.go => mediafile_repository.go} | 6 ++ ...pository.go => mediafolders_repository.go} | 0 scanner/scanner.go | 1 + tests/mocks/mock_mediafile_repo.go | 65 +++++++++++++++++ 10 files changed, 146 insertions(+), 15 deletions(-) rename domain/{media_file.go => mediafile.go} (85%) rename domain/{media_folder.go => mediafolder.go} (100%) rename persistence/{media_file_repository.go => mediafile_repository.go} (64%) rename persistence/{media_folders_repository.go => mediafolders_repository.go} (100%) create mode 100644 tests/mocks/mock_mediafile_repo.go diff --git a/api/get_music_directory.go b/api/get_music_directory.go index e32807fd..eb2c192b 100644 --- a/api/get_music_directory.go +++ b/api/get_music_directory.go @@ -12,11 +12,13 @@ type GetMusicDirectoryController struct { BaseAPIController artistRepo domain.ArtistRepository albumRepo domain.AlbumRepository + mFileRepo domain.MediaFileRepository } func (c *GetMusicDirectoryController) Prepare() { inject.ExtractAssignable(utils.Graph, &c.artistRepo) inject.ExtractAssignable(utils.Graph, &c.albumRepo) + inject.ExtractAssignable(utils.Graph, &c.mFileRepo) } func (c *GetMusicDirectoryController) Get() { @@ -26,16 +28,9 @@ func (c *GetMusicDirectoryController) Get() { c.SendError(responses.ERROR_MISSING_PARAMETER, "id parameter required") } - found, err := c.artistRepo.Exists(id) - if err != nil { - beego.Error("Error searching for Artist:", err) - c.SendError(responses.ERROR_GENERIC, "Internal Error") - } - dir := &responses.Directory{} + a, albums, found := c.retrieveArtist(id) if found { - a, albums := c.retrieveArtist(id) - dir.Id = a.Id dir.Name = a.Name dir.Child = make([]responses.Child, len(albums)) @@ -45,12 +40,29 @@ func (c *GetMusicDirectoryController) Get() { dir.Child[i].IsDir = true dir.Child[i].Album = al.Name dir.Child[i].Year = al.Year - dir.Child[i].Artist = a.Name + dir.Child[i].Artist = a.Name //TODO AlbumArtist dir.Child[i].Genre = al.Genre } } else { - beego.Info("Artist", id, "not found") - c.SendError(responses.ERROR_DATA_NOT_FOUND, "Directory not found") + al, tracks, found := c.retrieveAlbum(id) + if found { + dir.Id = al.Id + dir.Name = al.Name + dir.Child = make([]responses.Child, len(tracks)) + for i, mf := range tracks { + dir.Child[i].Id = mf.Id + dir.Child[i].Title = mf.Title + dir.Child[i].IsDir = false + dir.Child[i].Album = mf.Album + dir.Child[i].Year = mf.Year + dir.Child[i].Artist = mf.AlbumArtist + dir.Child[i].Genre = mf.Genre + dir.Child[i].Track = mf.Track + } + } else { + beego.Info("Id", id, "not found") + c.SendError(responses.ERROR_DATA_NOT_FOUND, "Directory not found") + } } response := c.NewEmpty() @@ -58,8 +70,15 @@ func (c *GetMusicDirectoryController) Get() { c.SendResponse(response) } -func (c *GetMusicDirectoryController) retrieveArtist(id string) (a *domain.Artist, as[]domain.Album) { - var err error +func (c *GetMusicDirectoryController) retrieveArtist(id string) (a *domain.Artist, as[]domain.Album, found bool) { + found, err := c.artistRepo.Exists(id) + if err != nil { + beego.Error("Error searching for Artist:", err) + c.SendError(responses.ERROR_GENERIC, "Internal Error") + } + if !found { + return nil, nil, false + } if a, err = c.artistRepo.Get(id); err != nil { beego.Error("Error reading Artist from DB", err) @@ -71,4 +90,26 @@ func (c *GetMusicDirectoryController) retrieveArtist(id string) (a *domain.Artis c.SendError(responses.ERROR_GENERIC, "Internal Error") } return -} \ No newline at end of file +} + +func (c *GetMusicDirectoryController) retrieveAlbum(id string) (al *domain.Album, mfs[]domain.MediaFile, found bool) { + found, err := c.albumRepo.Exists(id) + if err != nil { + beego.Error("Error searching for Album:", err) + c.SendError(responses.ERROR_GENERIC, "Internal Error") + } + if !found { + return nil, nil, false + } + + if al, err = c.albumRepo.Get(id); err != nil { + beego.Error("Error reading Album from DB", err) + c.SendError(responses.ERROR_GENERIC, "Internal Error") + } + + if mfs, err = c.mFileRepo.FindByAlbum(id); err != nil { + beego.Error("Error reading Album from DB", err) + c.SendError(responses.ERROR_GENERIC, "Internal Error") + } + return +} diff --git a/api/get_music_directory_test.go b/api/get_music_directory_test.go index 90b4054f..8b6f189e 100644 --- a/api/get_music_directory_test.go +++ b/api/get_music_directory_test.go @@ -22,6 +22,10 @@ func TestGetMusicDirectory(t *testing.T) { utils.DefineSingleton(new(domain.AlbumRepository), func() domain.AlbumRepository { return mockAlbumRepo }) + mockMediaFileRepo := mocks.CreateMockMediaFileRepo() + utils.DefineSingleton(new(domain.MediaFileRepository), func() domain.MediaFileRepository { + return mockMediaFileRepo + }) Convey("Subject: GetMusicDirectory Endpoint", t, func() { Convey("Should fail if missing Id parameter", func() { @@ -58,12 +62,23 @@ func TestGetMusicDirectory(t *testing.T) { So(w.Body, ShouldContainJSON, `"child":[{"album":"Tardis","artist":"The KLF","id":"A","isDir":true,"title":"Tardis"}]`) }) }) + Convey("When id matches an album with tracks", func() { + mockArtistRepo.SetData(`[{"Id":"2","Name":"Céu"}]`, 1) + mockAlbumRepo.SetData(`[{"Id":"A","Name":"Vagarosa","ArtistId":"2"}]`, 1) + mockMediaFileRepo.SetData(`[{"Id":"3","Title":"Cangote","AlbumId":"A"}]`, 1) + _, w := Get(AddParams("/rest/getMusicDirectory.view", "id=A"), "TestGetMusicDirectory") + + So(w.Body, ShouldContainJSON, `"child":[{"id":"3","isDir":false,"title":"Cangote"}]`) + }) Reset(func() { mockArtistRepo.SetData("[]", 0) mockArtistRepo.SetError(false) mockAlbumRepo.SetData("[]", 0) mockAlbumRepo.SetError(false) + + mockMediaFileRepo.SetData("[]", 0) + mockMediaFileRepo.SetError(false) }) }) } \ No newline at end of file diff --git a/conf/inject_definitions.go b/conf/inject_definitions.go index 22a27e2e..be1cc284 100644 --- a/conf/inject_definitions.go +++ b/conf/inject_definitions.go @@ -12,4 +12,5 @@ func init() { utils.DefineSingleton(new(domain.MediaFolderRepository), persistence.NewMediaFolderRepository) utils.DefineSingleton(new(domain.ArtistRepository), persistence.NewArtistRepository) utils.DefineSingleton(new(domain.AlbumRepository), persistence.NewAlbumRepository) + utils.DefineSingleton(new(domain.MediaFileRepository), persistence.NewMediaFileRepository) } diff --git a/domain/media_file.go b/domain/mediafile.go similarity index 85% rename from domain/media_file.go rename to domain/mediafile.go index e5aa3487..9ea8beef 100644 --- a/domain/media_file.go +++ b/domain/mediafile.go @@ -13,6 +13,7 @@ type MediaFile struct { AlbumArtist string AlbumId string `parent:"album"` Track int + Year int Genre string Compilation bool CreatedAt time.Time @@ -22,4 +23,5 @@ type MediaFile struct { type MediaFileRepository interface { BaseRepository Put(m *MediaFile) error + FindByAlbum(albumId string) ([]MediaFile, error) } diff --git a/domain/media_folder.go b/domain/mediafolder.go similarity index 100% rename from domain/media_folder.go rename to domain/mediafolder.go diff --git a/persistence/album_repository.go b/persistence/album_repository.go index 277e3ab7..b3ce5715 100644 --- a/persistence/album_repository.go +++ b/persistence/album_repository.go @@ -29,6 +29,6 @@ func (r *albumRepository) Get(id string) (*domain.Album, error) { func (r *albumRepository) FindByArtist(artistId string) ([]domain.Album, error) { var as = make([]domain.Album, 0) - err := r.loadChildren("artist", artistId, &as, "") + err := r.loadChildren("artist", artistId, &as, "Year") return as, err } diff --git a/persistence/media_file_repository.go b/persistence/mediafile_repository.go similarity index 64% rename from persistence/media_file_repository.go rename to persistence/mediafile_repository.go index c132f091..8a1978ad 100644 --- a/persistence/media_file_repository.go +++ b/persistence/mediafile_repository.go @@ -17,3 +17,9 @@ func NewMediaFileRepository() domain.MediaFileRepository { func (r *mediaFileRepository) Put(m *domain.MediaFile) error { return r.saveOrUpdate(m.Id, m) } + +func (r *mediaFileRepository) FindByAlbum(albumId string) ([]domain.MediaFile, error) { + var mfs = make([]domain.MediaFile, 0) + err := r.loadChildren("album", albumId, &mfs, "Track") + return mfs, err +} diff --git a/persistence/media_folders_repository.go b/persistence/mediafolders_repository.go similarity index 100% rename from persistence/media_folders_repository.go rename to persistence/mediafolders_repository.go diff --git a/scanner/scanner.go b/scanner/scanner.go index 59b2b520..307bee91 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -76,6 +76,7 @@ func parseTrack(t *Track) (*domain.MediaFile, *domain.Album, *domain.Artist) { UpdatedAt: t.UpdatedAt, Track: t.TrackNumber, Genre: t.Genre, + Year: t.Year, } album := &domain.Album{ diff --git a/tests/mocks/mock_mediafile_repo.go b/tests/mocks/mock_mediafile_repo.go new file mode 100644 index 00000000..8c35c36d --- /dev/null +++ b/tests/mocks/mock_mediafile_repo.go @@ -0,0 +1,65 @@ +package mocks + +import ( + "encoding/json" + "fmt" + "github.com/deluan/gosonic/domain" +"errors" +) + +func CreateMockMediaFileRepo() *MockMediaFile { + return &MockMediaFile{} +} + +type MockMediaFile struct { + domain.MediaFileRepository + data map[string]*domain.MediaFile + err bool +} + +func (m *MockMediaFile) SetError(err bool) { + m.err = err +} + +func (m *MockMediaFile) SetData(j string, size int) { + m.data = make(map[string]*domain.MediaFile) + var l = make([]domain.MediaFile, size) + err := json.Unmarshal([]byte(j), &l) + if err != nil { + fmt.Println("ERROR: ", err) + } + for _, a := range l { + m.data[a.Id] = &a + } +} + +func (m *MockMediaFile) Exists(id string) (bool, error) { + if m.err { + return false, errors.New("Error!") + } + _, found := m.data[id]; + return found, nil +} + +func (m *MockMediaFile) Get(id string) (*domain.MediaFile, error) { + if m.err { + return nil, errors.New("Error!") + } + return m.data[id], nil +} + +func (m *MockMediaFile) FindByAlbum(artistId string) ([]domain.MediaFile, error) { + if m.err { + return nil, errors.New("Error!") + } + var res = make([]domain.MediaFile, len(m.data)) + i := 0 + for _, a := range m.data { + if a.AlbumId == artistId { + res[i] = *a + i++ + } + } + + return res, nil +} \ No newline at end of file