diff --git a/api/playlists.go b/api/playlists.go index c82bbaad..1c9a2a35 100644 --- a/api/playlists.go +++ b/api/playlists.go @@ -56,6 +56,17 @@ func (c *PlaylistsController) Get() { c.SendResponse(response) } +func (c *PlaylistsController) Create() { + songIds := c.RequiredParamStrings("songId", "Required parameter songId is missing") + name := c.RequiredParamString("name", "Required parameter name is missing") + err := c.pls.Create(name, songIds) + if err != nil { + beego.Error(err) + c.SendError(responses.ErrorGeneric, "Internal Error") + } + c.SendEmptyResponse() +} + func (c *PlaylistsController) buildPlaylist(d *engine.PlaylistInfo) *responses.PlaylistWithSongs { pls := &responses.PlaylistWithSongs{} pls.Id = d.Id diff --git a/conf/router.go b/conf/router.go index a14aaa36..b94f37b3 100644 --- a/conf/router.go +++ b/conf/router.go @@ -41,6 +41,7 @@ func mapEndpoints() { beego.NSRouter("/getPlaylists.view", &api.PlaylistsController{}, "*:GetAll"), beego.NSRouter("/getPlaylist.view", &api.PlaylistsController{}, "*:Get"), + beego.NSRouter("/createPlaylist.view", &api.PlaylistsController{}, "*:Create"), beego.NSRouter("/getUser.view", &api.UsersController{}, "*:GetUser"), ) diff --git a/engine/playlists.go b/engine/playlists.go index 2a6af722..d4cecfb1 100644 --- a/engine/playlists.go +++ b/engine/playlists.go @@ -1,19 +1,25 @@ package engine import ( + "fmt" + + "github.com/astaxie/beego" "github.com/deluan/gosonic/domain" + "github.com/deluan/gosonic/itunesbridge" ) type Playlists interface { GetAll() (domain.Playlists, error) Get(id string) (*PlaylistInfo, error) + Create(name string, ids []string) error } -func NewPlaylists(pr domain.PlaylistRepository, mr domain.MediaFileRepository) Playlists { - return &playlists{pr, mr} +func NewPlaylists(itunes itunesbridge.ItunesControl, pr domain.PlaylistRepository, mr domain.MediaFileRepository) Playlists { + return &playlists{itunes, pr, mr} } type playlists struct { + itunes itunesbridge.ItunesControl plsRepo domain.PlaylistRepository mfileRepo domain.MediaFileRepository } @@ -32,6 +38,15 @@ type PlaylistInfo struct { Owner string } +func (p *playlists) Create(name string, ids []string) error { + pid, err := p.itunes.CreatePlaylist(name, ids) + if err != nil { + return err + } + beego.Info(fmt.Sprintf("Created playlist '%s' with id '%s'", name, pid)) + return nil +} + func (p *playlists) Get(id string) (*PlaylistInfo, error) { pl, err := p.plsRepo.Get(id) if err != nil { diff --git a/itunesbridge/itunes.go b/itunesbridge/itunes.go index 042fbd53..3a30d63c 100644 --- a/itunesbridge/itunes.go +++ b/itunesbridge/itunes.go @@ -2,6 +2,7 @@ package itunesbridge import ( "fmt" + "strings" "time" ) @@ -12,6 +13,7 @@ type ItunesControl interface { SetAlbumLoved(trackId string, loved bool) error SetTrackRating(trackId string, rating int) error SetAlbumRating(trackId string, rating int) error + CreatePlaylist(name string, ids []string) (string, error) } func NewItunesControl() ItunesControl { @@ -20,6 +22,23 @@ func NewItunesControl() ItunesControl { type itunesControl struct{} +func (c *itunesControl) CreatePlaylist(name string, ids []string) (string, error) { + pids := `"` + strings.Join(ids, `","`) + `"` + script := Script{ + fmt.Sprintf(`set pls to (make new user playlist with properties {name:"%s"})`, name), + fmt.Sprintf(`set pids to {%s}`, pids), + `repeat with trackPID in pids`, + ` set myTrack to the first item of (every track whose persistent ID is equal to trackPID)`, + ` duplicate myTrack to pls`, + `end repeat`, + `persistent ID of pls`} + pid, err := script.OutputString() + if err != nil { + return "", err + } + return strings.TrimSuffix(pid, "\n"), nil +} + func (c *itunesControl) MarkAsPlayed(trackId string, playDate time.Time) error { script := Script{fmt.Sprintf( `set theTrack to the first item of (every track whose persistent ID is equal to "%s")`, trackId),