98 lines
2.7 KiB
Go
98 lines
2.7 KiB
Go
package cmd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/bjarneo/cliamp/history"
|
|
)
|
|
|
|
// HistoryShow prints recently played tracks, newest first. limit <= 0 prints all.
|
|
// When jsonOutput is true, output is a JSON array suitable for scripting.
|
|
func HistoryShow(limit int, jsonOutput bool) error {
|
|
store := history.New()
|
|
if store == nil {
|
|
return fmt.Errorf("could not resolve config directory")
|
|
}
|
|
|
|
entries, err := store.Recent(limit)
|
|
if err != nil {
|
|
return fmt.Errorf("read history: %w", err)
|
|
}
|
|
|
|
if jsonOutput {
|
|
type jsonEntry struct {
|
|
PlayedAt string `json:"played_at"`
|
|
Path string `json:"path"`
|
|
Title string `json:"title"`
|
|
Artist string `json:"artist,omitempty"`
|
|
Album string `json:"album,omitempty"`
|
|
Genre string `json:"genre,omitempty"`
|
|
Year int `json:"year,omitempty"`
|
|
TrackNumber int `json:"track_number,omitempty"`
|
|
DurationSecs int `json:"duration_secs,omitempty"`
|
|
}
|
|
out := make([]jsonEntry, len(entries))
|
|
for i, e := range entries {
|
|
out[i] = jsonEntry{
|
|
PlayedAt: e.PlayedAt.UTC().Format(time.RFC3339),
|
|
Path: e.Track.Path,
|
|
Title: e.Track.Title,
|
|
Artist: e.Track.Artist,
|
|
Album: e.Track.Album,
|
|
Genre: e.Track.Genre,
|
|
Year: e.Track.Year,
|
|
TrackNumber: e.Track.TrackNumber,
|
|
DurationSecs: e.Track.DurationSecs,
|
|
}
|
|
}
|
|
enc := json.NewEncoder(os.Stdout)
|
|
enc.SetIndent("", " ")
|
|
return enc.Encode(out)
|
|
}
|
|
|
|
if len(entries) == 0 {
|
|
fmt.Println("No history yet — listen to a track for at least 50% of its duration to record it.")
|
|
return nil
|
|
}
|
|
|
|
fmt.Printf("Recently Played (%d tracks)\n\n", len(entries))
|
|
now := time.Now()
|
|
for i, e := range entries {
|
|
fmt.Printf(" %3d. %s (%s)\n", i+1, e.Track.DisplayName(), formatRelative(now, e.PlayedAt))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// HistoryClear wipes the history file.
|
|
func HistoryClear() error {
|
|
store := history.New()
|
|
if store == nil {
|
|
return fmt.Errorf("could not resolve config directory")
|
|
}
|
|
if err := store.Clear(); err != nil {
|
|
return fmt.Errorf("clear history: %w", err)
|
|
}
|
|
fmt.Println("History cleared.")
|
|
return nil
|
|
}
|
|
|
|
// formatRelative renders a short human-friendly duration like "3m ago" or
|
|
// "yesterday". Falls back to the date when older than a week.
|
|
func formatRelative(now, then time.Time) string {
|
|
d := now.Sub(then)
|
|
switch {
|
|
case d < time.Minute:
|
|
return "just now"
|
|
case d < time.Hour:
|
|
return fmt.Sprintf("%dm ago", int(d.Minutes()))
|
|
case d < 24*time.Hour:
|
|
return fmt.Sprintf("%dh ago", int(d.Hours()))
|
|
case d < 7*24*time.Hour:
|
|
return fmt.Sprintf("%dd ago", int(d.Hours()/24))
|
|
}
|
|
return then.Local().Format("2006-01-02")
|
|
}
|