mirror of
https://github.com/Horizontal42/Sort_YM.git
synced 2026-11-10 16:52:00 +03:00
Медленная/нестабильная сеть до api.music.yandex.net роняла весь процесс при первом же таймауте (5с по умолчанию у библиотеки). Добавлен with_retries с экспоненциальной паузой на всех сетевых точках входа (fetch, language, genres, apply, client.init), таймаут запроса поднят до 20с (настраивается в config.toml). Заодно поправлен скрытый баг: language.py раньше кэшировал таймаут как "текста нет" навсегда - теперь только настоящий NotFoundError трактуется так.
71 lines
2.2 KiB
Python
71 lines
2.2 KiB
Python
from __future__ import annotations
|
|
|
|
import time
|
|
|
|
from yandex_music import Client, Playlist
|
|
|
|
from .ymclient import with_retries
|
|
|
|
|
|
def _existing_playlists_by_title(client: Client) -> dict[str, Playlist]:
|
|
playlists = with_retries(lambda: client.users_playlists_list())
|
|
return {p.title: p for p in playlists if p.title}
|
|
|
|
|
|
def _existing_track_ids(client: Client, playlist: Playlist) -> set[str]:
|
|
full = with_retries(lambda: client.users_playlists(playlist.kind))
|
|
if full is None:
|
|
return set()
|
|
return {t.track_id for t in full.tracks}
|
|
|
|
|
|
def _get_or_create_playlist(client: Client, title: str, existing: dict[str, Playlist]) -> Playlist:
|
|
if title in existing:
|
|
return existing[title]
|
|
playlist = with_retries(lambda: client.users_playlists_create(title, visibility="private"))
|
|
existing[title] = playlist
|
|
return playlist
|
|
|
|
|
|
def apply_classification(
|
|
client: Client,
|
|
rows: list[dict],
|
|
delay: float,
|
|
limit: int | None = None,
|
|
) -> None:
|
|
if limit is not None:
|
|
rows = rows[:limit]
|
|
|
|
existing_playlists = _existing_playlists_by_title(client)
|
|
|
|
by_playlist: dict[str, list[dict]] = {}
|
|
for row in rows:
|
|
by_playlist.setdefault(row["target_playlist"], []).append(row)
|
|
|
|
for title, playlist_rows in by_playlist.items():
|
|
playlist = _get_or_create_playlist(client, title, existing_playlists)
|
|
already = _existing_track_ids(client, playlist)
|
|
revision = playlist.revision or 1
|
|
|
|
added = 0
|
|
for row in playlist_rows:
|
|
track_key = f"{row['id']}:{row['album_id']}" if row["album_id"] else str(row["id"])
|
|
if track_key in already:
|
|
continue
|
|
|
|
updated = with_retries(
|
|
lambda: client.users_playlists_insert_track(
|
|
playlist.kind,
|
|
row["id"],
|
|
row["album_id"],
|
|
revision=revision,
|
|
)
|
|
)
|
|
if updated is not None and updated.revision is not None:
|
|
revision = updated.revision
|
|
already.add(track_key)
|
|
added += 1
|
|
time.sleep(delay)
|
|
|
|
skipped = len(playlist_rows) - added
|
|
print(f"{title}: добавлено {added}, уже было {skipped}")
|