Skip to content

Migrate the Tidal provider to the official API where possible.#4875

Open
jozefKruszynski wants to merge 11 commits into
devfrom
tidal-openapi-migration
Open

Migrate the Tidal provider to the official API where possible.#4875
jozefKruszynski wants to merge 11 commits into
devfrom
tidal-openapi-migration

Conversation

@jozefKruszynski

Copy link
Copy Markdown
Contributor

What does this implement/fix?

Migrates the Tidal provider's catalog, search, library, favourites and playlist
operations from the unofficial api.tidal.com/v1 to the official
openapi.tidal.com/v2 JSON:API. Playback, lyrics and mixes stay on the
unofficial API (official playback is DRM-only, mixes are deprecated/404).

Highlights:

  • Survives Tidal's track-id churn. Tidal constantly deletes and re-adds
    tracks under new ids. Adding such a track to a playlist or favourites used to
    silently do nothing; it now resolves the live id via ISRC and actually adds it.
  • Self-healing library. Playing or adding a churned track rewrites its stored
    id from dead to live, so the library corrects itself as you use it.
  • Richer metadata. BPM, musical key, genres, artist biographies, external
    links, track version and finer-grained popularity now populate.
  • Generated JSON:API models from a vendored OpenAPI spec, no new dependency.

Models/spec and captured response fixtures account for the bulk of the diff.
All Tidal provider tests pass; mypy and pre-commit clean.

Related issue (if applicable):

  • related issue

Types of changes

  • Bugfix (non-breaking change which fixes an issue) — bugfix
  • New feature (non-breaking change which adds functionality) — new-feature
  • Enhancement to an existing feature — enhancement
  • New music/player/metadata/plugin provider — new-provider
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) — breaking-change
  • Refactor (no behaviour change) — refactor
  • Documentation only — documentation
  • Maintenance / chore — maintenance
  • CI / workflow change — ci
  • Dependencies bump — dependencies

Checklist

  • The code change is tested and works locally.
  • pre-commit run --all-files passes.
  • pytest passes, and tests have been added/updated under tests/ where applicable.
  • For changes to shared models, the companion PR in music-assistant/models is linked.
  • For changes affecting the UI, the companion PR in music-assistant/frontend is linked.
  • I have read and complied with the project's AI Policy for any AI-assisted contributions.
  • I have raised a PR against the documentation repository targeting the main or beta branch as appropriate.

Copilot AI review requested due to automatic review settings July 20, 2026 15:27
@github-actions

Copy link
Copy Markdown
Contributor

🔒 Dependency Security Report

✅ No dependency changes detected in this PR.

@codspeed-hq

codspeed-hq Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 11 untouched benchmarks
⏩ 7 skipped benchmarks1


Comparing tidal-openapi-migration (cd76359) with dev (eea9131)2

Open in CodSpeed

Footnotes

  1. 7 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on dev (240feab) during the generation of this report, so eea9131 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates large parts of the Tidal provider (catalog/search/library/favorites/playlists) from the unofficial api.tidal.com/v1 API to the official openapi.tidal.com/v2 JSON:API, adds parsers/models for the new payloads, and introduces track-id “churn” healing via ISRC-based resolution and cached redirects.

Changes:

  • Add JSON:API support to the Tidal API client (read/write + cursor pagination) and new v2 parsers/fixtures/tests.
  • Implement stale-track-id resolution (resolve_live_track_id) and best-effort library mapping healing.
  • Switch playlist + library write operations (add/remove) to official JSON:API relationship endpoints.

Reviewed changes

