From 50fde9dfa9529f2b286e702c555e788f40c616d1 Mon Sep 17 00:00:00 2001 From: Mathis Maquenne <124215603+mathismqn@users.noreply.github.com> Date: Wed, 6 Aug 2025 22:01:08 +0200 Subject: [PATCH] feat(media): fallback to lower quality if requested format is unavailable --- cmd/download.go | 3 +++ internal/deezer/client.go | 6 ++---- internal/deezer/media.go | 10 +--------- internal/downloader/client.go | 15 ++++++++++----- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/cmd/download.go b/cmd/download.go index 46fc4bf..0a9185a 100644 --- a/cmd/download.go +++ b/cmd/download.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strings" "time" "github.com/mathismqn/godeez/internal/config" @@ -53,6 +54,8 @@ func newDownloadCmd(resourceType string) *cobra.Command { } cmd.SetContext(context.WithValue(cmd.Context(), "appConfig", appConfig)) + opts.Quality = strings.ToLower(opts.Quality) + return opts.Validate() }, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/internal/deezer/client.go b/internal/deezer/client.go index 964b675..f789c9c 100644 --- a/internal/deezer/client.go +++ b/internal/deezer/client.go @@ -98,10 +98,8 @@ func (c *Client) FetchMedia(ctx context.Context, song *Song, quality string) (*M case "mp3_128": formats = `[{"cipher":"BF_CBC_STRIPE","format":"MP3_128"}]` case "mp3_320": - formats = `[{"cipher":"BF_CBC_STRIPE","format":"MP3_320"}]` - case "flac": - formats = `[{"cipher":"BF_CBC_STRIPE","format":"FLAC"}]` - case "best": + formats = `[{"cipher":"BF_CBC_STRIPE","format":"MP3_320"},{"cipher":"BF_CBC_STRIPE","format":"MP3_128"}]` + case "flac", "best": formats = `[{"cipher":"BF_CBC_STRIPE","format":"FLAC"},{"cipher":"BF_CBC_STRIPE","format":"MP3_320"},{"cipher":"BF_CBC_STRIPE","format":"MP3_128"}]` } diff --git a/internal/deezer/media.go b/internal/deezer/media.go index 928075b..aea0a6c 100644 --- a/internal/deezer/media.go +++ b/internal/deezer/media.go @@ -36,15 +36,7 @@ func (m *Media) GetURL() (string, error) { return "", fmt.Errorf("no media sources found") } - url := m.Data[0].Media[0].Sources[0].URL - for _, source := range m.Data[0].Media[0].Sources { - if source.Provider == "ak" { - url = source.URL - break - } - } - - return url, nil + return m.Data[0].Media[0].Sources[0].URL, nil } func (m *Media) GetFormat() (string, error) { diff --git a/internal/downloader/client.go b/internal/downloader/client.go index 5a6ed19..e7f6ba7 100644 --- a/internal/downloader/client.go +++ b/internal/downloader/client.go @@ -7,6 +7,7 @@ import ( "io" "os" "path" + "strings" "sync" "time" @@ -168,7 +169,7 @@ func (c *Client) downloadSong(ctx context.Context, resource deezer.Resource, son media, err := c.deezerClient.FetchMedia(ctx, song, opts.Quality) if err != nil { - return warnings, fmt.Errorf("failed to fetch media: %w", err) + return nil, fmt.Errorf("failed to fetch media: %w", err) } fileName := song.GetFileName(c.resourceType, song, media) @@ -176,11 +177,11 @@ func (c *Client) downloadSong(ctx context.Context, resource deezer.Resource, son mediaFormat, err := media.GetFormat() if err != nil { - return warnings, fmt.Errorf("failed to get media format: %w", err) + return nil, fmt.Errorf("failed to get media format: %w", err) } if path, skip := c.shouldSkipDownload(ctx, song.ID, mediaFormat); skip { - return warnings, SkipError{Path: path} + return nil, SkipError{Path: path} } var metricsChan chan *bpm.Metrics @@ -201,7 +202,7 @@ func (c *Client) downloadSong(ctx context.Context, resource deezer.Resource, son stream, err := c.deezerClient.GetMediaStream(ctx, media, song.ID) if err != nil { - return warnings, fmt.Errorf("failed to get media stream: %w", err) + return nil, fmt.Errorf("failed to get media stream: %w", err) } dlCtx, cancel := context.WithTimeout(ctx, opts.Timeout) @@ -211,7 +212,11 @@ func (c *Client) downloadSong(ctx context.Context, resource deezer.Resource, son if err := c.streamToFile(dlCtx, stream, outputPath, key); err != nil { fileutil.DeleteFile(outputPath) - return warnings, fmt.Errorf("failed to stream to file: %w", err) + return nil, fmt.Errorf("failed to stream to file: %w", err) + } + + if opts.Quality != strings.ToLower(mediaFormat) { + warnings = append(warnings, fmt.Sprintf("requested quality '%s' not available, using '%s' instead", opts.Quality, strings.ToLower(mediaFormat))) } metrics := &bpm.Metrics{}