diff --git a/api/get_indexes.go b/api/get_indexes.go index 00c3a423d..6504537eb 100644 --- a/api/get_indexes.go +++ b/api/get_indexes.go @@ -1,23 +1,23 @@ package api import ( + "fmt" "github.com/astaxie/beego" "github.com/deluan/gosonic/api/responses" - "github.com/deluan/gosonic/consts" "github.com/deluan/gosonic/domain" + "github.com/deluan/gosonic/engine" "github.com/deluan/gosonic/utils" "github.com/karlkfi/inject" - "strconv" ) type GetIndexesController struct { BaseAPIController - repo domain.ArtistIndexRepository properties domain.PropertyRepository + browser engine.Browser } func (c *GetIndexesController) Prepare() { - inject.ExtractAssignable(utils.Graph, &c.repo) + inject.ExtractAssignable(utils.Graph, &c.browser) inject.ExtractAssignable(utils.Graph, &c.properties) } @@ -25,40 +25,28 @@ func (c *GetIndexesController) Prepare() { func (c *GetIndexesController) Get() { var err error - ifModifiedSince := c.Input().Get("ifModifiedSince") - if ifModifiedSince == "" { - ifModifiedSince = "0" - } + var ifModifiedSince int64 + c.Ctx.Input.Bind(&ifModifiedSince, "ifModifiedSince") - res := responses.Indexes{} - res.IgnoredArticles = beego.AppConfig.String("ignoredArticles") - - res.LastModified, err = c.properties.DefaultGet(consts.LastScan, "-1") + indexes, lastModified, err := c.browser.Indexes(utils.ToTime(ifModifiedSince)) if err != nil { - beego.Error("Error retrieving LastScan property:", err) + beego.Error("Error retrieving Indexes:", err) c.SendError(responses.ERROR_GENERIC, "Internal Error") } - i, _ := strconv.Atoi(ifModifiedSince) - l, _ := strconv.Atoi(res.LastModified) + res := responses.Indexes{ + IgnoredArticles: beego.AppConfig.String("ignoredArticles"), + LastModified: fmt.Sprint(utils.ToMillis(lastModified)), + } - if l > i { - indexes, err := c.repo.GetAll() - if err != nil { - beego.Error("Error retrieving Indexes:", err) - c.SendError(responses.ERROR_GENERIC, "Internal Error") + res.Index = make([]responses.Index, len(indexes)) + for i, idx := range indexes { + res.Index[i].Name = idx.Id + res.Index[i].Artists = make([]responses.Artist, len(idx.Artists)) + for j, a := range idx.Artists { + res.Index[i].Artists[j].Id = a.ArtistId + res.Index[i].Artists[j].Name = a.Artist } - - res.Index = make([]responses.Index, len(indexes)) - for i, idx := range indexes { - res.Index[i].Name = idx.Id - res.Index[i].Artists = make([]responses.Artist, len(idx.Artists)) - for j, a := range idx.Artists { - res.Index[i].Artists[j].Id = a.ArtistId - res.Index[i].Artists[j].Name = a.Artist - } - } - } response := c.NewEmpty() diff --git a/api/get_music_folders.go b/api/get_music_folders.go index 3aed8b50d..787d8bba4 100644 --- a/api/get_music_folders.go +++ b/api/get_music_folders.go @@ -2,22 +2,22 @@ package api import ( "github.com/deluan/gosonic/api/responses" - "github.com/deluan/gosonic/domain" + "github.com/deluan/gosonic/engine" "github.com/deluan/gosonic/utils" "github.com/karlkfi/inject" ) type GetMusicFoldersController struct { BaseAPIController - repo domain.MediaFolderRepository + browser engine.Browser } func (c *GetMusicFoldersController) Prepare() { - inject.ExtractAssignable(utils.Graph, &c.repo) + inject.ExtractAssignable(utils.Graph, &c.browser) } func (c *GetMusicFoldersController) Get() { - mediaFolderList, _ := c.repo.GetAll() + mediaFolderList, _ := c.browser.MediaFolders() folders := make([]responses.MusicFolder, len(mediaFolderList)) for i, f := range mediaFolderList { folders[i].Id = f.Id diff --git a/conf/inject_definitions.go b/conf/inject_definitions.go index be1cc284f..86d1f5318 100644 --- a/conf/inject_definitions.go +++ b/conf/inject_definitions.go @@ -2,15 +2,20 @@ package conf import ( "github.com/deluan/gosonic/domain" + "github.com/deluan/gosonic/engine" "github.com/deluan/gosonic/persistence" "github.com/deluan/gosonic/utils" ) func init() { - utils.DefineSingleton(new(domain.ArtistIndexRepository), persistence.NewArtistIndexRepository) - utils.DefineSingleton(new(domain.PropertyRepository), persistence.NewPropertyRepository) - utils.DefineSingleton(new(domain.MediaFolderRepository), persistence.NewMediaFolderRepository) + // Persistence + ir := utils.DefineSingleton(new(domain.ArtistIndexRepository), persistence.NewArtistIndexRepository) + pr := utils.DefineSingleton(new(domain.PropertyRepository), persistence.NewPropertyRepository) + mfr := 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) + + // Engine (Use cases) + utils.DefineSingleton(new(engine.Browser), engine.NewBrowser, pr, mfr, ir) } diff --git a/engine/browser.go b/engine/browser.go new file mode 100644 index 000000000..1aa85e06a --- /dev/null +++ b/engine/browser.go @@ -0,0 +1,47 @@ +package engine + +import ( + "errors" + "fmt" + "github.com/deluan/gosonic/consts" + "github.com/deluan/gosonic/domain" + "github.com/deluan/gosonic/utils" + "strconv" + "time" +) + +type Browser interface { + MediaFolders() (domain.MediaFolders, error) + Indexes(ifModifiedSince time.Time) (domain.ArtistIndexes, time.Time, error) +} + +func NewBrowser(propRepo domain.PropertyRepository, folderRepo domain.MediaFolderRepository, indexRepo domain.ArtistIndexRepository) Browser { + return browser{propRepo, folderRepo, indexRepo} +} + +type browser struct { + propRepo domain.PropertyRepository + folderRepo domain.MediaFolderRepository + indexRepo domain.ArtistIndexRepository +} + +func (b browser) MediaFolders() (domain.MediaFolders, error) { + return b.folderRepo.GetAll() +} + +func (b browser) Indexes(ifModifiedSince time.Time) (domain.ArtistIndexes, time.Time, error) { + l, err := b.propRepo.DefaultGet(consts.LastScan, "-1") + ms, _ := strconv.ParseInt(l, 10, 64) + lastModified := utils.ToTime(ms) + + if err != nil { + return domain.ArtistIndexes{}, time.Time{}, errors.New(fmt.Sprintf("Error retrieving LastScan property: %v", err)) + } + + if lastModified.After(ifModifiedSince) { + indexes, err := b.indexRepo.GetAll() + return indexes, lastModified, err + } + + return domain.ArtistIndexes{}, lastModified, nil +} diff --git a/utils/graph.go b/utils/graph.go index 9aacb449a..18891db2f 100644 --- a/utils/graph.go +++ b/utils/graph.go @@ -11,7 +11,7 @@ var ( definitions map[reflect.Type]interface{} ) -func DefineSingleton(ptr interface{}, constructor interface{}, args ...interface{}) { +func DefineSingleton(ptr interface{}, constructor interface{}, args ...interface{}) interface{} { typ := reflect.TypeOf(ptr) provider := inject.NewProvider(constructor, args...) @@ -21,6 +21,7 @@ func DefineSingleton(ptr interface{}, constructor interface{}, args ...interface definitions[typ] = ptr } Graph.Define(ptr, provider) + return ptr } func init() { diff --git a/utils/time.go b/utils/time.go new file mode 100644 index 000000000..cc99ab495 --- /dev/null +++ b/utils/time.go @@ -0,0 +1,11 @@ +package utils + +import "time" + +func ToTime(millis int64) time.Time { + return time.Unix(0, millis*int64(time.Millisecond)) +} + +func ToMillis(t time.Time) int64 { + return t.UnixNano() / int64(time.Millisecond) +}