diff --git a/go_backend/tidal.go b/go_backend/tidal.go index 5ed6eb1d..a8dbdac1 100644 --- a/go_backend/tidal.go +++ b/go_backend/tidal.go @@ -770,95 +770,6 @@ func getDownloadURLParallel(apis []string, trackID int64, quality string) (strin return "", TidalDownloadInfo{}, fmt.Errorf("all %d Tidal APIs failed. Errors: %v", len(apis), errors) } -// getDownloadURLSequential requests download URL from APIs sequentially (fallback) -// Returns the first successful result (supports both v1 and v2 API formats) -func getDownloadURLSequential(apis []string, trackID int64, quality string) (string, TidalDownloadInfo, error) { - if len(apis) == 0 { - return "", TidalDownloadInfo{}, fmt.Errorf("no APIs available") - } - - client := NewHTTPClientWithTimeout(DefaultTimeout) - retryConfig := DefaultRetryConfig() - var errors []string - - for _, apiURL := range apis { - reqURL := fmt.Sprintf("%s/track/?id=%d&quality=%s", apiURL, trackID, quality) - GoLog("[Tidal] Trying API: %s\n", reqURL) - - req, err := http.NewRequest("GET", reqURL, nil) - if err != nil { - errors = append(errors, BuildErrorMessage(apiURL, 0, err.Error())) - continue - } - - resp, err := DoRequestWithRetry(client, req, retryConfig) - if err != nil { - GoLog("[Tidal] API error: %v\n", err) - errors = append(errors, BuildErrorMessage(apiURL, 0, err.Error())) - continue - } - - body, err := ReadResponseBody(resp) - resp.Body.Close() - if err != nil { - GoLog("[Tidal] Read body error: %v\n", err) - errors = append(errors, BuildErrorMessage(apiURL, resp.StatusCode, err.Error())) - continue - } - - // Log response preview - bodyPreview := string(body) - if len(bodyPreview) > 300 { - bodyPreview = bodyPreview[:300] + "..." - } - GoLog("[Tidal] API response (HTTP %d): %s\n", resp.StatusCode, bodyPreview) - - // Try v2 format first (object with manifest) - var v2Response TidalAPIResponseV2 - if err := json.Unmarshal(body, &v2Response); err == nil && v2Response.Data.Manifest != "" { - GoLog("[Tidal] Got v2 response from %s - Quality: %d-bit/%dHz, AssetPresentation: %s\n", - apiURL, v2Response.Data.BitDepth, v2Response.Data.SampleRate, v2Response.Data.AssetPresentation) - - // IMPORTANT: Reject PREVIEW responses - we need FULL tracks - if v2Response.Data.AssetPresentation == "PREVIEW" { - GoLog("[Tidal] ✗ Rejecting PREVIEW response from %s, trying next API...\n", apiURL) - errors = append(errors, BuildErrorMessage(apiURL, resp.StatusCode, "returned PREVIEW instead of FULL")) - continue - } - - GoLog("[Tidal] ✓ Got FULL track from %s\n", apiURL) - info := TidalDownloadInfo{ - URL: "MANIFEST:" + v2Response.Data.Manifest, - BitDepth: v2Response.Data.BitDepth, - SampleRate: v2Response.Data.SampleRate, - } - return apiURL, info, nil - } - - // Fallback to v1 format (array with OriginalTrackUrl) - var v1Responses []struct { - OriginalTrackURL string `json:"OriginalTrackUrl"` - } - if err := json.Unmarshal(body, &v1Responses); err == nil { - for _, item := range v1Responses { - if item.OriginalTrackURL != "" { - // v1 format doesn't have quality info, assume 16-bit/44.1kHz - info := TidalDownloadInfo{ - URL: item.OriginalTrackURL, - BitDepth: 16, - SampleRate: 44100, - } - return apiURL, info, nil - } - } - } - - errors = append(errors, BuildErrorMessage(apiURL, resp.StatusCode, "no download URL or manifest in response")) - } - - return "", TidalDownloadInfo{}, fmt.Errorf("all %d Tidal APIs failed. Errors: %v", len(apis), errors) -} - // GetDownloadURL gets download URL for a track - tries ALL APIs in parallel // "Siapa cepat dia dapat" - first successful response wins func (t *TidalDownloader) GetDownloadURL(trackID int64, quality string) (TidalDownloadInfo, error) {