diff --git a/yandex_music/__init__.py b/yandex_music/__init__.py index 39bc7d6..3705242 100644 --- a/yandex_music/__init__.py +++ b/yandex_music/__init__.py @@ -62,6 +62,8 @@ from .shot.shot_event import ShotEvent from .tracks_list import TracksList from .track.major import Major from .track.licence_text_part import LicenceTextPart +from .track.track_lyrics import TrackLyrics +from .track.lyrics_major import LyricsMajor from .track.poetry_lover_match import PoetryLoverMatch from .track.meta_data import MetaData from .track.normalization import Normalization @@ -260,4 +262,5 @@ __all__ = [ 'Queue', 'QueueItem', 'Deprecation', + 'TrackLyrics', ] diff --git a/yandex_music/client.py b/yandex_music/client.py index d9afe81..a9c5f8e 100644 --- a/yandex_music/client.py +++ b/yandex_music/client.py @@ -28,6 +28,7 @@ from yandex_music import ( Status, Suggestions, SimilarTracks, + TrackLyrics, Track, TracksList, UserSettings, @@ -45,6 +46,7 @@ from yandex_music import ( from yandex_music.exceptions import BadRequestError from yandex_music.utils.difference import Difference from yandex_music.utils.request import Request +from yandex_music.utils.sign_request import get_sign_request de_list = { 'artist': Artist.de_list, @@ -561,6 +563,40 @@ class Client(YandexMusicObject): return Supplement.de_json(result, self) + @log + def tracks_lyrics( + self, + track_id: Union[str, int], + format: str = 'TEXT', + **kwargs, + ) -> Optional[TrackLyrics]: + """Получение текста трека. + + Args: + track_id (:obj:`str` | :obj:`int`): Уникальный идентификатор трека. + format (:obj:`str`): Формат текста. + **kwargs (:obj:`dict`, optional): Произвольные аргументы (будут переданы в запрос). + + Returns: + TODO + + Raises: + :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки. + """ + + url = f'{self.base_url}/tracks/{track_id}/lyrics' + + sign = get_sign_request(track_id) + params = { + 'format': format, + 'timeStamp': sign.timestamp, + 'sign': sign.value, + } + + result = self._request.get(url, params=params, **kwargs) + + return TrackLyrics.de_json(result, self) + @log def tracks_similar(self, track_id: Union[str, int], *args, **kwargs) -> Optional[SimilarTracks]: """Получение похожих треков. @@ -2408,6 +2444,8 @@ class Client(YandexMusicObject): tracksDownloadInfo = tracks_download_info #: Псевдоним для :attr:`track_supplement` trackSupplement = track_supplement + #: Псевдоним для :attr:`tracks_lyrics` + tracksLyrics = tracks_lyrics #: Псевдоним для :attr:`tracks_similar` tracksSimilar = tracks_similar #: Псевдоним для :attr:`play_audio` diff --git a/yandex_music/client_async.py b/yandex_music/client_async.py index dda5f6f..37d48a3 100644 --- a/yandex_music/client_async.py +++ b/yandex_music/client_async.py @@ -32,6 +32,7 @@ from yandex_music import ( Status, Suggestions, SimilarTracks, + TrackLyrics, Track, TracksList, UserSettings, @@ -49,6 +50,7 @@ from yandex_music import ( from yandex_music.exceptions import BadRequestError from yandex_music.utils.difference import Difference from yandex_music.utils.request_async import Request +from yandex_music.utils.sign_request import get_sign_request de_list = { 'artist': Artist.de_list, @@ -567,6 +569,40 @@ class ClientAsync(YandexMusicObject): return Supplement.de_json(result, self) + @log + async def tracks_lyrics( + self, + track_id: Union[str, int], + format: str = 'TEXT', + **kwargs, + ) -> Optional[TrackLyrics]: + """Получение текста трека. + + Args: + track_id (:obj:`str` | :obj:`int`): Уникальный идентификатор трека. + format (:obj:`str`): Формат текста. + **kwargs (:obj:`dict`, optional): Произвольные аргументы (будут переданы в запрос). + + Returns: + TODO + + Raises: + :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки. + """ + + url = f'{self.base_url}/tracks/{track_id}/lyrics' + + sign = get_sign_request(track_id) + params = { + 'format': format, + 'timeStamp': sign.timestamp, + 'sign': sign.value, + } + + result = await self._request.get(url, params=params, **kwargs) + + return TrackLyrics.de_json(result, self) + @log async def tracks_similar(self, track_id: Union[str, int], *args, **kwargs) -> Optional[SimilarTracks]: """Получение похожих треков. @@ -2426,6 +2462,8 @@ class ClientAsync(YandexMusicObject): tracksDownloadInfo = tracks_download_info #: Псевдоним для :attr:`track_supplement` trackSupplement = track_supplement + #: Псевдоним для :attr:`tracks_lyrics` + tracksLyrics = tracks_lyrics #: Псевдоним для :attr:`tracks_similar` tracksSimilar = tracks_similar #: Псевдоним для :attr:`play_audio` diff --git a/yandex_music/track/lyrics_major.py b/yandex_music/track/lyrics_major.py new file mode 100644 index 0000000..8cafe71 --- /dev/null +++ b/yandex_music/track/lyrics_major.py @@ -0,0 +1,30 @@ +from typing import TYPE_CHECKING, Optional + +from yandex_music import YandexMusicObject +from yandex_music.utils import model + + +if TYPE_CHECKING: + from yandex_music import Client + + +@model +class LyricsMajor(YandexMusicObject): + """TODO""" + + id: int + name: str + pretty_name: str + client: Optional['Client'] = None + + def __post_init__(self): + self._id_attrs = (self.id,) + + @classmethod + def de_json(cls, data: dict, client: 'Client') -> Optional['LyricsMajor']: + if not data: + return None + + data = super(LyricsMajor, cls).de_json(data, client) + + return cls(client=client, **data) diff --git a/yandex_music/track/track_lyrics.py b/yandex_music/track/track_lyrics.py new file mode 100644 index 0000000..13882f4 --- /dev/null +++ b/yandex_music/track/track_lyrics.py @@ -0,0 +1,39 @@ +from typing import TYPE_CHECKING, List, Optional + +from yandex_music import YandexMusicObject +from yandex_music.utils import model + + +if TYPE_CHECKING: + from yandex_music import Client, LyricsMajor + + +@model +class TrackLyrics(YandexMusicObject): + """TODO""" + + download_url: str + lyric_id: int + external_lyric_id: str + writers: List[str] + major: 'LyricsMajor' + client: Optional['Client'] = None + + def __post_init__(self): + self._id_attrs = ( + self.lyric_id, + self.external_lyric_id, + ) + + @classmethod + def de_json(cls, data: dict, client: 'Client') -> Optional['TrackLyrics']: + """TODO""" + if not data: + return None + + data = super(TrackLyrics, cls).de_json(data, client) + from yandex_music import LyricsMajor + + data['major'] = LyricsMajor.de_json(data.get('major'), client) + + return cls(client=client, **data)