From 652bb376d37360c462726cff4599f93ad9e9dbf8 Mon Sep 17 00:00:00 2001 From: abs3nt Date: Thu, 12 Jan 2023 18:48:41 -0800 Subject: [PATCH] artists and albums --- cmd/albums.go | 21 +++++ cmd/artists.go | 27 ++++++ cmd/tracks.go | 2 +- cmd/tui.go | 2 +- go.mod | 1 - go.sum | 2 - internal/commands/commands.go | 18 +++- internal/tui/main.go | 161 ++++++++++++++++++++++++++++++++-- 8 files changed, 222 insertions(+), 12 deletions(-) create mode 100644 cmd/albums.go create mode 100644 cmd/artists.go diff --git a/cmd/albums.go b/cmd/albums.go new file mode 100644 index 0000000..ccf32f7 --- /dev/null +++ b/cmd/albums.go @@ -0,0 +1,21 @@ +package cmd + +import ( + "gospt/internal/commands" + + "github.com/spf13/cobra" +) + +// albumsCmd represents the albums command +var albumsCmd = &cobra.Command{ + Use: "albums", + Short: "get all saved albums", + Long: `get all saved albums`, + Run: func(cmd *cobra.Command, args []string) { + commands.UserAlbums(ctx, client, 1) + }, +} + +func init() { + rootCmd.AddCommand(albumsCmd) +} diff --git a/cmd/artists.go b/cmd/artists.go new file mode 100644 index 0000000..913f2f0 --- /dev/null +++ b/cmd/artists.go @@ -0,0 +1,27 @@ +package cmd + +import ( + "fmt" + + "gospt/internal/commands" + + "github.com/spf13/cobra" +) + +// artistsCmd represents the artists command +var artistsCmd = &cobra.Command{ + Use: "artists", + Short: "return all users artists", + Long: `return all users artists`, + Run: func(cmd *cobra.Command, args []string) { + _, err := commands.UserArtists(ctx, client, 1) + if err != nil { + fmt.Println(err.Error()) + } + return + }, +} + +func init() { + rootCmd.AddCommand(artistsCmd) +} diff --git a/cmd/tracks.go b/cmd/tracks.go index 8acd4fe..ca16d96 100644 --- a/cmd/tracks.go +++ b/cmd/tracks.go @@ -20,7 +20,7 @@ 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.DeviceActive(ctx, client) { + if commands.ActiveDeviceExists(ctx, client) { return tui.StartTea(ctx, client, "tracks") } if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err != nil { diff --git a/cmd/tui.go b/cmd/tui.go index 1b301cf..c97da54 100644 --- a/cmd/tui.go +++ b/cmd/tui.go @@ -20,7 +20,7 @@ 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.DeviceActive(ctx, client) { + if commands.ActiveDeviceExists(ctx, client) { return tui.StartTea(ctx, client, "main") } if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err != nil { diff --git a/go.mod b/go.mod index f93aac4..24d4e08 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/cristalhq/aconfig v0.18.3 github.com/cristalhq/aconfig/aconfigyaml v0.17.1 github.com/spf13/cobra v1.6.1 - github.com/zmb3/spotify v1.3.0 github.com/zmb3/spotify/v2 v2.3.1 golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5 ) diff --git a/go.sum b/go.sum index 6514b50..56a1851 100644 --- a/go.sum +++ b/go.sum @@ -180,8 +180,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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= -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= github.com/zmb3/spotify/v2 v2.3.1 h1:aEyIPotROM3JJjHMCImFROgnPIUpzVo8wymYSaPSd9w= github.com/zmb3/spotify/v2 v2.3.1/go.mod h1:+LVh9CafHu7SedyqYmEf12Rd01dIVlEL845yNhksW0E= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= diff --git a/internal/commands/commands.go b/internal/commands/commands.go index fad05d5..f8506f5 100644 --- a/internal/commands/commands.go +++ b/internal/commands/commands.go @@ -35,7 +35,7 @@ func Play(ctx *gctx.Context, client *spotify.Client) error { return nil } -func DeviceActive(ctx *gctx.Context, client *spotify.Client) bool { +func ActiveDeviceExists(ctx *gctx.Context, client *spotify.Client) bool { current, err := client.PlayerDevices(ctx) if err != nil { return false @@ -48,6 +48,22 @@ func DeviceActive(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)) + if err != nil { + return nil, err + } + return artists, 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)) + if err != nil { + return nil, err + } + return albums, nil +} + func PlayUrl(ctx *gctx.Context, client *spotify.Client, args []string) error { url, err := url.Parse(args[0]) if err != nil { diff --git a/internal/tui/main.go b/internal/tui/main.go index 81a68ac..da91ee6 100644 --- a/internal/tui/main.go +++ b/internal/tui/main.go @@ -2,6 +2,7 @@ package tui import ( "fmt" + "sync" "time" "gospt/internal/commands" @@ -117,6 +118,44 @@ func HandleSetDevice(ctx *gctx.Context, client *spotify.Client, player spotify.P func (m *mainModel) LoadMoreItems() { switch m.mode { + case "artists": + artists, err := commands.UserArtists(m.ctx, m.client, (page + 1)) + page++ + if err != nil { + return + } + items := []list.Item{} + for _, artist := range artists.Artists { + items = append(items, mainItem{ + Name: artist.Name, + ID: artist.ID, + Desc: fmt.Sprintf("%d followers, genres: %s, popularity: %d", artist.Followers.Count, artist.Genres, artist.Popularity), + }) + } + for _, item := range items { + m.list.InsertItem(len(m.list.Items())+1, item) + } + main_updates <- m + return + case "albums": + albums, err := commands.UserAlbums(m.ctx, m.client, (page + 1)) + page++ + if err != nil { + return + } + items := []list.Item{} + for _, album := range albums.Albums { + items = append(items, mainItem{ + Name: album.Name, + ID: album.ID, + Desc: fmt.Sprintf("%s, %d tracks", album.Artists[0].Name, album.Tracks.Total), + }) + } + for _, item := range items { + m.list.InsertItem(len(m.list.Items())+1, item) + } + main_updates <- m + return case "main": playlists, err := commands.Playlists(m.ctx, m.client, (page + 1)) page++ @@ -209,7 +248,7 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.list.NewStatusMessage("Setting view to devices") } if msg.String() == "backspace" || msg.String() == "esc" || msg.String() == "q" { - if m.mode == "playlist" || m.mode == "tracks" || m.mode == "devices" { + if m.mode != "main" { m.mode = "main" m.list.NewStatusMessage("Setting view to main") new_items, err := MainView(m.ctx, m.client) @@ -221,6 +260,7 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, tea.Quit } m.list.ResetSelected() + page = 0 } if msg.String() == "ctrl+c" { return m, tea.Quit @@ -229,6 +269,26 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch m.mode { case "main": switch m.list.SelectedItem().(mainItem).SpotifyItem.(type) { + case *spotify.FullArtistCursorPage: + m.mode = "artists" + m.list.NewStatusMessage("Setting view to artists") + new_items, err := ArtistsView(m.ctx, m.client) + if err != nil { + fmt.Println(err.Error()) + return m, tea.Quit + } + m.list.SetItems(new_items) + m.list.ResetSelected() + case *spotify.SavedAlbumPage: + m.mode = "albums" + m.list.NewStatusMessage("Setting view to albums") + new_items, err := AlbumsView(m.ctx, m.client) + if err != nil { + fmt.Println(err.Error()) + return m, tea.Quit + } + m.list.SetItems(new_items) + m.list.ResetSelected() case spotify.SimplePlaylist: m.mode = "playlist" playlist := m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimplePlaylist) @@ -372,6 +432,38 @@ 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) { + items := []list.Item{} + artists, err := commands.UserArtists(ctx, client, 1) + if err != nil { + return nil, err + } + for _, artist := range artists.Artists { + items = append(items, mainItem{ + Name: artist.Name, + ID: artist.ID, + Desc: fmt.Sprintf("%d followers, genres: %s, popularity: %d", artist.Followers.Count, artist.Genres, artist.Popularity), + }) + } + return items, nil +} + +func AlbumsView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { + items := []list.Item{} + albums, err := commands.UserAlbums(ctx, client, 1) + if err != nil { + return nil, err + } + for _, album := range albums.Albums { + items = append(items, mainItem{ + Name: album.Name, + ID: album.ID, + Desc: fmt.Sprintf("%s, %d tracks", album.Artists[0].Name, album.Tracks.Total), + }) + } + return items, nil +} + func SavedTracksView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { items := []list.Item{} tracks, err := commands.TrackList(ctx, client, 1) @@ -391,17 +483,74 @@ func SavedTracksView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, er } func MainView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { + var wg sync.WaitGroup + var saved_items *spotify.SavedTrackPage + var playlists *spotify.SimplePlaylistPage + var artists *spotify.FullArtistCursorPage + var albums *spotify.SavedAlbumPage + + wg.Add(1) + go func() { + defer wg.Done() + var err error + saved_items, err = commands.TrackList(ctx, client, 1) + if err != nil { + fmt.Println(err.Error()) + return + } + }() + + wg.Add(1) + go func() { + defer wg.Done() + var err error + playlists, err = commands.Playlists(ctx, client, 1) + if err != nil { + fmt.Println(err.Error()) + return + } + }() + + wg.Add(1) + go func() { + defer wg.Done() + var err error + artists, err = commands.UserArtists(ctx, client, 1) + if err != nil { + fmt.Println(err.Error()) + return + } + }() + + wg.Add(1) + go func() { + defer wg.Done() + var err error + albums, err = commands.UserAlbums(ctx, client, 1) + if err != nil { + fmt.Println(err.Error()) + return + } + }() + + wg.Wait() + items := []list.Item{} - saved_items, err := commands.TrackList(ctx, client, 1) items = append(items, mainItem{ Name: "Saved Tracks", Desc: fmt.Sprintf("%d saved songs", saved_items.Total), SpotifyItem: saved_items, }) - playlists, err := commands.Playlists(ctx, client, 1) - if err != nil { - return nil, err - } + items = append(items, mainItem{ + Name: "Albums", + Desc: fmt.Sprintf("%d albums", albums.Total), + SpotifyItem: albums, + }) + items = append(items, mainItem{ + Name: "Albums", + Desc: fmt.Sprintf("%d artists", artists.Total), + SpotifyItem: artists, + }) for _, playlist := range playlists.Playlists { items = append(items, mainItem{ Name: playlist.Name,