spogo/internal/cli/render.go
2026-01-02 19:00:04 +01:00

100 lines
3.2 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":
return fmt.Sprintf("%s — %s %s", accent(item.Name), item.Owner, muted(fmt.Sprintf("· %d tracks", item.TotalTracks)))
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))
}