Merge branch 'feature/download-track' into dev
This commit is contained in:
@@ -45,6 +45,8 @@ func (c *Client) FetchResource(ctx context.Context, resource Resource, id string
|
||||
payload["alb_id"] = id
|
||||
case *Artist:
|
||||
payload["art_id"] = id
|
||||
case *Track:
|
||||
payload["sng_id"] = id
|
||||
default:
|
||||
return fmt.Errorf("unsupported resource type: %T", r)
|
||||
}
|
||||
@@ -75,15 +77,17 @@ func (c *Client) FetchResource(ctx context.Context, resource Resource, id string
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.Contains(string(body), `"DATA_ERROR":"playlist::getData"`) {
|
||||
switch {
|
||||
case strings.Contains(string(body), `"DATA_ERROR":"playlist::getData"`):
|
||||
return fmt.Errorf("invalid playlist ID")
|
||||
}
|
||||
if strings.Contains(string(body), `"DATA_ERROR":"album::getData"`) {
|
||||
case strings.Contains(string(body), `"DATA_ERROR":"album::getData"`):
|
||||
return fmt.Errorf("invalid album ID")
|
||||
}
|
||||
if strings.Contains(string(body), `"DATA_ERROR":"artist::getData"`) {
|
||||
case strings.Contains(string(body), `"DATA_ERROR":"artist::getData"`):
|
||||
return fmt.Errorf("invalid artist ID")
|
||||
case strings.Contains(string(body), `"DATA_ERROR":"song::getData"`):
|
||||
return fmt.Errorf("invalid track ID")
|
||||
}
|
||||
|
||||
if strings.Contains(string(body), `"results":{}`) {
|
||||
return fmt.Errorf("unexpected response")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package deezer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/flytam/filenamify"
|
||||
)
|
||||
|
||||
type Track struct {
|
||||
Results struct {
|
||||
Data *Song `json:"DATA"`
|
||||
} `json:"results"`
|
||||
}
|
||||
|
||||
func (t *Track) String() string {
|
||||
if t.Results.Data == nil {
|
||||
return "Track: No data available"
|
||||
}
|
||||
|
||||
duration := "Unknown"
|
||||
if t.Results.Data.Duration != "" {
|
||||
if d, err := time.ParseDuration(t.Results.Data.Duration + "s"); err == nil {
|
||||
duration = d.String()
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
`================= [ Track Info ] =================
|
||||
Title: %s
|
||||
Artist: %s
|
||||
Duration: %s
|
||||
==================================================`,
|
||||
t.Results.Data.GetTitle(),
|
||||
t.Results.Data.Artist,
|
||||
duration,
|
||||
)
|
||||
}
|
||||
|
||||
func (t *Track) GetType() string {
|
||||
return "Track"
|
||||
}
|
||||
|
||||
func (t *Track) GetTitle() string {
|
||||
if t.Results.Data == nil {
|
||||
return ""
|
||||
}
|
||||
return t.Results.Data.GetTitle()
|
||||
}
|
||||
|
||||
func (t *Track) GetSongs() []*Song {
|
||||
if t.Results.Data == nil {
|
||||
return []*Song{}
|
||||
}
|
||||
return []*Song{t.Results.Data}
|
||||
}
|
||||
|
||||
func (t *Track) SetSongs(songs []*Song) {}
|
||||
|
||||
func (t *Track) GetOutputDir(outputDir string) string {
|
||||
if t.Results.Data == nil {
|
||||
return outputDir
|
||||
}
|
||||
|
||||
// For single tracks, create a simple "Singles" folder
|
||||
base := "Singles"
|
||||
base, _ = filenamify.Filenamify(base, filenamify.Options{})
|
||||
outputDir = path.Join(outputDir, base)
|
||||
|
||||
return outputDir
|
||||
}
|
||||
|
||||
func (t *Track) Unmarshal(data []byte) error {
|
||||
return json.Unmarshal(data, t)
|
||||
}
|
||||
@@ -63,6 +63,8 @@ func (c *Client) Run(ctx context.Context, opts Options, id string) error {
|
||||
resource = &deezer.Playlist{}
|
||||
case "artist":
|
||||
resource = &deezer.Artist{}
|
||||
case "track":
|
||||
resource = &deezer.Track{}
|
||||
default:
|
||||
return fmt.Errorf("unsupported resource type: %s", c.resourceType)
|
||||
}
|
||||
@@ -73,6 +75,9 @@ func (c *Client) Run(ctx context.Context, opts Options, id string) error {
|
||||
|
||||
songs := resource.GetSongs()
|
||||
if len(songs) == 0 {
|
||||
if c.resourceType == "track" {
|
||||
return fmt.Errorf("track with ID %s not found", id)
|
||||
}
|
||||
return fmt.Errorf("%s has no songs", c.resourceType)
|
||||
}
|
||||
if c.resourceType == "artist" && len(songs) > opts.Limit {
|
||||
@@ -87,7 +92,9 @@ func (c *Client) Run(ctx context.Context, opts Options, id string) error {
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
fmt.Printf("%s\n\nStarting download...\n\n", resource)
|
||||
if c.resourceType != "track" {
|
||||
fmt.Printf("%s\n\nStarting download...\n\n", resource)
|
||||
}
|
||||
|
||||
downloaded := 0
|
||||
skipped := 0
|
||||
@@ -146,7 +153,9 @@ func (c *Client) Run(ctx context.Context, opts Options, id string) error {
|
||||
if downloaded > 0 || failed > 0 {
|
||||
c.Logger.Infof("Playlist %s (%s): %d downloaded, %d skipped, %d failed\n", resource.GetTitle(), id, downloaded, skipped, failed)
|
||||
}
|
||||
fmt.Printf(`
|
||||
|
||||
if c.resourceType != "track" {
|
||||
fmt.Printf(`
|
||||
================== [ Summary ] ==================
|
||||
Downloaded: %d
|
||||
Skipped: %d
|
||||
@@ -155,12 +164,13 @@ Elapsed time: %s
|
||||
Files saved to: %s
|
||||
=================================================
|
||||
`,
|
||||
downloaded,
|
||||
skipped,
|
||||
failed,
|
||||
time.Since(startTime).Round(time.Second),
|
||||
resourceOutputDir,
|
||||
)
|
||||
downloaded,
|
||||
skipped,
|
||||
failed,
|
||||
time.Since(startTime).Round(time.Second),
|
||||
resourceOutputDir,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user