- Introduced a `--shuffle` flag for the `play` command to enable shuffle before playing. - Updated playback logic to handle context URIs for playlists and tracks. - Enhanced error handling and added support for library tracks and albums in the Connect client. - Improved rendering of playlist information in the CLI output. - Added tests for new playback features and context URI handling.
103 lines
3.3 KiB
Go
103 lines
3.3 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/steipete/spogo/internal/output"
|
|
"github.com/steipete/spogo/internal/spotify"
|
|
)
|
|
|
|
func renderItems(w *output.Writer, items []spotify.Item) (plain []string, human []string) {
|
|
plain = make([]string, 0, len(items))
|
|
human = make([]string, 0, len(items))
|
|
for _, item := range items {
|
|
plain = append(plain, itemPlain(item))
|
|
human = append(human, itemHuman(w, item))
|
|
}
|
|
return plain, human
|
|
}
|
|
|
|
func itemPlain(item spotify.Item) string {
|
|
switch item.Type {
|
|
case "track":
|
|
return fmt.Sprintf("track\t%s\t%s\t%s\t%s\t%s", item.ID, item.Name, strings.Join(item.Artists, ", "), item.Album, item.URI)
|
|
case "album":
|
|
return fmt.Sprintf("album\t%s\t%s\t%s\t%s\t%d", item.ID, item.Name, strings.Join(item.Artists, ", "), item.ReleaseDate, item.TotalTracks)
|
|
case "artist":
|
|
return fmt.Sprintf("artist\t%s\t%s\t%d", item.ID, item.Name, item.Followers)
|
|
case "playlist":
|
|
return fmt.Sprintf("playlist\t%s\t%s\t%s\t%d", item.ID, item.Name, item.Owner, item.TotalTracks)
|
|
case "show":
|
|
return fmt.Sprintf("show\t%s\t%s\t%s\t%d", item.ID, item.Name, item.Publisher, item.TotalEpisodes)
|
|
case "episode":
|
|
return fmt.Sprintf("episode\t%s\t%s\t%d", item.ID, item.Name, item.DurationMS)
|
|
default:
|
|
return fmt.Sprintf("item\t%s\t%s\t%s", item.ID, item.Name, item.URI)
|
|
}
|
|
}
|
|
|
|
func itemHuman(w *output.Writer, item spotify.Item) string {
|
|
accent := w.Theme.Accent
|
|
muted := w.Theme.Muted
|
|
switch item.Type {
|
|
case "track":
|
|
return fmt.Sprintf("%s — %s %s", accent(item.Name), strings.Join(item.Artists, ", "), muted("· "+item.Album))
|
|
case "album":
|
|
return fmt.Sprintf("%s — %s %s", accent(item.Name), strings.Join(item.Artists, ", "), muted("· "+item.ReleaseDate))
|
|
case "artist":
|
|
return fmt.Sprintf("%s %s", accent(item.Name), muted(fmt.Sprintf("· %d followers", item.Followers)))
|
|
case "playlist":
|
|
if item.TotalTracks > 0 {
|
|
return fmt.Sprintf("%s — %s %s", accent(item.Name), item.Owner, muted(fmt.Sprintf("· %d tracks", item.TotalTracks)))
|
|
}
|
|
return fmt.Sprintf("%s — %s", accent(item.Name), item.Owner)
|
|
case "show":
|
|
return fmt.Sprintf("%s — %s %s", accent(item.Name), item.Publisher, muted(fmt.Sprintf("· %d episodes", item.TotalEpisodes)))
|
|
case "episode":
|
|
return fmt.Sprintf("%s %s", accent(item.Name), muted(fmt.Sprintf("· %s", humanDuration(item.DurationMS))))
|
|
default:
|
|
return accent(item.Name)
|
|
}
|
|
}
|
|
|
|
func humanDuration(ms int) string {
|
|
if ms <= 0 {
|
|
return "0s"
|
|
}
|
|
d := time.Duration(ms) * time.Millisecond
|
|
h := int(d.Hours())
|
|
m := int(d.Minutes()) % 60
|
|
s := int(d.Seconds()) % 60
|
|
if h > 0 {
|
|
return fmt.Sprintf("%dh%02dm%02ds", h, m, s)
|
|
}
|
|
if m > 0 {
|
|
return fmt.Sprintf("%dm%02ds", m, s)
|
|
}
|
|
return fmt.Sprintf("%ds", s)
|
|
}
|
|
|
|
func playbackPlain(status spotify.PlaybackStatus) string {
|
|
track := ""
|
|
if status.Item != nil {
|
|
track = status.Item.Name
|
|
}
|
|
return fmt.Sprintf("%t\t%d\t%s\t%s", status.IsPlaying, status.ProgressMS, status.Device.Name, track)
|
|
}
|
|
|
|
func playbackHuman(w *output.Writer, status spotify.PlaybackStatus) string {
|
|
accent := w.Theme.Accent
|
|
muted := w.Theme.Muted
|
|
state := "paused"
|
|
if status.IsPlaying {
|
|
state = "playing"
|
|
}
|
|
track := ""
|
|
if status.Item != nil {
|
|
track = fmt.Sprintf("%s — %s", accent(status.Item.Name), strings.Join(status.Item.Artists, ", "))
|
|
}
|
|
return fmt.Sprintf("%s %s %s", accent(strings.ToUpper(state)), track, muted("· "+status.Device.Name))
|
|
}
|