From a7f6b55bf82061b23b315e481a47a1ec584ac9c9 Mon Sep 17 00:00:00 2001 From: Thom Ribeiro Date: Sun, 25 Jun 2023 12:27:02 -0300 Subject: [PATCH 1/9] lint, vet, spellcheck, whitespace --- cmd/auth.go | 7 ++++++- cmd/playlist.go | 43 ++++++++++++++++++++++++++++--------------- cmd/root.go | 11 ++++++----- cmd/search.go | 2 +- main.go | 4 +--- 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/cmd/auth.go b/cmd/auth.go index adf50d5..c8e806f 100644 --- a/cmd/auth.go +++ b/cmd/auth.go @@ -51,7 +51,12 @@ func authorize(cmd *cobra.Command, args []string) error { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { log.Println("Got request for: ", r.URL.String()) }) - go http.ListenAndServe(":8080", nil) + go func() { + err := http.ListenAndServe(":8080", nil) + if err != nil { + log.Fatal("ListenAndServe: ", err) + } + }() // User authentication process fmt.Println("authorize") diff --git a/cmd/playlist.go b/cmd/playlist.go index cab8964..b030d6e 100644 --- a/cmd/playlist.go +++ b/cmd/playlist.go @@ -12,7 +12,7 @@ import ( ) var ( - addtoPlaylistName string + addToPlaylistName string ) var ( @@ -58,27 +58,29 @@ func newCurrentTrackCmd() *cobra.Command { } func newShowTrackCmd() *cobra.Command { - addtoCmd := &cobra.Command{ + addToCmd := &cobra.Command{ Use: "show --tid [TRACK_ID]", Short: "Display information about a track by ID", RunE: func(cmd *cobra.Command, args []string) error { return displayTrackById(cmd, args) }, } - addtoCmd.Flags().StringVar(&trackID, "tid", "", "Id of track to display.") - return addtoCmd + addToCmd.Flags().StringVar(&trackID, "tid", "", "Id of track to display.") + + return addToCmd } -func newAddtoPlaylistCmd() *cobra.Command { - addtoCmd := &cobra.Command{ +func newAddToPlaylistCmd() *cobra.Command { + addToCmd := &cobra.Command{ Use: "ato --p [PLAYLIST_NAME]", Short: "Add currently playing track to playlist", RunE: func(cmd *cobra.Command, args []string) error { - return addto(cmd, args) + return addTo(cmd, args) }, } - addtoCmd.Flags().StringVar(&addtoPlaylistName, "p", "", "Add current track to specified playlist.") - return addtoCmd + addToCmd.Flags().StringVar(&addToPlaylistName, "p", "", "Add current track to specified playlist.") + + return addToCmd } func newAddTrackByIDToPlaylistCmd() *cobra.Command { @@ -203,8 +205,12 @@ func displayTrackById(cmd *cobra.Command, args []string) error { return err } - displayTrack(track) - return nil + err = displayTrack(track) + if err != nil { + return err + } + + return nil } func displayCurrentTrack(cmd *cobra.Command, args []string) error { @@ -221,11 +227,15 @@ func displayCurrentTrack(cmd *cobra.Command, args []string) error { return err } - displayTrack(playing.Item) + err = displayTrack(playing.Item) + if err != nil { + return err + } + return nil } -func addto(cmd *cobra.Command, args []string) error { +func addTo(cmd *cobra.Command, args []string) error { // current user user, err := client.CurrentUser() if err != nil { @@ -234,7 +244,7 @@ func addto(cmd *cobra.Command, args []string) error { fmt.Println("User: ", user.DisplayName) // get my playlists - pl, err := getPlaylistByName(addtoPlaylistName) + pl, err := getPlaylistByName(addToPlaylistName) if err != nil { return err } @@ -417,6 +427,9 @@ func rmTrackByNameFromPlaylist(cmd *cobra.Command, args []string) error { // get track in playlist and validate existence var matchedTrack spotify.SimpleTrack ptracks, err := client.GetPlaylistTracks(user.ID, pl.ID) + if err != nil { + return err + } for _, t := range ptracks.Tracks { if rmTrackName == t.Track.SimpleTrack.Name { matchedTrack = t.Track.SimpleTrack @@ -485,7 +498,7 @@ func getPlaylists() (*spotify.SimplePlaylistPage, error) { return &(spotify.SimplePlaylistPage{}), err } - return playlists, nil + return playlists, nil } func getPlaylistByName(playlistName string) (spotify.SimplePlaylist, error) { diff --git a/cmd/root.go b/cmd/root.go index a8f4d73..4a6d292 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -28,8 +28,8 @@ func NewRootCmd() *cobra.Command { rootCmd := &cobra.Command{ Use: "spotifycli", Short: "A command line interface to manage Spotify playlists.", - PersistentPreRun: prerun, - PersistentPostRun: postrun, + PersistentPreRun: preRun, + PersistentPostRun: postRun, } // auth ops rootCmd.AddCommand(newLoginCmd()) @@ -43,16 +43,17 @@ func NewRootCmd() *cobra.Command { rootCmd.AddCommand(newListPlaylistsCmd()) rootCmd.AddCommand(newCreatePlaylistCmd()) rootCmd.AddCommand(newDeletePlaylistCmd()) - rootCmd.AddCommand(newAddtoPlaylistCmd()) + rootCmd.AddCommand(newAddToPlaylistCmd()) rootCmd.AddCommand(newAddTrackByIDToPlaylistCmd()) rootCmd.AddCommand(newAddTrackByNameToPlaylistCmd()) rootCmd.AddCommand(newRemoveTrackFromPlaylistCmd()) rootCmd.AddCommand(newListPlaylistTracksCmd()) rootCmd.AddCommand(newShowTrackCmd()) + return rootCmd } -func prerun(cmd *cobra.Command, args []string) { +func preRun(cmd *cobra.Command, args []string) { // initialize authenticator auth = spotify.NewAuthenticator( redirectURI, @@ -78,7 +79,7 @@ func prerun(cmd *cobra.Command, args []string) { client = auth.NewClient(token) } -func postrun(cmd *cobra.Command, args []string) { +func postRun(cmd *cobra.Command, args []string) { // exit early if cmd.Use == "login" || cmd.Use == "logout" { return diff --git a/cmd/search.go b/cmd/search.go index 7694e49..36c7c26 100644 --- a/cmd/search.go +++ b/cmd/search.go @@ -40,7 +40,7 @@ func search(cmd *cobra.Command, args []string) error { case "pl": return displaySearchPlaylists(searchQuery) default: - return errors.New("Not supported") + return errors.New("not supported") } } diff --git a/main.go b/main.go index da776f2..3229058 100644 --- a/main.go +++ b/main.go @@ -2,14 +2,12 @@ package main import ( "log" - "os" "github.com/masroorhasan/spotifycli/cmd" ) func main() { if err := cmd.NewRootCmd().Execute(); err != nil { - log.Fatalln(err) - os.Exit(1) + log.Fatal(err) } } From 5d61fcc290554114f8952f28635b2d6a6e79eab7 Mon Sep 17 00:00:00 2001 From: Thom Ribeiro Date: Sun, 25 Jun 2023 12:31:43 -0300 Subject: [PATCH 2/9] gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e43b0f9..be47843 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +.env From ea981e1e155002a85c5cd50d69e5eed76a2aeb7e Mon Sep 17 00:00:00 2001 From: Thom Ribeiro Date: Sun, 25 Jun 2023 12:41:24 -0300 Subject: [PATCH 3/9] update spotify --- cmd/playlist.go | 14 +++++++------- go.mod | 10 +++++----- go.sum | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/cmd/playlist.go b/cmd/playlist.go index b030d6e..314733b 100644 --- a/cmd/playlist.go +++ b/cmd/playlist.go @@ -258,7 +258,7 @@ func addTo(cmd *cobra.Command, args []string) error { fmt.Println("Track: ", playing.Item.Name) // add track to playlist - _, err = client.AddTracksToPlaylist(user.ID, pl.ID, playing.Item.ID) + _, err = client.AddTracksToPlaylist(pl.ID, playing.Item.ID) if err != nil { return err } @@ -313,7 +313,7 @@ func newPlaylist(cmd *cobra.Command, args []string) error { fmt.Println("User: ", user.DisplayName) // create new playlist - playlist, err := client.CreatePlaylistForUser(user.ID, newPlaylistName, true) + playlist, err := client.CreatePlaylistForUser(user.ID, newPlaylistName, "", true) if err != nil { return err } @@ -363,7 +363,7 @@ func addTrackByIDToPlaylist(cmd *cobra.Command, args []string) error { fmt.Println("Track: ", tr.Name) // add track to playlist - _, err = client.AddTracksToPlaylist(user.ID, pl.ID, tr.ID) + _, err = client.AddTracksToPlaylist(pl.ID, tr.ID) if err != nil { return err } @@ -399,7 +399,7 @@ func addTrackByNameToPlaylist(cmd *cobra.Command, args []string) error { fmt.Println("Track: ", tracks[0].Name) // add track to playlist - _, err = client.AddTracksToPlaylist(user.ID, pl.ID, tracks[0].ID) + _, err = client.AddTracksToPlaylist(pl.ID, tracks[0].ID) if err != nil { return err } @@ -426,7 +426,7 @@ func rmTrackByNameFromPlaylist(cmd *cobra.Command, args []string) error { // get track in playlist and validate existence var matchedTrack spotify.SimpleTrack - ptracks, err := client.GetPlaylistTracks(user.ID, pl.ID) + ptracks, err := client.GetPlaylistTracks(pl.ID) if err != nil { return err } @@ -442,7 +442,7 @@ func rmTrackByNameFromPlaylist(cmd *cobra.Command, args []string) error { fmt.Println("Track: ", matchedTrack.Name) // remove track from playlist - _, err = client.RemoveTracksFromPlaylist(user.ID, pl.ID, matchedTrack.ID) + _, err = client.RemoveTracksFromPlaylist(pl.ID, matchedTrack.ID) if err != nil { return err } @@ -464,7 +464,7 @@ func listTracksFromPlaylist(cmd *cobra.Command, args []string) error { } // get tracks from playlist - tracks, err := client.GetPlaylistTracks(user.ID, pl.ID) + tracks, err := client.GetPlaylistTracks(pl.ID) if err != nil { return err } diff --git a/go.mod b/go.mod index 6e3dc05..55217ab 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.15 require ( github.com/agext/uuid v1.0.1 github.com/bndr/gotabulate v1.1.2 - github.com/golang/protobuf v1.1.0 + github.com/golang/protobuf v1.2.0 github.com/inconshreveable/mousetrap v1.0.0 github.com/spf13/cobra v0.0.3 github.com/spf13/pflag v1.0.1 - github.com/zmb3/spotify v0.0.0-20180212041948-79deba8533f6 - golang.org/x/net v0.0.0-20180530234432-1e491301e022 - golang.org/x/oauth2 v0.0.0-20180529203656-ec22f46f877b - google.golang.org/appengine v1.0.0 + github.com/zmb3/spotify v1.3.0 + golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e + golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d + google.golang.org/appengine v1.4.0 ) diff --git a/go.sum b/go.sum index cd3978b..02f1671 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,37 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/agext/uuid v1.0.1 h1:Za6toqrdwQwHJzTfsgt3JaPuQ2xeYuak6N0513NdFeQ= github.com/agext/uuid v1.0.1/go.mod h1:S35kGCagARSdmRVLoWmwmevvhFsiZkmtEqdw4hcDePs= github.com/bndr/gotabulate v1.1.2 h1:yC9izuZEphojb9r+KYL4W9IJKO/ceIO8HDwxMA24U4c= github.com/bndr/gotabulate v1.1.2/go.mod h1:0+8yUgaPTtLRTjf49E8oju7ojpU11YmXyvq1LbPAb3U= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/zmb3/spotify v0.0.0-20180212041948-79deba8533f6 h1:07d/UYzbd/YHT31y8aiRg/eG7YuTqYm1XPgXMg2PEAo= github.com/zmb3/spotify v0.0.0-20180212041948-79deba8533f6/go.mod h1:pHsWAmY9PfX7i/uwPZkmWrebc8JbK8FppKbvyevwzSU= +github.com/zmb3/spotify v1.3.0 h1:6Z2F1IMx0Hviq/dpf8nFwvKPppFEMXn8yfReSBVi16k= +github.com/zmb3/spotify v1.3.0/go.mod h1:GD7AAEMUJVYc2Z7p2a2S0E3/5f/KxM/vOnErNr4j+Tw= golang.org/x/net v0.0.0-20180530234432-1e491301e022 h1:MVYFTUmVD3/+ERcvRRI+P/C2+WOUimXh+Pd8LVsklZ4= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/oauth2 v0.0.0-20180529203656-ec22f46f877b h1:nCwwlzLoBQhkY/S3CJ2CGAU4pYfR8+5/TPGEHT+p5Nk= golang.org/x/oauth2 v0.0.0-20180529203656-ec22f46f877b/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From aaa2b13ffbf6ae0b309ebfd67ce66c98e7600af6 Mon Sep 17 00:00:00 2001 From: Thom Ribeiro Date: Sun, 25 Jun 2023 12:56:53 -0300 Subject: [PATCH 4/9] err context, README --- README.md | 8 ++++++++ cmd/auth.go | 2 +- cmd/root.go | 8 ++++---- main.go | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c410dda..4791f63 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,14 @@ export SPOTIFY_SECRET=xxx ## Usage +### login + +To login, add `"http://localhost:8080/callback"` to your spotify app redirect URLs + ### Commands + List of available commands: + ``` $ ./spotifycli --help A command line interface to manage Spotify playlists. @@ -47,6 +53,7 @@ Use "spotifycli [command] --help" for more information about a command. ``` ### Search + Search using query terms on top of tracks (`tr`), albums (`al`), artists (`ar`) or playlists (`pl`) by name. ``` @@ -63,6 +70,7 @@ Flags: ``` Sample search for type `tr` (track). + ``` ./spotifycli search --t "tr" --q "one step closer - live" ``` diff --git a/cmd/auth.go b/cmd/auth.go index c8e806f..62bb507 100644 --- a/cmd/auth.go +++ b/cmd/auth.go @@ -72,7 +72,7 @@ func (handler *authenticationHandler) ServeHTTP(w http.ResponseWriter, r *http.R token, err := handler.auth.Token(handler.state, r) if err != nil { http.Error(w, "Couldn't get token", http.StatusForbidden) - log.Fatal(err) + log.Fatal("handler.auth.Token: ", err) } if st := r.FormValue("state"); st != handler.state { http.NotFound(w, r) diff --git a/cmd/root.go b/cmd/root.go index 4a6d292..3212d23 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -73,7 +73,7 @@ func preRun(cmd *cobra.Command, args []string) { token, err := getToken() if err != nil { if err := authorize(cmd, args); err != nil { - log.Fatal(err) + log.Fatal("authorize: ", err) } } client = auth.NewClient(token) @@ -88,15 +88,15 @@ func postRun(cmd *cobra.Command, args []string) { // refresh token currTok, err := client.Token() if err != nil { - log.Fatal(err) + log.Fatal("client token: ", err) } token, err := getToken() if err != nil { - log.Fatal(err) + log.Fatal("getToken: ", err) } if token != currTok { if err := persistToken(token); err != nil { - log.Fatal(err) + log.Fatal("persistToken: ", err) } } } diff --git a/main.go b/main.go index 3229058..04979bd 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,6 @@ import ( func main() { if err := cmd.NewRootCmd().Execute(); err != nil { - log.Fatal(err) + log.Fatal("execute: ", err) } } From aa22c42812340cc5cee9bc83da7c6be12b282571 Mon Sep 17 00:00:00 2001 From: Thom Ribeiro Date: Sun, 25 Jun 2023 13:04:57 -0300 Subject: [PATCH 5/9] list track from playlist data adjustments --- cmd/playlist.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/cmd/playlist.go b/cmd/playlist.go index 314733b..98e2c7f 100644 --- a/cmd/playlist.go +++ b/cmd/playlist.go @@ -471,24 +471,35 @@ func listTracksFromPlaylist(cmd *cobra.Command, args []string) error { // format resulting data var data [][]interface{} + if tracks.Tracks != nil { for _, item := range tracks.Tracks { + artist := item.Track.Artists[0].Name + + if len(item.Track.Artists) > 0 { + for _, a := range item.Track.Artists { + artist += ", " + a.Name + } + } + track := []string{ - string(item.Track.ID), - item.Track.Name, - item.Track.Album.Name, item.Track.Artists[0].Name, - strconv.Itoa(item.Track.Popularity)} + item.Track.Name, + string(item.Track.ID), + } + row := make([]interface{}, len(track)) + for i, d := range track { row[i] = d } + data = append(data, row) } } // pretty print track results - printSimple([]string{"ID", "Name", "Album", "Artist", "Popularity"}, data) + printSimple([]string{"Artist", "Name", "ID"}, data) return nil } From a65cdf15a64c29d057862cc0e5ef3aaf49232ba4 Mon Sep 17 00:00:00 2001 From: Thom Ribeiro Date: Sun, 25 Jun 2023 13:09:09 -0300 Subject: [PATCH 6/9] change tabulate options --- cmd/search.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/search.go b/cmd/search.go index 36c7c26..aa59274 100644 --- a/cmd/search.go +++ b/cmd/search.go @@ -194,6 +194,11 @@ func searchPlaylists(query string) ([][]interface{}, error) { func printSimple(headers []string, data [][]interface{}) { tabulate := gotabulate.Create(data) + tabulate.SetHeaders(headers) + tabulate.SetAlign("left") + // tabulate.SetMaxCellSize(50) + // tabulate.SetWrapStrings(true) + fmt.Println(tabulate.Render("simple")) } From 7542448950dd0da12eb605b595a531be6f89224f Mon Sep 17 00:00:00 2001 From: Thom Ribeiro Date: Sun, 25 Jun 2023 13:30:40 -0300 Subject: [PATCH 7/9] add --offset flag to list playlist --- cmd/playlist.go | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/cmd/playlist.go b/cmd/playlist.go index 98e2c7f..3ddbff6 100644 --- a/cmd/playlist.go +++ b/cmd/playlist.go @@ -13,37 +13,27 @@ import ( var ( addToPlaylistName string -) -var ( trackID string -) -var ( addTrackID string addTrackByIDToPlaylistName string -) -var ( addTrackName string addTrackByNameToPlaylistName string -) -var ( rmTrackName string rmTrackFromPlaylistName string -) -var ( newPlaylistName string -) -var ( delPlaylistName string -) -var ( - listPlaylistTracksName string + flagListPlaylistTracksName string + + flagListPlaylistTracksOffset = "offset" + + spotifyMaxLimit = 100 ) func newCurrentTrackCmd() *cobra.Command { @@ -165,7 +155,10 @@ func newListPlaylistTracksCmd() *cobra.Command { return listTracksFromPlaylist(cmd, args) }, } - listCmd.Flags().StringVar(&listPlaylistTracksName, "p", "", "Name of playlist to list tracks from.") + + listCmd.Flags().StringVar(&flagListPlaylistTracksName, "p", "", "Name of playlist to list tracks from.") + listCmd.Flags().Int(flagListPlaylistTracksOffset, 0, "Offset to paginate long playlists") + return listCmd } @@ -458,13 +451,25 @@ func listTracksFromPlaylist(cmd *cobra.Command, args []string) error { } fmt.Println("User: ", user.DisplayName) - pl, err := getPlaylistByName(listPlaylistTracksName) + pl, err := getPlaylistByName(flagListPlaylistTracksName) if err != nil { return err } + flags := cmd.Flags() + + offset, err := flags.GetInt(flagListPlaylistTracksOffset) + if err != nil { + return fmt.Errorf("GetInt flag offset %w", err) + } + + opts := &spotify.Options{ + Limit: &spotifyMaxLimit, + Offset: &offset, + } + // get tracks from playlist - tracks, err := client.GetPlaylistTracks(pl.ID) + tracks, err := client.GetPlaylistTracksOpt(pl.ID, opts, "") if err != nil { return err } From 0622ad3012d61a1f89838429d79cb8785d1665c2 Mon Sep 17 00:00:00 2001 From: Thom Ribeiro Date: Sun, 25 Jun 2023 14:03:39 -0300 Subject: [PATCH 8/9] duration colum, remove user printLn, helper func to convert seconds to minutes, helper script --- .gitignore | 1 + cmd/playlist.go | 67 ++++++++++--------------------------------------- helper.sh | 9 +++++++ 3 files changed, 23 insertions(+), 54 deletions(-) create mode 100755 helper.sh diff --git a/.gitignore b/.gitignore index be47843..6096075 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store .env +likes.txt diff --git a/cmd/playlist.go b/cmd/playlist.go index 3ddbff6..a001f73 100644 --- a/cmd/playlist.go +++ b/cmd/playlist.go @@ -185,12 +185,6 @@ func displayTrack(track *spotify.FullTrack) error { } func displayTrackById(cmd *cobra.Command, args []string) error { - // current user - user, err := client.CurrentUser() - if err != nil { - return err - } - fmt.Println("User: ", user.DisplayName) // get the track (check for existence) track, err := client.GetTrack(spotify.ID(trackID)) @@ -207,12 +201,6 @@ func displayTrackById(cmd *cobra.Command, args []string) error { } func displayCurrentTrack(cmd *cobra.Command, args []string) error { - // current user - user, err := client.CurrentUser() - if err != nil { - return err - } - fmt.Println("User: ", user.DisplayName) // get current playing song playing, err := client.PlayerCurrentlyPlaying() @@ -229,12 +217,6 @@ func displayCurrentTrack(cmd *cobra.Command, args []string) error { } func addTo(cmd *cobra.Command, args []string) error { - // current user - user, err := client.CurrentUser() - if err != nil { - return err - } - fmt.Println("User: ", user.DisplayName) // get my playlists pl, err := getPlaylistByName(addToPlaylistName) @@ -260,12 +242,6 @@ func addTo(cmd *cobra.Command, args []string) error { } func listPlaylists(cmd *cobra.Command, args []string) error { - // current user - user, err := client.CurrentUser() - if err != nil { - return err - } - fmt.Println("User: ", user.DisplayName) // get all playlists for the user playlists, err := getPlaylists() @@ -298,12 +274,10 @@ func listPlaylists(cmd *cobra.Command, args []string) error { } func newPlaylist(cmd *cobra.Command, args []string) error { - // current user user, err := client.CurrentUser() if err != nil { return err } - fmt.Println("User: ", user.DisplayName) // create new playlist playlist, err := client.CreatePlaylistForUser(user.ID, newPlaylistName, "", true) @@ -315,12 +289,10 @@ func newPlaylist(cmd *cobra.Command, args []string) error { } func deletePlaylist(cmd *cobra.Command, args []string) error { - // current user user, err := client.CurrentUser() if err != nil { return err } - fmt.Println("User: ", user.DisplayName) // get the playlist pl, err := getPlaylistByName(delPlaylistName) @@ -334,12 +306,6 @@ func deletePlaylist(cmd *cobra.Command, args []string) error { } func addTrackByIDToPlaylist(cmd *cobra.Command, args []string) error { - // current user - user, err := client.CurrentUser() - if err != nil { - return err - } - fmt.Println("User: ", user.DisplayName) // get the playlist by name pl, err := getPlaylistByName(addTrackByIDToPlaylistName) @@ -365,12 +331,6 @@ func addTrackByIDToPlaylist(cmd *cobra.Command, args []string) error { } func addTrackByNameToPlaylist(cmd *cobra.Command, args []string) error { - // current user - user, err := client.CurrentUser() - if err != nil { - return err - } - fmt.Println("User: ", user.DisplayName) // get the playlist by name pl, err := getPlaylistByName(addTrackByNameToPlaylistName) @@ -404,12 +364,6 @@ func addTrackByNameToPlaylist(cmd *cobra.Command, args []string) error { } func rmTrackByNameFromPlaylist(cmd *cobra.Command, args []string) error { - // current user - user, err := client.CurrentUser() - if err != nil { - return err - } - fmt.Println("User: ", user.DisplayName) // get the playlist by name pl, err := getPlaylistByName(rmTrackFromPlaylistName) @@ -444,13 +398,6 @@ func rmTrackByNameFromPlaylist(cmd *cobra.Command, args []string) error { } func listTracksFromPlaylist(cmd *cobra.Command, args []string) error { - // current user - user, err := client.CurrentUser() - if err != nil { - return err - } - fmt.Println("User: ", user.DisplayName) - pl, err := getPlaylistByName(flagListPlaylistTracksName) if err != nil { return err @@ -490,6 +437,7 @@ func listTracksFromPlaylist(cmd *cobra.Command, args []string) error { track := []string{ item.Track.Artists[0].Name, item.Track.Name, + secondsToMinutes(item.Track.Duration / 1000), string(item.Track.ID), } @@ -504,7 +452,7 @@ func listTracksFromPlaylist(cmd *cobra.Command, args []string) error { } // pretty print track results - printSimple([]string{"Artist", "Name", "ID"}, data) + printSimple([]string{"Artist", "Name", "Duration", "ID"}, data) return nil } @@ -539,3 +487,14 @@ func getPlaylistByName(playlistName string) (spotify.SimplePlaylist, error) { } return matchPlaylist, nil } + +func secondsToMinutes(seconds int) string { + minutes := seconds / 60 + remainder := seconds % 60 + + if remainder < 10 { + return fmt.Sprintf("%d:0%d", minutes, remainder) + } + + return fmt.Sprintf("%d:%d", minutes, remainder) +} diff --git a/helper.sh b/helper.sh new file mode 100755 index 0000000..fdeb801 --- /dev/null +++ b/helper.sh @@ -0,0 +1,9 @@ +#! /usr/bin/env bash + +# for offset in 0 100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500; do +# echo gorun main.go list --p "__Liked Songs 1536" --offset $offset >>likes.txt +# done + +for i in {0..15}; do + godotenv -f .env go run main.go list --p "__Liked Songs 1536" --offset $((i * 100)) >>likes.txt +done From bf618d74dfb715ed0b70b6009e0579e6f87f1090 Mon Sep 17 00:00:00 2001 From: Thom Ribeiro Date: Sun, 25 Jun 2023 21:27:27 -0300 Subject: [PATCH 9/9] correctly handle offset --- .gitignore | 2 +- cmd/playlist.go | 47 ++++++++++++++++++++++++++--------------------- helper.sh | 9 --------- 3 files changed, 27 insertions(+), 31 deletions(-) delete mode 100755 helper.sh diff --git a/.gitignore b/.gitignore index 6096075..7200a57 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .DS_Store .env -likes.txt +likes* diff --git a/cmd/playlist.go b/cmd/playlist.go index a001f73..f6cee03 100644 --- a/cmd/playlist.go +++ b/cmd/playlist.go @@ -31,8 +31,6 @@ var ( flagListPlaylistTracksName string - flagListPlaylistTracksOffset = "offset" - spotifyMaxLimit = 100 ) @@ -157,7 +155,6 @@ func newListPlaylistTracksCmd() *cobra.Command { } listCmd.Flags().StringVar(&flagListPlaylistTracksName, "p", "", "Name of playlist to list tracks from.") - listCmd.Flags().Int(flagListPlaylistTracksOffset, 0, "Offset to paginate long playlists") return listCmd } @@ -403,29 +400,36 @@ func listTracksFromPlaylist(cmd *cobra.Command, args []string) error { return err } - flags := cmd.Flags() - - offset, err := flags.GetInt(flagListPlaylistTracksOffset) - if err != nil { - return fmt.Errorf("GetInt flag offset %w", err) - } - opts := &spotify.Options{ - Limit: &spotifyMaxLimit, - Offset: &offset, + Limit: &spotifyMaxLimit, } - // get tracks from playlist - tracks, err := client.GetPlaylistTracksOpt(pl.ID, opts, "") - if err != nil { - return err + var tracks []spotify.PlaylistTrack + i := 0 + + for { + offset := i + opts.Offset = &offset + + res, err := client.GetPlaylistTracksOpt(pl.ID, opts, "") + if err != nil { + return fmt.Errorf("could not get playlist tracks: %v", err) + } + + tracks = append(tracks, res.Tracks...) + + if len(res.Tracks) < spotifyMaxLimit { + break + } + + i += spotifyMaxLimit } // format resulting data - var data [][]interface{} + var data = make([][]interface{}, 0, len(tracks)) - if tracks.Tracks != nil { - for _, item := range tracks.Tracks { + if len(tracks) > 0 { + for _, item := range tracks { artist := item.Track.Artists[0].Name if len(item.Track.Artists) > 0 { @@ -449,10 +453,11 @@ func listTracksFromPlaylist(cmd *cobra.Command, args []string) error { data = append(data, row) } + + // pretty print track results + printSimple([]string{"Artist", "Name", "Duration", "ID"}, data) } - // pretty print track results - printSimple([]string{"Artist", "Name", "Duration", "ID"}, data) return nil } diff --git a/helper.sh b/helper.sh deleted file mode 100755 index fdeb801..0000000 --- a/helper.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /usr/bin/env bash - -# for offset in 0 100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500; do -# echo gorun main.go list --p "__Liked Songs 1536" --offset $offset >>likes.txt -# done - -for i in {0..15}; do - godotenv -f .env go run main.go list --p "__Liked Songs 1536" --offset $((i * 100)) >>likes.txt -done