/
/
# What does this implement/fix? <!-- Quick description and explanation of changes. --> Migrates the Tidal provider's catalog, search, library and favourites operations from the unofficial api.tidal.com/v1 to the official openapi.tidal.com/v2 JSON:API. Playback, lyrics, mixes and playlist operations stay on the unofficial API: official playback is DRM-only, official mixes need a scope our client type cannot obtain, and playlist reads/writes deliberately share the v1 listing so track positions map onto deletes consistently (the official items relationship orders and heals ids differently, which could delete the wrong track; it also caps at 20 items per request, making large playlists ~10x slower to load). Highlights: - **Survives Tidal's track-id churn**. Tidal constantly deletes and re-adds tracks under new ids. Adding such a track to favourites used to silently do nothing; it now resolves the live id via ISRC and actually adds it (and reports failure if it cannot). For playlist additions, if a track's id is already known to be dead from an earlier heal, the replacement id is sent instead. - **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. Note for reviewers: existing installs are not force-logged-out by the client switch. Tidal's token endpoint accepts refresh tokens issued to the previous client when presented with the new client credentials; verified live with a real pre-migration token. The breaking-change label covers the residual risk of a re-link being needed. **Related issue (if applicable):** - related issue <link to issue> ## Types of changes <!-- Tick exactly one box. CI (.github/workflows/pr-labels.yaml) derives the label from the ticked box and applies it automatically; the release-notes generator uses that same label to slot this change into the next release notes. --> - [ ] 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` - [x] 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 - [x] The code change is tested and works locally. - [x] `pre-commit run --all-files` passes. - [x] `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. - [x] I have read and complied with the project's [AI Policy](https://github.com/music-assistant/.github/blob/main/AI_POLICY.md) for any AI-assisted contributions. - [ ] I have raised a PR against the documentation repository targeting the main or beta branch as appropriate. --------- Co-authored-by: OzGav <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: MarvinSchenkel <[email protected]>