report/apply/digest can now point at any Yandex Music playlist via a
share link instead of only the account's likes. Fetches the playlist's
tracks and artist genres straight into memory (no disk cache, nothing
persisted) and feeds them through the existing build_rows/render_digest/
apply_classification pipeline. apply supports --label to keep a foreign
playlist's tracks in separate genre playlists instead of merging them
into your own. Closes a gap where UnauthorizedError went uncaught anywhere.
Playlist deletes are positional (from/to index), so a network error
during dedupe just aborts that playlist instead of retrying blindly -
indices may have already shifted. Re-running dedupe is safe since it
recomputes ranges from the live playlist state each time.
client.users_playlists(kind) silently returns None on any response-parse
failure, not just when the playlist genuinely doesn't exist - this isn't
an exception, so with_retries doesn't catch it. Previously this was
treated as "playlist is empty", which risked re-inserting everything on
top of existing tracks. Now retry with backoff and raise instead of
guessing.
track_key compared "id:albumId" against playlist track_id, but Yandex
never echoes albumId back for playlist entries (always None on read) -
so the existing-tracks check could never match anything, and every
apply run re-inserted the whole account on top of itself.
apply --yes падал целиком на первом же самозалитом/пиратском треке без
альбома (105 из 1984) - Яндекс отвечает BadRequestError (wrong-json),
т.к. albumId обязателен, а with_retries лечил это как временный сетевой
сбой и вслепую повторял заведомо безнадёжный запрос 4 раза. Теперь
BadRequestError (как и NotFoundError) не ретраится нигде - это
окончательный ответ сервера, а не таймаут. Треки без album_id
пропускаются проактивно с понятным сообщением, а неожиданный
BadRequestError на отдельном треке больше не прерывает весь прогон -
пропускается со счётчиком, остальные треки обрабатываются дальше.
users_playlists_insert_track и users_playlists_create - операции записи:
таймаут не значит, что запрос не дошёл до сервера. Прошлый фикс слепо
повторял такой вызов при NetworkError, и если сервер уже применил
вставку (а ответ просто потерялся), трек добавлялся в плейлист второй
раз. Теперь при сетевой ошибке сначала перепроверяется фактическое
состояние плейлиста/списка плейлистов, и повтор происходит только если
трек/плейлист там правда ещё отсутствует.