diff --git a/api/base_api_controller.go b/api/base_api_controller.go index 6287c25f7..7138069d8 100644 --- a/api/base_api_controller.go +++ b/api/base_api_controller.go @@ -89,6 +89,10 @@ func (c *BaseAPIController) SendError(errorCode int, message ...interface{}) { c.CustomAbort(200, xml.Header+string(xmlBody)) } +func (c *BaseAPIController) SendEmptyResponse() { + c.SendResponse(c.NewEmpty()) +} + func (c *BaseAPIController) SendResponse(response responses.Subsonic) { f := c.GetString("f") switch f { diff --git a/api/media_annotation.go b/api/media_annotation.go index ffb368eb5..7209b98d8 100644 --- a/api/media_annotation.go +++ b/api/media_annotation.go @@ -13,10 +13,45 @@ import ( type MediaAnnotationController struct { BaseAPIController scrobbler engine.Scrobbler + ratings engine.Ratings } func (c *MediaAnnotationController) Prepare() { - utils.ResolveDependencies(&c.scrobbler) + utils.ResolveDependencies(&c.scrobbler, &c.ratings) +} + +func (c *MediaAnnotationController) Star() { + ids := c.RequiredParamStrings("id", "Required id parameter is missing") + + beego.Debug("Starring ids:", ids) + err := c.ratings.SetStar(true, ids...) + switch { + case err == engine.ErrDataNotFound: + beego.Error(err) + c.SendError(responses.ErrorDataNotFound, "Directory not found") + case err != nil: + beego.Error(err) + c.SendError(responses.ErrorGeneric, "Internal Error") + } + + c.SendEmptyResponse() +} + +func (c *MediaAnnotationController) Unstar() { + ids := c.RequiredParamStrings("id", "Required id parameter is missing") + + beego.Debug("Unstarring ids:", ids) + err := c.ratings.SetStar(false, ids...) + switch { + case err == engine.ErrDataNotFound: + beego.Error(err) + c.SendError(responses.ErrorDataNotFound, "Directory not found") + case err != nil: + beego.Error(err) + c.SendError(responses.ErrorGeneric, "Internal Error") + } + + c.SendEmptyResponse() } func (c *MediaAnnotationController) Scrobble() { @@ -54,6 +89,5 @@ func (c *MediaAnnotationController) Scrobble() { beego.Info(fmt.Sprintf(`Now Playing (%s) "%s" at %v`, id, mf.Title, t)) } } - response := c.NewEmpty() - c.SendResponse(response) + c.SendEmptyResponse() } diff --git a/api/system.go b/api/system.go index 53a7377cb..33d346c0b 100644 --- a/api/system.go +++ b/api/system.go @@ -5,7 +5,7 @@ import "github.com/deluan/gosonic/api/responses" type SystemController struct{ BaseAPIController } func (c *SystemController) Ping() { - c.SendResponse(c.NewEmpty()) + c.SendEmptyResponse() } func (c *SystemController) GetLicense() { diff --git a/conf/inject_definitions.go b/conf/inject_definitions.go index daf42f780..204b427b6 100644 --- a/conf/inject_definitions.go +++ b/conf/inject_definitions.go @@ -29,6 +29,7 @@ func init() { utils.DefineSingleton(new(engine.Playlists), engine.NewPlaylists) utils.DefineSingleton(new(engine.Search), engine.NewSearch) utils.DefineSingleton(new(engine.Scrobbler), engine.NewScrobbler) + utils.DefineSingleton(new(engine.Ratings), engine.NewRatings) utils.DefineSingleton(new(scanner.CheckSumRepository), persistence.NewCheckSumRepository) utils.DefineSingleton(new(scanner.Scanner), scanner.NewItunesScanner) diff --git a/conf/router.go b/conf/router.go index 9694539e7..55caf56f8 100644 --- a/conf/router.go +++ b/conf/router.go @@ -31,6 +31,8 @@ func mapEndpoints() { beego.NSRouter("/download.view", &api.StreamController{}, "*:Download"), beego.NSRouter("/scrobble.view", &api.MediaAnnotationController{}, "*:Scrobble"), + beego.NSRouter("/star.view", &api.MediaAnnotationController{}, "*:Star"), + beego.NSRouter("/unstar.view", &api.MediaAnnotationController{}, "*:Unstar"), beego.NSRouter("/getAlbumList.view", &api.AlbumListController{}, "*:GetAlbumList"), beego.NSRouter("/getStarred.view", &api.AlbumListController{}, "*:GetStarred"), diff --git a/engine/ratings.go b/engine/ratings.go new file mode 100644 index 000000000..651eeb080 --- /dev/null +++ b/engine/ratings.go @@ -0,0 +1,53 @@ +package engine + +import ( + "github.com/astaxie/beego" + "github.com/deluan/gosonic/domain" + "github.com/deluan/gosonic/itunesbridge" +) + +type Ratings interface { + SetStar(star bool, ids ...string) error +} + +func NewRatings(itunes itunesbridge.ItunesControl, mr domain.MediaFileRepository, alr domain.AlbumRepository, ar domain.ArtistRepository) Ratings { + return &ratings{itunes, mr, alr, ar} +} + +type ratings struct { + itunes itunesbridge.ItunesControl + mfRepo domain.MediaFileRepository + albumRepo domain.AlbumRepository + artistRepo domain.ArtistRepository +} + +func (r ratings) SetStar(star bool, ids ...string) error { + for _, id := range ids { + isAlbum, _ := r.albumRepo.Exists(id) + if isAlbum { + mfs, _ := r.mfRepo.FindByAlbum(id) + if len(mfs) > 0 { + beego.Debug("SetStar:", star, "Album:", mfs[0].Album) + if err := r.itunes.SetAlbumLoved(mfs[0].Id, star); err != nil { + return err + } + } + continue + } + + mf, err := r.mfRepo.Get(id) + if err != nil { + return err + } + if mf != nil { + beego.Debug("SetStar:", star, "Song:", mf.Title) + if err := r.itunes.SetTrackLoved(mf.Id, star); err != nil { + return err + } + continue + } + return ErrDataNotFound + } + + return nil +}