From 67e67d32eb0dba5ecbf6186edbbc69afc994fe0d Mon Sep 17 00:00:00 2001 From: a Date: Fri, 17 Feb 2023 15:45:24 -0600 Subject: [PATCH] changes --- go.mod | 4 +- go.sum | 11 +- src/cmd/root.go | 19 +- src/commands/commands.go | 448 +++++++++++++++++++++------------------ 4 files changed, 250 insertions(+), 232 deletions(-) diff --git a/go.mod b/go.mod index 0a170a0..b148bff 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module gitea.asdf.cafe/abs3nt/gospt go 1.19 require ( + gfx.cafe/util/go/frand v0.0.0-20230121041905-80dafb1e973e github.com/atotto/clipboard v0.1.4 github.com/charmbracelet/bubbles v0.14.0 github.com/charmbracelet/bubbletea v0.23.1 @@ -16,6 +17,7 @@ require ( ) require ( + github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/aymanbagabas/go-osc52 v1.0.3 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect github.com/containerd/console v1.0.3 // indirect @@ -38,7 +40,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect golang.org/x/mod v0.3.0 // indirect golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/sys v0.1.0 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 // indirect diff --git a/go.sum b/go.sum index 9255823..89e7b9d 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,12 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gfx.cafe/util/go/frand v0.0.0-20230121041905-80dafb1e973e h1:A62zlsu3HkEAVRIb+cCpRIpSTmd047+ABV1KC2RsI2U= +gfx.cafe/util/go/frand v0.0.0-20230121041905-80dafb1e973e/go.mod h1:LNHxMJl0WnIr5+OChYxlVopxk+j7qxZv0XvWCzB6uGE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg= @@ -61,8 +65,8 @@ github.com/cristalhq/aconfig v0.18.3 h1:Or12LIWIF+2mQpcGWA2PQnNc55+WiHFAqRjYh/pQ github.com/cristalhq/aconfig v0.18.3/go.mod h1:NXaRp+1e6bkO4dJn+wZ71xyaihMDYPtCSvEhMTm/H3E= github.com/cristalhq/aconfig/aconfigyaml v0.17.1 h1:xCCbRKVmKrft9gQj3gHOq6U5PduasvlXEIsxtyzmFZ0= github.com/cristalhq/aconfig/aconfigyaml v0.17.1/go.mod h1:5DTsjHkvQ6hfbyxfG32roB1lF0U82rROtFaLxibL8V8= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -186,8 +190,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -313,8 +317,9 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/src/cmd/root.go b/src/cmd/root.go index 24e0e36..9363563 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -1,27 +1,24 @@ package cmd import ( - "context" "fmt" "os" "os/exec" "path/filepath" "strings" - "gitea.asdf.cafe/abs3nt/gospt/src/auth" "gitea.asdf.cafe/abs3nt/gospt/src/config" "gitea.asdf.cafe/abs3nt/gospt/src/gctx" "github.com/cristalhq/aconfig" "github.com/cristalhq/aconfig/aconfigyaml" "github.com/spf13/cobra" - "github.com/zmb3/spotify/v2" ) var ( // Used for flags. ctx *gctx.Context - client *spotify.Client + commands *commands.Commands cfgFile string userLicense string @@ -54,20 +51,6 @@ func init() { cobra.OnInitialize(initClient) } -func initClient() { - var err error - ctx = gctx.NewContext(context.Background()) - client, err = auth.GetClient(ctx) - if err != nil { - panic(err) - } - currentUser, err := client.CurrentUser(ctx) - if err != nil { - panic(err) - } - ctx.UserId = currentUser.ID -} - func initConfig() { configDir, _ := os.UserConfigDir() cfgFile = filepath.Join(configDir, "gospt/client.yml") diff --git a/src/commands/commands.go b/src/commands/commands.go index d287eef..cf00cc8 100644 --- a/src/commands/commands.go +++ b/src/commands/commands.go @@ -1,39 +1,72 @@ package commands import ( + "context" "database/sql" "encoding/json" "errors" "fmt" "io" "math" - "math/rand" "net/url" "os" "path/filepath" "strings" + "sync" "time" + "gfx.cafe/util/go/frand" + "gitea.asdf.cafe/abs3nt/gospt/src/auth" "gitea.asdf.cafe/abs3nt/gospt/src/gctx" "github.com/zmb3/spotify/v2" _ "modernc.org/sqlite" ) -func SetVolume(ctx *gctx.Context, client *spotify.Client, vol int) error { - return client.Volume(ctx, vol) +type Commands struct { + cl *spotify.Client + mu sync.RWMutex } -func SetPosition(ctx *gctx.Context, client *spotify.Client, pos int) error { - err := client.Seek(ctx, pos) +func (c *Commands) Client() *spotify.Client { + c.mu.Lock() + if c.cl == nil { + c.cl = c.connectClient() + } + c.mu.Unlock() + c.mu.RLock() + defer c.mu.RUnlock() + return c.cl +} + +func (c *Commands) connectClient() *spotify.Client { + ctx := gctx.NewContext(context.Background()) + client, err := auth.GetClient(ctx) + if err != nil { + panic(err) + } + currentUser, err := client.CurrentUser(ctx) + if err != nil { + panic(err) + } + ctx.UserId = currentUser.ID + return &spotify.Client{} +} + +func (c *Commands) SetVolume(ctx *gctx.Context, vol int) error { + return c.Client().Volume(ctx, vol) +} + +func (c *Commands) SetPosition(ctx *gctx.Context, pos int) error { + err := c.Client().Seek(ctx, pos) if err != nil { return err } return nil } -func Seek(ctx *gctx.Context, client *spotify.Client, fwd bool) error { - current, err := client.PlayerCurrentlyPlaying(ctx) +func (c *Commands) Seek(ctx *gctx.Context, fwd bool) error { + current, err := c.Client().PlayerCurrentlyPlaying(ctx) if err != nil { return err } @@ -41,15 +74,15 @@ func Seek(ctx *gctx.Context, client *spotify.Client, fwd bool) error { if !fwd { newPos = current.Progress - 5000 } - err = client.Seek(ctx, newPos) + err = c.Client().Seek(ctx, newPos) if err != nil { return err } return nil } -func ChangeVolume(ctx *gctx.Context, client *spotify.Client, vol int) error { - state, err := client.PlayerState(ctx) +func (c *Commands) ChangeVolume(ctx *gctx.Context, vol int) error { + state, err := c.Client().PlayerState(ctx) if err != nil { return err } @@ -60,18 +93,18 @@ func ChangeVolume(ctx *gctx.Context, client *spotify.Client, vol int) error { if newVolume < 0 { newVolume = 0 } - return client.Volume(ctx, newVolume) + return c.Client().Volume(ctx, newVolume) } -func Play(ctx *gctx.Context, client *spotify.Client) error { - err := client.Play(ctx) +func (c *Commands) Play(ctx *gctx.Context) error { + err := c.Client().Play(ctx) if err != nil { if isNoActiveError(err) { - deviceID, err := activateDevice(ctx, client) + deviceID, err := c.activateDevice(ctx) if err != nil { return err } - err = client.PlayOpt(ctx, &spotify.PlayOptions{ + err = c.Client().PlayOpt(ctx, &spotify.PlayOptions{ DeviceID: &deviceID, }) if err != nil { @@ -84,8 +117,8 @@ func Play(ctx *gctx.Context, client *spotify.Client) error { return nil } -func ActiveDeviceExists(ctx *gctx.Context, client *spotify.Client) bool { - current, err := client.PlayerDevices(ctx) +func (c *Commands) ActiveDeviceExists(ctx *gctx.Context) bool { + current, err := c.Client().PlayerDevices(ctx) if err != nil { return false } @@ -97,66 +130,66 @@ func ActiveDeviceExists(ctx *gctx.Context, client *spotify.Client) bool { return false } -func UserArtists(ctx *gctx.Context, client *spotify.Client, page int) (*spotify.FullArtistCursorPage, error) { - artists, err := client.CurrentUsersFollowedArtists(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) +func (c *Commands) UserArtists(ctx *gctx.Context, page int) (*spotify.FullArtistCursorPage, error) { + artists, err := c.Client().CurrentUsersFollowedArtists(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) if err != nil { return nil, err } return artists, nil } -func ArtistAlbums(ctx *gctx.Context, client *spotify.Client, artist spotify.ID, page int) (*spotify.SimpleAlbumPage, error) { - albums, err := client.GetArtistAlbums(ctx, artist, []spotify.AlbumType{1, 2, 3, 4}, spotify.Market(spotify.CountryUSA), spotify.Limit(50), spotify.Offset((page-1)*50)) +func (c *Commands) ArtistAlbums(ctx *gctx.Context, artist spotify.ID, page int) (*spotify.SimpleAlbumPage, error) { + albums, err := c.Client().GetArtistAlbums(ctx, artist, []spotify.AlbumType{1, 2, 3, 4}, spotify.Market(spotify.CountryUSA), spotify.Limit(50), spotify.Offset((page-1)*50)) if err != nil { return nil, err } return albums, nil } -func Search(ctx *gctx.Context, client *spotify.Client, search string, page int) (*spotify.SearchResult, error) { - result, err := client.Search(ctx, search, spotify.SearchTypeAlbum|spotify.SearchTypeArtist|spotify.SearchTypeTrack|spotify.SearchTypePlaylist, spotify.Limit(50), spotify.Offset((page-1)*50)) +func (c *Commands) Search(ctx *gctx.Context, search string, page int) (*spotify.SearchResult, error) { + result, err := c.Client().Search(ctx, search, spotify.SearchTypeAlbum|spotify.SearchTypeArtist|spotify.SearchTypeTrack|spotify.SearchTypePlaylist, spotify.Limit(50), spotify.Offset((page-1)*50)) if err != nil { return nil, err } return result, nil } -func AlbumTracks(ctx *gctx.Context, client *spotify.Client, album spotify.ID, page int) (*spotify.SimpleTrackPage, error) { - tracks, err := client.GetAlbumTracks(ctx, album, spotify.Limit(50), spotify.Offset((page-1)*50), spotify.Market(spotify.CountryUSA)) +func (c *Commands) AlbumTracks(ctx *gctx.Context, album spotify.ID, page int) (*spotify.SimpleTrackPage, error) { + tracks, err := c.Client().GetAlbumTracks(ctx, album, spotify.Limit(50), spotify.Offset((page-1)*50), spotify.Market(spotify.CountryUSA)) if err != nil { return nil, err } return tracks, nil } -func UserAlbums(ctx *gctx.Context, client *spotify.Client, page int) (*spotify.SavedAlbumPage, error) { - albums, err := client.CurrentUsersAlbums(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) +func (c *Commands) UserAlbums(ctx *gctx.Context, page int) (*spotify.SavedAlbumPage, error) { + albums, err := c.Client().CurrentUsersAlbums(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) if err != nil { return nil, err } return albums, nil } -func PlayUrl(ctx *gctx.Context, client *spotify.Client, args []string) error { +func (c *Commands) PlayUrl(ctx *gctx.Context, args []string) error { url, err := url.Parse(args[0]) if err != nil { return err } track_id := strings.Split(url.Path, "/")[2] - err = client.QueueSong(ctx, spotify.ID(track_id)) + err = c.Client().QueueSong(ctx, spotify.ID(track_id)) if err != nil { if isNoActiveError(err) { - deviceID, err := activateDevice(ctx, client) + deviceID, err := c.activateDevice(ctx) if err != nil { return err } - err = client.QueueSongOpt(ctx, spotify.ID(track_id), &spotify.PlayOptions{ + err = c.Client().QueueSongOpt(ctx, spotify.ID(track_id), &spotify.PlayOptions{ DeviceID: &deviceID, }) if err != nil { return err } - err = client.NextOpt(ctx, &spotify.PlayOptions{ + err = c.Client().NextOpt(ctx, &spotify.PlayOptions{ DeviceID: &deviceID, }) if err != nil { @@ -167,22 +200,22 @@ func PlayUrl(ctx *gctx.Context, client *spotify.Client, args []string) error { return err } } - err = client.Next(ctx) + err = c.Client().Next(ctx) if err != nil { return err } return nil } -func QueueSong(ctx *gctx.Context, client *spotify.Client, id spotify.ID) error { - err := client.QueueSong(ctx, id) +func (c *Commands) QueueSong(ctx *gctx.Context, id spotify.ID) error { + err := c.Client().QueueSong(ctx, id) if err != nil { if isNoActiveError(err) { - deviceID, err := activateDevice(ctx, client) + deviceID, err := c.activateDevice(ctx) if err != nil { return err } - err = client.QueueSongOpt(ctx, id, &spotify.PlayOptions{ + err = c.Client().QueueSongOpt(ctx, id, &spotify.PlayOptions{ DeviceID: &deviceID, }) if err != nil { @@ -196,18 +229,18 @@ func QueueSong(ctx *gctx.Context, client *spotify.Client, id spotify.ID) error { return nil } -func PlaySongInPlaylist(ctx *gctx.Context, client *spotify.Client, context *spotify.URI, offset int) error { - e := client.PlayOpt(ctx, &spotify.PlayOptions{ +func (c *Commands) PlaySongInPlaylist(ctx *gctx.Context, context *spotify.URI, offset int) error { + e := c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackOffset: &spotify.PlaybackOffset{Position: offset}, PlaybackContext: context, }) if e != nil { if isNoActiveError(e) { - deviceID, err := activateDevice(ctx, client) + deviceID, err := c.activateDevice(ctx) if err != nil { return err } - err = client.PlayOpt(ctx, &spotify.PlayOptions{ + err = c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackOffset: &spotify.PlaybackOffset{Position: offset}, PlaybackContext: context, DeviceID: &deviceID, @@ -215,11 +248,11 @@ func PlaySongInPlaylist(ctx *gctx.Context, client *spotify.Client, context *spot if err != nil { if isNoActiveError(err) { - deviceID, err := activateDevice(ctx, client) + deviceID, err := c.activateDevice(ctx) if err != nil { return err } - err = client.PlayOpt(ctx, &spotify.PlayOptions{ + err = c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackOffset: &spotify.PlaybackOffset{Position: offset}, PlaybackContext: context, DeviceID: &deviceID, @@ -229,7 +262,7 @@ func PlaySongInPlaylist(ctx *gctx.Context, client *spotify.Client, context *spot } } } - err = client.Play(ctx) + err = c.Client().Play(ctx) if err != nil { return err } @@ -240,16 +273,16 @@ func PlaySongInPlaylist(ctx *gctx.Context, client *spotify.Client, context *spot return nil } -func PlayLikedSongs(ctx *gctx.Context, client *spotify.Client, position int) error { - err := ClearRadio(ctx, client) +func (c *Commands) PlayLikedSongs(ctx *gctx.Context, position int) error { + err := c.ClearRadio(ctx) if err != nil { return err } - playlist, _, err := GetRadioPlaylist(ctx, client, "Saved Songs") + playlist, _, err := c.GetRadioPlaylist(ctx, "Saved Songs") if err != nil { return err } - songs, err := client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset(position)) + songs, err := c.Client().CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset(position)) if err != nil { return err } @@ -257,11 +290,11 @@ func PlayLikedSongs(ctx *gctx.Context, client *spotify.Client, position int) err for _, song := range songs.Tracks { to_add = append(to_add, song.ID) } - _, err = client.AddTracksToPlaylist(ctx, playlist.ID, to_add...) + _, err = c.Client().AddTracksToPlaylist(ctx, playlist.ID, to_add...) if err != nil { return err } - err = client.PlayOpt(ctx, &spotify.PlayOptions{ + err = c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackContext: &playlist.URI, PlaybackOffset: &spotify.PlaybackOffset{ Position: 0, @@ -269,11 +302,11 @@ func PlayLikedSongs(ctx *gctx.Context, client *spotify.Client, position int) err }) if err != nil { if isNoActiveError(err) { - deviceID, err := activateDevice(ctx, client) + deviceID, err := c.activateDevice(ctx) if err != nil { return err } - err = client.PlayOpt(ctx, &spotify.PlayOptions{ + err = c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackContext: &playlist.URI, PlaybackOffset: &spotify.PlaybackOffset{ Position: 0, @@ -286,7 +319,7 @@ func PlayLikedSongs(ctx *gctx.Context, client *spotify.Client, position int) err } } for page := 2; page <= 5; page++ { - songs, err := client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset((50*(page-1))+position)) + songs, err := c.Client().CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset((50*(page-1))+position)) if err != nil { return err } @@ -294,17 +327,17 @@ func PlayLikedSongs(ctx *gctx.Context, client *spotify.Client, position int) err for _, song := range songs.Tracks { to_add = append(to_add, song.ID) } - client.AddTracksToPlaylist(ctx, playlist.ID, to_add...) + c.Client().AddTracksToPlaylist(ctx, playlist.ID, to_add...) } return err } -func RadioGivenArtist(ctx *gctx.Context, client *spotify.Client, artist spotify.SimpleArtist) error { +func (c *Commands) RadioGivenArtist(ctx *gctx.Context, artist spotify.SimpleArtist) error { seed := spotify.Seeds{ Artists: []spotify.ID{artist.ID}, } - recomendations, err := client.GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) + recomendations, err := c.Client().GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) if err != nil { return err } @@ -312,17 +345,17 @@ func RadioGivenArtist(ctx *gctx.Context, client *spotify.Client, artist spotify. for _, song := range recomendations.Tracks { recomendationIds = append(recomendationIds, song.ID) } - err = ClearRadio(ctx, client) + err = c.ClearRadio(ctx) if err != nil { return err } - radioPlaylist, db, err := GetRadioPlaylist(ctx, client, artist.Name) + radioPlaylist, db, err := c.GetRadioPlaylist(ctx, artist.Name) if err != nil { return err } queue := []spotify.ID{} for _, rec := range recomendationIds { - exists, err := SongExists(db, rec) + exists, err := c.SongExists(db, rec) if err != nil { return err } @@ -334,32 +367,32 @@ func RadioGivenArtist(ctx *gctx.Context, client *spotify.Client, artist spotify. queue = append(queue, rec) } } - _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, queue...) + _, err = c.Client().AddTracksToPlaylist(ctx, radioPlaylist.ID, queue...) if err != nil { return err } - client.PlayOpt(ctx, &spotify.PlayOptions{ + c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackContext: &radioPlaylist.URI, PlaybackOffset: &spotify.PlaybackOffset{ Position: 0, }, }) - err = client.Repeat(ctx, "context") + err = c.Client().Repeat(ctx, "context") if err != nil { return err } for i := 0; i < 4; i++ { - id := rand.Intn(len(recomendationIds)-2) + 1 + id := frand.Intn(len(recomendationIds)-2) + 1 seed := spotify.Seeds{ Tracks: []spotify.ID{recomendationIds[id]}, } - additional_recs, err := client.GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) + additional_recs, err := c.Client().GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) if err != nil { return err } additionalRecsIds := []spotify.ID{} for _, song := range additional_recs.Tracks { - exists, err := SongExists(db, song.ID) + exists, err := c.SongExists(db, song.ID) if err != nil { return err } @@ -371,7 +404,7 @@ func RadioGivenArtist(ctx *gctx.Context, client *spotify.Client, artist spotify. additionalRecsIds = append(additionalRecsIds, song.ID) } } - _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, additionalRecsIds...) + _, err = c.Client().AddTracksToPlaylist(ctx, radioPlaylist.ID, additionalRecsIds...) if err != nil { return err } @@ -379,12 +412,12 @@ func RadioGivenArtist(ctx *gctx.Context, client *spotify.Client, artist spotify. return nil } -func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song spotify.SimpleTrack, pos int) error { +func (c *Commands) RadioGivenSong(ctx *gctx.Context, song spotify.SimpleTrack, pos int) error { start := time.Now().UnixMilli() seed := spotify.Seeds{ Tracks: []spotify.ID{song.ID}, } - recomendations, err := client.GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(99)) + recomendations, err := c.Client().GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(99)) if err != nil { return err } @@ -392,11 +425,11 @@ func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song spotify.Simp for _, song := range recomendations.Tracks { recomendationIds = append(recomendationIds, song.ID) } - err = ClearRadio(ctx, client) + err = c.ClearRadio(ctx) if err != nil { return err } - radioPlaylist, db, err := GetRadioPlaylist(ctx, client, song.Name) + radioPlaylist, db, err := c.GetRadioPlaylist(ctx, song.Name) if err != nil { return err } @@ -406,7 +439,7 @@ func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song spotify.Simp } queue := []spotify.ID{song.ID} for _, rec := range recomendationIds { - exists, err := SongExists(db, rec) + exists, err := c.SongExists(db, rec) if err != nil { return err } @@ -418,7 +451,7 @@ func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song spotify.Simp queue = append(queue, rec) } } - _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, queue...) + _, err = c.Client().AddTracksToPlaylist(ctx, radioPlaylist.ID, queue...) if err != nil { return err } @@ -426,7 +459,7 @@ func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song spotify.Simp if pos != 0 { pos = pos + int(delay) } - err = client.PlayOpt(ctx, &spotify.PlayOptions{ + err = c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackContext: &radioPlaylist.URI, PlaybackOffset: &spotify.PlaybackOffset{ Position: 0, @@ -435,11 +468,11 @@ func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song spotify.Simp }) if err != nil { if isNoActiveError(err) { - deviceID, err := activateDevice(ctx, client) + deviceID, err := c.activateDevice(ctx) if err != nil { return err } - err = client.PlayOpt(ctx, &spotify.PlayOptions{ + err = c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackContext: &radioPlaylist.URI, PlaybackOffset: &spotify.PlaybackOffset{ Position: 0, @@ -452,22 +485,22 @@ func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song spotify.Simp } } } - err = client.Repeat(ctx, "context") + err = c.Client().Repeat(ctx, "context") if err != nil { return err } for i := 0; i < 4; i++ { - id := rand.Intn(len(recomendationIds)-2) + 1 + id := frand.Intn(len(recomendationIds)-2) + 1 seed := spotify.Seeds{ Tracks: []spotify.ID{recomendationIds[id]}, } - additional_recs, err := client.GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) + additional_recs, err := c.Client().GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) if err != nil { return err } additionalRecsIds := []spotify.ID{} for _, song := range additional_recs.Tracks { - exists, err := SongExists(db, song.ID) + exists, err := c.SongExists(db, song.ID) if err != nil { return err } @@ -479,7 +512,7 @@ func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song spotify.Simp additionalRecsIds = append(additionalRecsIds, song.ID) } } - _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, additionalRecsIds...) + _, err = c.Client().AddTracksToPlaylist(ctx, radioPlaylist.ID, additionalRecsIds...) if err != nil { return err } @@ -487,7 +520,7 @@ func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song spotify.Simp return nil } -func SongExists(db *sql.DB, song spotify.ID) (bool, error) { +func (c *Commands) SongExists(db *sql.DB, song spotify.ID) (bool, error) { song_id := string(song) sqlStmt := `SELECT id FROM radio WHERE id = ?` err := db.QueryRow(sqlStmt, string(song_id)).Scan(&song_id) @@ -502,9 +535,8 @@ func SongExists(db *sql.DB, song spotify.ID) (bool, error) { return true, nil } -func Radio(ctx *gctx.Context, client *spotify.Client) error { - rand.Seed(time.Now().Unix()) - current_song, err := client.PlayerCurrentlyPlaying(ctx) +func (c *Commands) Radio(ctx *gctx.Context) error { + current_song, err := c.Client().PlayerCurrentlyPlaying(ctx) if err != nil { return err } @@ -514,30 +546,30 @@ func Radio(ctx *gctx.Context, client *spotify.Client) error { seed_song = current_song.Item.SimpleTrack } if current_song.Item == nil { - _, err := activateDevice(ctx, client) + _, err := c.activateDevice(ctx) if err != nil { return err } - tracks, err := client.CurrentUsersTracks(ctx, spotify.Limit(10)) + tracks, err := c.Client().CurrentUsersTracks(ctx, spotify.Limit(10)) if err != nil { return err } - seed_song = tracks.Tracks[rand.Intn(len(tracks.Tracks))].SimpleTrack + seed_song = tracks.Tracks[frand.Intn(len(tracks.Tracks))].SimpleTrack } else { if !current_song.Playing { - tracks, err := client.CurrentUsersTracks(ctx, spotify.Limit(10)) + tracks, err := c.Client().CurrentUsersTracks(ctx, spotify.Limit(10)) if err != nil { return err } - seed_song = tracks.Tracks[rand.Intn(len(tracks.Tracks))].SimpleTrack + seed_song = tracks.Tracks[frand.Intn(len(tracks.Tracks))].SimpleTrack } } - return RadioGivenSong(ctx, client, seed_song, current_song.Progress) + return c.RadioGivenSong(ctx, seed_song, current_song.Progress) } -func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { - status, err := client.PlayerCurrentlyPlaying(ctx) +func (c *Commands) RefillRadio(ctx *gctx.Context) error { + status, err := c.Client().PlayerCurrentlyPlaying(ctx) if err != nil { return err } @@ -545,7 +577,7 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { return nil } to_remove := []spotify.ID{} - radioPlaylist, db, err := GetRadioPlaylist(ctx, client, "") + radioPlaylist, db, err := c.GetRadioPlaylist(ctx, "") if err != nil { } @@ -553,7 +585,7 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { return nil } - playlistItems, err := client.GetPlaylistItems(ctx, radioPlaylist.ID) + playlistItems, err := c.Client().GetPlaylistItems(ctx, radioPlaylist.ID) if err != nil { return err } @@ -561,7 +593,7 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { found := false page := 0 for !found { - tracks, err := client.GetPlaylistItems(ctx, radioPlaylist.ID, spotify.Limit(50), spotify.Offset(page*50)) + tracks, err := c.Client().GetPlaylistItems(ctx, radioPlaylist.ID, spotify.Limit(50), spotify.Offset(page*50)) if err != nil { return err } @@ -578,7 +610,7 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { var trackGroups []spotify.ID for idx, item := range to_remove { if idx%100 == 0 { - _, err = client.RemoveTracksFromPlaylist(ctx, radioPlaylist.ID, trackGroups...) + _, err = c.Client().RemoveTracksFromPlaylist(ctx, radioPlaylist.ID, trackGroups...) trackGroups = []spotify.ID{} } trackGroups = append(trackGroups, item) @@ -586,12 +618,11 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { return err } } - _, err = client.RemoveTracksFromPlaylist(ctx, radioPlaylist.ID, trackGroups...) + _, err = c.Client().RemoveTracksFromPlaylist(ctx, radioPlaylist.ID, trackGroups...) } to_add := 500 - (playlistItems.Total - len(to_remove)) - rand.Seed(time.Now().Unix()) - playlistItems, err = client.GetPlaylistItems(ctx, radioPlaylist.ID) + playlistItems, err = c.Client().GetPlaylistItems(ctx, radioPlaylist.ID) if err != nil { return err } @@ -599,14 +630,14 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { pages := int(math.Ceil(float64(total) / 50)) randomPage := 1 if pages > 1 { - randomPage = rand.Intn(int(pages-1)) + 1 + randomPage = frand.Intn(int(pages-1)) + 1 } - playlistPage, err := client.GetPlaylistItems(ctx, radioPlaylist.ID, spotify.Limit(50), spotify.Offset((randomPage-1)*50)) + playlistPage, err := c.Client().GetPlaylistItems(ctx, radioPlaylist.ID, spotify.Limit(50), spotify.Offset((randomPage-1)*50)) if err != nil { return err } pageSongs := playlistPage.Items - rand.Shuffle(len(pageSongs), func(i, j int) { pageSongs[i], pageSongs[j] = pageSongs[j], pageSongs[i] }) + frand.Shuffle(len(pageSongs), func(i, j int) { pageSongs[i], pageSongs[j] = pageSongs[j], pageSongs[i] }) seedCount := 5 if len(pageSongs) < seedCount { seedCount = len(pageSongs) @@ -621,13 +652,13 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { seed := spotify.Seeds{ Tracks: seedIds, } - recomendations, err := client.GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(95)) + recomendations, err := c.Client().GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(95)) if err != nil { return err } recomendationIds := []spotify.ID{} for _, song := range recomendations.Tracks { - exists, err := SongExists(db, song.ID) + exists, err := c.SongExists(db, song.ID) if err != nil { return err } @@ -644,26 +675,26 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { queue = append(queue, rec) } to_add -= len(queue) - _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, queue...) + _, err = c.Client().AddTracksToPlaylist(ctx, radioPlaylist.ID, queue...) if err != nil { return err } - err = client.Repeat(ctx, "context") + err = c.Client().Repeat(ctx, "context") if err != nil { return err } for to_add > 0 { - id := rand.Intn(len(recomendationIds)-2) + 1 + id := frand.Intn(len(recomendationIds)-2) + 1 seed := spotify.Seeds{ Tracks: []spotify.ID{recomendationIds[id]}, } - additional_recs, err := client.GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) + additional_recs, err := c.Client().GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) if err != nil { return err } additionalRecsIds := []spotify.ID{} for idx, song := range additional_recs.Tracks { - exists, err := SongExists(db, song.ID) + exists, err := c.SongExists(db, song.ID) if err != nil { return err } @@ -676,7 +707,7 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { } } to_add -= len(queue) - _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, additionalRecsIds...) + _, err = c.Client().AddTracksToPlaylist(ctx, radioPlaylist.ID, additionalRecsIds...) if err != nil { return err } @@ -684,83 +715,83 @@ func RefillRadio(ctx *gctx.Context, client *spotify.Client) error { return nil } -func ClearRadio(ctx *gctx.Context, client *spotify.Client) error { - radioPlaylist, db, err := GetRadioPlaylist(ctx, client, "") +func (c *Commands) ClearRadio(ctx *gctx.Context) error { + radioPlaylist, db, err := c.GetRadioPlaylist(ctx, "") if err != nil { return err } - err = client.UnfollowPlaylist(ctx, radioPlaylist.ID) + err = c.Client().UnfollowPlaylist(ctx, radioPlaylist.ID) if err != nil { return err } db.Query("DROP TABLE IF EXISTS radio") configDir, _ := os.UserConfigDir() os.Remove(filepath.Join(configDir, "gospt/radio.json")) - client.Pause(ctx) + c.Client().Pause(ctx) return nil } -func Devices(ctx *gctx.Context, client *spotify.Client) error { - devices, err := client.PlayerDevices(ctx) +func (c *Commands) Devices(ctx *gctx.Context) error { + devices, err := c.Client().PlayerDevices(ctx) if err != nil { return err } - return PrintDevices(devices) + return c.PrintDevices(devices) } -func Pause(ctx *gctx.Context, client *spotify.Client) error { - err := client.Pause(ctx) +func (c *Commands) Pause(ctx *gctx.Context) error { + err := c.Client().Pause(ctx) if err != nil { return err } return nil } -func TogglePlay(ctx *gctx.Context, client *spotify.Client) error { - current, err := client.PlayerCurrentlyPlaying(ctx) +func (c *Commands) TogglePlay(ctx *gctx.Context) error { + current, err := c.Client().PlayerCurrentlyPlaying(ctx) if err != nil { return err } if !current.Playing { - return Play(ctx, client) + return c.Play(ctx) } - return Pause(ctx, client) + return c.Pause(ctx) } -func Like(ctx *gctx.Context, client *spotify.Client) error { - playing, err := client.PlayerCurrentlyPlaying(ctx) +func (c *Commands) Like(ctx *gctx.Context) error { + playing, err := c.Client().PlayerCurrentlyPlaying(ctx) if err != nil { return err } - err = client.AddTracksToLibrary(ctx, playing.Item.ID) + err = c.Client().AddTracksToLibrary(ctx, playing.Item.ID) if err != nil { return err } return nil } -func Unlike(ctx *gctx.Context, client *spotify.Client) error { - playing, err := client.PlayerCurrentlyPlaying(ctx) +func (c *Commands) Unlike(ctx *gctx.Context) error { + playing, err := c.Client().PlayerCurrentlyPlaying(ctx) if err != nil { return err } - err = client.RemoveTracksFromLibrary(ctx, playing.Item.ID) + err = c.Client().RemoveTracksFromLibrary(ctx, playing.Item.ID) if err != nil { return err } return nil } -func Next(ctx *gctx.Context, client *spotify.Client, amt int) error { +func (c *Commands) Next(ctx *gctx.Context, amt int) error { if amt == 1 { - err := client.Next(ctx) + err := c.Client().Next(ctx) if err != nil { if isNoActiveError(err) { - deviceId, err := activateDevice(ctx, client) + deviceId, err := c.activateDevice(ctx) if err != nil { return err } - err = client.NextOpt(ctx, &spotify.PlayOptions{ + err = c.Client().NextOpt(ctx, &spotify.PlayOptions{ DeviceID: &deviceId, }) if err != nil { @@ -773,7 +804,7 @@ func Next(ctx *gctx.Context, client *spotify.Client, amt int) error { } // found := false // playingIndex := 0 - current, err := client.PlayerCurrentlyPlaying(ctx) + current, err := c.Client().PlayerCurrentlyPlaying(ctx) if err != nil { return err } @@ -784,7 +815,7 @@ func Next(ctx *gctx.Context, client *spotify.Client, amt int) error { currentTrackIndex := 0 for !found { page := 1 - playlist, err := client.GetPlaylistItems(ctx, spotify.ID(strings.Split(string(current.PlaybackContext.URI), ":")[2]), spotify.Limit(50), spotify.Offset((page-1)*50)) + playlist, err := c.Client().GetPlaylistItems(ctx, spotify.ID(strings.Split(string(current.PlaybackContext.URI), ":")[2]), spotify.Limit(50), spotify.Offset((page-1)*50)) if err != nil { return err } @@ -797,7 +828,7 @@ func Next(ctx *gctx.Context, client *spotify.Client, amt int) error { } page++ } - client.PlayOpt(ctx, &spotify.PlayOptions{ + c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackContext: ¤t.PlaybackContext.URI, PlaybackOffset: &spotify.PlaybackOffset{ Position: currentTrackIndex + amt, @@ -809,7 +840,7 @@ func Next(ctx *gctx.Context, client *spotify.Client, amt int) error { currentTrackIndex := 0 for !found { page := 1 - playlist, err := client.GetAlbumTracks(ctx, spotify.ID(strings.Split(string(current.PlaybackContext.URI), ":")[2]), spotify.Limit(50), spotify.Offset((page-1)*50)) + playlist, err := c.Client().GetAlbumTracks(ctx, spotify.ID(strings.Split(string(current.PlaybackContext.URI), ":")[2]), spotify.Limit(50), spotify.Offset((page-1)*50)) if err != nil { return err } @@ -822,7 +853,7 @@ func Next(ctx *gctx.Context, client *spotify.Client, amt int) error { } page++ } - client.PlayOpt(ctx, &spotify.PlayOptions{ + c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackContext: ¤t.PlaybackContext.URI, PlaybackOffset: &spotify.PlaybackOffset{ Position: currentTrackIndex + amt, @@ -831,58 +862,58 @@ func Next(ctx *gctx.Context, client *spotify.Client, amt int) error { return nil default: for i := 0; i < amt; i++ { - client.Next(ctx) + c.Client().Next(ctx) } } return nil } -func Previous(ctx *gctx.Context, client *spotify.Client) error { - err := client.Previous(ctx) +func (c *Commands) Previous(ctx *gctx.Context) error { + err := c.Client().Previous(ctx) if err != nil { return err } return nil } -func Status(ctx *gctx.Context, client *spotify.Client) error { - state, err := client.PlayerState(ctx) +func (c *Commands) Status(ctx *gctx.Context) error { + state, err := c.Client().PlayerState(ctx) if err != nil { return err } - return PrintState(state) + return c.PrintState(state) } -func Link(ctx *gctx.Context, client *spotify.Client) (string, error) { - state, err := client.PlayerState(ctx) +func (c *Commands) Link(ctx *gctx.Context) (string, error) { + state, err := c.Client().PlayerState(ctx) if err != nil { return "", err } return state.Item.ExternalURLs["spotify"], nil } -func LinkContext(ctx *gctx.Context, client *spotify.Client) (string, error) { - state, err := client.PlayerState(ctx) +func (c *Commands) LinkContext(ctx *gctx.Context) (string, error) { + state, err := c.Client().PlayerState(ctx) if err != nil { return "", err } return string(state.PlaybackContext.ExternalURLs["spotify"]), nil } -func NowPlaying(ctx *gctx.Context, client *spotify.Client) error { - current, err := client.PlayerCurrentlyPlaying(ctx) +func (c *Commands) NowPlaying(ctx *gctx.Context) error { + current, err := c.Client().PlayerCurrentlyPlaying(ctx) if err != nil { return err } - return PrintPlaying(current) + return c.PrintPlaying(current) } -func Shuffle(ctx *gctx.Context, client *spotify.Client) error { - state, err := client.PlayerState(ctx) +func (c *Commands) Shuffle(ctx *gctx.Context) error { + state, err := c.Client().PlayerState(ctx) if err != nil { return fmt.Errorf("Failed to get current playstate") } - err = client.Shuffle(ctx, !state.ShuffleState) + err = c.Client().Shuffle(ctx, !state.ShuffleState) if err != nil { return err } @@ -890,8 +921,8 @@ func Shuffle(ctx *gctx.Context, client *spotify.Client) error { return nil } -func Repeat(ctx *gctx.Context, client *spotify.Client) error { - state, err := client.PlayerState(ctx) +func (c *Commands) Repeat(ctx *gctx.Context) error { + state, err := c.Client().PlayerState(ctx) if err != nil { return fmt.Errorf("Failed to get current playstate") } @@ -900,7 +931,7 @@ func Repeat(ctx *gctx.Context, client *spotify.Client) error { newState = "context" } // spotifyd only supports binary value for repeat, context or off, change when/if spotifyd is better - err = client.Repeat(ctx, newState) + err = c.Client().Repeat(ctx, newState) if err != nil { return err } @@ -908,23 +939,23 @@ func Repeat(ctx *gctx.Context, client *spotify.Client) error { return nil } -func TrackList(ctx *gctx.Context, client *spotify.Client, page int) (*spotify.SavedTrackPage, error) { - return client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) +func (c *Commands) TrackList(ctx *gctx.Context, page int) (*spotify.SavedTrackPage, error) { + return c.Client().CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) } -func GetQueue(ctx *gctx.Context, client *spotify.Client) (*spotify.Queue, error) { - return client.GetQueue(ctx) +func (c *Commands) GetQueue(ctx *gctx.Context) (*spotify.Queue, error) { + return c.Client().GetQueue(ctx) } -func Playlists(ctx *gctx.Context, client *spotify.Client, page int) (*spotify.SimplePlaylistPage, error) { - return client.CurrentUsersPlaylists(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) +func (c *Commands) Playlists(ctx *gctx.Context, page int) (*spotify.SimplePlaylistPage, error) { + return c.Client().CurrentUsersPlaylists(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) } -func PlaylistTracks(ctx *gctx.Context, client *spotify.Client, playlist spotify.ID, page int) (*spotify.PlaylistTrackPage, error) { - return client.GetPlaylistTracks(ctx, playlist, spotify.Limit(50), spotify.Offset((page-1)*50)) +func (c *Commands) PlaylistTracks(ctx *gctx.Context, playlist spotify.ID, page int) (*spotify.PlaylistTrackPage, error) { + return c.Client().GetPlaylistTracks(ctx, playlist, spotify.Limit(50), spotify.Offset((page-1)*50)) } -func PrintState(state *spotify.PlayerState) error { +func (c *Commands) PrintState(state *spotify.PlayerState) error { state.Item.AvailableMarkets = []string{} state.Item.Album.AvailableMarkets = []string{} out, err := json.MarshalIndent(state, "", " ") @@ -935,7 +966,7 @@ func PrintState(state *spotify.PlayerState) error { return nil } -func PrintPlaying(current *spotify.CurrentlyPlaying) error { +func (c *Commands) PrintPlaying(current *spotify.CurrentlyPlaying) error { icon := "▶" if !current.Playing { icon = "⏸" @@ -944,7 +975,7 @@ func PrintPlaying(current *spotify.CurrentlyPlaying) error { return nil } -func PrintDevices(devices []spotify.PlayerDevice) error { +func (c *Commands) PrintDevices(devices []spotify.PlayerDevice) error { out, err := json.MarshalIndent(devices, "", " ") if err != nil { return err @@ -953,7 +984,7 @@ func PrintDevices(devices []spotify.PlayerDevice) error { return nil } -func SetDevice(ctx *gctx.Context, client *spotify.Client, device spotify.PlayerDevice) error { +func (c *Commands) SetDevice(ctx *gctx.Context, device spotify.PlayerDevice) error { out, err := json.MarshalIndent(device, "", " ") if err != nil { return err @@ -963,7 +994,7 @@ func SetDevice(ctx *gctx.Context, client *spotify.Client, device spotify.PlayerD if err != nil { return err } - _, err = activateDevice(ctx, client) + _, err = c.activateDevice(ctx) if err != nil { return err } @@ -974,8 +1005,7 @@ func isNoActiveError(err error) bool { return strings.Contains(err.Error(), "No active device found") } -func RadioFromPlaylist(ctx *gctx.Context, client *spotify.Client, playlist spotify.SimplePlaylist) error { - rand.Seed(time.Now().Unix()) +func (c *Commands) RadioFromPlaylist(ctx *gctx.Context, playlist spotify.SimplePlaylist) error { total := playlist.Tracks.Total if total == 0 { return fmt.Errorf("This playlist is empty") @@ -983,14 +1013,14 @@ func RadioFromPlaylist(ctx *gctx.Context, client *spotify.Client, playlist spoti pages := int(math.Ceil(float64(total) / 50)) randomPage := 1 if pages > 1 { - randomPage = rand.Intn(int(pages-1)) + 1 + randomPage = frand.Intn(int(pages-1)) + 1 } - playlistPage, err := client.GetPlaylistItems(ctx, playlist.ID, spotify.Limit(50), spotify.Offset((randomPage-1)*50)) + playlistPage, err := c.Client().GetPlaylistItems(ctx, playlist.ID, spotify.Limit(50), spotify.Offset((randomPage-1)*50)) if err != nil { return err } pageSongs := playlistPage.Items - rand.Shuffle(len(pageSongs), func(i, j int) { pageSongs[i], pageSongs[j] = pageSongs[j], pageSongs[i] }) + frand.Shuffle(len(pageSongs), func(i, j int) { pageSongs[i], pageSongs[j] = pageSongs[j], pageSongs[i] }) seedCount := 5 if len(pageSongs) < seedCount { seedCount = len(pageSongs) @@ -1002,12 +1032,11 @@ func RadioFromPlaylist(ctx *gctx.Context, client *spotify.Client, playlist spoti } seedIds = append(seedIds, song.Track.Track.ID) } - return RadioGivenList(ctx, client, seedIds[:seedCount], playlist.Name) + return c.RadioGivenList(ctx, seedIds[:seedCount], playlist.Name) } -func RadioFromAlbum(ctx *gctx.Context, client *spotify.Client, album spotify.SimpleAlbum) error { - rand.Seed(time.Now().Unix()) - tracks, err := AlbumTracks(ctx, client, album.ID, 1) +func (c *Commands) RadioFromAlbum(ctx *gctx.Context, album spotify.SimpleAlbum) error { + tracks, err := c.AlbumTracks(ctx, album.ID, 1) if err != nil { return err } @@ -1018,14 +1047,14 @@ func RadioFromAlbum(ctx *gctx.Context, client *spotify.Client, album spotify.Sim pages := int(math.Ceil(float64(total) / 50)) randomPage := 1 if pages > 1 { - randomPage = rand.Intn(int(pages-1)) + 1 + randomPage = frand.Intn(int(pages-1)) + 1 } - albumTrackPage, err := AlbumTracks(ctx, client, album.ID, randomPage) + albumTrackPage, err := c.AlbumTracks(ctx, album.ID, randomPage) if err != nil { return err } pageSongs := albumTrackPage.Tracks - rand.Shuffle(len(pageSongs), func(i, j int) { pageSongs[i], pageSongs[j] = pageSongs[j], pageSongs[i] }) + frand.Shuffle(len(pageSongs), func(i, j int) { pageSongs[i], pageSongs[j] = pageSongs[j], pageSongs[i] }) seedCount := 5 if len(pageSongs) < seedCount { seedCount = len(pageSongs) @@ -1037,12 +1066,11 @@ func RadioFromAlbum(ctx *gctx.Context, client *spotify.Client, album spotify.Sim } seedIds = append(seedIds, song.ID) } - return RadioGivenList(ctx, client, seedIds[:seedCount], album.Name) + return c.RadioGivenList(ctx, seedIds[:seedCount], album.Name) } -func RadioFromSavedTracks(ctx *gctx.Context, client *spotify.Client) error { - rand.Seed(time.Now().Unix()) - savedSongs, err := client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset(0)) +func (c *Commands) RadioFromSavedTracks(ctx *gctx.Context) error { + savedSongs, err := c.Client().CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset(0)) if err != nil { return err } @@ -1052,14 +1080,14 @@ func RadioFromSavedTracks(ctx *gctx.Context, client *spotify.Client) error { pages := int(math.Ceil(float64(savedSongs.Total) / 50)) randomPage := 1 if pages > 1 { - randomPage = rand.Intn(int(pages-1)) + 1 + randomPage = frand.Intn(int(pages-1)) + 1 } - trackPage, err := client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset(randomPage*50)) + trackPage, err := c.Client().CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset(randomPage*50)) if err != nil { return err } pageSongs := trackPage.Tracks - rand.Shuffle(len(pageSongs), func(i, j int) { pageSongs[i], pageSongs[j] = pageSongs[j], pageSongs[i] }) + frand.Shuffle(len(pageSongs), func(i, j int) { pageSongs[i], pageSongs[j] = pageSongs[j], pageSongs[i] }) seedCount := 4 seedIds := []spotify.ID{} for idx, song := range pageSongs { @@ -1069,14 +1097,14 @@ func RadioFromSavedTracks(ctx *gctx.Context, client *spotify.Client) error { seedIds = append(seedIds, song.ID) } seedIds = append(seedIds, savedSongs.Tracks[0].ID) - return RadioGivenList(ctx, client, seedIds, "Saved Tracks") + return c.RadioGivenList(ctx, seedIds, "Saved Tracks") } -func RadioGivenList(ctx *gctx.Context, client *spotify.Client, song_ids []spotify.ID, name string) error { +func (c *Commands) RadioGivenList(ctx *gctx.Context, song_ids []spotify.ID, name string) error { seed := spotify.Seeds{ Tracks: song_ids, } - recomendations, err := client.GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(99)) + recomendations, err := c.Client().GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(99)) if err != nil { return err } @@ -1084,17 +1112,17 @@ func RadioGivenList(ctx *gctx.Context, client *spotify.Client, song_ids []spotif for _, song := range recomendations.Tracks { recomendationIds = append(recomendationIds, song.ID) } - err = ClearRadio(ctx, client) + err = c.ClearRadio(ctx) if err != nil { return err } - radioPlaylist, db, err := GetRadioPlaylist(ctx, client, name) + radioPlaylist, db, err := c.GetRadioPlaylist(ctx, name) if err != nil { return err } queue := []spotify.ID{song_ids[0]} for _, rec := range recomendationIds { - exists, err := SongExists(db, rec) + exists, err := c.SongExists(db, rec) if err != nil { return err } @@ -1106,11 +1134,11 @@ func RadioGivenList(ctx *gctx.Context, client *spotify.Client, song_ids []spotif queue = append(queue, rec) } } - _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, queue...) + _, err = c.Client().AddTracksToPlaylist(ctx, radioPlaylist.ID, queue...) if err != nil { return err } - err = client.PlayOpt(ctx, &spotify.PlayOptions{ + err = c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackContext: &radioPlaylist.URI, PlaybackOffset: &spotify.PlaybackOffset{ Position: 0, @@ -1118,11 +1146,11 @@ func RadioGivenList(ctx *gctx.Context, client *spotify.Client, song_ids []spotif }) if err != nil { if isNoActiveError(err) { - deviceId, err := activateDevice(ctx, client) + deviceId, err := c.activateDevice(ctx) if err != nil { return err } - err = client.PlayOpt(ctx, &spotify.PlayOptions{ + err = c.Client().PlayOpt(ctx, &spotify.PlayOptions{ PlaybackContext: &radioPlaylist.URI, PlaybackOffset: &spotify.PlaybackOffset{ Position: 0, @@ -1135,17 +1163,17 @@ func RadioGivenList(ctx *gctx.Context, client *spotify.Client, song_ids []spotif } } for i := 0; i < 4; i++ { - id := rand.Intn(len(recomendationIds)-2) + 1 + id := frand.Intn(len(recomendationIds)-2) + 1 seed := spotify.Seeds{ Tracks: []spotify.ID{recomendationIds[id]}, } - additional_recs, err := client.GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) + additional_recs, err := c.Client().GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) if err != nil { return err } additionalRecsIds := []spotify.ID{} for _, song := range additional_recs.Tracks { - exists, err := SongExists(db, song.ID) + exists, err := c.SongExists(db, song.ID) if err != nil { return err } @@ -1157,7 +1185,7 @@ func RadioGivenList(ctx *gctx.Context, client *spotify.Client, song_ids []spotif additionalRecsIds = append(additionalRecsIds, song.ID) } } - _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, additionalRecsIds...) + _, err = c.Client().AddTracksToPlaylist(ctx, radioPlaylist.ID, additionalRecsIds...) if err != nil { return err } @@ -1165,7 +1193,7 @@ func RadioGivenList(ctx *gctx.Context, client *spotify.Client, song_ids []spotif return nil } -func activateDevice(ctx *gctx.Context, client *spotify.Client) (spotify.ID, error) { +func (c *Commands) activateDevice(ctx *gctx.Context) (spotify.ID, error) { var device *spotify.PlayerDevice configDir, _ := os.UserConfigDir() if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err == nil { @@ -1182,7 +1210,7 @@ func activateDevice(ctx *gctx.Context, client *spotify.Client) (spotify.ID, erro if err != nil { return "", err } - err = client.TransferPlayback(ctx, device.ID, true) + err = c.Client().TransferPlayback(ctx, device.ID, true) if err != nil { return "", err } @@ -1192,7 +1220,7 @@ func activateDevice(ctx *gctx.Context, client *spotify.Client) (spotify.ID, erro return device.ID, nil } -func getDefaultDevice(ctx *gctx.Context, client *spotify.Client) (spotify.ID, error) { +func (c *Commands) getDefaultDevice(ctx *gctx.Context) (spotify.ID, error) { configDir, _ := os.UserConfigDir() if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err == nil { deviceFile, err := os.Open(filepath.Join(configDir, "gospt/device.json")) @@ -1215,11 +1243,11 @@ func getDefaultDevice(ctx *gctx.Context, client *spotify.Client) (spotify.ID, er } } -func GetRadioPlaylist(ctx *gctx.Context, client *spotify.Client, name string) (*spotify.FullPlaylist, *sql.DB, error) { +func (c *Commands) GetRadioPlaylist(ctx *gctx.Context, name string) (*spotify.FullPlaylist, *sql.DB, error) { configDir, _ := os.UserConfigDir() playlistFile, err := os.ReadFile(filepath.Join(configDir, "gospt/radio.json")) if errors.Is(err, os.ErrNotExist) { - return CreateRadioPlaylist(ctx, client, name) + return c.CreateRadioPlaylist(ctx, name) } if err != nil { return nil, nil, err @@ -1233,10 +1261,10 @@ func GetRadioPlaylist(ctx *gctx.Context, client *spotify.Client, name string) (* return playlist, db, nil } -func CreateRadioPlaylist(ctx *gctx.Context, client *spotify.Client, name string) (*spotify.FullPlaylist, *sql.DB, error) { +func (c *Commands) CreateRadioPlaylist(ctx *gctx.Context, name string) (*spotify.FullPlaylist, *sql.DB, error) { // private flag doesnt work configDir, _ := os.UserConfigDir() - playlist, err := client.CreatePlaylistForUser(ctx, ctx.UserId, name+" - autoradio", "Automanaged radio playlist", false, false) + playlist, err := c.Client().CreatePlaylistForUser(ctx, ctx.UserId, name+" - autoradio", "Automanaged radio playlist", false, false) if err != nil { return nil, nil, err }