* 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>
* feat: Add `--skip-errors` flag to skip unavailable items during download
* feat: skip-error handling for unavailable items in albums, artists & mixes; fix some missing template variables
* fixes#267
* refactor variable name in _clean_segment function for clarity
* Add error handling documentation for format_template function
* Add error handling for album template formatting in download_callback
* adding flag for download lyrics
* adding sum debug info
* adding configuration part
* Update config.example.toml
* refactor: move lyrics to utility and apply code review feedback
* refactor: optimize lyrics download and apply code review feedback
- Pass album_items directly to lyrics function to avoid redundant API calls
- Remove unused Path import from api.py
- Remove duplicate debug logging already covered elsewhere
- Use last_album_items reference instead of fetching data again
- Move lyrics download logic to separate utility function in core.utils.lyrics
- Keep lyrics configuration only in docs/config.example.toml without modifying other settings
This optimization reduces API calls by reusing already fetched album items data instead of making new requests for lyrics download.
* rename `VideoQuality` to `StreamVideoQuality`
* remove bad logic from predicting video quality
* print info when skipping video
* bump to 3.1.1 alpha
* strip formatted parts of path
* handle "None" explicit attribute
* add explicit field to items
* add explicit to template example
* add docs for explicit
* add `dolby` field to items
* add `dolby` docs
* 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
* added `update_mtime` to config
* update mtime on files
* update only existing files that wont be redownloaded
* allow updating mtime if `DOWNLOAD_VIDEO` is False
* add custom message for skipped videos