artist.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. from typing import TYPE_CHECKING, Any, List, Optional, Union
  2. from yandex_music import YandexMusicModel
  3. from yandex_music.utils import model
  4. if TYPE_CHECKING:
  5. from yandex_music import (
  6. ArtistAlbums,
  7. ArtistTracks,
  8. ClientType,
  9. Counts,
  10. Cover,
  11. Description,
  12. JSONType,
  13. Link,
  14. Ratings,
  15. Track,
  16. )
  17. @model
  18. class Artist(YandexMusicModel):
  19. """Класс, представляющий исполнителя.
  20. Attributes:
  21. id (:obj:`int`): Уникальный идентификатор.
  22. error (:obj:`str`, optional): Сообщение об ошибке с объяснением почему не вернуло исполнителя.
  23. reason (:obj:`str`, optional): Причина отсутствия исполнителя (сообщение об ошибке).
  24. name (:obj:`str`, optional): Название.
  25. cover (:obj:`yandex_music.Cover`, optional): Обложка.
  26. various (:obj:`bool`, optional): TODO.
  27. composer (:obj:`bool`, optional): TODO.
  28. genres (:obj:`list` из :obj:`str`, optional): Жанры.
  29. og_image (:obj:`str`, optional): Ссылка на изображение для Open Graph.
  30. op_image (:obj:`str`, optional): Ссылка на изображение обложки. Используется когда не указано поле cover.
  31. no_pictures_from_search: TODO.
  32. counts (:obj:`yandex_music.Counts`, optional): Счётчики.
  33. available (:obj:`bool`, optional): Доступен ли для прослушивания.
  34. ratings (:obj:`yandex_music.Ratings`, optional): Рейтинги.
  35. links (:obj:`list` из :obj:`yandex_music.Link`, optional): Ссылки на ресурсы исполнителя.
  36. tickets_available (:obj:`bool`, optional): Имеются ли в продаже билеты на концерт.
  37. likes_count (:obj:`int`, optional): Количество лайков.
  38. popular_tracks (:obj:`list` из :obj:`yandex_music.Track`, optional): Популярные треки.
  39. regions (:obj:`list` из :obj:`str`, optional): Регион TODO.
  40. decomposed (:obj:`list` из :obj:`str` и :obj:`yandex_music.Artist`, optional): Декомпозиция всех исполнителей.
  41. Лист, где чередуется разделитель и артист. Фиты и прочее.
  42. full_names: TODO.
  43. hand_made_description (:obj:`str`, optional): Описание от Яндекс TODO.
  44. description (:obj:`yandex_music.Description`, optional): Описание.
  45. countries (:obj:`list` из :obj:`str`, optional): Страны.
  46. en_wikipedia_link (:obj:`str`, optional): Адрес страницы на wikipedia.org.
  47. db_aliases (:obj:`list` из :obj:`str`, optional): Другие названия. Как правило названия на разных языках.
  48. aliases: TODO.
  49. init_date (:obj:`str`, optional): Дата начала в формате YYYY-MM-DD или YYYY.
  50. end_date (:obj:`str`, optional): Дата окончания в формате YYYY-MM-DD или YYYY.
  51. ya_money_id (:obj:`str`): Номер кошеляка Яндекс.Деньги TODO.
  52. client (:obj:`yandex_music.Client`): Клиент Yandex Music.
  53. """
  54. id: int
  55. error: Optional[str] = None
  56. reason: Optional[str] = None
  57. name: Optional[str] = None
  58. cover: Optional['Cover'] = None
  59. various: Optional[bool] = None
  60. composer: Optional[bool] = None
  61. genres: Optional[List[str]] = None
  62. og_image: Optional[str] = None
  63. op_image: Optional[str] = None
  64. no_pictures_from_search: Any = None
  65. counts: Optional['Counts'] = None
  66. available: Optional[bool] = None
  67. ratings: Optional['Ratings'] = None
  68. links: Optional[List['Link']] = None
  69. tickets_available: Optional[bool] = None
  70. likes_count: Optional[int] = None
  71. popular_tracks: Optional[List['Track']] = None
  72. regions: Optional[List[str]] = None
  73. decomposed: Optional[List[Union[str, 'Artist']]] = None
  74. full_names: Any = None
  75. hand_made_description: Optional[str] = None
  76. description: Optional['Description'] = None
  77. countries: Optional[List[str]] = None
  78. en_wikipedia_link: Optional[str] = None
  79. db_aliases: Optional[List[str]] = None
  80. aliases: Any = None
  81. init_date: Optional[str] = None
  82. end_date: Optional[str] = None
  83. ya_money_id: Optional[str] = None
  84. client: Optional['ClientType'] = None
  85. def __post_init__(self) -> None:
  86. self._id_attrs = (self.id, self.name, self.cover)
  87. def get_op_image_url(self, size: str = '200x200') -> str:
  88. """Возвращает URL OP обложки.
  89. Args:
  90. size (:obj:`str`, optional): Размер обложки.
  91. Returns:
  92. :obj:`str`: URL обложки.
  93. """
  94. assert isinstance(self.op_image, str)
  95. return f'https://{self.op_image.replace("%%", size)}'
  96. def get_og_image_url(self, size: str = '200x200') -> str:
  97. """Возвращает URL OG обложки.
  98. Args:
  99. size (:obj:`str`, optional): Размер обложки.
  100. Returns:
  101. :obj:`str`: URL обложки.
  102. """
  103. assert isinstance(self.og_image, str)
  104. return f'https://{self.og_image.replace("%%", size)}'
  105. def download_og_image(self, filename: str, size: str = '200x200') -> None:
  106. """Загрузка изображения для Open Graph.
  107. Args:
  108. filename (:obj:`str`): Путь для сохранения файла с названием и расширением.
  109. size (:obj:`str`, optional): Размер обложки.
  110. """
  111. assert self.valid_client(self.client)
  112. self.client.request.download(self.get_og_image_url(size), filename)
  113. async def download_og_image_async(self, filename: str, size: str = '200x200') -> None:
  114. """Загрузка изображения для Open Graph.
  115. Args:
  116. filename (:obj:`str`): Путь для сохранения файла с названием и расширением.
  117. size (:obj:`str`, optional): Размер обложки.
  118. """
  119. assert self.valid_async_client(self.client)
  120. await self.client.request.download(self.get_og_image_url(size), filename)
  121. def download_op_image(self, filename: str, size: str = '200x200') -> None:
  122. """Загрузка обложки.
  123. Notes:
  124. Используйте это только когда нет self.cover!
  125. Args:
  126. filename (:obj:`str`): Путь для сохранения файла с названием и расширением.
  127. size (:obj:`str`, optional): Размер обложки.
  128. """
  129. assert self.valid_client(self.client)
  130. self.client.request.download(self.get_op_image_url(size), filename)
  131. async def download_op_image_async(self, filename: str, size: str = '200x200') -> None:
  132. """Загрузка обложки.
  133. Notes:
  134. Используйте это только когда нет self.cover!
  135. Args:
  136. filename (:obj:`str`): Путь для сохранения файла с названием и расширением.
  137. size (:obj:`str`, optional): Размер обложки.
  138. """
  139. assert self.valid_async_client(self.client)
  140. await self.client.request.download(self.get_op_image_url(size), filename)
  141. def download_og_image_bytes(self, size: str = '200x200') -> bytes:
  142. """Загрузка изображения для Open Graph и возврат в виде байтов.
  143. Args:
  144. size (:obj:`str`, optional): Размер обложки.
  145. Returns:
  146. :obj:`bytes`: Изображение в виде байтов.
  147. """
  148. assert self.valid_client(self.client)
  149. return self.client.request.retrieve(self.get_og_image_url(size))
  150. async def download_og_image_bytes_async(self, size: str = '200x200') -> bytes:
  151. """Загрузка изображения для Open Graph и возврат в виде байтов.
  152. Args:
  153. size (:obj:`str`, optional): Размер обложки.
  154. Returns:
  155. :obj:`bytes`: Изображение в виде байтов.
  156. """
  157. assert self.valid_async_client(self.client)
  158. return await self.client.request.retrieve(self.get_og_image_url(size))
  159. def download_op_image_bytes(self, size: str = '200x200') -> bytes:
  160. """Загрузка обложки и возврат в виде байтов.
  161. Notes:
  162. Используйте это только когда нет self.cover!
  163. Args:
  164. size (:obj:`str`, optional): Размер обложки.
  165. Returns:
  166. :obj:`bytes`: Обложка в виде байтов.
  167. """
  168. assert self.valid_client(self.client)
  169. return self.client.request.retrieve(self.get_op_image_url(size))
  170. async def download_op_image_bytes_async(self, size: str = '200x200') -> bytes:
  171. """Загрузка обложки и возврат в виде байтов.
  172. Notes:
  173. Используйте это только когда нет self.cover!
  174. Args:
  175. size (:obj:`str`, optional): Размер обложки.
  176. Returns:
  177. :obj:`bytes`: Обложка в виде байтов.
  178. """
  179. assert self.valid_async_client(self.client)
  180. return await self.client.request.retrieve(self.get_op_image_url(size))
  181. def like(self, *args: Any, **kwargs: Any) -> bool:
  182. """Сокращение для::
  183. client.users_likes_artists_add(artist.id, user.id *args, **kwargs)
  184. """
  185. assert self.valid_client(self.client)
  186. return self.client.users_likes_artists_add(self.id, self.client.account_uid, *args, **kwargs)
  187. async def like_async(self, *args: Any, **kwargs: Any) -> bool:
  188. """Сокращение для::
  189. await client.users_likes_artists_add(artist.id, user.id *args, **kwargs)
  190. """
  191. assert self.valid_async_client(self.client)
  192. return await self.client.users_likes_artists_add(self.id, self.client.account_uid, *args, **kwargs)
  193. def dislike(self, *args: Any, **kwargs: Any) -> bool:
  194. """Сокращение для::
  195. client.users_likes_artists_remove(artist.id, user.id *args, **kwargs)
  196. """
  197. assert self.valid_client(self.client)
  198. return self.client.users_likes_artists_remove(self.id, self.client.account_uid, *args, **kwargs)
  199. async def dislike_async(self, *args: Any, **kwargs: Any) -> bool:
  200. """Сокращение для::
  201. await client.users_likes_artists_remove(artist.id, user.id *args, **kwargs)
  202. """
  203. assert self.valid_async_client(self.client)
  204. return await self.client.users_likes_artists_remove(self.id, self.client.account_uid, *args, **kwargs)
  205. def get_tracks(self, page: int = 0, page_size: int = 20, *args: Any, **kwargs: Any) -> Optional['ArtistTracks']:
  206. """Сокращение для::
  207. client.artists_tracks(artist.id, page, page_size, *args, **kwargs)
  208. """
  209. assert self.valid_client(self.client)
  210. return self.client.artists_tracks(self.id, page, page_size, *args, **kwargs)
  211. async def get_tracks_async(
  212. self, page: int = 0, page_size: int = 20, *args: Any, **kwargs: Any
  213. ) -> Optional['ArtistTracks']:
  214. """Сокращение для::
  215. await client.artists_tracks(artist.id, page, page_size, *args, **kwargs)
  216. """
  217. assert self.valid_async_client(self.client)
  218. return await self.client.artists_tracks(self.id, page, page_size, *args, **kwargs)
  219. def get_albums(
  220. self, page: int = 0, page_size: int = 20, sort_by: str = 'year', *args: Any, **kwargs: Any
  221. ) -> Optional['ArtistAlbums']:
  222. """Сокращение для::
  223. client.artists_direct_albums(artist.id, page, page_size, sort_by, *args, **kwargs)
  224. """
  225. assert self.valid_client(self.client)
  226. return self.client.artists_direct_albums(self.id, page, page_size, sort_by, *args, **kwargs)
  227. async def get_albums_async(
  228. self, page: int = 0, page_size: int = 20, sort_by: str = 'year', *args: Any, **kwargs: Any
  229. ) -> Optional['ArtistAlbums']:
  230. """Сокращение для::
  231. await client.artists_direct_albums(artist.id, page, page_size, sort_by, *args, **kwargs)
  232. """
  233. assert self.valid_async_client(self.client)
  234. return await self.client.artists_direct_albums(self.id, page, page_size, sort_by, *args, **kwargs)
  235. @classmethod
  236. def de_json(cls, data: 'JSONType', client: 'ClientType') -> Optional['Artist']:
  237. """Десериализация объекта.
  238. Args:
  239. data (:obj:`dict`): Поля и значения десериализуемого объекта.
  240. client (:obj:`yandex_music.Client`): Клиент Yandex Music.
  241. Returns:
  242. :obj:`yandex_music.Artist`: Исполнитель.
  243. """
  244. if not cls.is_dict_model_data(data):
  245. return None
  246. cls_data = cls.cleanup_data(data, client)
  247. from yandex_music import Counts, Cover, Description, Link, Ratings, Track
  248. cls_data['cover'] = Cover.de_json(data.get('cover'), client)
  249. cls_data['ratings'] = Ratings.de_json(data.get('ratings'), client)
  250. cls_data['counts'] = Counts.de_json(data.get('counts'), client)
  251. cls_data['links'] = Link.de_list(data.get('links'), client)
  252. cls_data['popular_tracks'] = Track.de_list(data.get('popular_tracks'), client)
  253. cls_data['description'] = Description.de_json(data.get('description'), client)
  254. # Мне всё равно как в яндухе на клиентах солвят свой бэковский костыль
  255. decomposed = data.get('decomposed')
  256. if isinstance(decomposed, list):
  257. decomposed_items: List[Union[str, 'Artist']] = []
  258. for part in decomposed:
  259. if isinstance(part, str):
  260. decomposed_items.append(part)
  261. elif isinstance(part, dict):
  262. artist = Artist.de_json(part, client)
  263. if artist:
  264. decomposed_items.append(artist)
  265. cls_data['decomposed'] = decomposed_items
  266. return cls(client=client, **cls_data) # type: ignore
  267. # camelCase псевдонимы
  268. #: Псевдоним для :attr:`get_op_image_url`
  269. getOpImageUrl = get_op_image_url
  270. #: Псевдоним для :attr:`get_og_image_url`
  271. getOgImageUrl = get_og_image_url
  272. #: Псевдоним для :attr:`download_og_image`
  273. downloadOgImage = download_og_image
  274. #: Псевдоним для :attr:`download_og_image_async`
  275. downloadOgImageAsync = download_og_image_async
  276. #: Псевдоним для :attr:`download_op_image`
  277. downloadOpImage = download_op_image
  278. #: Псевдоним для :attr:`download_op_image_async`
  279. downloadOpImageAsync = download_op_image_async
  280. #: Псевдоним для :attr:`download_og_image_bytes`
  281. downloadOgImageBytes = download_og_image_bytes
  282. #: Псевдоним для :attr:`download_og_image_bytes_async`
  283. downloadOgImageBytesAsync = download_og_image_bytes_async
  284. #: Псевдоним для :attr:`download_op_image_bytes`
  285. downloadOpImageBytes = download_op_image_bytes
  286. #: Псевдоним для :attr:`download_op_image_bytes_async`
  287. downloadOpImageBytesAsync = download_op_image_bytes_async
  288. #: Псевдоним для :attr:`like_async`
  289. likeAsync = like_async
  290. #: Псевдоним для :attr:`dislike_async`
  291. dislikeAsync = dislike_async
  292. #: Псевдоним для :attr:`get_tracks`
  293. getTracks = get_tracks
  294. #: Псевдоним для :attr:`get_tracks_async`
  295. getTracksAsync = get_tracks_async
  296. #: Псевдоним для :attr:`get_albums`
  297. getAlbums = get_albums
  298. #: Псевдоним для :attr:`get_albums_async`
  299. getAlbumsAsync = get_albums_async