Copilot reviewed 35 out of 40 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/providers/tidal/test_streaming.py Updates streaming tests to use the new resolve_live_track_id fallback instead of ISRC lookup in streaming manager.
tests/providers/tidal/test_provider.py Adds tests for cached redirect + live-id resolution + mapping heal scheduling behavior.
tests/providers/tidal/test_playlist.py Rewrites playlist create/add/remove tests for JSON:API write endpoints and healing behavior.
tests/providers/tidal/test_parsers_v2.py Adds comprehensive tests for new v2 JSON:API parsers (track/album/artist/playlist, images, durations, credits).
tests/providers/tidal/test_media.py Updates media manager tests for official search and relationship endpoints; keeps lyrics on unofficial API.
tests/providers/tidal/test_media_extended.py Updates extended media tests for v2 similar-tracks/search-empty behavior.
tests/providers/tidal/test_library.py Rewrites library manager tests to use official user collections + healing on add-track.
tests/providers/tidal/test_jsonapi.py Adds unit tests for JsonApiDocument relationship resolution and cursor parsing.
tests/providers/tidal/test_api_client.py Adds tests for official/unofficial param scoping, JSON:API writes, and cursor pagination.
tests/providers/tidal/fixtures/v2/track.json Adds captured official v2 track document fixture.
tests/providers/tidal/fixtures/v2/track_credits.json Adds captured official v2 track-with-credits document fixture.
tests/providers/tidal/fixtures/v2/artist.json Adds captured official v2 artist (bio/profileArt) fixture.
tests/providers/tidal/fixtures/v2/artist_wimplink.json Adds captured fixture validating stripping of [wimpLink] biography markup.
tests/providers/tidal/fixtures/v2/album.json Adds captured official v2 album document fixture.
tests/providers/tidal/fixtures/v2/album_items.json Adds captured album relationship/items fixture to validate ordering metadata parsing.
scripts/tidal_openapi/README.md Documents the vendored spec + model generation workflow for official API TypedDicts.
scripts/tidal_openapi/generate_models.py Adds script to generate TypedDict models from vendored OpenAPI spec (via uvx datamodel-codegen).
scripts/tidal_openapi/init.py Marks scripts.tidal_openapi as a module.
scripts/lint_baselines/private_methods_not_last.txt Updates baseline after moving private methods to the end in tidal provider/media.
pyproject.toml Excludes Tidal fixtures from codespell.
music_assistant/providers/tidal/streaming.py Switches stream-details fallback to provider-level live-id resolution and removes streaming-local ISRC lookup.
music_assistant/providers/tidal/provider.py Adds cached redirect + ISRC-based live-id resolution + mapping healing; adds similar-artists feature.
music_assistant/providers/tidal/playlist.py Migrates playlist create/add/remove to official JSON:API writes; adds stale-id healing retry logic.
music_assistant/providers/tidal/parsers_v2.py Adds new official JSON:API parsers for artist/album/track/playlist + helpers (images, durations, popularity, links).
music_assistant/providers/tidal/media.py Migrates search + several “relationship” reads to official JSON:API; keeps mixes/lyrics on unofficial endpoints.
music_assistant/providers/tidal/library.py Migrates library CRUD to official user collections; adds track-add healing retry.
music_assistant/providers/tidal/jsonapi.py Introduces JsonApiDocument helper for included-resource indexing, relationship resolution, and cursor parsing.
music_assistant/providers/tidal/constants.py Adds JSON:API content-type constant and removes legacy favorites endpoint constants.
music_assistant/providers/tidal/api_client.py Adds JSON:API read/write helpers and cursor pagination; scopes sessionId to unofficial API only.
music_assistant/providers/tidal/_openapi_models.py Adds generated TypedDicts for selected official API attribute schemas.

Comment thread music_assistant/providers/tidal/playlist.py
Comment thread music_assistant/providers/tidal/library.py
Comment thread music_assistant/providers/tidal/media.py
Comment thread music_assistant/providers/tidal/playlist.py Outdated
Copilot AI review requested due to automatic review settings July 20, 2026 15:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 35 out of 40 changed files in this pull request and generated 2 comments.

body = {"data": [{"type": resource_type, "id": item_id}]}
await self.api.write_jsonapi(method, f"{resource_name}/me/relationships/items", body)
return True
except ClientError, MediaNotFoundError, ResourceTemporarilyUnavailable:
Comment on lines +40 to +45
playlist = parse_playlist_v2(self.provider, doc, doc.data)
# The create response doesn't include the "owners" relationship, so
# parse_playlist_v2 can't infer editability from it. The authenticated
# user is by definition the owner of a playlist they just created.
playlist.is_editable = True
playlist.owner = (
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants