diff --git a/internal/commands/commands.go b/internal/commands/commands.go index ddb7f52..870ef04 100644 --- a/internal/commands/commands.go +++ b/internal/commands/commands.go @@ -198,6 +198,67 @@ func PlayLikedSongs(ctx *gctx.Context, client *spotify.Client, position int) err return err } +func RadioGivenArtist(ctx *gctx.Context, client *spotify.Client, artist_id spotify.ID) error { + seed := spotify.Seeds{ + Tracks: []spotify.ID{artist_id}, + } + recomendations, err := client.GetRecommendations(ctx, seed, &spotify.TrackAttributes{}, spotify.Limit(100)) + if err != nil { + return err + } + recomendationIds := []spotify.ID{} + for _, song := range recomendations.Tracks { + recomendationIds = append(recomendationIds, song.ID) + } + err = ClearRadio(ctx, client) + if err != nil { + return err + } + radioPlaylist, err := GetRadioPlaylist(ctx, client) + if err != nil { + return err + } + queue := []spotify.ID{} + all_recs := map[spotify.ID]bool{} + for _, rec := range recomendationIds { + all_recs[rec] = true + queue = append(queue, rec) + } + _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, queue...) + if err != nil { + return err + } + client.PlayOpt(ctx, &spotify.PlayOptions{ + PlaybackContext: &radioPlaylist.URI, + PlaybackOffset: &spotify.PlaybackOffset{ + Position: 0, + }, + }) + err = client.Repeat(ctx, "context") + if err != nil { + return err + } + for i := 0; i < 4; i++ { + id := rand.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)) + if err != nil { + return err + } + additionalRecsIds := []spotify.ID{} + for _, song := range additional_recs.Tracks { + additionalRecsIds = append(additionalRecsIds, song.ID) + } + _, err = client.AddTracksToPlaylist(ctx, radioPlaylist.ID, additionalRecsIds...) + if err != nil { + return err + } + } + return nil +} + func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song_id spotify.ID, pos int) error { start := time.Now().UnixMilli() seed := spotify.Seeds{ @@ -570,9 +631,9 @@ func RadioFromPlaylist(ctx *gctx.Context, client *spotify.Client, playlist spoti return fmt.Errorf("This playlist is empty") } pages := (total / 50) - randomPage := 0 + randomPage := 1 if pages != 0 { - randomPage = rand.Intn(int(pages)) + randomPage = rand.Intn(int(pages-1)) + 1 } playlistPage, err := client.GetPlaylistItems(ctx, playlist.ID, spotify.Limit(50), spotify.Offset(randomPage*50)) if err != nil { @@ -594,6 +655,41 @@ func RadioFromPlaylist(ctx *gctx.Context, client *spotify.Client, playlist spoti return RadioGivenList(ctx, client, seedIds[:seedCount]) } +func RadioFromAlbum(ctx *gctx.Context, client *spotify.Client, album spotify.ID) error { + rand.Seed(time.Now().Unix()) + tracks, err := AlbumTracks(ctx, client, album, 1) + if err != nil { + return err + } + total := tracks.Total + if total == 0 { + return fmt.Errorf("This playlist is empty") + } + pages := (total / 50) + randomPage := 1 + if pages != 0 { + randomPage = rand.Intn(int(pages-1)) + 1 + } + albumTrackPage, err := AlbumTracks(ctx, client, album, 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] }) + seedCount := 5 + if len(pageSongs) < seedCount { + seedCount = len(pageSongs) + } + seedIds := []spotify.ID{} + for idx, song := range pageSongs { + if idx >= seedCount { + break + } + seedIds = append(seedIds, song.ID) + } + return RadioGivenList(ctx, client, seedIds[:seedCount]) +} + 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)) diff --git a/internal/tui/handlers.go b/internal/tui/handlers.go new file mode 100644 index 0000000..d788d6c --- /dev/null +++ b/internal/tui/handlers.go @@ -0,0 +1,72 @@ +package tui + +import ( + "fmt" + + "gospt/internal/commands" + "gospt/internal/gctx" + + "github.com/zmb3/spotify/v2" +) + +func HandlePlay(ctx *gctx.Context, client *spotify.Client, uri *spotify.URI, pos int) { + var err error + err = commands.PlaySongInPlaylist(ctx, client, uri, pos) + if err != nil { + return + } +} + +func HandleRadio(ctx *gctx.Context, client *spotify.Client, id spotify.ID) { + err := commands.RadioGivenSong(ctx, client, id, 0) + if err != nil { + return + } +} + +func HandleAlbumRadio(ctx *gctx.Context, client *spotify.Client, id spotify.ID) { + err := commands.RadioFromAlbum(ctx, client, id) + if err != nil { + return + } +} + +func HandleAlbumArtist(ctx *gctx.Context, client *spotify.Client, id spotify.ID) { + err := commands.RadioGivenArtist(ctx, client, id) + if err != nil { + return + } +} + +func HandlePlaylistRadio(ctx *gctx.Context, client *spotify.Client, playlist spotify.SimplePlaylist) { + err := commands.RadioFromPlaylist(ctx, client, playlist) + if err != nil { + return + } +} + +func HandleLibraryRadio(ctx *gctx.Context, client *spotify.Client) { + err := commands.RadioFromSavedTracks(ctx, client) + if err != nil { + fmt.Println(err.Error()) + return + } +} + +func HandlePlayLikedSong(ctx *gctx.Context, client *spotify.Client, position int) { + err := commands.PlayLikedSongs(ctx, client, position) + if err != nil { + fmt.Println(err.Error()) + return + } +} + +func HandleSetDevice(ctx *gctx.Context, client *spotify.Client, player spotify.PlayerDevice) { + fmt.Println("WHOA") + var err error + err = commands.SetDevice(ctx, client, player) + if err != nil { + fmt.Println(err.Error()) + return + } +} diff --git a/internal/tui/loader.go b/internal/tui/loader.go new file mode 100644 index 0000000..88f5e15 --- /dev/null +++ b/internal/tui/loader.go @@ -0,0 +1,158 @@ +package tui + +import ( + "fmt" + "time" + + "gospt/internal/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)) + 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 by %s", album.AlbumType, album.Artists[0].Name), + SpotifyItem: album, + }) + } + for _, item := range items { + m.list.InsertItem(len(m.list.Items())+1, item) + } + main_updates <- m + return + 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), + SpotifyItem: artist.SimpleArtist, + }) + } + for _, item := range items { + m.list.InsertItem(len(m.list.Items())+1, item) + } + main_updates <- m + return + case "album": + tracks, err := commands.AlbumTracks(m.ctx, m.client, m.album.ID, (page + 1)) + page++ + if err != nil { + return + } + items := []mainItem{} + for _, track := range tracks.Tracks { + items = append(items, mainItem{ + Name: track.Name, + Artist: track.Artists[0], + Duration: track.TimeDuration().Round(time.Second).String(), + ID: track.ID, + Desc: track.Artists[0].Name + " - " + track.TimeDuration().Round(time.Second).String(), + }) + } + 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), + SpotifyItem: album.SimpleAlbum, + }) + } + 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++ + if err != nil { + return + } + items := []list.Item{} + for _, playlist := range playlists.Playlists { + items = append(items, mainItem{ + Name: playlist.Name, + Desc: playlist.Description, + SpotifyItem: playlist, + }) + } + for _, item := range items { + m.list.InsertItem(len(m.list.Items())+1, item) + } + main_updates <- m + return + case "playlist": + tracks, err := commands.PlaylistTracks(m.ctx, m.client, m.playlist.ID, (page + 1)) + page++ + if err != nil { + return + } + items := []mainItem{} + for _, track := range tracks.Tracks { + items = append(items, mainItem{ + Name: track.Track.Name, + Artist: track.Track.Artists[0], + Duration: track.Track.TimeDuration().Round(time.Second).String(), + ID: track.Track.ID, + Desc: track.Track.Artists[0].Name + " - " + track.Track.TimeDuration().Round(time.Second).String(), + }) + } + for _, item := range items { + m.list.InsertItem(len(m.list.Items())+1, item) + } + main_updates <- m + return + case "tracks": + tracks, err := commands.TrackList(m.ctx, m.client, (page + 1)) + page++ + if err != nil { + return + } + page++ + items := []list.Item{} + for _, track := range tracks.Tracks { + items = append(items, mainItem{ + Name: track.Name, + Artist: track.Artists[0], + Duration: track.TimeDuration().Round(time.Second).String(), + ID: track.ID, + Desc: track.Artists[0].Name + " - " + track.TimeDuration().Round(time.Second).String(), + }) + } + for _, item := range items { + m.list.InsertItem(len(m.list.Items())+1, item) + } + main_updates <- m + return + } +} diff --git a/internal/tui/main.go b/internal/tui/main.go index 85bb8b4..79bf320 100644 --- a/internal/tui/main.go +++ b/internal/tui/main.go @@ -2,10 +2,8 @@ package tui import ( "fmt" - "sync" "time" - "gospt/internal/commands" "gospt/internal/gctx" "github.com/charmbracelet/bubbles/key" @@ -71,200 +69,8 @@ func (m *mainModel) Tick() { }() } -func HandlePlay(ctx *gctx.Context, client *spotify.Client, uri *spotify.URI, pos int) { - var err error - err = commands.PlaySongInPlaylist(ctx, client, uri, pos) - if err != nil { - return - } -} - -func HandleRadio(ctx *gctx.Context, client *spotify.Client, id spotify.ID) { - err := commands.RadioGivenSong(ctx, client, id, 0) - if err != nil { - return - } -} - -func HandlePlaylistRadio(ctx *gctx.Context, client *spotify.Client, playlist spotify.SimplePlaylist) { - err := commands.RadioFromPlaylist(ctx, client, playlist) - if err != nil { - return - } -} - -func HandleLibraryRadio(ctx *gctx.Context, client *spotify.Client) { - err := commands.RadioFromSavedTracks(ctx, client) - if err != nil { - fmt.Println(err.Error()) - return - } -} - -func HandlePlayLikedSong(ctx *gctx.Context, client *spotify.Client, position int) { - err := commands.PlayLikedSongs(ctx, client, position) - if err != nil { - fmt.Println(err.Error()) - return - } -} - -func HandleSetDevice(ctx *gctx.Context, client *spotify.Client, player spotify.PlayerDevice) { - fmt.Println("WHOA") - var err error - err = commands.SetDevice(ctx, client, player) - if err != nil { - fmt.Println(err.Error()) - return - } -} - -func (m *mainModel) LoadMoreItems() { - switch m.mode { - case "artist": - albums, err := commands.ArtistAlbums(m.ctx, m.client, m.artist.ID, (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 by %s", album.AlbumType, album.Artists[0].Name), - SpotifyItem: album, - }) - } - for _, item := range items { - m.list.InsertItem(len(m.list.Items())+1, item) - } - main_updates <- m - return - 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), - SpotifyItem: artist.SimpleArtist, - }) - } - for _, item := range items { - m.list.InsertItem(len(m.list.Items())+1, item) - } - main_updates <- m - return - case "album": - tracks, err := commands.AlbumTracks(m.ctx, m.client, m.album.ID, (page + 1)) - page++ - if err != nil { - return - } - items := []mainItem{} - for _, track := range tracks.Tracks { - items = append(items, mainItem{ - Name: track.Name, - Artist: track.Artists[0], - Duration: track.TimeDuration().Round(time.Second).String(), - ID: track.ID, - Desc: track.Artists[0].Name + " - " + track.TimeDuration().Round(time.Second).String(), - }) - } - 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), - SpotifyItem: album.SimpleAlbum, - }) - } - 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++ - if err != nil { - return - } - items := []list.Item{} - for _, playlist := range playlists.Playlists { - items = append(items, mainItem{ - Name: playlist.Name, - Desc: playlist.Description, - SpotifyItem: playlist, - }) - } - for _, item := range items { - m.list.InsertItem(len(m.list.Items())+1, item) - } - main_updates <- m - return - case "playlist": - tracks, err := commands.PlaylistTracks(m.ctx, m.client, m.playlist.ID, (page + 1)) - page++ - if err != nil { - return - } - items := []mainItem{} - for _, track := range tracks.Tracks { - items = append(items, mainItem{ - Name: track.Track.Name, - Artist: track.Track.Artists[0], - Duration: track.Track.TimeDuration().Round(time.Second).String(), - ID: track.Track.ID, - Desc: track.Track.Artists[0].Name + " - " + track.Track.TimeDuration().Round(time.Second).String(), - }) - } - for _, item := range items { - m.list.InsertItem(len(m.list.Items())+1, item) - } - main_updates <- m - return - case "tracks": - tracks, err := commands.TrackList(m.ctx, m.client, (page + 1)) - page++ - if err != nil { - return - } - page++ - items := []list.Item{} - for _, track := range tracks.Tracks { - items = append(items, mainItem{ - Name: track.Name, - Artist: track.Artists[0], - Duration: track.TimeDuration().Round(time.Second).String(), - ID: track.ID, - Desc: track.Artists[0].Name + " - " + track.TimeDuration().Round(time.Second).String(), - }) - } - for _, item := range items { - m.list.InsertItem(len(m.list.Items())+1, item) - } - main_updates <- m - return - } +func (m mainModel) View() string { + return DocStyle.Render(m.list.View()) } func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -463,6 +269,14 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.list.NewStatusMessage("Starting radio for " + currentlyPlaying) go HandleLibraryRadio(m.ctx, m.client) } + case "albums": + currentlyPlaying = m.list.SelectedItem().FilterValue() + m.list.NewStatusMessage("Stating radio for" + currentlyPlaying) + go HandleAlbumRadio(m.ctx, m.client, m.list.SelectedItem().(mainItem).SpotifyItem.(spotify.SimpleAlbum).ID) + case "album": + currentlyPlaying = m.list.SelectedItem().FilterValue() + m.list.NewStatusMessage("Stating radio for" + currentlyPlaying) + go HandleRadio(m.ctx, m.client, m.list.SelectedItem().(mainItem).ID) case "playlist": currentlyPlaying = m.list.SelectedItem().FilterValue() m.list.NewStatusMessage("Starting radio for " + currentlyPlaying) @@ -490,231 +304,6 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, cmd } -func (m mainModel) View() string { - return DocStyle.Render(m.list.View()) -} - -func DisplayMain(ctx *gctx.Context, client *spotify.Client) error { - 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 err - } - for _, playlist := range playlists.Playlists { - items = append(items, mainItem{ - Name: playlist.Name, - Desc: playlist.Description, - SpotifyItem: playlist, - }) - } - m := mainModel{ - list: list.New(items, list.NewDefaultDelegate(), 0, 0), - ctx: ctx, - client: client, - mode: "main", - } - m.list.Title = "GOSPT" - go m.Tick() - - p := tea.NewProgram(m, tea.WithAltScreen(), tea.WithMouseCellMotion()) - - if _, err := p.Run(); err != nil { - fmt.Println("Error running program:", err) - return err - } - return nil -} - -func PlaylistView(ctx *gctx.Context, client *spotify.Client, playlist spotify.SimplePlaylist) ([]list.Item, error) { - items := []list.Item{} - tracks, err := commands.PlaylistTracks(ctx, client, playlist.ID, 1) - if err != nil { - return nil, err - } - for _, track := range tracks.Tracks { - items = append(items, mainItem{ - Name: track.Track.Name, - Artist: track.Track.Artists[0], - Duration: track.Track.TimeDuration().Round(time.Second).String(), - ID: track.Track.ID, - Desc: track.Track.Artists[0].Name + " - " + track.Track.TimeDuration().Round(time.Second).String(), - }) - } - 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), - SpotifyItem: artist.SimpleArtist, - }) - } - 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), - SpotifyItem: album.SimpleAlbum, - }) - } - return items, nil -} - -func ArtistAlbumsView(ctx *gctx.Context, album spotify.ID, client *spotify.Client) ([]list.Item, error) { - items := []list.Item{} - albums, err := commands.ArtistAlbums(ctx, client, album, 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 by %s", album.AlbumType, album.Artists[0].Name), - SpotifyItem: album, - }) - } - return items, err -} - -func AlbumTracksView(ctx *gctx.Context, album spotify.ID, client *spotify.Client) ([]list.Item, error) { - items := []list.Item{} - tracks, err := commands.AlbumTracks(ctx, client, album, 1) - if err != nil { - return nil, err - } - for _, track := range tracks.Tracks { - items = append(items, mainItem{ - Name: track.Name, - Artist: track.Artists[0], - Duration: track.TimeDuration().Round(time.Second).String(), - ID: track.ID, - Desc: track.Artists[0].Name + " - " + track.TimeDuration().Round(time.Second).String(), - }) - } - return items, err -} - -func SavedTracksView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { - items := []list.Item{} - tracks, err := commands.TrackList(ctx, client, 1) - if err != nil { - return nil, err - } - for _, track := range tracks.Tracks { - items = append(items, mainItem{ - Name: track.Name, - Artist: track.Artists[0], - Duration: track.TimeDuration().Round(time.Second).String(), - ID: track.ID, - Desc: track.Artists[0].Name + " - " + track.TimeDuration().Round(time.Second).String(), - }) - } - return items, err -} - -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{} - items = append(items, mainItem{ - Name: "Saved Tracks", - Desc: fmt.Sprintf("%d saved songs", saved_items.Total), - SpotifyItem: saved_items, - }) - items = append(items, mainItem{ - Name: "Albums", - Desc: fmt.Sprintf("%d albums", albums.Total), - SpotifyItem: albums, - }) - items = append(items, mainItem{ - Name: "Artists", - Desc: fmt.Sprintf("%d artists", artists.Total), - SpotifyItem: artists, - }) - for _, playlist := range playlists.Playlists { - items = append(items, mainItem{ - Name: playlist.Name, - Desc: playlist.Description, - SpotifyItem: playlist, - }) - } - return items, nil -} - func InitMain(ctx *gctx.Context, client *spotify.Client, mode string) (tea.Model, error) { playing, _ := client.PlayerCurrentlyPlaying(ctx) if playing.Playing { @@ -766,19 +355,3 @@ func InitMain(ctx *gctx.Context, client *spotify.Client, mode string) (tea.Model } return m, nil } - -func DeviceView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { - items := []list.Item{} - devices, err := client.PlayerDevices(ctx) - if err != nil { - return nil, err - } - for _, device := range devices { - items = append(items, mainItem{ - Name: device.Name, - Desc: fmt.Sprintf("%s - active: %t", device.ID, device.Active), - SpotifyItem: device, - }) - } - return items, nil -} diff --git a/internal/tui/views.go b/internal/tui/views.go new file mode 100644 index 0000000..1949c53 --- /dev/null +++ b/internal/tui/views.go @@ -0,0 +1,213 @@ +package tui + +import ( + "fmt" + "sync" + "time" + + "gospt/internal/commands" + "gospt/internal/gctx" + + "github.com/charmbracelet/bubbles/list" + "github.com/zmb3/spotify/v2" +) + +func DeviceView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { + items := []list.Item{} + devices, err := client.PlayerDevices(ctx) + if err != nil { + return nil, err + } + for _, device := range devices { + items = append(items, mainItem{ + Name: device.Name, + Desc: fmt.Sprintf("%s - active: %t", device.ID, device.Active), + SpotifyItem: device, + }) + } + return items, nil +} + +func PlaylistView(ctx *gctx.Context, client *spotify.Client, playlist spotify.SimplePlaylist) ([]list.Item, error) { + items := []list.Item{} + tracks, err := commands.PlaylistTracks(ctx, client, playlist.ID, 1) + if err != nil { + return nil, err + } + for _, track := range tracks.Tracks { + items = append(items, mainItem{ + Name: track.Track.Name, + Artist: track.Track.Artists[0], + Duration: track.Track.TimeDuration().Round(time.Second).String(), + ID: track.Track.ID, + Desc: track.Track.Artists[0].Name + " - " + track.Track.TimeDuration().Round(time.Second).String(), + }) + } + 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), + SpotifyItem: artist.SimpleArtist, + }) + } + 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), + SpotifyItem: album.SimpleAlbum, + }) + } + return items, nil +} + +func ArtistAlbumsView(ctx *gctx.Context, album spotify.ID, client *spotify.Client) ([]list.Item, error) { + items := []list.Item{} + albums, err := commands.ArtistAlbums(ctx, client, album, 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 by %s", album.AlbumType, album.Artists[0].Name), + SpotifyItem: album, + }) + } + return items, err +} + +func AlbumTracksView(ctx *gctx.Context, album spotify.ID, client *spotify.Client) ([]list.Item, error) { + items := []list.Item{} + tracks, err := commands.AlbumTracks(ctx, client, album, 1) + if err != nil { + return nil, err + } + for _, track := range tracks.Tracks { + items = append(items, mainItem{ + Name: track.Name, + Artist: track.Artists[0], + Duration: track.TimeDuration().Round(time.Second).String(), + ID: track.ID, + Desc: track.Artists[0].Name + " - " + track.TimeDuration().Round(time.Second).String(), + }) + } + return items, err +} + +func SavedTracksView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) { + items := []list.Item{} + tracks, err := commands.TrackList(ctx, client, 1) + if err != nil { + return nil, err + } + for _, track := range tracks.Tracks { + items = append(items, mainItem{ + Name: track.Name, + Artist: track.Artists[0], + Duration: track.TimeDuration().Round(time.Second).String(), + ID: track.ID, + Desc: track.Artists[0].Name + " - " + track.TimeDuration().Round(time.Second).String(), + }) + } + return items, err +} + +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{} + items = append(items, mainItem{ + Name: "Saved Tracks", + Desc: fmt.Sprintf("%d saved songs", saved_items.Total), + SpotifyItem: saved_items, + }) + items = append(items, mainItem{ + Name: "Albums", + Desc: fmt.Sprintf("%d albums", albums.Total), + SpotifyItem: albums, + }) + items = append(items, mainItem{ + Name: "Artists", + Desc: fmt.Sprintf("%d artists", artists.Total), + SpotifyItem: artists, + }) + for _, playlist := range playlists.Playlists { + items = append(items, mainItem{ + Name: playlist.Name, + Desc: playlist.Description, + SpotifyItem: playlist, + }) + } + return items, nil +}