From 8bc97d5bd303da82d4d557d873150a50398fb469 Mon Sep 17 00:00:00 2001 From: zarzet Date: Thu, 8 Jan 2026 00:52:24 +0700 Subject: [PATCH] v2.1.5: Deezer API 2.0, Qobuz default, fetch ISRC for search results --- go_backend/deezer.go | 53 +++++++++++++++++++++---------- go_backend/exports.go | 4 +-- lib/models/settings.dart | 2 +- lib/services/platform_bridge.dart | 2 +- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/go_backend/deezer.go b/go_backend/deezer.go index c3eb879..dc51148 100644 --- a/go_backend/deezer.go +++ b/go_backend/deezer.go @@ -13,11 +13,12 @@ import ( ) const ( - deezerSearchURL = "https://api.deezer.com/search" - deezerTrackURL = "https://api.deezer.com/track/%s" - deezerAlbumURL = "https://api.deezer.com/album/%s" - deezerArtistURL = "https://api.deezer.com/artist/%s" - deezerPlaylistURL = "https://api.deezer.com/playlist/%s" + deezerBaseURL = "https://api.deezer.com/2.0" + deezerSearchURL = deezerBaseURL + "/search" + deezerTrackURL = deezerBaseURL + "/track/%s" + deezerAlbumURL = deezerBaseURL + "/album/%s" + deezerArtistURL = deezerBaseURL + "/artist/%s" + deezerPlaylistURL = deezerBaseURL + "/playlist/%s" deezerCacheTTL = 10 * time.Minute ) @@ -152,7 +153,14 @@ func (c *DeezerClient) SearchAll(ctx context.Context, query string, trackLimit, } for _, track := range trackResp.Data { - result.Tracks = append(result.Tracks, c.convertTrack(track)) + // Fetch full track info to get ISRC (search results don't include ISRC) + fullTrack, err := c.fetchFullTrack(ctx, fmt.Sprintf("%d", track.ID)) + if err == nil && fullTrack != nil { + result.Tracks = append(result.Tracks, c.convertTrack(*fullTrack)) + } else { + // Fallback to search result without ISRC + result.Tracks = append(result.Tracks, c.convertTrack(track)) + } } // Search artists @@ -423,23 +431,36 @@ func (c *DeezerClient) GetPlaylist(ctx context.Context, playlistID string) (*Pla }, nil } -// SearchByISRC searches for a track by ISRC +// SearchByISRC searches for a track by ISRC using direct endpoint func (c *DeezerClient) SearchByISRC(ctx context.Context, isrc string) (*TrackMetadata, error) { - searchURL := fmt.Sprintf("%s/track?q=isrc:%s&limit=1", deezerSearchURL, isrc) + // Use direct ISRC endpoint (API 2.0) + // https://api.deezer.com/2.0/track/isrc:{ISRC} + directURL := fmt.Sprintf("%s/track/isrc:%s", deezerBaseURL, isrc) - var resp struct { - Data []deezerTrack `json:"data"` - } - if err := c.getJSON(ctx, searchURL, &resp); err != nil { - return nil, err + var track deezerTrack + if err := c.getJSON(ctx, directURL, &track); err != nil { + // Fallback to search if direct endpoint fails + searchURL := fmt.Sprintf("%s/track?q=isrc:%s&limit=1", deezerSearchURL, isrc) + var resp struct { + Data []deezerTrack `json:"data"` + } + if err := c.getJSON(ctx, searchURL, &resp); err != nil { + return nil, err + } + if len(resp.Data) == 0 { + return nil, fmt.Errorf("no track found for ISRC: %s", isrc) + } + result := c.convertTrack(resp.Data[0]) + return &result, nil } - if len(resp.Data) == 0 { + // Check if we got a valid response (ID > 0) + if track.ID == 0 { return nil, fmt.Errorf("no track found for ISRC: %s", isrc) } - track := c.convertTrack(resp.Data[0]) - return &track, nil + result := c.convertTrack(track) + return &result, nil } func (c *DeezerClient) fetchFullTrack(ctx context.Context, trackID string) (*deezerTrack, error) { diff --git a/go_backend/exports.go b/go_backend/exports.go index 94c8a69..158526d 100644 --- a/go_backend/exports.go +++ b/go_backend/exports.go @@ -276,10 +276,10 @@ func DownloadWithFallback(requestJSON string) (string, error) { req.OutputDir = strings.TrimSpace(req.OutputDir) // Build service order starting with preferred service - allServices := []string{"tidal", "qobuz", "amazon"} + allServices := []string{"qobuz", "tidal", "amazon"} preferredService := req.Service if preferredService == "" { - preferredService = "tidal" + preferredService = "qobuz" } fmt.Printf("[DownloadWithFallback] Preferred service from request: '%s'\n", req.Service) diff --git a/lib/models/settings.dart b/lib/models/settings.dart index cad0de2..ca733f1 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -25,7 +25,7 @@ class AppSettings { final String metadataSource; // spotify, deezer - source for search and metadata const AppSettings({ - this.defaultService = 'tidal', + this.defaultService = 'qobuz', this.audioQuality = 'LOSSLESS', this.filenameFormat = '{title} - {artist}', this.downloadDirectory = '', diff --git a/lib/services/platform_bridge.dart b/lib/services/platform_bridge.dart index 442158b..9ee8f9a 100644 --- a/lib/services/platform_bridge.dart +++ b/lib/services/platform_bridge.dart @@ -111,7 +111,7 @@ class PlatformBridge { int discNumber = 1, int totalTracks = 1, String? releaseDate, - String preferredService = 'tidal', + String preferredService = 'qobuz', String? itemId, int durationMs = 0, }) async {