Qobuz: allow free accounts to download purchased (download-store) content#1007
Open
jrejaud wants to merge 1 commit into
Open
Qobuz: allow free accounts to download purchased (download-store) content#1007jrejaud wants to merge 1 commit into
jrejaud wants to merge 1 commit into
Conversation
A Qobuz account with no streaming subscription returns an empty credential.parameters on login. Previously login() raised IneligibleError, so such an account could not download albums it had *purchased* from the Qobuz download store (nathom#673, nathom#918). Make the behavior conditional instead of regressing streaming for subscribers: - login() flags the client download_only=True (WARNING log) on empty credential.parameters instead of raising. Genuine 401/400 auth failures still raise. - _request_file_url() selects intent=download when download_only else intent=stream, in both the signed request_sig preimage and the params dict. - get_downloadable() clamps quality for purchased content: on a FormatRestrictedByFormatAvailability restriction it retries one tier down (Qobuz offers no automatic fallback for owned content). Adds unit tests covering both account types and both intent paths. This only enables downloading content the account already owns; Qobuz still gates getFileUrl on ownership server-side. Closes nathom#673 Closes nathom#918 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A Qobuz account with no streaming subscription returns an empty
credential.parameterson login. TodayQobuzClient.login()unconditionally raisesIneligibleErrorin that case, so the account cannot download albums it has purchased from the Qobuz download store — even though Qobuz serves those files fine viaintent=download.This is the long-standing #673 (open since Apr 2024) and #918.
Fix
Make the behavior conditional so streaming for subscribers is untouched:
login()— on emptycredential.parameters, setself.download_only = Trueand log aWARNINGinstead of raising. Genuine auth failures (401/400) still raise as before; only the free-but-owns-content case is reclassified._request_file_url()— pickintent = "download" if self.download_only else "stream", applied to both the signedrequest_sigpreimage and the params dict (they must agree or Qobuz returns HTTP 400).get_downloadable()— purchased content is sold in exactly one format and Qobuz offers no automatic fallback. Whendownload_onlyand the response isFormatRestrictedByFormatAvailability, retry one quality tier down so a too-high configured quality clamps instead of erroring.download_onlyis auto-detected from the login response — no new config flag, existing configs keep working. Subscribers keepintent=streamexactly as before.Security note
This only enables downloading content the account already owns. There is no entitlement bypass: Qobuz still gates
track/getFileUrlon ownership server-side, so a non-owned track returns a restriction regardless ofintent.Tests
Added
tests/test_qobuz_download_only.py(fully mocked, no credentials needed):parameters) →download_only is False, no raiseparameters) →download_only is True, no raisedownload_only=True→intent=downloadin the params dict and the signed preimage (verified by reconstructing the md5)download_only=False→intent=streamin bothVerified end-to-end against a real free Qobuz account with purchased albums: a 12-track 24-bit/44.1 kHz album downloads all 12 FLACs at full quality (
ffprobe:bits_per_raw_sample=24,sample_rate=44100, full track durations), and the quality-clamp path retries down correctly when a higher tier is requested.Existing suite passes with no new failures.
Closes #673
Closes #918