When enabled, existing path components are reused even if Tidal returns
different casing. This avoids creating separate paths on case-sensitive
filesystems that would conflict later when moved to case-insensitive systems.
For example, if "FooBar" already exists and the API returns "foobar",
downloads will continue under "FooBar".
Co-authored-by: Piotr Karbowski <git.throwaway941@simplelogin.com>
* fix: handle null/missing fields in Video API responses
Tidal's API returns some Video objects (lyric/visualiser videos on
artist pages) with fields that don't match the current strict models:
- `imageId` can be null instead of a string
- The nested `album` object can be present but missing `id`, `title`,
and `cover`
These validation failures cause the entire `ArtistVideosItems` page
to be rejected by Pydantic before any video can be parsed, resulting
in 0 downloads when targeting an artist with `--videos`.
A second independent bug causes an `AttributeError` on every video:
the default template `{album.artist}/{album.title}/{item.title}` is
shared with videos, but many videos have no album. When `album=None`
is passed to `format_template`, Python's `str.format()` evaluates
`None.artist` and raises `AttributeError: 'NoneType' object has no
attribute 'artist'`, which is caught and printed as an error for
every single video.
Fix:
- `resources.py`: make `Video.imageId` and `Video.Album.{id,title,
cover}` optional so incomplete API responses pass validation
- `format.py`: give `AlbumTemplate` field defaults so it can be
instantiated empty; use `AlbumTemplate()` as fallback instead of
`None` when no album is present, so `{album.*}` tokens render as
empty strings rather than raising AttributeError
- `download/__init__.py`: guard `video.album.id` accesses against
`None` (now possible after the model fix) in both video code paths
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: add tests for Video model null fields and AlbumTemplate fallback
Covers the two bugs fixed in the previous commit:
- Video model accepts null/missing imageId and partial album objects
- format_template does not raise AttributeError when album is None
and the template references {album.*} tokens
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* add `get_album_review` endpoint
* add `metadata.album_review` config option
* add comment to `add_track_metadata`
* move `AlbumReview` model to its own file and clean up imports
* fix API endpoint for fetching album reviews
* add normalized_text method to AlbumReview model for text processing
* add unit test for `normalize_review_text` function and refactor `AlbumReview` model
* add `album_review` to metadata
* update comment
* add comment