From a8bfc458ef89b7163f61a114e40129ffd3758f6e Mon Sep 17 00:00:00 2001 From: a Date: Fri, 17 Feb 2023 15:05:06 -0600 Subject: [PATCH 1/4] cache --- src/cache/cache.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/cache/cache.go diff --git a/src/cache/cache.go b/src/cache/cache.go new file mode 100644 index 0000000..3c3dc9d --- /dev/null +++ b/src/cache/cache.go @@ -0,0 +1,85 @@ +package cache + +import ( + "encoding/json" + "os" + "path/filepath" + "time" +) + +type Cache struct { + Root string +} + +type CacheEntry struct { + Expire time.Time `json:"e"` + Value string `json:"v"` +} + +func DefaultCache() *Cache { + return &Cache{ + Root: filepath.Join(os.TempDir(), "gospt.cache"), + } +} + +func (c *Cache) load() (map[string]CacheEntry, error) { + out := map[string]CacheEntry{} + cache, err := os.Open(c.Root) + if err != nil { + return nil, err + } + if err := json.NewDecoder(cache).Decode(&out); err != nil { + return nil, err + } + return out, nil +} + +func (c *Cache) save(map[string]CacheEntry) error { + out := map[string]CacheEntry{} + payload, err := json.Marshal(out) + if err != nil { + return err + } + err = os.WriteFile(c.Root, payload, 0640) + if err != nil { + return err + } + return nil +} + +func (c *Cache) GetOrDo(key string, do func() (string, error), ttl time.Duration) (string, error) { + conf, err := c.load() + if err != nil { + return c.Do(key, do, ttl) + } + val, ok := conf[key] + if !ok { + return c.Do(key, do, ttl) + } + if time.Now().After(val.Expire) { + return c.Do(key, do, ttl) + } + return val.Value, nil +} + +func (c *Cache) Do(key string, do func() (string, error), ttl time.Duration) (string, error) { + if do == nil { + return "", nil + } + res, err := do() + if err != nil { + return "", err + } + return c.Put(key, res, ttl) +} +func (c *Cache) Put(key string, value string, ttl time.Duration) (string, error) { + conf, err := c.load() + if err != nil { + conf = map[string]CacheEntry{} + } + conf[key] = CacheEntry{ + Expire: time.Now().Add(ttl), + Value: value, + } + return value, nil +} -- 2.45.2 From e58674ce171fab0a1b43158a1dd6e1750554b698 Mon Sep 17 00:00:00 2001 From: a Date: Fri, 17 Feb 2023 15:31:19 -0600 Subject: [PATCH 2/4] cache --- go.mod | 5 ++++- go.sum | 16 +++++++++++++++- src/cache/cache.go | 19 ++++++++++++++++--- src/cmd/root.go | 14 ++++++++++++-- src/commands/commands.go | 29 ++++++++++++++++++----------- 5 files changed, 65 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 0a170a0..7ac0f72 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/zmb3/spotify/v2 v2.3.1 golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5 modernc.org/sqlite v1.20.3 + tuxpa.in/a/zlog v1.60.0 ) require ( @@ -25,6 +26,7 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect @@ -34,11 +36,12 @@ require ( github.com/muesli/termenv v0.13.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/rs/zerolog v1.28.0 // indirect github.com/sahilm/fuzzy v0.1.0 // indirect 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.0.0-20220915200043-7b5979e65e41 // 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..4dbc1df 100644 --- a/go.sum +++ b/go.sum @@ -55,6 +55,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cristalhq/aconfig v0.17.0/go.mod h1:NXaRp+1e6bkO4dJn+wZ71xyaihMDYPtCSvEhMTm/H3E= github.com/cristalhq/aconfig v0.18.3 h1:Or12LIWIF+2mQpcGWA2PQnNc55+WiHFAqRjYh/pQNtM= @@ -72,6 +74,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -145,6 +148,9 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -168,6 +174,7 @@ github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0= github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -177,6 +184,9 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= +github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= @@ -311,10 +321,12 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/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.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc= +golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/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= @@ -497,3 +509,5 @@ modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +tuxpa.in/a/zlog v1.60.0 h1:bU4wJk6nwvaFsKIvKKxgGM0uO+Z2kaE8LzgRiQ4NCRw= +tuxpa.in/a/zlog v1.60.0/go.mod h1:1t8SX1a4zLy+p6ylGn6m1ZXnssTPr/2ErdPjjSP+C2k= diff --git a/src/cache/cache.go b/src/cache/cache.go index 3c3dc9d..afd8005 100644 --- a/src/cache/cache.go +++ b/src/cache/cache.go @@ -5,6 +5,8 @@ import ( "os" "path/filepath" "time" + + "tuxpa.in/a/zlog/log" ) type Cache struct { @@ -34,12 +36,12 @@ func (c *Cache) load() (map[string]CacheEntry, error) { return out, nil } -func (c *Cache) save(map[string]CacheEntry) error { - out := map[string]CacheEntry{} - payload, err := json.Marshal(out) +func (c *Cache) save(m map[string]CacheEntry) error { + payload, err := json.Marshal(m) if err != nil { return err } + log.Trace().Str("tosave", string(payload)).Msg("saving cache") err = os.WriteFile(c.Root, payload, 0640) if err != nil { return err @@ -50,6 +52,7 @@ func (c *Cache) save(map[string]CacheEntry) error { func (c *Cache) GetOrDo(key string, do func() (string, error), ttl time.Duration) (string, error) { conf, err := c.load() if err != nil { + log.Trace().Err(err).Msg("cache failed read") return c.Do(key, do, ttl) } val, ok := conf[key] @@ -72,6 +75,7 @@ func (c *Cache) Do(key string, do func() (string, error), ttl time.Duration) (st } return c.Put(key, res, ttl) } + func (c *Cache) Put(key string, value string, ttl time.Duration) (string, error) { conf, err := c.load() if err != nil { @@ -81,5 +85,14 @@ func (c *Cache) Put(key string, value string, ttl time.Duration) (string, error) Expire: time.Now().Add(ttl), Value: value, } + log.Trace().Str("key", key).Str("val", value).Msg("saving new cache key") + err = c.save(conf) + if err != nil { + log.Trace().Err(err).Msg("cache failed save") + } return value, nil } + +func (c *Cache) Clear() error { + return os.Remove(c.Root) +} diff --git a/src/cmd/root.go b/src/cmd/root.go index 24e0e36..ff7b88d 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -11,6 +11,7 @@ import ( "gitea.asdf.cafe/abs3nt/gospt/src/auth" "gitea.asdf.cafe/abs3nt/gospt/src/config" "gitea.asdf.cafe/abs3nt/gospt/src/gctx" + "tuxpa.in/a/zlog" "github.com/cristalhq/aconfig" "github.com/cristalhq/aconfig/aconfigyaml" @@ -24,6 +25,7 @@ var ( client *spotify.Client cfgFile string userLicense string + verbose bool rootCmd = &cobra.Command{ Use: "gospt", @@ -45,13 +47,21 @@ func Execute(defCmd string) { } func init() { + zlog.SetGlobalLevel(zlog.DebugLevel) if len(os.Args) > 1 { if os.Args[1] == "completion" || os.Args[1] == "__complete" { return } } - cobra.OnInitialize(initConfig) - cobra.OnInitialize(initClient) + rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "enable verbose logging") + + cobra.OnInitialize(func() { + if verbose { + zlog.SetGlobalLevel(zlog.TraceLevel) + } + }) + cobra.OnInitialize(initConfig, initClient) + } func initClient() { diff --git a/src/commands/commands.go b/src/commands/commands.go index d287eef..4039307 100644 --- a/src/commands/commands.go +++ b/src/commands/commands.go @@ -14,6 +14,7 @@ import ( "strings" "time" + "gitea.asdf.cafe/abs3nt/gospt/src/cache" "gitea.asdf.cafe/abs3nt/gospt/src/gctx" "github.com/zmb3/spotify/v2" @@ -870,11 +871,26 @@ func LinkContext(ctx *gctx.Context, client *spotify.Client) (string, error) { } func NowPlaying(ctx *gctx.Context, client *spotify.Client) error { - current, err := client.PlayerCurrentlyPlaying(ctx) + song, err := cache.DefaultCache().GetOrDo("now_playing", func() (string, error) { + current, err := client.PlayerCurrentlyPlaying(ctx) + if err != nil { + return "", err + } + str := FormatSong(current) + return str, nil + }, 5*time.Second) if err != nil { return err } - return PrintPlaying(current) + fmt.Println(song) + return nil +} +func FormatSong(current *spotify.CurrentlyPlaying) string { + icon := "▶" + if !current.Playing { + icon = "⏸" + } + return fmt.Sprintf("%s %s - %s", icon, current.Item.Name, current.Item.Artists[0].Name) } func Shuffle(ctx *gctx.Context, client *spotify.Client) error { @@ -935,15 +951,6 @@ func PrintState(state *spotify.PlayerState) error { return nil } -func PrintPlaying(current *spotify.CurrentlyPlaying) error { - icon := "▶" - if !current.Playing { - icon = "⏸" - } - fmt.Println(fmt.Sprintf("%s %s - %s", icon, current.Item.Name, current.Item.Artists[0].Name)) - return nil -} - func PrintDevices(devices []spotify.PlayerDevice) error { out, err := json.MarshalIndent(devices, "", " ") if err != nil { -- 2.45.2 From 67e67d32eb0dba5ecbf6186edbbc69afc994fe0d Mon Sep 17 00:00:00 2001 From: a Date: Fri, 17 Feb 2023 15:45:24 -0600 Subject: [PATCH 3/4] 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 } -- 2.45.2 From 8a4ac1774386fcef7c15e0723f5de3cb507c3a1c Mon Sep 17 00:00:00 2001 From: a Date: Fri, 17 Feb 2023 16:08:25 -0600 Subject: [PATCH 4/4] works maybe --- src/cmd/clearradio.go | 4 +- src/cmd/devices.go | 4 +- src/cmd/like.go | 4 +- src/cmd/link.go | 4 +- src/cmd/linkcontext.go | 4 +- src/cmd/mute.go | 4 +- src/cmd/next.go | 4 +- src/cmd/nowplaying.go | 4 +- src/cmd/pause.go | 4 +- src/cmd/play.go | 4 +- src/cmd/playurl.go | 4 +- src/cmd/previous.go | 4 +- src/cmd/radio.go | 4 +- src/cmd/refillradio.go | 4 +- src/cmd/repeat.go | 4 +- src/cmd/root.go | 11 ++-- src/cmd/seek.go | 8 +-- src/cmd/setdevice.go | 2 +- src/cmd/shuffle.go | 4 +- src/cmd/status.go | 4 +- src/cmd/toggleplay.go | 4 +- src/cmd/tracks.go | 9 ++- src/cmd/tui.go | 9 ++- src/cmd/unlike.go | 4 +- src/cmd/unmute.go | 4 +- src/cmd/volume.go | 8 +-- src/commands/commands.go | 10 ++-- src/gctx/context.go | 12 +++- src/tui/handlers.go | 50 ++++++++--------- src/tui/loader.go | 16 +++--- src/tui/main.go | 115 ++++++++++++++++++++------------------- src/tui/tui.go | 6 +- src/tui/views.go | 50 ++++++++--------- 33 files changed, 176 insertions(+), 210 deletions(-) diff --git a/src/cmd/clearradio.go b/src/cmd/clearradio.go index 5110224..b9bb903 100644 --- a/src/cmd/clearradio.go +++ b/src/cmd/clearradio.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -15,6 +13,6 @@ var clearRadioCmd = &cobra.Command{ Short: "Wipes the radio playlist and creates an empty one", Long: `Wipes the radio playlist and creates an empty one, mostly for debugging or if something goes wrong`, Run: func(cmd *cobra.Command, args []string) { - commands.ClearRadio(ctx, client) + commands.ClearRadio(ctx) }, } diff --git a/src/cmd/devices.go b/src/cmd/devices.go index 71c9677..044d34c 100644 --- a/src/cmd/devices.go +++ b/src/cmd/devices.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -15,6 +13,6 @@ var devicesCmd = &cobra.Command{ Short: "Prints out devices", Long: `Prints out devices`, Run: func(cmd *cobra.Command, args []string) { - commands.Devices(ctx, client) + commands.Devices(ctx) }, } diff --git a/src/cmd/like.go b/src/cmd/like.go index db42e3e..62c71e9 100644 --- a/src/cmd/like.go +++ b/src/cmd/like.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var likeCmd = &cobra.Command{ Short: "Likes song", Long: `Likes song`, Run: func(cmd *cobra.Command, args []string) { - commands.Like(ctx, client) + commands.Like(ctx) }, } diff --git a/src/cmd/link.go b/src/cmd/link.go index bd19458..c1a97d6 100644 --- a/src/cmd/link.go +++ b/src/cmd/link.go @@ -4,8 +4,6 @@ import ( "fmt" "os" - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,7 +14,7 @@ var linkCmd = &cobra.Command{ Short: "Print link to currently playing song", Long: `Print link to currently playing song`, Run: func(cmd *cobra.Command, args []string) { - link, err := commands.Link(ctx, client) + link, err := commands.Link(ctx) if err != nil { fmt.Println(err) os.Exit(1) diff --git a/src/cmd/linkcontext.go b/src/cmd/linkcontext.go index e2992e6..97386d7 100644 --- a/src/cmd/linkcontext.go +++ b/src/cmd/linkcontext.go @@ -4,8 +4,6 @@ import ( "fmt" "os" - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,7 +14,7 @@ var linkContextCmd = &cobra.Command{ Short: "Get url to current context(album, playlist)", Long: `Get url to current context(album, playlist)`, Run: func(cmd *cobra.Command, args []string) { - link, err := commands.LinkContext(ctx, client) + link, err := commands.LinkContext(ctx) if err != nil { fmt.Println(err) os.Exit(1) diff --git a/src/cmd/mute.go b/src/cmd/mute.go index ef999f9..1754009 100644 --- a/src/cmd/mute.go +++ b/src/cmd/mute.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -15,7 +13,7 @@ var muteCmd = &cobra.Command{ Short: "mutes playback", Long: `Mutes the spotify device, playback will continue`, RunE: func(cmd *cobra.Command, args []string) error { - err := commands.SetVolume(ctx, client, 0) + err := commands.SetVolume(ctx, 0) if err != nil { return err } diff --git a/src/cmd/next.go b/src/cmd/next.go index 792d8d3..d5c9f72 100644 --- a/src/cmd/next.go +++ b/src/cmd/next.go @@ -3,8 +3,6 @@ package cmd import ( "strconv" - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -27,6 +25,6 @@ var nextCmd = &cobra.Command{ return err } } - return commands.Next(ctx, client, skipAmt) + return commands.Next(ctx, skipAmt) }, } diff --git a/src/cmd/nowplaying.go b/src/cmd/nowplaying.go index 85fb560..4974a39 100644 --- a/src/cmd/nowplaying.go +++ b/src/cmd/nowplaying.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var nowPlayingCmd = &cobra.Command{ Short: "Shows song and artist of currently playing song", Long: `Shows song and artist of currently playing song, useful for scripting`, Run: func(cmd *cobra.Command, args []string) { - commands.NowPlaying(ctx, client) + commands.NowPlaying(ctx) }, } diff --git a/src/cmd/pause.go b/src/cmd/pause.go index 63ae064..a9c77c6 100644 --- a/src/cmd/pause.go +++ b/src/cmd/pause.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var pauseCmd = &cobra.Command{ Aliases: []string{"pa"}, Long: `Pauses currently playing song on spotify`, Run: func(cmd *cobra.Command, args []string) { - commands.Pause(ctx, client) + commands.Pause(ctx) }, } diff --git a/src/cmd/play.go b/src/cmd/play.go index a3c1f3c..f3e69fa 100644 --- a/src/cmd/play.go +++ b/src/cmd/play.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var playCmd = &cobra.Command{ Short: "Plays spotify", Long: `Plays queued song on spotify, uses last used device and activates it if needed`, Run: func(cmd *cobra.Command, args []string) { - commands.Play(ctx, client) + commands.Play(ctx) }, } diff --git a/src/cmd/playurl.go b/src/cmd/playurl.go index d573533..5307e15 100644 --- a/src/cmd/playurl.go +++ b/src/cmd/playurl.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var playurlCmd = &cobra.Command{ Args: cobra.MatchAll(cobra.ExactArgs(1)), Long: `Plays song from provided url`, Run: func(cmd *cobra.Command, args []string) { - commands.PlayUrl(ctx, client, args) + commands.PlayUrl(ctx, args) }, } diff --git a/src/cmd/previous.go b/src/cmd/previous.go index 2756d05..503eba5 100644 --- a/src/cmd/previous.go +++ b/src/cmd/previous.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var previousCmd = &cobra.Command{ Short: "goes to previous song", Long: `if song is playing it will start over, if close to begining of song it will go to previous song`, Run: func(cmd *cobra.Command, args []string) { - commands.Previous(ctx, client) + commands.Previous(ctx) }, } diff --git a/src/cmd/radio.go b/src/cmd/radio.go index e28cc50..c9d62ff 100644 --- a/src/cmd/radio.go +++ b/src/cmd/radio.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var radioCmd = &cobra.Command{ Short: "Starts radio", Long: `Starts radio`, RunE: func(cmd *cobra.Command, args []string) error { - return commands.Radio(ctx, client) + return commands.Radio(ctx) }, } diff --git a/src/cmd/refillradio.go b/src/cmd/refillradio.go index e6bea38..c053126 100644 --- a/src/cmd/refillradio.go +++ b/src/cmd/refillradio.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var refillRadioCmd = &cobra.Command{ Short: "Refills the radio", Long: `Deletes all songs up to your position in the radio and adds that many songs to the end of the radio`, RunE: func(cmd *cobra.Command, args []string) error { - return commands.RefillRadio(ctx, client) + return commands.RefillRadio(ctx) }, } diff --git a/src/cmd/repeat.go b/src/cmd/repeat.go index b9fd607..54fa9cc 100644 --- a/src/cmd/repeat.go +++ b/src/cmd/repeat.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -15,6 +13,6 @@ var repeatCmd = &cobra.Command{ Short: "Toggles repeat", Long: `Switches between repeating your current context or not, spotifyd does not support single track loops`, Run: func(cmd *cobra.Command, args []string) { - commands.Repeat(ctx, client) + commands.Repeat(ctx) }, } diff --git a/src/cmd/root.go b/src/cmd/root.go index 8185e58..bfe1e12 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -1,12 +1,15 @@ package cmd import ( + "context" "fmt" "os" "os/exec" "path/filepath" "strings" + cmds "gitea.asdf.cafe/abs3nt/gospt/src/commands" + "gitea.asdf.cafe/abs3nt/gospt/src/config" "gitea.asdf.cafe/abs3nt/gospt/src/gctx" "tuxpa.in/a/zlog" @@ -19,7 +22,7 @@ import ( var ( // Used for flags. ctx *gctx.Context - commands *commands.Commands + commands *cmds.Commands cfgFile string userLicense string verbose bool @@ -51,14 +54,14 @@ func init() { } } rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "enable verbose logging") - cobra.OnInitialize(func() { if verbose { zlog.SetGlobalLevel(zlog.TraceLevel) } }) - cobra.OnInitialize(initConfig, initClient) - + ctx = gctx.NewContext(context.Background()) + commands = &cmds.Commands{Context: ctx} + cobra.OnInitialize(initConfig) } func initConfig() { diff --git a/src/cmd/seek.go b/src/cmd/seek.go index 0238ac5..f0bb931 100644 --- a/src/cmd/seek.go +++ b/src/cmd/seek.go @@ -3,8 +3,6 @@ package cmd import ( "strconv" - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -20,7 +18,7 @@ var seekCmd = &cobra.Command{ Long: `Seeks forward or backward, or seeks to a given position in seconds`, RunE: func(cmd *cobra.Command, args []string) error { if args[0] == "forward" || args[0] == "f" { - err := commands.Seek(ctx, client, true) + err := commands.Seek(ctx, true) if err != nil { return err } @@ -28,7 +26,7 @@ var seekCmd = &cobra.Command{ } if args[0] == "backward" || args[0] == "b" { - err := commands.Seek(ctx, client, false) + err := commands.Seek(ctx, false) if err != nil { return err } @@ -40,7 +38,7 @@ var seekCmd = &cobra.Command{ return err } pos = pos * 1000 - err = commands.SetPosition(ctx, client, pos) + err = commands.SetPosition(ctx, pos) if err != nil { return err } diff --git a/src/cmd/setdevice.go b/src/cmd/setdevice.go index 9a6fbe1..075a6c9 100644 --- a/src/cmd/setdevice.go +++ b/src/cmd/setdevice.go @@ -15,6 +15,6 @@ var setDeviceCmd = &cobra.Command{ Short: "Shows tui to pick active device", Long: `Allows setting or changing the active spotify device, shown in a tui`, Run: func(cmd *cobra.Command, args []string) { - tui.StartTea(ctx, client, "devices") + tui.StartTea(ctx, commands, "devices") }, } diff --git a/src/cmd/shuffle.go b/src/cmd/shuffle.go index 047106f..5272bb9 100644 --- a/src/cmd/shuffle.go +++ b/src/cmd/shuffle.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -15,6 +13,6 @@ var shuffleCmd = &cobra.Command{ Short: "Toggles shuffle", Long: `Enables shuffle if it is currently disabled or disables it if it is currently active`, Run: func(cmd *cobra.Command, args []string) { - commands.Shuffle(ctx, client) + commands.Shuffle(ctx) }, } diff --git a/src/cmd/status.go b/src/cmd/status.go index f3a3a43..a706565 100644 --- a/src/cmd/status.go +++ b/src/cmd/status.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -15,6 +13,6 @@ var statusCmd = &cobra.Command{ Short: "Returns player status in json", Long: `Returns all player status in json, useful for scripting`, Run: func(cmd *cobra.Command, args []string) { - commands.Status(ctx, client) + commands.Status(ctx) }, } diff --git a/src/cmd/toggleplay.go b/src/cmd/toggleplay.go index ada7d07..6b8d0f6 100644 --- a/src/cmd/toggleplay.go +++ b/src/cmd/toggleplay.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var togglePlayCmd = &cobra.Command{ Short: "Toggles the play state of spotify", Long: `If you are playing a song it will pause and if a song is paused it will play`, Run: func(cmd *cobra.Command, args []string) { - commands.TogglePlay(ctx, client) + commands.TogglePlay(ctx) }, } diff --git a/src/cmd/tracks.go b/src/cmd/tracks.go index 63aee24..70aa187 100644 --- a/src/cmd/tracks.go +++ b/src/cmd/tracks.go @@ -4,7 +4,6 @@ import ( "os" "path/filepath" - "gitea.asdf.cafe/abs3nt/gospt/src/commands" "gitea.asdf.cafe/abs3nt/gospt/src/tui" "github.com/spf13/cobra" @@ -20,12 +19,12 @@ var tracksCmd = &cobra.Command{ Long: `Uses TUI to open a list of saved tracks`, RunE: func(cmd *cobra.Command, args []string) error { configDir, _ := os.UserConfigDir() - if commands.ActiveDeviceExists(ctx, client) { - return tui.StartTea(ctx, client, "tracks") + if commands.ActiveDeviceExists(ctx) { + return tui.StartTea(ctx, commands, "tracks") } if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err != nil { - return tui.StartTea(ctx, client, "devices") + return tui.StartTea(ctx, commands, "devices") } - return tui.StartTea(ctx, client, "tracks") + return tui.StartTea(ctx, commands, "tracks") }, } diff --git a/src/cmd/tui.go b/src/cmd/tui.go index cadb6dc..54673b9 100644 --- a/src/cmd/tui.go +++ b/src/cmd/tui.go @@ -4,7 +4,6 @@ import ( "os" "path/filepath" - "gitea.asdf.cafe/abs3nt/gospt/src/commands" "gitea.asdf.cafe/abs3nt/gospt/src/tui" "github.com/spf13/cobra" @@ -20,12 +19,12 @@ var tuiCmd = &cobra.Command{ Long: `Default command. this is what will run if no other commands are present. Shows the main menu.`, RunE: func(cmd *cobra.Command, args []string) error { configDir, _ := os.UserConfigDir() - if commands.ActiveDeviceExists(ctx, client) { - return tui.StartTea(ctx, client, "main") + if commands.ActiveDeviceExists(ctx) { + return tui.StartTea(ctx, commands, "main") } if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err != nil { - return tui.StartTea(ctx, client, "devices") + return tui.StartTea(ctx, commands, "devices") } - return tui.StartTea(ctx, client, "main") + return tui.StartTea(ctx, commands, "main") }, } diff --git a/src/cmd/unlike.go b/src/cmd/unlike.go index 97b6665..527c4f8 100644 --- a/src/cmd/unlike.go +++ b/src/cmd/unlike.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -16,6 +14,6 @@ var unlikeCmd = &cobra.Command{ Short: "unlikes song", Long: `unlikes song`, Run: func(cmd *cobra.Command, args []string) { - commands.Unlike(ctx, client) + commands.Unlike(ctx) }, } diff --git a/src/cmd/unmute.go b/src/cmd/unmute.go index 2188bf2..f977434 100644 --- a/src/cmd/unmute.go +++ b/src/cmd/unmute.go @@ -1,8 +1,6 @@ package cmd import ( - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -15,7 +13,7 @@ var unmuteCmd = &cobra.Command{ Short: "unmutes playback", Long: `unmutes the spotify device, playback will continue`, RunE: func(cmd *cobra.Command, args []string) error { - err := commands.SetVolume(ctx, client, 100) + err := commands.SetVolume(ctx, 100) if err != nil { return err } diff --git a/src/cmd/volume.go b/src/cmd/volume.go index bacdb69..8fbc4a4 100644 --- a/src/cmd/volume.go +++ b/src/cmd/volume.go @@ -3,8 +3,6 @@ package cmd import ( "strconv" - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/spf13/cobra" ) @@ -20,7 +18,7 @@ var volumeCmd = &cobra.Command{ Long: `Sets the volume to the given percent [0-100] or increases/decreases by 5 percent if you say up or down`, RunE: func(cmd *cobra.Command, args []string) error { if args[0] == "up" { - err := commands.ChangeVolume(ctx, client, 5) + err := commands.ChangeVolume(ctx, 5) if err != nil { return err } @@ -28,7 +26,7 @@ var volumeCmd = &cobra.Command{ } if args[0] == "down" { - err := commands.ChangeVolume(ctx, client, -5) + err := commands.ChangeVolume(ctx, -5) if err != nil { return err } @@ -39,7 +37,7 @@ var volumeCmd = &cobra.Command{ if err != nil { return err } - err = commands.SetVolume(ctx, client, vol) + err = commands.SetVolume(ctx, vol) if err != nil { return err } diff --git a/src/commands/commands.go b/src/commands/commands.go index 8335851..e2a1285 100644 --- a/src/commands/commands.go +++ b/src/commands/commands.go @@ -1,7 +1,6 @@ package commands import ( - "context" "database/sql" "encoding/json" "errors" @@ -25,8 +24,9 @@ import ( ) type Commands struct { - cl *spotify.Client - mu sync.RWMutex + Context *gctx.Context + cl *spotify.Client + mu sync.RWMutex user string } @@ -48,7 +48,7 @@ func (c *Commands) User() string { } func (c *Commands) connectClient() *spotify.Client { - ctx := gctx.NewContext(context.Background()) + ctx := c.Context client, err := auth.GetClient(ctx) if err != nil { panic(err) @@ -58,7 +58,7 @@ func (c *Commands) connectClient() *spotify.Client { panic(err) } c.user = currentUser.ID - return &spotify.Client{} + return client } func (c *Commands) SetVolume(ctx *gctx.Context, vol int) error { diff --git a/src/gctx/context.go b/src/gctx/context.go index 9d8f9eb..66ec1f9 100644 --- a/src/gctx/context.go +++ b/src/gctx/context.go @@ -2,15 +2,25 @@ package gctx import ( "context" + "fmt" "os" "tuxpa.in/a/zlog" ) type Context struct { - context.Context zlog.Logger Debug zlog.Logger + + context.Context +} + +func (c *Context) Err() error { + return c.Context.Err() +} + +func (c *Context) Println(args ...any) { + c.Info().Msg(fmt.Sprint(args...)) } func NewContext(ctx context.Context) *Context { diff --git a/src/tui/handlers.go b/src/tui/handlers.go index a10521c..8269b35 100644 --- a/src/tui/handlers.go +++ b/src/tui/handlers.go @@ -7,95 +7,95 @@ import ( "github.com/zmb3/spotify/v2" ) -func HandlePlayWithContext(ctx *gctx.Context, client *spotify.Client, uri *spotify.URI, pos int) { +func HandlePlayWithContext(ctx *gctx.Context, commands *commands.Commands, uri *spotify.URI, pos int) { var err error - err = commands.PlaySongInPlaylist(ctx, client, uri, pos) + err = commands.PlaySongInPlaylist(ctx, uri, pos) if err != nil { return } } -func HandleRadio(ctx *gctx.Context, client *spotify.Client, song spotify.SimpleTrack) { - err := commands.RadioGivenSong(ctx, client, song, 0) +func HandleRadio(ctx *gctx.Context, commands *commands.Commands, song spotify.SimpleTrack) { + err := commands.RadioGivenSong(ctx, song, 0) if err != nil { return } } -func HandleAlbumRadio(ctx *gctx.Context, client *spotify.Client, album spotify.SimpleAlbum) { - err := commands.RadioFromAlbum(ctx, client, album) +func HandleAlbumRadio(ctx *gctx.Context, commands *commands.Commands, album spotify.SimpleAlbum) { + err := commands.RadioFromAlbum(ctx, album) if err != nil { return } } -func HandleSeek(ctx *gctx.Context, client *spotify.Client, fwd bool) { - err := commands.Seek(ctx, client, fwd) +func HandleSeek(ctx *gctx.Context, commands *commands.Commands, fwd bool) { + err := commands.Seek(ctx, fwd) if err != nil { return } } -func HandleVolume(ctx *gctx.Context, client *spotify.Client, up bool) { +func HandleVolume(ctx *gctx.Context, commands *commands.Commands, up bool) { vol := 10 if !up { vol = -10 } - err := commands.ChangeVolume(ctx, client, vol) + err := commands.ChangeVolume(ctx, vol) if err != nil { return } } -func HandleArtistRadio(ctx *gctx.Context, client *spotify.Client, artist spotify.SimpleArtist) { - err := commands.RadioGivenArtist(ctx, client, artist) +func HandleArtistRadio(ctx *gctx.Context, commands *commands.Commands, artist spotify.SimpleArtist) { + err := commands.RadioGivenArtist(ctx, artist) if err != nil { return } } -func HandleAlbumArtist(ctx *gctx.Context, client *spotify.Client, artist spotify.SimpleArtist) { - err := commands.RadioGivenArtist(ctx, client, artist) +func HandleAlbumArtist(ctx *gctx.Context, commands *commands.Commands, artist spotify.SimpleArtist) { + err := commands.RadioGivenArtist(ctx, artist) if err != nil { return } } -func HandlePlaylistRadio(ctx *gctx.Context, client *spotify.Client, playlist spotify.SimplePlaylist) { - err := commands.RadioFromPlaylist(ctx, client, playlist) +func HandlePlaylistRadio(ctx *gctx.Context, commands *commands.Commands, playlist spotify.SimplePlaylist) { + err := commands.RadioFromPlaylist(ctx, playlist) if err != nil { return } } -func HandleLibraryRadio(ctx *gctx.Context, client *spotify.Client) { - err := commands.RadioFromSavedTracks(ctx, client) +func HandleLibraryRadio(ctx *gctx.Context, commands *commands.Commands) { + err := commands.RadioFromSavedTracks(ctx) if err != nil { return } } -func HandlePlayLikedSong(ctx *gctx.Context, client *spotify.Client, position int) { - err := commands.PlayLikedSongs(ctx, client, position) +func HandlePlayLikedSong(ctx *gctx.Context, commands *commands.Commands, position int) { + err := commands.PlayLikedSongs(ctx, position) if err != nil { return } } -func HandlePlayTrack(ctx *gctx.Context, client *spotify.Client, track spotify.ID) { - err := commands.QueueSong(ctx, client, track) +func HandlePlayTrack(ctx *gctx.Context, commands *commands.Commands, track spotify.ID) { + err := commands.QueueSong(ctx, track) if err != nil { return } - err = commands.Next(ctx, client, 1) + err = commands.Next(ctx, 1) if err != nil { return } } -func HandleSetDevice(ctx *gctx.Context, client *spotify.Client, player spotify.PlayerDevice) { +func HandleSetDevice(ctx *gctx.Context, commands *commands.Commands, player spotify.PlayerDevice) { var err error - err = commands.SetDevice(ctx, client, player) + err = commands.SetDevice(ctx, player) if err != nil { return } diff --git a/src/tui/loader.go b/src/tui/loader.go index d1127bb..f3768da 100644 --- a/src/tui/loader.go +++ b/src/tui/loader.go @@ -4,15 +4,13 @@ import ( "fmt" "time" - "gitea.asdf.cafe/abs3nt/gospt/src/commands" - "github.com/charmbracelet/bubbles/list" ) func (m *mainModel) LoadMoreItems() { switch m.mode { case "artist": - albums, err := commands.ArtistAlbums(m.ctx, m.client, m.artist.ID, (page + 1)) + albums, err := m.commands.ArtistAlbums(m.ctx, m.artist.ID, (page + 1)) page++ if err != nil { return @@ -32,7 +30,7 @@ func (m *mainModel) LoadMoreItems() { main_updates <- m return case "artists": - artists, err := commands.UserArtists(m.ctx, m.client, (page + 1)) + artists, err := m.commands.UserArtists(m.ctx, (page + 1)) page++ if err != nil { return @@ -52,7 +50,7 @@ func (m *mainModel) LoadMoreItems() { main_updates <- m return case "album": - tracks, err := commands.AlbumTracks(m.ctx, m.client, m.album.ID, (page + 1)) + tracks, err := m.commands.AlbumTracks(m.ctx, m.album.ID, (page + 1)) page++ if err != nil { return @@ -73,7 +71,7 @@ func (m *mainModel) LoadMoreItems() { main_updates <- m return case "albums": - albums, err := commands.UserAlbums(m.ctx, m.client, (page + 1)) + albums, err := m.commands.UserAlbums(m.ctx, (page + 1)) page++ if err != nil { return @@ -93,7 +91,7 @@ func (m *mainModel) LoadMoreItems() { main_updates <- m return case "main": - playlists, err := commands.Playlists(m.ctx, m.client, (page + 1)) + playlists, err := m.commands.Playlists(m.ctx, (page + 1)) page++ if err != nil { return @@ -112,7 +110,7 @@ func (m *mainModel) LoadMoreItems() { main_updates <- m return case "playlist": - tracks, err := commands.PlaylistTracks(m.ctx, m.client, m.playlist.ID, (page + 1)) + tracks, err := m.commands.PlaylistTracks(m.ctx, m.playlist.ID, (page + 1)) page++ if err != nil { return @@ -133,7 +131,7 @@ func (m *mainModel) LoadMoreItems() { main_updates <- m return case "tracks": - tracks, err := commands.TrackList(m.ctx, m.client, (page + 1)) + tracks, err := m.commands.TrackList(m.ctx, (page + 1)) page++ if err != nil { return diff --git a/src/tui/main.go b/src/tui/main.go index 753da2d..63e9f22 100644 --- a/src/tui/main.go +++ b/src/tui/main.go @@ -5,6 +5,7 @@ import ( "strings" "time" + "gitea.asdf.cafe/abs3nt/gospt/src/commands" "gitea.asdf.cafe/abs3nt/gospt/src/gctx" "github.com/atotto/clipboard" @@ -74,7 +75,7 @@ type mainModel struct { list list.Model input textinput.Model ctx *gctx.Context - client *spotify.Client + commands *commands.Commands mode Mode playlist spotify.SimplePlaylist artist spotify.SimpleArtist @@ -91,34 +92,34 @@ func (m *mainModel) PlayRadio() { selectedItem := m.list.SelectedItem().(mainItem).SpotifyItem switch selectedItem.(type) { case spotify.SimplePlaylist: - go HandlePlaylistRadio(m.ctx, m.client, selectedItem.(spotify.SimplePlaylist)) + go HandlePlaylistRadio(m.ctx, m.commands, selectedItem.(spotify.SimplePlaylist)) return case *spotify.SavedTrackPage: - go HandleLibraryRadio(m.ctx, m.client) + go HandleLibraryRadio(m.ctx, m.commands) return case spotify.SimpleAlbum: - go HandleAlbumRadio(m.ctx, m.client, selectedItem.(spotify.SimpleAlbum)) + go HandleAlbumRadio(m.ctx, m.commands, selectedItem.(spotify.SimpleAlbum)) return case spotify.FullAlbum: - go HandleAlbumRadio(m.ctx, m.client, selectedItem.(spotify.FullAlbum).SimpleAlbum) + go HandleAlbumRadio(m.ctx, m.commands, selectedItem.(spotify.FullAlbum).SimpleAlbum) return case spotify.SimpleArtist: - go HandleArtistRadio(m.ctx, m.client, selectedItem.(spotify.SimpleArtist)) + go HandleArtistRadio(m.ctx, m.commands, selectedItem.(spotify.SimpleArtist)) return case spotify.FullArtist: - go HandleArtistRadio(m.ctx, m.client, selectedItem.(spotify.FullArtist).SimpleArtist) + go HandleArtistRadio(m.ctx, m.commands, selectedItem.(spotify.FullArtist).SimpleArtist) return case spotify.SimpleTrack: - go HandleRadio(m.ctx, m.client, selectedItem.(spotify.SimpleTrack)) + go HandleRadio(m.ctx, m.commands, selectedItem.(spotify.SimpleTrack)) return case spotify.FullTrack: - go HandleRadio(m.ctx, m.client, selectedItem.(spotify.FullTrack).SimpleTrack) + go HandleRadio(m.ctx, m.commands, selectedItem.(spotify.FullTrack).SimpleTrack) return case spotify.PlaylistTrack: - go HandleRadio(m.ctx, m.client, selectedItem.(spotify.PlaylistTrack).Track.SimpleTrack) + go HandleRadio(m.ctx, m.commands, selectedItem.(spotify.PlaylistTrack).Track.SimpleTrack) return case spotify.SavedTrack: - go HandleRadio(m.ctx, m.client, selectedItem.(spotify.SavedTrack).SimpleTrack) + go HandleRadio(m.ctx, m.commands, selectedItem.(spotify.SavedTrack).SimpleTrack) return } } @@ -129,34 +130,34 @@ func (m *mainModel) GoBack() (tea.Cmd, error) { return tea.Quit, nil case Albums, Artists, Tracks, Playlist, Devices, Search: m.mode = Main - new_items, err := MainView(m.ctx, m.client) + new_items, err := MainView(m.ctx, m.commands) if err != nil { } m.list.SetItems(new_items) case Album: m.mode = Albums - new_items, err := AlbumsView(m.ctx, m.client) + new_items, err := AlbumsView(m.ctx, m.commands) if err != nil { return nil, err } m.list.SetItems(new_items) case Artist: m.mode = Artists - new_items, err := ArtistsView(m.ctx, m.client) + new_items, err := ArtistsView(m.ctx, m.commands) if err != nil { return nil, err } m.list.SetItems(new_items) case ArtistAlbum: m.mode = Artist - new_items, err := ArtistAlbumsView(m.ctx, m.artist.ID, m.client) + new_items, err := ArtistAlbumsView(m.ctx, m.artist.ID, m.commands) if err != nil { return nil, err } m.list.SetItems(new_items) case SearchArtists, SearchTracks, SearchAlbums, SearchPlaylists: m.mode = Search - items, result, err := SearchView(m.ctx, m.client, m.search) + items, result, err := SearchView(m.ctx, m.commands, m.search) if err != nil { return nil, err } @@ -164,28 +165,28 @@ func (m *mainModel) GoBack() (tea.Cmd, error) { m.list.SetItems(items) case SearchArtist: m.mode = SearchArtists - new_items, err := SearchArtistsView(m.ctx, m.client, m.searchResults.Artists) + new_items, err := SearchArtistsView(m.ctx, m.commands, m.searchResults.Artists) if err != nil { return nil, err } m.list.SetItems(new_items) case SearchArtistAlbum: m.mode = SearchArtist - new_items, err := ArtistAlbumsView(m.ctx, m.artist.ID, m.client) + new_items, err := ArtistAlbumsView(m.ctx, m.artist.ID, m.commands) if err != nil { return nil, err } m.list.SetItems(new_items) case SearchAlbum: m.mode = SearchAlbums - new_items, err := SearchAlbumsView(m.ctx, m.client, m.searchResults.Albums) + new_items, err := SearchAlbumsView(m.ctx, m.commands, m.searchResults.Albums) if err != nil { return nil, err } m.list.SetItems(new_items) case SearchPlaylist: m.mode = SearchPlaylists - new_items, err := SearchPlaylistsView(m.ctx, m.client, m.searchResults.Playlists) + new_items, err := SearchPlaylistsView(m.ctx, m.commands, m.searchResults.Playlists) if err != nil { return nil, err } @@ -243,7 +244,7 @@ func (m *mainModel) SelectItem() error { switch m.list.SelectedItem().(mainItem).SpotifyItem.(type) { case *spotify.FullArtistPage: m.mode = SearchArtists - new_items, err := SearchArtistsView(m.ctx, m.client, m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.FullArtistPage)) + new_items, err := SearchArtistsView(m.ctx, m.commands, m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.FullArtistPage)) if err != nil { return err } @@ -251,7 +252,7 @@ func (m *mainModel) SelectItem() error { m.list.ResetSelected() case *spotify.SimpleAlbumPage: m.mode = SearchAlbums - new_items, err := SearchAlbumsView(m.ctx, m.client, m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.SimpleAlbumPage)) + new_items, err := SearchAlbumsView(m.ctx, m.commands, m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.SimpleAlbumPage)) if err != nil { return err } @@ -260,7 +261,7 @@ func (m *mainModel) SelectItem() error { case *spotify.SimplePlaylistPage: m.mode = SearchPlaylists playlists := m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.SimplePlaylistPage) - new_items, err := SearchPlaylistsView(m.ctx, m.client, playlists) + new_items, err := SearchPlaylistsView(m.ctx, m.commands, playlists) if err != nil { return err } @@ -268,7 +269,7 @@ func (m *mainModel) SelectItem() error { m.list.ResetSelected() case *spotify.FullTrackPage: m.mode = SearchTracks - new_items, err := SearchTracksView(m.ctx, m.client, m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.FullTrackPage)) + new_items, err := SearchTracksView(m.ctx, m.commands, m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.FullTrackPage)) if err != nil { return err } @@ -278,7 +279,7 @@ func (m *mainModel) SelectItem() error { case SearchArtists: m.mode = SearchArtist m.artist = m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimpleArtist) - new_items, err := ArtistAlbumsView(m.ctx, m.artist.ID, m.client) + new_items, err := ArtistAlbumsView(m.ctx, m.artist.ID, m.commands) if err != nil { return err } @@ -287,7 +288,7 @@ func (m *mainModel) SelectItem() error { case SearchArtist: m.mode = SearchArtistAlbum m.album = m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimpleAlbum) - new_items, err := AlbumTracksView(m.ctx, m.album.ID, m.client) + new_items, err := AlbumTracksView(m.ctx, m.album.ID, m.commands) if err != nil { return err } @@ -296,7 +297,7 @@ func (m *mainModel) SelectItem() error { case SearchAlbums: m.mode = SearchAlbum m.album = m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimpleAlbum) - new_items, err := AlbumTracksView(m.ctx, m.album.ID, m.client) + new_items, err := AlbumTracksView(m.ctx, m.album.ID, m.commands) if err != nil { return err } @@ -306,7 +307,7 @@ func (m *mainModel) SelectItem() error { m.mode = SearchPlaylist playlist := m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimplePlaylist) m.playlist = playlist - new_items, err := PlaylistView(m.ctx, m.client, playlist) + new_items, err := PlaylistView(m.ctx, m.commands, playlist) if err != nil { return err } @@ -316,7 +317,7 @@ func (m *mainModel) SelectItem() error { switch m.list.SelectedItem().(mainItem).SpotifyItem.(type) { case *spotify.FullArtistCursorPage: m.mode = Artists - new_items, err := ArtistsView(m.ctx, m.client) + new_items, err := ArtistsView(m.ctx, m.commands) if err != nil { return err } @@ -324,7 +325,7 @@ func (m *mainModel) SelectItem() error { m.list.ResetSelected() case *spotify.SavedAlbumPage: m.mode = Albums - new_items, err := AlbumsView(m.ctx, m.client) + new_items, err := AlbumsView(m.ctx, m.commands) if err != nil { return err } @@ -334,7 +335,7 @@ func (m *mainModel) SelectItem() error { m.mode = Playlist playlist := m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimplePlaylist) m.playlist = playlist - new_items, err := PlaylistView(m.ctx, m.client, playlist) + new_items, err := PlaylistView(m.ctx, m.commands, playlist) if err != nil { return err } @@ -342,7 +343,7 @@ func (m *mainModel) SelectItem() error { m.list.ResetSelected() case *spotify.SavedTrackPage: m.mode = Tracks - new_items, err := SavedTracksView(m.ctx, m.client) + new_items, err := SavedTracksView(m.ctx, m.commands) if err != nil { return err } @@ -352,7 +353,7 @@ func (m *mainModel) SelectItem() error { case Albums: m.mode = Album m.album = m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimpleAlbum) - new_items, err := AlbumTracksView(m.ctx, m.album.ID, m.client) + new_items, err := AlbumTracksView(m.ctx, m.album.ID, m.commands) if err != nil { return err } @@ -361,7 +362,7 @@ func (m *mainModel) SelectItem() error { case Artist: m.mode = ArtistAlbum m.album = m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimpleAlbum) - new_items, err := AlbumTracksView(m.ctx, m.album.ID, m.client) + new_items, err := AlbumTracksView(m.ctx, m.album.ID, m.commands) if err != nil { return err } @@ -370,26 +371,26 @@ func (m *mainModel) SelectItem() error { case Artists: m.mode = Artist m.artist = m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimpleArtist) - new_items, err := ArtistAlbumsView(m.ctx, m.artist.ID, m.client) + new_items, err := ArtistAlbumsView(m.ctx, m.artist.ID, m.commands) if err != nil { return err } m.list.SetItems(new_items) m.list.ResetSelected() case Album, ArtistAlbum, SearchArtistAlbum, SearchAlbum: - go HandlePlayWithContext(m.ctx, m.client, &m.album.URI, m.list.Cursor()+(m.list.Paginator.Page*m.list.Paginator.TotalPages)) + go HandlePlayWithContext(m.ctx, m.commands, &m.album.URI, m.list.Cursor()+(m.list.Paginator.Page*m.list.Paginator.TotalPages)) case Playlist, SearchPlaylist: - go HandlePlayWithContext(m.ctx, m.client, &m.playlist.URI, m.list.Cursor()+(m.list.Paginator.Page*m.list.Paginator.PerPage)) + go HandlePlayWithContext(m.ctx, m.commands, &m.playlist.URI, m.list.Cursor()+(m.list.Paginator.Page*m.list.Paginator.PerPage)) case Tracks: - go HandlePlayLikedSong(m.ctx, m.client, m.list.Cursor()+(m.list.Paginator.Page*m.list.Paginator.PerPage)) + go HandlePlayLikedSong(m.ctx, m.commands, m.list.Cursor()+(m.list.Paginator.Page*m.list.Paginator.PerPage)) case SearchTracks: - go HandlePlayTrack(m.ctx, m.client, m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.FullTrack).ID) + go HandlePlayTrack(m.ctx, m.commands, m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.FullTrack).ID) case Devices: - go HandleSetDevice(m.ctx, m.client, m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.PlayerDevice)) + go HandleSetDevice(m.ctx, m.commands, m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.PlayerDevice)) m.list.NewStatusMessage("Setting device to " + m.list.SelectedItem().FilterValue()) m.mode = "main" m.list.NewStatusMessage("Setting view to main") - new_items, err := MainView(m.ctx, m.client) + new_items, err := MainView(m.ctx, m.commands) if err != nil { return err } @@ -412,7 +413,7 @@ func Tick() tea.Cmd { } func (m *mainModel) TickPlayback() { - playing, _ := m.client.PlayerCurrentlyPlaying(m.ctx) + playing, _ := m.commands.Client().PlayerCurrentlyPlaying(m.ctx) if playing != nil && playing.Playing && playing.Item != nil { currentlyPlaying = playing playbackContext, _ = m.getContext(playing) @@ -423,7 +424,7 @@ func (m *mainModel) TickPlayback() { for { select { case <-ticker.C: - playing, _ := m.client.PlayerCurrentlyPlaying(m.ctx) + playing, _ := m.commands.Client().PlayerCurrentlyPlaying(m.ctx) if playing != nil && playing.Playing && playing.Item != nil { currentlyPlaying = playing playbackContext, _ = m.getContext(playing) @@ -445,7 +446,7 @@ func (m mainModel) View() string { func (m *mainModel) Typing(msg tea.KeyMsg) (bool, tea.Cmd) { if msg.String() == "enter" { - items, result, err := SearchView(m.ctx, m.client, m.input.Value()) + items, result, err := SearchView(m.ctx, m.commands, m.input.Value()) if err != nil { return false, tea.Quit } @@ -475,19 +476,19 @@ func (m *mainModel) getContext(playing *spotify.CurrentlyPlaying) (string, error id := strings.Split(string(context.URI), ":")[2] switch context.Type { case "album": - album, err := m.client.GetAlbum(m.ctx, spotify.ID(id)) + album, err := m.commands.Client().GetAlbum(m.ctx, spotify.ID(id)) if err != nil { return "", err } return album.Name, nil case "playlist": - playlist, err := m.client.GetPlaylist(m.ctx, spotify.ID(id)) + playlist, err := m.commands.Client().GetPlaylist(m.ctx, spotify.ID(id)) if err != nil { return "", err } return playlist.Name, nil case "artist": - artist, err := m.client.GetArtist(m.ctx, spotify.ID(id)) + artist, err := m.commands.Client().GetArtist(m.ctx, spotify.ID(id)) if err != nil { return "", err } @@ -547,16 +548,16 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } } if msg.String() == ">" { - go HandleSeek(m.ctx, m.client, true) + go HandleSeek(m.ctx, m.commands, true) } if msg.String() == "<" { - go HandleSeek(m.ctx, m.client, false) + go HandleSeek(m.ctx, m.commands, false) } if msg.String() == "+" { - go HandleVolume(m.ctx, m.client, true) + go HandleVolume(m.ctx, m.commands, true) } if msg.String() == "-" { - go HandleVolume(m.ctx, m.client, false) + go HandleVolume(m.ctx, m.commands, false) } // search input if m.input.Focused() { @@ -573,7 +574,7 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // enter device selection if msg.String() == "d" { m.mode = Devices - new_items, err := DeviceView(m.ctx, m.client) + new_items, err := DeviceView(m.ctx, m.commands) if err != nil { return m, tea.Quit } @@ -624,24 +625,24 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, cmd } -func InitMain(ctx *gctx.Context, client *spotify.Client, mode Mode) (tea.Model, error) { +func InitMain(ctx *gctx.Context, c *commands.Commands, mode Mode) (tea.Model, error) { prog := progress.New(progress.WithColorProfile(2), progress.WithoutPercentage()) var err error lipgloss.SetColorProfile(2) items := []list.Item{} switch mode { case Main: - items, err = MainView(ctx, client) + items, err = MainView(ctx, c) if err != nil { return nil, err } case Devices: - items, err = DeviceView(ctx, client) + items, err = DeviceView(ctx, c) if err != nil { return nil, err } case Tracks: - items, err = SavedTracksView(ctx, client) + items, err = SavedTracksView(ctx, c) if err != nil { return nil, err } @@ -649,7 +650,7 @@ func InitMain(ctx *gctx.Context, client *spotify.Client, mode Mode) (tea.Model, m := mainModel{ list: list.New(items, list.NewDefaultDelegate(), 0, 0), ctx: ctx, - client: client, + commands: c, mode: mode, progress: prog, } diff --git a/src/tui/tui.go b/src/tui/tui.go index fbce6e8..4770490 100644 --- a/src/tui/tui.go +++ b/src/tui/tui.go @@ -3,15 +3,15 @@ package tui import ( "fmt" + "gitea.asdf.cafe/abs3nt/gospt/src/commands" "gitea.asdf.cafe/abs3nt/gospt/src/gctx" tea "github.com/charmbracelet/bubbletea" - "github.com/zmb3/spotify/v2" ) // StartTea the entry point for the UI. Initializes the model. -func StartTea(ctx *gctx.Context, client *spotify.Client, mode string) error { - m, err := InitMain(ctx, client, Mode(mode)) +func StartTea(ctx *gctx.Context, cmd *commands.Commands, mode string) error { + m, err := InitMain(ctx, cmd, Mode(mode)) if err != nil { fmt.Println("UH OH") } diff --git a/src/tui/views.go b/src/tui/views.go index 7fd96b6..319d61e 100644 --- a/src/tui/views.go +++ b/src/tui/views.go @@ -12,9 +12,9 @@ import ( "github.com/zmb3/spotify/v2" ) -func DeviceView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { +func DeviceView(ctx *gctx.Context, commands *commands.Commands) ([]list.Item, error) { items := []list.Item{} - devices, err := client.PlayerDevices(ctx) + devices, err := commands.Client().PlayerDevices(ctx) if err != nil { return nil, err } @@ -28,9 +28,9 @@ func DeviceView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) return items, nil } -func PlaylistView(ctx *gctx.Context, client *spotify.Client, playlist spotify.SimplePlaylist) ([]list.Item, error) { +func PlaylistView(ctx *gctx.Context, commands *commands.Commands, playlist spotify.SimplePlaylist) ([]list.Item, error) { items := []list.Item{} - tracks, err := commands.PlaylistTracks(ctx, client, playlist.ID, 1) + tracks, err := commands.PlaylistTracks(ctx, playlist.ID, 1) if err != nil { return nil, err } @@ -47,9 +47,9 @@ func PlaylistView(ctx *gctx.Context, client *spotify.Client, playlist spotify.Si return items, nil } -func ArtistsView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { +func ArtistsView(ctx *gctx.Context, commands *commands.Commands) ([]list.Item, error) { items := []list.Item{} - artists, err := commands.UserArtists(ctx, client, 1) + artists, err := commands.UserArtists(ctx, 1) if err != nil { return nil, err } @@ -64,7 +64,7 @@ func ArtistsView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) return items, nil } -func SearchArtistsView(ctx *gctx.Context, client *spotify.Client, artists *spotify.FullArtistPage) ([]list.Item, error) { +func SearchArtistsView(ctx *gctx.Context, commands *commands.Commands, artists *spotify.FullArtistPage) ([]list.Item, error) { items := []list.Item{} for _, artist := range artists.Artists { items = append(items, mainItem{ @@ -77,10 +77,10 @@ func SearchArtistsView(ctx *gctx.Context, client *spotify.Client, artists *spoti return items, nil } -func SearchView(ctx *gctx.Context, client *spotify.Client, search string) ([]list.Item, *SearchResults, error) { +func SearchView(ctx *gctx.Context, commands *commands.Commands, search string) ([]list.Item, *SearchResults, error) { items := []list.Item{} - result, err := commands.Search(ctx, client, search, 1) + result, err := commands.Search(ctx, search, 1) if err != nil { return nil, nil, err } @@ -114,9 +114,9 @@ func SearchView(ctx *gctx.Context, client *spotify.Client, search string) ([]lis return items, results, nil } -func AlbumsView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { +func AlbumsView(ctx *gctx.Context, commands *commands.Commands) ([]list.Item, error) { items := []list.Item{} - albums, err := commands.UserAlbums(ctx, client, 1) + albums, err := commands.UserAlbums(ctx, 1) if err != nil { return nil, err } @@ -131,7 +131,7 @@ func AlbumsView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) return items, nil } -func SearchPlaylistsView(ctx *gctx.Context, client *spotify.Client, playlists *spotify.SimplePlaylistPage) ([]list.Item, error) { +func SearchPlaylistsView(ctx *gctx.Context, commands *commands.Commands, playlists *spotify.SimplePlaylistPage) ([]list.Item, error) { items := []list.Item{} for _, playlist := range playlists.Playlists { items = append(items, mainItem{ @@ -143,7 +143,7 @@ func SearchPlaylistsView(ctx *gctx.Context, client *spotify.Client, playlists *s return items, nil } -func SearchAlbumsView(ctx *gctx.Context, client *spotify.Client, albums *spotify.SimpleAlbumPage) ([]list.Item, error) { +func SearchAlbumsView(ctx *gctx.Context, commands *commands.Commands, albums *spotify.SimpleAlbumPage) ([]list.Item, error) { items := []list.Item{} for _, album := range albums.Albums { items = append(items, mainItem{ @@ -156,9 +156,9 @@ func SearchAlbumsView(ctx *gctx.Context, client *spotify.Client, albums *spotify return items, nil } -func ArtistAlbumsView(ctx *gctx.Context, album spotify.ID, client *spotify.Client) ([]list.Item, error) { +func ArtistAlbumsView(ctx *gctx.Context, album spotify.ID, commands *commands.Commands) ([]list.Item, error) { items := []list.Item{} - albums, err := commands.ArtistAlbums(ctx, client, album, 1) + albums, err := commands.ArtistAlbums(ctx, album, 1) if err != nil { return nil, err } @@ -173,9 +173,9 @@ func ArtistAlbumsView(ctx *gctx.Context, album spotify.ID, client *spotify.Clien return items, err } -func AlbumTracksView(ctx *gctx.Context, album spotify.ID, client *spotify.Client) ([]list.Item, error) { +func AlbumTracksView(ctx *gctx.Context, album spotify.ID, commands *commands.Commands) ([]list.Item, error) { items := []list.Item{} - tracks, err := commands.AlbumTracks(ctx, client, album, 1) + tracks, err := commands.AlbumTracks(ctx, album, 1) if err != nil { return nil, err } @@ -192,7 +192,7 @@ func AlbumTracksView(ctx *gctx.Context, album spotify.ID, client *spotify.Client return items, err } -func SearchTracksView(ctx *gctx.Context, client *spotify.Client, tracks *spotify.FullTrackPage) ([]list.Item, error) { +func SearchTracksView(ctx *gctx.Context, commands *commands.Commands, tracks *spotify.FullTrackPage) ([]list.Item, error) { items := []list.Item{} for _, track := range tracks.Tracks { items = append(items, mainItem{ @@ -207,9 +207,9 @@ func SearchTracksView(ctx *gctx.Context, client *spotify.Client, tracks *spotify return items, nil } -func SavedTracksView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { +func SavedTracksView(ctx *gctx.Context, commands *commands.Commands) ([]list.Item, error) { items := []list.Item{} - tracks, err := commands.TrackList(ctx, client, 1) + tracks, err := commands.TrackList(ctx, 1) if err != nil { return nil, err } @@ -226,7 +226,7 @@ func SavedTracksView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, er return items, err } -func MainView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { +func MainView(ctx *gctx.Context, commands *commands.Commands) ([]list.Item, error) { var wg sync.WaitGroup var saved_items *spotify.SavedTrackPage var playlists *spotify.SimplePlaylistPage @@ -237,7 +237,7 @@ func MainView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { go func() { defer wg.Done() var err error - saved_items, err = commands.TrackList(ctx, client, 1) + saved_items, err = commands.TrackList(ctx, 1) if err != nil { fmt.Println(err.Error()) return @@ -248,7 +248,7 @@ func MainView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { go func() { defer wg.Done() var err error - playlists, err = commands.Playlists(ctx, client, 1) + playlists, err = commands.Playlists(ctx, 1) if err != nil { fmt.Println(err.Error()) return @@ -259,7 +259,7 @@ func MainView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { go func() { defer wg.Done() var err error - artists, err = commands.UserArtists(ctx, client, 1) + artists, err = commands.UserArtists(ctx, 1) if err != nil { fmt.Println(err.Error()) return @@ -270,7 +270,7 @@ func MainView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { go func() { defer wg.Done() var err error - albums, err = commands.UserAlbums(ctx, client, 1) + albums, err = commands.UserAlbums(ctx, 1) if err != nil { fmt.Println(err.Error()) return -- 2.45.2