diff --git a/commands/commands.go b/commands/commands.go new file mode 100644 index 0000000..c3c09ef --- /dev/null +++ b/commands/commands.go @@ -0,0 +1,74 @@ +package commands + +import ( + "encoding/json" + "fmt" + + "gospt/ctx" + + "github.com/zmb3/spotify/v2" +) + +func Play(ctx *ctx.Context, client *spotify.Client) error { + var err error + err = client.Play(ctx) + if err != nil { + return err + } + ctx.Println("Playing!") + return nil +} + +func Pause(ctx *ctx.Context, client *spotify.Client) error { + err := client.Pause(ctx) + if err != nil { + return err + } + ctx.Println("Pausing!") + return nil +} + +func Skip(ctx *ctx.Context, client *spotify.Client) error { + err := client.Next(ctx) + if err != nil { + return err + } + ctx.Println("Skipping!") + return nil +} + +func Status(ctx *ctx.Context, client *spotify.Client) error { + state, err := client.PlayerState(ctx) + if err != nil { + return err + } + return PrintState(state) +} + +func Shuffle(ctx *ctx.Context, client *spotify.Client) error { + state, err := client.PlayerState(ctx) + if err != nil { + return fmt.Errorf("Failed to get current playstate") + } + err = client.Shuffle(ctx, !state.ShuffleState) + if err != nil { + return err + } + ctx.Println("Shuffle set to", !state.ShuffleState) + return nil +} + +func TrackList(ctx *ctx.Context, client *spotify.Client, page int) (*spotify.SavedTrackPage, error) { + return client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) +} + +func PrintState(state *spotify.PlayerState) error { + state.Item.AvailableMarkets = []string{} + state.Item.Album.AvailableMarkets = []string{} + out, err := json.MarshalIndent(state, "", " ") + if err != nil { + return err + } + fmt.Println(string(out)) + return nil +} diff --git a/runner/runner.go b/runner/runner.go index 14c92fb..094a5f6 100644 --- a/runner/runner.go +++ b/runner/runner.go @@ -3,6 +3,7 @@ package runner import ( "fmt" + "gospt/commands" "gospt/ctx" "gospt/tui" @@ -20,60 +21,18 @@ func Run(ctx *ctx.Context, client *spotify.Client, args []string) error { } switch args[0] { case "play": - return Play(ctx, client) + return commands.Play(ctx, client) case "pause": - return Pause(ctx, client) + return commands.Pause(ctx, client) case "next": - return Skip(ctx, client) + return commands.Skip(ctx, client) case "shuffle": - return Shuffle(ctx, client) + return commands.Shuffle(ctx, client) case "tracks": - return GetTracks(ctx, client, args) + return tui.DisplayList(ctx, client) + case "status": + return commands.Status(ctx, client) default: return fmt.Errorf("Unsupported Command") } } - -func Play(ctx *ctx.Context, client *spotify.Client) error { - err := client.Play(ctx) - if err != nil { - return err - } - fmt.Println("Playing!") - return nil -} - -func Pause(ctx *ctx.Context, client *spotify.Client) error { - err := client.Pause(ctx) - if err != nil { - return err - } - fmt.Println("Pausing!") - return nil -} - -func Skip(ctx *ctx.Context, client *spotify.Client) error { - err := client.Next(ctx) - if err != nil { - return err - } - fmt.Println("Skipping!") - return nil -} - -func Shuffle(ctx *ctx.Context, client *spotify.Client) error { - state, err := client.PlayerState(ctx) - if err != nil { - return fmt.Errorf("Failed to get current playstate") - } - err = client.Shuffle(ctx, !state.ShuffleState) - if err != nil { - return err - } - fmt.Println("Shuffle set to", !state.ShuffleState) - return nil -} - -func GetTracks(ctx *ctx.Context, client *spotify.Client, args []string) error { - return tui.DisplayList(ctx, client) -} diff --git a/tui/list.go b/tui/list.go index 47402a7..b3d4e72 100644 --- a/tui/list.go +++ b/tui/list.go @@ -5,6 +5,7 @@ import ( "os" "time" + "gospt/commands" "gospt/ctx" "github.com/charmbracelet/bubbles/list" @@ -16,14 +17,18 @@ import ( var docStyle = lipgloss.NewStyle().Margin(1, 2) type item struct { + Name string + Duration string + Artist spotify.SimpleArtist + ID spotify.ID spotify.SavedTrack } func (i item) Title() string { return i.Name } func (i item) Description() string { - return fmt.Sprint(i.TimeDuration().Round(time.Second), " by ", i.Artists[0].Name) + return fmt.Sprint(i.Duration, " by ", i.Artist.Name) } -func (i item) FilterValue() string { return i.Title() } +func (i item) FilterValue() string { return i.Title() + i.Artist.Name } type model struct { list list.Model @@ -37,26 +42,42 @@ func (m model) Init() tea.Cmd { } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + if m.list.Paginator.OnLastPage() { + tracks, err := commands.TrackList(m.ctx, m.client, (m.page + 1)) + if err != nil { + return m, tea.Quit + } + m.page++ + items := []list.Item{} + for _, track := range tracks.Tracks { + items = append(items, item{ + Name: track.Name, + Artist: track.Artists[0], + Duration: track.TimeDuration().Round(time.Second).String(), + ID: track.ID, + }) + } + for _, item := range items { + m.list.InsertItem(len(m.list.Items())+1, item) + } + } switch msg := msg.(type) { case tea.KeyMsg: if msg.String() == "ctrl+c" { return m, tea.Quit } - if msg.String() == "ctrl+n" { - tracks, err := TrackList(m.ctx, m.client, (m.page + 1)) + if msg.String() == "enter" { + track := m.list.SelectedItem() + var err error + err = m.client.QueueSong(m.ctx, track.(item).ID) if err != nil { - return m, tea.Quit + m.ctx.Printf(err.Error()) } - m.page++ - items := []list.Item{} - for _, track := range tracks.Tracks { - items = append(items, item{ - track, - }) - } - for _, item := range items { - m.list.InsertItem(len(m.list.Items())+1, item) + err = m.client.Next(m.ctx) + if err != nil { + m.ctx.Printf(err.Error()) } + } case tea.WindowSizeMsg: h, v := docStyle.GetFrameSize() @@ -73,16 +94,20 @@ func (m model) View() string { } func DisplayList(ctx *ctx.Context, client *spotify.Client) error { - tracks, err := TrackList(ctx, client, 1) + items := []list.Item{} + tracks, err := commands.TrackList(ctx, client, 1) if err != nil { return err } - items := []list.Item{} for _, track := range tracks.Tracks { items = append(items, item{ - track, + Name: track.Name, + Artist: track.Artists[0], + Duration: track.TimeDuration().Round(time.Second).String(), + ID: track.ID, }) } + m := model{list: list.New(items, list.NewDefaultDelegate(), 0, 0), page: 1, ctx: ctx, client: client} m.list.Title = "Saved Tracks" @@ -94,7 +119,3 @@ func DisplayList(ctx *ctx.Context, client *spotify.Client) error { } return nil } - -func TrackList(ctx *ctx.Context, client *spotify.Client, page int) (*spotify.SavedTrackPage, error) { - return client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset((page-1)*50)) -}