Skip to content

feat(qobuz): Implement Qobuz provider#206

Open
Lioncat6 wants to merge 22 commits into
kellnerd:mainfrom
Lioncat6:qobuz
Open

feat(qobuz): Implement Qobuz provider#206
Lioncat6 wants to merge 22 commits into
kellnerd:mainfrom
Lioncat6:qobuz

Conversation

@Lioncat6
Copy link
Copy Markdown

@Lioncat6 Lioncat6 commented Apr 3, 2026

Closes #189

@Lioncat6
Copy link
Copy Markdown
Author

Lioncat6 commented Apr 3, 2026

~~Tests seem to fail with a server error 500 for whatever reason, but lookups are running fine outside of tests. Perhaps the test command I'm using is incorrect: deno test --allow-net --allow-write --allow-env ./providers/Qobuz/mod.test.ts -- --download

Edit: seems the environment variables aren't loading properly during the test~~

Forgot to specify .env path :p

deno test --allow-net --allow-write --allow-read --allow-env ./providers/Qobuz/mod.test.ts -- --download --update

@Lioncat6 Lioncat6 mentioned this pull request Apr 3, 2026
17 tasks
@Lioncat6
Copy link
Copy Markdown
Author

Lioncat6 commented Apr 3, 2026

Just realized eti isn't included in track titles

Copy link
Copy Markdown
Owner

@kellnerd kellnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much, this is looking good already!
I've got a couple of comments nevertheless. These are only based on reading the code, I will come back once I've tested the provider with a couple of releases (but that will have to wait until I'm done with my Discogs provider testing).

P.S. The formatter doesn't like your API interface definitions, please fix with deno fmt. You can locally check that CI (except tests) passes by running deno task ok.

Comment thread providers/Qobuz/mod.test.ts Outdated
Comment thread providers/Qobuz/mod.ts Outdated

readonly supportedUrls = new URLPattern({
hostname: '(play|www|open).qobuz.com',
pathname: '/:region?/:type(artist|album|track|interpreter|label)/:slug?/:id',
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't call the combination of country and language code :region here, it will cause problems for other providers which only expect a country code as region. The simplest solution would be to call the group :locale and be done with it, but this doesn't provide much value.
Alternatively we can extract two named groups :region and :language, which makes the region usable for other providers, but requires us to define a mapping between regions and default languages (for incoming regions from other providers or the web input where we don't know the language).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using locale group for now...

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented the extraction of country and language in 5fd1a46.
Unfortunately it doesn't seem to be possible to define an optional path segment with two named groups in an URLPattern.
Hence the simplest solution was to have one combined group region again and split it into country and language afterwards 😅

Comment thread providers/Qobuz/mod.ts Outdated
Comment thread providers/Qobuz/mod.ts Outdated
Comment thread providers/Qobuz/mod.ts Outdated
Comment thread providers/mod.ts Outdated
Comment thread providers/Qobuz/mod.ts Outdated
Comment thread providers/Qobuz/mod.test.ts
Comment thread providers/Qobuz/__snapshots__/mod.test.ts.snap Outdated
Comment thread providers/Qobuz/__snapshots__/mod.test.ts.snap Outdated
@kellnerd kellnerd added feature New feature or request provider Metadata provider labels Apr 3, 2026
@Lioncat6 Lioncat6 requested a review from kellnerd April 5, 2026 02:31
Copy link
Copy Markdown
Owner

@kellnerd kellnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deno test --allow-net --allow-write --allow-read --allow-env ./providers/Qobuz/mod.test.ts -- --download --update

Quick tips:

  1. You can abbreviate the allow flags with -NWRE.
  2. Usually you want either the --download or the --update flag (or none of them most of the time).
  3. --download should be rarely enabled after all the testdata has been cached once because responses often cause irrelevant noise for git because of unstable sort order (like your Qobuz search response changing with every commit :/) or irrelevant properties (like popularity) changing their values.
  4. You should only --update the snapshots if there was an intended change that caused an assertion error, otherwise it will always update and swallow unintended breaking changes.

Comment thread providers/Qobuz/mod.ts Outdated
Comment thread providers/Qobuz/mod.ts Outdated
Comment thread providers/Qobuz/mod.ts Outdated
@Lioncat6 Lioncat6 requested a review from kellnerd April 8, 2026 17:59
@kellnerd
Copy link
Copy Markdown
Owner

My quick update from your other PR applies here as well: Code-wise this is looking good, but I still have to actually test the provider with a few releases myself.

@Lioncat6
Copy link
Copy Markdown
Author

Lioncat6 commented Apr 15, 2026

After some testing, label matching seems to work perfectly with qobuz, even when using another provider as the source for the UPC:
image

This is really cool since AFAIK this is the only provider to actually have usable label URLs so far

@Lioncat6
Copy link
Copy Markdown
Author

Side note: Was doing some testing and I had an issue where 2 artists were getting assigned the same URL.

@kellnerd
Copy link
Copy Markdown
Owner

kellnerd commented May 11, 2026

A few additional thoughts after I finally found time to test the implementation a bit:

  • open.qobuz.com does not show multiple release artists, but the www subdomain does... Maybe we should standardize on the www URL format (for releases), even if it contains locale and slug? Or maybe have both? Really unsure about that, I will check the MBS ticket again when I have more time.
  • A track artist can be extracted from the track.performer object (example), multiple artists are only included in the track.performers string with the role MainArtist.
  • I can't verify play.qobuz.com/label links without an account, so I assume that you have checked them as logged in user.

I already did some changes locally, so please don't push any new commits for now, thanks.

@Lioncat6
Copy link
Copy Markdown
Author

@kellnerd From what I can tell, the www subdomain is the best, but qobuz does seem to like making their URLs as confusing as possible... I have made some more recent descoveries on that ticket that have changed my mind a bit...

open.qobuz.com links are the only ones that are functional without a slug or region, but are themselves region restricted

www.qobuz links work regardless of the user's region, but the region codes do matter in very specific circumstances:
https://www.qobuz.com/jp-ja/album/-/u483rtr3vmcrb <- works
https://www.qobuz.com/us-en/album/-/u483rtr3vmcrb <- does not
slugs on www.qobuz links are simply cosmetic and are should always be cleaned up to a hypen (-) as qobuz does themselves for track titles comprised of all non-latin characters.

Copy link
Copy Markdown
Owner

@kellnerd kellnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed a few additional commits, the provider should be more or less ready for the initial release now. Most importantly, the provider is now extracting track artists (first performer with ID, all others name only) and catches 404 errors (which gives a more meaningful error for e.g. JP-exclusive releases).

Two open questions remain:

  1. Should we remove HARMONY_QOBUZ_AUTH_TOKEN again or would it be useful to keep this? In that case I want to at least document that it is usually not needed.
  2. I've kept constructUrl as is for now since we don't have the locale and the slug to construct www URLs in all cases. Should we still attempt to do this at least for release URLs whenever possible? Instead of or in addition to open.qobuz URLs?

For me the API responses seem to always assume fr-fr as the locale (even for my requests from DE), so the release URL input is currently the only reliable source for localized Qobuz (release) URLs. I have code to construct www release URLs from the extracted URL region and language (if available) on a separate branch at b901643.
If we want to follow that path, we could even use the region from other providers or Harmony's region input.
A matching language to complete the locale could be inferred from the region in that case. Qobuz has only 26 available regions, so that would be manageable.
We could use the release locale for the artist and label URLs as well, but we don't always have the slug available, so I tend to keep those as open/play.qobuz URLs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request provider Metadata provider

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Qobuz implementation

2 participants