client.py 122 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605
  1. import functools
  2. import logging
  3. from datetime import datetime
  4. from typing import TYPE_CHECKING, Any, Callable, List, Optional, TypeVar, Union, cast
  5. from yandex_music import (
  6. Album,
  7. Artist,
  8. ArtistAlbums,
  9. ArtistTracks,
  10. BriefInfo,
  11. ChartInfo,
  12. Dashboard,
  13. DownloadInfo,
  14. Experiments,
  15. Feed,
  16. Genre,
  17. Landing,
  18. LandingList,
  19. Like,
  20. PermissionAlerts,
  21. Playlist,
  22. PlaylistRecommendations,
  23. PromoCodeStatus,
  24. Queue,
  25. QueueItem,
  26. Search,
  27. Settings,
  28. ShotEvent,
  29. SimilarTracks,
  30. StationResult,
  31. StationTracksResult,
  32. Status,
  33. Suggestions,
  34. Supplement,
  35. TagResult,
  36. Track,
  37. TrackLyrics,
  38. TracksList,
  39. UserSettings,
  40. YandexMusicObject,
  41. __copyright__,
  42. __license__,
  43. __version__,
  44. )
  45. if TYPE_CHECKING:
  46. from yandex_music.base import JSONType
  47. from yandex_music.exceptions import BadRequestError
  48. from yandex_music.utils.difference import Difference
  49. from yandex_music.utils.request import Request
  50. from yandex_music.utils.sign_request import get_sign_request
  51. de_list = {
  52. 'artist': Artist.de_list,
  53. 'album': Album.de_list,
  54. 'track': Track.de_list,
  55. 'playlist': Playlist.de_list,
  56. }
  57. logging.getLogger(__name__).addHandler(logging.NullHandler())
  58. F = TypeVar('F', bound=Callable[..., Any])
  59. UserIdType = Optional[Union[str, int]]
  60. TimestampType = Optional[Union[str, float, int]]
  61. def log(method: F) -> F:
  62. logger = logging.getLogger(method.__module__)
  63. @functools.wraps(method)
  64. def wrapper(*args: Any, **kwargs: Any) -> Any: # noqa: ANN401:
  65. logger.debug(f'Entering: {method.__name__}')
  66. result = method(*args, **kwargs)
  67. logger.debug(result)
  68. logger.debug(f'Exiting: {method.__name__}')
  69. return result
  70. return wrapper
  71. class Client(YandexMusicObject):
  72. """Класс, представляющий клиент Yandex Music.
  73. Note:
  74. Доступные языки: en, uz, uk, us, ru, kk, hy.
  75. Поле `device` используется только при работе с очередью прослушивания.
  76. Attributes:
  77. logger (:obj:`logging.Logger`): Объект логгера.
  78. token (:obj:`str`): Уникальный ключ для аутентификации.
  79. base_url (:obj:`str`): Ссылка на API Yandex Music.
  80. me (:obj:`yandex_music.Status`): Информация об аккаунте.
  81. device (:obj:`str`): Строка, содержащая сведения об устройстве, с которого выполняются запросы.
  82. report_unknown_fields (:obj:`bool`): Включены ли предупреждения о неизвестных полях от API,
  83. которых нет в библиотеке.
  84. Args:
  85. token (:obj:`str`, optional): Уникальный ключ для аутентификации.
  86. base_url (:obj:`str`, optional): Ссылка на API Yandex Music.
  87. request (:obj:`yandex_music.utils.request.Request`, optional): Пре-инициализация
  88. :class:`yandex_music.utils.request.Request`.
  89. language (:obj:`str`, optional): Язык, на котором будут приходить ответы от API. По умолчанию русский.
  90. report_unknown_fields (:obj:`bool`, optional): Включить предупреждения о неизвестных полях от API,
  91. которых нет в библиотеке.
  92. """
  93. __notice_displayed = True # больше не используется
  94. def __init__(
  95. self,
  96. token: Optional[str] = None,
  97. base_url: Optional[str] = None,
  98. request: Optional[Request] = None,
  99. language: str = 'ru',
  100. report_unknown_fields: bool = False,
  101. ) -> None:
  102. if not Client.__notice_displayed:
  103. print(f'Yandex Music API v{__version__}, {__copyright__}')
  104. print(f'Licensed under the terms of the {__license__}', end='\n\n')
  105. Client.__notice_displayed = True
  106. self.logger = logging.getLogger(__name__)
  107. self.token = token
  108. if base_url is None:
  109. base_url = 'https://api.music.yandex.net'
  110. self.base_url = base_url
  111. self.report_unknown_fields = report_unknown_fields
  112. if request:
  113. self._request = request
  114. self._request.set_and_return_client(self)
  115. else:
  116. self._request = Request(self)
  117. self.language = language
  118. self._request.set_language(self.language)
  119. self.device = (
  120. 'os=Python; os_version=; manufacturer=Marshal; '
  121. 'model=Yandex Music API; clid=; device_id=random; uuid=random'
  122. )
  123. self.me: Optional['Status'] = None
  124. self.account_uid: Optional[str] = None
  125. @property
  126. def request(self) -> Request:
  127. """:obj:`yandex_music.utils.request.Request`: Объект вспомогательного класса для отправки запросов."""
  128. return self._request
  129. @log
  130. def init(self) -> 'Client':
  131. """Получение информацию об аккаунте использующихся в других запросах."""
  132. self.me = self.account_status()
  133. if self.me and self.me.account:
  134. self.account_uid = self.me.account.uid
  135. return self
  136. @log
  137. def account_status(self, *args: Any, **kwargs: Any) -> Optional[Status]:
  138. """Получение статуса аккаунта. Нет обязательных параметров.
  139. Args:
  140. *args: Произвольные аргументы (будут переданы в запрос).
  141. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  142. Returns:
  143. :obj:`yandex_music.Status` | :obj:`None`: Информация об аккаунте если он валиден, иначе :obj:`None`.
  144. Raises:
  145. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  146. """
  147. url = f'{self.base_url}/account/status'
  148. result = self._request.get(url, *args, **kwargs)
  149. return Status.de_json(result, self)
  150. @log
  151. def account_settings(self, *args: Any, **kwargs: Any) -> Optional[UserSettings]:
  152. """Получение настроек текущего пользователя.
  153. Args:
  154. *args: Произвольные аргументы (будут переданы в запрос).
  155. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  156. Returns:
  157. :obj:`yandex_music.UserSettings` | :obj:`None`: Настройки пользователя если аккаунт валиден,
  158. иначе :obj:`None`.
  159. Raises:
  160. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  161. """
  162. url = f'{self.base_url}/account/settings'
  163. result = self._request.get(url, *args, **kwargs)
  164. return UserSettings.de_json(result, self)
  165. @log
  166. def account_settings_set(
  167. self,
  168. param: Optional[str] = None,
  169. value: Optional[Union[str, int, bool]] = None,
  170. data: Optional['JSONType'] = None,
  171. *args: Any,
  172. **kwargs: Any,
  173. ) -> Optional[UserSettings]:
  174. """Изменение настроек текущего пользователя.
  175. Note:
  176. Доступные названия параметров есть поля в классе :class:`yandex_music.UserSettings`, только в CamelCase.
  177. Args:
  178. param (:obj:`str`): Название параметра для изменения.
  179. value (:obj:`str` | :obj:`int` | :obj:`bool`): Значение параметра.
  180. data (:obj:`dict`): Словарь параметров и значений для множественного изменения.
  181. *args: Произвольные аргументы (будут переданы в запрос).
  182. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  183. Returns:
  184. :obj:`yandex_music.UserSettings` | :obj:`None`: Настройки пользователя или :obj:`None`.
  185. Raises:
  186. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  187. """
  188. url = f'{self.base_url}/account/settings'
  189. if not data and param:
  190. data = {param: str(value)}
  191. result = self._request.post(url, data, *args, **kwargs)
  192. return UserSettings.de_json(result, self)
  193. @log
  194. def settings(self, *args: Any, **kwargs: Any) -> Optional[Settings]:
  195. """Получение предложений по покупке. Нет обязательных параметров.
  196. Args:
  197. *args: Произвольные аргументы (будут переданы в запрос).
  198. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  199. Returns:
  200. :obj:`yandex_music.Settings` | :obj:`None`: Информацию о предлагаемых продуктах если аккаунт валиден
  201. или :obj:`None`.
  202. Raises:
  203. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  204. """
  205. url = f'{self.base_url}/settings'
  206. result = self._request.get(url, *args, **kwargs)
  207. return Settings.de_json(result, self)
  208. @log
  209. def permission_alerts(self, *args: Any, **kwargs: Any) -> Optional[PermissionAlerts]:
  210. """Получение оповещений. Нет обязательных параметров.
  211. Args:
  212. *args: Произвольные аргументы (будут переданы в запрос).
  213. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  214. Returns:
  215. :obj:`yandex_music.PermissionAlerts` | :obj:`None`: Оповещения если аккаунт валиден или :obj:`None`.
  216. Raises:
  217. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  218. """
  219. url = f'{self.base_url}/permission-alerts'
  220. result = self._request.get(url, *args, **kwargs)
  221. return PermissionAlerts.de_json(result, self)
  222. @log
  223. def account_experiments(self, *args: Any, **kwargs: Any) -> Optional[Experiments]:
  224. """Получение значений экспериментальных функций аккаунта.
  225. Args:
  226. *args: Произвольные аргументы (будут переданы в запрос).
  227. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  228. Returns:
  229. :obj:`yandex_music.Experiments` | :obj:`None`: Состояние экспериментальных функций или :obj:`None`.
  230. Raises:
  231. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  232. """
  233. url = f'{self.base_url}/account/experiments'
  234. result = self._request.get(url, *args, **kwargs)
  235. return Experiments.de_json(result, self)
  236. @log
  237. def consume_promo_code(
  238. self, code: str, language: Optional[str] = None, *args, **kwargs
  239. ) -> Optional[PromoCodeStatus]:
  240. """Активация промо-кода.
  241. Note:
  242. Доступные языки: en, uz, uk, us, ru, kk, hy.
  243. Args:
  244. code (:obj:`str`): Промо-код.
  245. language (:obj:`str`, optional): Язык ответа API в ISO 639-1. По умолчанию язык клиента.
  246. *args: Произвольные аргументы (будут переданы в запрос).
  247. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  248. Returns:
  249. :obj:`yandex_music.PromoCodeStatus` | :obj:`None`: Информация об активации промо-кода или :obj:`None`.
  250. Raises:
  251. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  252. """
  253. url = f'{self.base_url}/account/consume-promo-code'
  254. if not language:
  255. language = self.language
  256. result = self._request.post(url, {'code': code, 'language': language}, *args, **kwargs)
  257. return PromoCodeStatus.de_json(result, self)
  258. @log
  259. def feed(self, *args: Any, **kwargs: Any) -> Optional[Feed]:
  260. """Получение потока информации (фида) подобранного под пользователя. Содержит умные плейлисты.
  261. Args:
  262. *args: Произвольные аргументы (будут переданы в запрос).
  263. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  264. Returns:
  265. :obj:`yandex_music.Feed` | :obj:`None`: Умные плейлисты пользователя или :obj:`None`.
  266. Raises:
  267. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  268. """
  269. url = f'{self.base_url}/feed'
  270. result = self._request.get(url, *args, **kwargs)
  271. return Feed.de_json(result, self)
  272. @log
  273. def feed_wizard_is_passed(self, *args: Any, **kwargs: Any) -> bool:
  274. """Получение информации о прохождении визарда.
  275. Note:
  276. Временное событие на хэллоуин.
  277. Args:
  278. *args: Произвольные аргументы (будут переданы в запрос).
  279. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  280. Returns:
  281. :obj:`bool`: Прошел ли пользователь визард или нет.
  282. """
  283. url = f'{self.base_url}/feed/wizard/is-passed'
  284. result = self._request.get(url, *args, **kwargs)
  285. return result.get('is_wizard_passed') or False
  286. @log
  287. def landing(self, blocks: Union[str, List[str]], *args: Any, **kwargs: Any) -> Optional[Landing]:
  288. """Получение лендинг-страницы содержащий блоки с новыми релизами, чартами, плейлистами с новинками и т.д.
  289. Note:
  290. Поддерживаемые типы блоков: `personalplaylists`, `promotions`, `new-releases`, `new-playlists`, `mixes`,
  291. `chart`, `artists`, `albums`, `playlists`, `play_contexts`.
  292. Args:
  293. blocks (:obj:`str` | :obj:`list` из :obj:`str`): Блок или список блоков необходимых для выдачи.
  294. *args: Произвольные аргументы (будут переданы в запрос).
  295. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  296. Returns:
  297. :obj:`yandex_music.Landing` | :obj:`None`: Лендинг-страница или :obj:`None`.
  298. Raises:
  299. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  300. """
  301. url = f'{self.base_url}/landing3'
  302. params = cast('JSONType', {'blocks': blocks, 'eitherUserId': '10254713668400548221'})
  303. result = self._request.get(url, params, *args, **kwargs)
  304. # TODO (MarshalX) что тут делает константа с чьим-то User ID
  305. # https://github.com/MarshalX/yandex-music-api/issues/553
  306. return Landing.de_json(result, self)
  307. @log
  308. def chart(self, chart_option: str = '', *args: Any, **kwargs: Any) -> Optional[ChartInfo]:
  309. """Получение чарта.
  310. Note:
  311. `chart_option` - это постфикс к запросу из поля `menu` чарта.
  312. Например, на сайте можно выбрать глобальный (world) чарт или российский (russia).
  313. Args:
  314. chart_option (:obj:`str` optional): Параметры чарта.
  315. *args: Произвольные аргументы (будут переданы в запрос).
  316. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  317. Returns:
  318. :obj:`yandex_music.ChartInfo`: Чарт.
  319. Raises:
  320. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  321. """
  322. url = f'{self.base_url}/landing3/chart'
  323. if chart_option:
  324. url = f'{url}/{chart_option}'
  325. result = self._request.get(url, *args, **kwargs)
  326. return ChartInfo.de_json(result, self)
  327. @log
  328. def new_releases(self, *args: Any, **kwargs: Any) -> Optional[LandingList]:
  329. """Получение полного списка всех новых релизов (альбомов).
  330. Args:
  331. *args: Произвольные аргументы (будут переданы в запрос).
  332. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  333. Returns:
  334. :obj:`yandex_music.LandingList`: Список новых альбомов.
  335. Raises:
  336. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  337. """
  338. url = f'{self.base_url}/landing3/new-releases'
  339. result = self._request.get(url, *args, **kwargs)
  340. return LandingList.de_json(result, self)
  341. @log
  342. def new_playlists(self, *args: Any, **kwargs: Any) -> Optional[LandingList]:
  343. """Получение полного списка всех новых плейлистов.
  344. Args:
  345. *args: Произвольные аргументы (будут переданы в запрос).
  346. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  347. Returns:
  348. :obj:`yandex_music.LandingList`: Список новых плейлистов.
  349. Raises:
  350. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  351. """
  352. url = f'{self.base_url}/landing3/new-playlists'
  353. result = self._request.get(url, *args, **kwargs)
  354. return LandingList.de_json(result, self)
  355. @log
  356. def podcasts(self, *args: Any, **kwargs: Any) -> Optional[LandingList]:
  357. """Получение подкастов с лендинга.
  358. Args:
  359. *args: Произвольные аргументы (будут переданы в запрос).
  360. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  361. Returns:
  362. :obj:`yandex_music.LandingList`: Список подкастов.
  363. Raises:
  364. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  365. """
  366. url = f'{self.base_url}/landing3/podcasts'
  367. result = self._request.get(url, *args, **kwargs)
  368. return LandingList.de_json(result, self)
  369. @log
  370. def genres(self, *args: Any, **kwargs: Any) -> List[Genre]:
  371. """Получение жанров музыки.
  372. Args:
  373. *args: Произвольные аргументы (будут переданы в запрос).
  374. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  375. Returns:
  376. :obj:`list` из :obj:`yandex_music.Genre` | :obj:`None`: Жанры музыки или :obj:`None`.
  377. Raises:
  378. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  379. """
  380. url = f'{self.base_url}/genres'
  381. result = self._request.get(url, *args, **kwargs)
  382. return Genre.de_list(result, self)
  383. @log
  384. def tags(self, tag_id: str, *args: Any, **kwargs: Any) -> Optional[TagResult]:
  385. """Получение тега (подборки).
  386. Note:
  387. Теги есть в `MixLink` у `Landing`, а также плейлистов в `.tags`.
  388. У `MixLink` есть `URL`, но `tag_id` только его последняя часть.
  389. Например, `/tag/belarus/`. `Tag` - `belarus`.
  390. Args:
  391. tag_id (:obj:`str`): Уникальный идентификатор тега.
  392. *args: Произвольные аргументы (будут переданы в запрос).
  393. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  394. Returns:
  395. :obj:`yandex_music.TagResult`: Тег с плейлистами.
  396. Raises:
  397. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  398. """
  399. url = f'{self.base_url}/tags/{tag_id}/playlist-ids'
  400. result = self._request.get(url, *args, **kwargs)
  401. return TagResult.de_json(result, self)
  402. @log
  403. def tracks_download_info(
  404. self,
  405. track_id: Union[str, int],
  406. get_direct_links: bool = False,
  407. *args: Any,
  408. **kwargs: Any,
  409. ) -> List[DownloadInfo]:
  410. """Получение информации о доступных вариантах загрузки трека.
  411. Args:
  412. track_id (:obj:`str` | :obj:`list` из :obj:`str`): Уникальный идентификатор трека или треков.
  413. get_direct_links (:obj:`bool`, optional): Получить ли при вызове метода прямую ссылку на загрузку.
  414. *args: Произвольные аргументы (будут переданы в запрос).
  415. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  416. Returns:
  417. :obj:`list` из :obj:`yandex_music.DownloadInfo` | :obj:`None`: Варианты загрузки трека или :obj:`None`.
  418. Raises:
  419. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  420. """
  421. url = f'{self.base_url}/tracks/{track_id}/download-info'
  422. result = self._request.get(url, *args, **kwargs)
  423. return DownloadInfo.de_list(result, self, get_direct_links)
  424. @log
  425. def track_supplement(self, track_id: Union[str, int], *args: Any, **kwargs: Any) -> Optional[Supplement]:
  426. """Получение дополнительной информации о треке.
  427. Warning:
  428. Получение текста из дополнительной информации устарело. Используйте
  429. :func:`yandex_music.Client.tracks_lyrics`.
  430. Args:
  431. track_id (:obj:`str` | :obj:`int`): Уникальный идентификатор трека.
  432. *args: Произвольные аргументы (будут переданы в запрос).
  433. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  434. Returns:
  435. :obj:`yandex_music.Supplement`: Дополнительная информация о треке.
  436. Raises:
  437. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  438. """
  439. url = f'{self.base_url}/tracks/{track_id}/supplement'
  440. result = self._request.get(url, *args, **kwargs)
  441. return Supplement.de_json(result, self)
  442. @log
  443. def tracks_lyrics(
  444. self,
  445. track_id: Union[str, int],
  446. format_: str = 'TEXT',
  447. **kwargs: Any,
  448. ) -> Optional[TrackLyrics]:
  449. """Получение текста трека.
  450. Note:
  451. Для работы с методом необходима авторизация.
  452. Известные значения для аргумента format:
  453. - `LRC` - формат с временными метками.
  454. - `TEXT` - простой текст.
  455. Args:
  456. track_id (:obj:`str` | :obj:`int`): Уникальный идентификатор трека.
  457. format_ (:obj:`str`): Формат текста.
  458. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  459. Returns:
  460. :obj:`yandex_music.TrackLyrics` | :obj:`None`: Информация о тексте трека.
  461. Raises:
  462. :class:`yandex_music.exceptions.UnauthorizedError`: Метод вызван без авторизации.
  463. :class:`yandex_music.exceptions.NotFoundError`: Текст у трека отсутствует.
  464. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  465. """
  466. url = f'{self.base_url}/tracks/{track_id}/lyrics'
  467. sign = get_sign_request(track_id)
  468. params = {
  469. 'format': format_,
  470. 'timeStamp': sign.timestamp,
  471. 'sign': sign.value,
  472. }
  473. result = self._request.get(url, params=params, **kwargs)
  474. return TrackLyrics.de_json(result, self)
  475. @log
  476. def tracks_similar(self, track_id: Union[str, int], *args: Any, **kwargs: Any) -> Optional[SimilarTracks]:
  477. """Получение похожих треков.
  478. Args:
  479. track_id (:obj:`str` | :obj:`int`): Уникальный идентификатор трека.
  480. *args: Произвольные аргументы (будут переданы в запрос).
  481. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  482. Returns:
  483. :obj:`yandex_music.SimilarTracks`: Похожие треки на другой трек.
  484. Raises:
  485. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  486. """
  487. url = f'{self.base_url}/tracks/{track_id}/similar'
  488. result = self._request.get(url, *args, **kwargs)
  489. return SimilarTracks.de_json(result, self)
  490. @log
  491. def play_audio(
  492. self,
  493. track_id: Union[str, int],
  494. from_: str,
  495. album_id: Union[str, int],
  496. playlist_id: Optional[str] = None,
  497. from_cache: bool = False,
  498. play_id: Optional[str] = None,
  499. uid: Optional[int] = None,
  500. timestamp: Optional[str] = None,
  501. track_length_seconds: int = 0,
  502. total_played_seconds: int = 0,
  503. end_position_seconds: int = 0,
  504. client_now: Optional[str] = None,
  505. *args: Any,
  506. **kwargs: Any,
  507. ) -> bool:
  508. """Метод для отправки текущего состояния прослушиваемого трека.
  509. Args:
  510. track_id (:obj:`str` | :obj:`int`): Уникальный идентификатор трека.
  511. from_ (:obj:`str`): Наименования клиента с которого происходит прослушивание.
  512. album_id (:obj:`str` | :obj:`int`): Уникальный идентификатор альбома.
  513. playlist_id (:obj:`str`, optional): Уникальный идентификатор плейлиста, если таковой прослушивается.
  514. from_cache (:obj:`bool`, optional): Проигрывается ли трек с кеша.
  515. play_id (:obj:`str`, optional): Уникальный идентификатор проигрывания.
  516. uid (:obj:`int`, optional): Уникальный идентификатор пользователя.
  517. timestamp (:obj:`str`, optional): Текущая дата и время в ISO.
  518. track_length_seconds (:obj:`int`, optional): Продолжительность трека в секундах.
  519. total_played_seconds (:obj:`int`, optional): Сколько было всего воспроизведено трека в секундах.
  520. end_position_seconds (:obj:`int`, optional): Окончательное значение воспроизведенных секунд.
  521. client_now (:obj:`str`, optional): Текущая дата и время клиента в ISO.
  522. *args: Произвольные аргументы (будут переданы в запрос).
  523. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  524. Returns:
  525. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  526. Raises:
  527. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  528. """
  529. if uid is None and self.account_uid is not None:
  530. uid = self.account_uid
  531. url = f'{self.base_url}/play-audio'
  532. data = {
  533. 'track-id': track_id,
  534. 'from-cache': str(from_cache),
  535. 'from': from_,
  536. 'play-id': play_id or '',
  537. 'uid': uid,
  538. 'timestamp': timestamp or f'{datetime.now().isoformat()}Z',
  539. 'track-length-seconds': track_length_seconds,
  540. 'total-played-seconds': total_played_seconds,
  541. 'end-position-seconds': end_position_seconds,
  542. 'album-id': album_id,
  543. 'playlist-id': playlist_id,
  544. 'client-now': client_now or f'{datetime.now().isoformat()}Z',
  545. }
  546. result = self._request.post(url, data, *args, **kwargs)
  547. return result == 'ok'
  548. @log
  549. def albums_with_tracks(self, album_id: Union[str, int], *args: Any, **kwargs: Any) -> Optional[Album]:
  550. """Получение альбома по его уникальному идентификатору вместе с треками.
  551. Args:
  552. album_id (:obj:`str` | :obj:`int`): Уникальный идентификатор альбома.
  553. *args: Произвольные аргументы (будут переданы в запрос).
  554. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  555. Returns:
  556. :obj:`list` из :obj:`yandex_music.Album` | :obj:`None`: Альбом или :obj:`None`.
  557. Raises:
  558. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  559. """
  560. url = f'{self.base_url}/albums/{album_id}/with-tracks'
  561. result = self._request.get(url, *args, **kwargs)
  562. return Album.de_json(result, self)
  563. @log
  564. def search(
  565. self,
  566. text: str,
  567. nocorrect: bool = False,
  568. type_: str = 'all',
  569. page: int = 0,
  570. playlist_in_best: bool = True,
  571. *args: Any,
  572. **kwargs: Any,
  573. ) -> Optional[Search]:
  574. """Осуществление поиска по запросу и типу, получение результатов.
  575. Note:
  576. Известные значения для поля `type_`: `all`, `artist`, `user`, `album`, `playlist`, `track`, `podcast`,
  577. `podcast_episode`.
  578. При поиске `type=all` не возвращаются подкасты и эпизоды. Указывайте конкретный тип для поиска.
  579. Args:
  580. text (:obj:`str`): Текст запроса.
  581. nocorrect (:obj:`bool`): Если :obj:`False`, то ошибочный запрос будет исправлен. Например, запрос
  582. "Гражданская абарона" будет исправлен на "Гражданская оборона".
  583. type_ (:obj:`str`): Среди какого типа искать (трек, плейлист, альбом, исполнитель, пользователь, подкаст).
  584. page (:obj:`int`): Номер страницы.
  585. playlist_in_best (:obj:`bool`): Выдавать ли плейлисты лучшим вариантом поиска.
  586. *args: Произвольные аргументы (будут переданы в запрос).
  587. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  588. Returns:
  589. :obj:`yandex_music.Search` | :obj:`None`: Результаты поиска или :obj:`None`.
  590. Raises:
  591. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  592. """
  593. url = f'{self.base_url}/search'
  594. params = {
  595. 'text': text,
  596. 'nocorrect': str(nocorrect),
  597. 'type': type_,
  598. 'page': page,
  599. 'playlist-in-best': str(playlist_in_best),
  600. }
  601. result = self._request.get(url, params, *args, **kwargs)
  602. if isinstance(result, str):
  603. raise BadRequestError(result)
  604. return Search.de_json(result, self)
  605. @log
  606. def search_suggest(self, part: str, *args: Any, **kwargs: Any) -> Optional[Suggestions]:
  607. """Получение подсказок по введенной части поискового запроса.
  608. Args:
  609. part (:obj:`str`): Часть поискового запроса.
  610. *args: Произвольные аргументы (будут переданы в запрос).
  611. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  612. Returns:
  613. :obj:`yandex_music.Suggestions` | :obj:`None`: Подсказки для запроса или :obj:`None`.
  614. Raises:
  615. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  616. """
  617. url = f'{self.base_url}/search/suggest'
  618. result = self._request.get(url, {'part': part}, *args, **kwargs)
  619. return Suggestions.de_json(result, self)
  620. @log
  621. def users_settings(self, user_id: UserIdType = None, *args: Any, **kwargs: Any) -> Optional[UserSettings]:
  622. """Получение настроек пользователя.
  623. Note:
  624. Для получения настроек пользователя нужно быть авторизованным или владеть `user_id`.
  625. Args:
  626. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя чьи настройки хотим
  627. получить.
  628. *args: Произвольные аргументы (будут переданы в запрос).
  629. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  630. Returns:
  631. :obj:`yandex_music.UserSettings` | :obj:`None`: Настройки пользователя или :obj:`None`.
  632. Raises:
  633. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  634. """
  635. if user_id is None and self.account_uid is not None:
  636. user_id = self.account_uid
  637. url = f'{self.base_url}/users/{user_id}/settings'
  638. result = self._request.get(url, *args, **kwargs)
  639. return UserSettings.de_json(result.get('user_settings'), self)
  640. @log
  641. def users_playlists(
  642. self,
  643. kind: Union[List[Union[str, int]], str, int],
  644. user_id: UserIdType = None,
  645. *args: Any,
  646. **kwargs: Any,
  647. ) -> Union[Playlist, List[Playlist], None]:
  648. """Получение плейлиста или списка плейлистов по уникальным идентификаторам.
  649. Note:
  650. Если передан один `kind`, то вернётся не список плейлистов, а один плейлист.
  651. Args:
  652. kind (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`int`): Уникальный идентификатор плейлиста
  653. или их список.
  654. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя владеющим плейлистом.
  655. *args: Произвольные аргументы (будут переданы в запрос).
  656. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  657. Returns:
  658. :obj:`list` из :obj:`yandex_music.Playlist` | :obj:`yandex_music.Playlist` | :obj:`None`:
  659. Список плейлистов или плейлист, иначе :obj:`None`.
  660. Raises:
  661. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  662. """
  663. if user_id is None and self.account_uid is not None:
  664. user_id = self.account_uid
  665. if isinstance(kind, list):
  666. url = f'{self.base_url}/users/{user_id}/playlists'
  667. data = {'kinds': kind}
  668. result = self._request.post(url, data, *args, **kwargs)
  669. return Playlist.de_list(result, self)
  670. url = f'{self.base_url}/users/{user_id}/playlists/{kind}'
  671. result = self._request.get(url, *args, **kwargs)
  672. return Playlist.de_json(result, self)
  673. @log
  674. def users_playlists_recommendations(
  675. self, kind: Union[str, int], user_id: UserIdType = None, *args: Any, **kwargs: Any
  676. ) -> Optional[PlaylistRecommendations]:
  677. """Получение рекомендаций для плейлиста.
  678. Args:
  679. kind (:obj:`str` | :obj:`int`): Уникальный идентификатор плейлиста.
  680. user_id (:obj:`str` | :obj:`int`): Уникальный идентификатор пользователя владеющим плейлистом.
  681. *args: Произвольные аргументы (будут переданы в запрос).
  682. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  683. Returns:
  684. :obj:`yandex_music.PlaylistRecommendations` | :obj:`None`: Рекомендации для плейлиста или :obj:`None`.
  685. Raises:
  686. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  687. """
  688. if user_id is None and self.account_uid is not None:
  689. user_id = self.account_uid
  690. url = f'{self.base_url}/users/{user_id}/playlists/{kind}/recommendations'
  691. result = self._request.get(url, *args, **kwargs)
  692. return PlaylistRecommendations.de_json(result, self)
  693. @log
  694. def users_playlists_create(
  695. self,
  696. title: str,
  697. visibility: str = 'public',
  698. user_id: UserIdType = None,
  699. *args: Any,
  700. **kwargs: Any,
  701. ) -> Optional[Playlist]:
  702. """Создание плейлиста.
  703. Args:
  704. title (:obj:`str`): Название.
  705. visibility (:obj:`str`, optional): Модификатор доступа.
  706. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя владеющим плейлистом.
  707. *args: Произвольные аргументы (будут переданы в запрос).
  708. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  709. Returns:
  710. :obj:`yandex_music.Playlist` | :obj:`None`: Созданный плейлист или :obj:`None`.
  711. Raises:
  712. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  713. """
  714. if user_id is None and self.account_uid is not None:
  715. user_id = self.account_uid
  716. url = f'{self.base_url}/users/{user_id}/playlists/create'
  717. data = {'title': title, 'visibility': visibility}
  718. result = self._request.post(url, data, *args, **kwargs)
  719. return Playlist.de_json(result, self)
  720. @log
  721. def users_playlists_delete(
  722. self, kind: Union[str, int], user_id: UserIdType = None, *args: Any, **kwargs: Any
  723. ) -> bool:
  724. """Удаление плейлиста.
  725. Args:
  726. kind (:obj:`str` | :obj:`int`): Уникальный идентификатор плейлиста.
  727. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя владеющим плейлистом.
  728. *args: Произвольные аргументы (будут переданы в запрос).
  729. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  730. Returns:
  731. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  732. Raises:
  733. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  734. """
  735. if user_id is None and self.account_uid is not None:
  736. user_id = self.account_uid
  737. url = f'{self.base_url}/users/{user_id}/playlists/{kind}/delete'
  738. result = self._request.post(url, *args, **kwargs)
  739. return result == 'ok'
  740. @log
  741. def users_playlists_name(
  742. self,
  743. kind: Union[str, int],
  744. name: str,
  745. user_id: UserIdType = None,
  746. *args: Any,
  747. **kwargs: Any,
  748. ) -> Optional[Playlist]:
  749. """Изменение названия плейлиста.
  750. Args:
  751. kind (:obj:`str` | :obj:`int`): Уникальный идентификатор плейлиста.
  752. name (:obj:`str`): Новое название.
  753. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя владеющим плейлистом.
  754. *args: Произвольные аргументы (будут переданы в запрос).
  755. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  756. Returns:
  757. :obj:`yandex_music.Playlist` | :obj:`None`: Изменённый плейлист или :obj:`None`.
  758. Raises:
  759. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  760. """
  761. if user_id is None and self.account_uid is not None:
  762. user_id = self.account_uid
  763. url = f'{self.base_url}/users/{user_id}/playlists/{kind}/name'
  764. result = self._request.post(url, {'value': name}, *args, **kwargs)
  765. return Playlist.de_json(result, self)
  766. @log
  767. def users_playlists_visibility(
  768. self,
  769. kind: Union[str, int],
  770. visibility: str,
  771. user_id: UserIdType = None,
  772. *args: Any,
  773. **kwargs: Any,
  774. ) -> Optional[Playlist]:
  775. """Изменение видимости плейлиста.
  776. Note:
  777. Видимость (`visibility`) может быть задана только одним из двух значений: `private`, `public`.
  778. Args:
  779. kind (:obj:`str` | :obj:`int`): Уникальный идентификатор плейлиста.
  780. visibility (:obj:`str`): Новое название.
  781. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя владеющим плейлистом.
  782. *args: Произвольные аргументы (будут переданы в запрос).
  783. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  784. Returns:
  785. :obj:`yandex_music.Playlist` | :obj:`None`: Изменённый плейлист или :obj:`None`.
  786. Raises:
  787. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  788. """
  789. if user_id is None and self.account_uid is not None:
  790. user_id = self.account_uid
  791. url = f'{self.base_url}/users/{user_id}/playlists/{kind}/visibility'
  792. result = self._request.post(url, {'value': visibility}, *args, **kwargs)
  793. return Playlist.de_json(result, self)
  794. @log
  795. def users_playlists_change(
  796. self,
  797. kind: Union[str, int],
  798. diff: str,
  799. revision: int = 1,
  800. user_id: UserIdType = None,
  801. *args: Any,
  802. **kwargs: Any,
  803. ) -> Optional[Playlist]:
  804. """Изменение плейлиста.
  805. Note:
  806. Для получения отличий есть вспомогательный класс :class:`yandex_music.utils.difference.Difference`.
  807. Так же существуют уже готовые методы-обёртки над операциями.
  808. Args:
  809. kind (:obj:`str` | :obj:`int`): Уникальный идентификатор плейлиста.
  810. revision (:obj:`int`): TODO.
  811. diff (:obj:`str`): JSON представления отличий старого и нового плейлиста.
  812. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя владеющим плейлистом.
  813. *args: Произвольные аргументы (будут переданы в запрос).
  814. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  815. Returns:
  816. :obj:`yandex_music.Playlist`: Изменённый плейлист или :obj:`None`.
  817. Raises:
  818. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  819. """
  820. if user_id is None and self.account_uid is not None:
  821. user_id = self.account_uid
  822. url = f'{self.base_url}/users/{user_id}/playlists/{kind}/change'
  823. data = {'kind': kind, 'revision': revision, 'diff': diff}
  824. result = self._request.post(url, data, *args, **kwargs)
  825. return Playlist.de_json(result, self)
  826. @log
  827. def users_playlists_insert_track(
  828. self,
  829. kind: Union[str, int],
  830. track_id: Union[str, int],
  831. album_id: Union[str, int],
  832. at: int = 0,
  833. revision: int = 1,
  834. user_id: UserIdType = None,
  835. *args: Any,
  836. **kwargs: Any,
  837. ) -> Optional[Playlist]:
  838. """Добавление трека в плейлист.
  839. Note:
  840. Трек можно вставить с любое место плейлиста задав индекс вставки (аргумент `at`).
  841. Args:
  842. kind (:obj:`str` | :obj:`int`): Уникальный идентификатор плейлиста.
  843. track_id (:obj:`str` | :obj:`int`): Уникальный идентификатор трека.
  844. album_id (:obj:`str` | :obj:`int`): Уникальный идентификатор альбома.
  845. at (:obj:`int`): Индекс для вставки.
  846. revision (:obj:`int`): TODO.
  847. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя владеющим плейлистом.
  848. *args: Произвольные аргументы (будут переданы в запрос).
  849. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  850. Returns:
  851. :obj:`yandex_music.Playlist`: Изменённый плейлист или :obj:`None`.
  852. Raises:
  853. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  854. """
  855. if user_id is None and self.account_uid is not None:
  856. user_id = self.account_uid
  857. diff = Difference().add_insert(at, {'id': track_id, 'album_id': album_id})
  858. return self.users_playlists_change(kind, diff.to_json(), revision, user_id, *args, **kwargs)
  859. @log
  860. def users_playlists_delete_track(
  861. self,
  862. kind: Union[str, int],
  863. from_: int,
  864. to: int,
  865. revision: int = 1,
  866. user_id: UserIdType = None,
  867. *args: Any,
  868. **kwargs: Any,
  869. ) -> Optional[Playlist]:
  870. """Удаление треков из плейлиста.
  871. Note:
  872. Для удаление необходимо указать границы с какого по какой элемент (трек) удалить.
  873. Args:
  874. kind (:obj:`str` | :obj:`int`): Уникальный идентификатор плейлиста.
  875. from_ (:obj:`int`): С какого индекса.
  876. to (:obj:`int`): По какой индекс.
  877. revision (:obj:`int`): TODO.
  878. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя владеющим плейлистом.
  879. *args: Произвольные аргументы (будут переданы в запрос).
  880. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  881. Returns:
  882. :obj:`yandex_music.Playlist` | :obj:`None`: Изменённый плейлист или :obj:`None`.
  883. Raises:
  884. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  885. """
  886. if user_id is None and self.account_uid is not None:
  887. user_id = self.account_uid
  888. diff = Difference().add_delete(from_, to)
  889. return self.users_playlists_change(kind, diff.to_json(), revision, user_id, *args, **kwargs)
  890. @log
  891. def rotor_account_status(self, *args: Any, **kwargs: Any) -> Optional[Status]:
  892. """Получение статуса пользователя с дополнительными полями.
  893. Note:
  894. Данный статус отличается от обычного наличием дополнительных полей, например, `skips_per_hour`.
  895. Args:
  896. *args: Произвольные аргументы (будут переданы в запрос).
  897. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  898. Returns:
  899. :obj:`yandex_music.Status` | :obj:`None`: Статус пользователя с дополнительными полями от радио или
  900. :obj:`None`.
  901. Raises:
  902. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  903. """
  904. url = f'{self.base_url}/rotor/account/status'
  905. result = self._request.get(url, *args, **kwargs)
  906. return Status.de_json(result, self)
  907. @log
  908. def rotor_stations_dashboard(self, *args: Any, **kwargs: Any) -> Optional[Dashboard]:
  909. """Получение рекомендованных станций текущего пользователя.
  910. Args:
  911. *args: Произвольные аргументы (будут переданы в запрос).
  912. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  913. Returns:
  914. :obj:`yandex_music.Dashboard` | :obj:`None`: Рекомендованные станции или :obj:`None`.
  915. Raises:
  916. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  917. """
  918. url = f'{self.base_url}/rotor/stations/dashboard'
  919. result = self._request.get(url, *args, **kwargs)
  920. return Dashboard.de_json(result, self)
  921. @log
  922. def rotor_stations_list(self, language: Optional[str] = None, *args: Any, **kwargs: Any) -> List[StationResult]:
  923. """Получение всех радиостанций с настройками пользователя.
  924. Note:
  925. Доступные языки: en, uz, uk, us, ru, kk, hy.
  926. Чтобы определить что за тип станции (жанры, настроения, занятие и т.д.) необходимо смотреть в поле
  927. `id_for_from`.
  928. Args:
  929. language (:obj:`str`, optional): Язык, на котором будет информация о станциях. По умолчанию язык клиента.
  930. *args: Произвольные аргументы (будут переданы в запрос).
  931. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  932. Returns:
  933. :obj:`list` из :obj:`yandex_music.StationResult`: Список станций.
  934. Raises:
  935. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  936. """
  937. url = f'{self.base_url}/rotor/stations/list'
  938. if not language:
  939. language = self.language
  940. result = self._request.get(url, {'language': language}, *args, **kwargs)
  941. return StationResult.de_list(result, self)
  942. @log
  943. def rotor_station_feedback(
  944. self,
  945. station: str,
  946. type_: str,
  947. timestamp: TimestampType = None,
  948. from_: Optional[str] = None,
  949. batch_id: Optional[str] = None,
  950. total_played_seconds: Optional[Union[int, float]] = None,
  951. track_id: Optional[Union[str, int]] = None,
  952. **kwargs: Any,
  953. ) -> bool:
  954. """Отправка обратной связи на действия при прослушивании радио.
  955. Note:
  956. Сообщения о начале прослушивания радио, начале и конце трека, его пропуска.
  957. Известные типы обратной связи: `radioStarted`, `trackStarted`, `trackFinished`, `skip`.
  958. Пример `station`: `user:onyourwave`, `genre:allrock`.
  959. Пример `from_`: `mobile-radio-user-123456789`.
  960. Args:
  961. station (:obj:`str`): Станция.
  962. type_ (:obj:`str`): Тип отправляемого отзыва.
  963. timestamp (:obj:`str` | :obj:`float` | :obj:`int`, optional): Текущее время и дата.
  964. from_ (:obj:`str`, optional): Откуда начато воспроизведение радио.
  965. batch_id (:obj:`str`, optional): Уникальный идентификатор партии треков. Возвращается при получении треков.
  966. total_played_seconds (:obj:`int` |:obj:`float`, optional): Сколько было проиграно секунд трека
  967. перед действием.
  968. track_id (:obj:`int` | :obj:`str`, optional): Уникальной идентификатор трека.
  969. *args: Произвольные аргументы (будут переданы в запрос).
  970. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  971. Returns:
  972. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  973. Raises:
  974. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  975. """
  976. if timestamp is None:
  977. timestamp = datetime.now().timestamp()
  978. url = f'{self.base_url}/rotor/station/{station}/feedback'
  979. params = {}
  980. data = {'type': type_, 'timestamp': timestamp}
  981. if batch_id:
  982. params = {'batch-id': batch_id}
  983. if track_id:
  984. data.update({'trackId': track_id})
  985. if from_:
  986. data.update({'from': from_})
  987. if total_played_seconds:
  988. data.update({'totalPlayedSeconds': total_played_seconds})
  989. result = self._request.post(url, params=params, json=data, **kwargs)
  990. return result == 'ok'
  991. @log
  992. def rotor_station_feedback_radio_started(
  993. self,
  994. station: str,
  995. from_: str,
  996. batch_id: Optional[str] = None,
  997. timestamp: TimestampType = None,
  998. **kwargs: Any,
  999. ) -> bool:
  1000. """Сокращение для::
  1001. client.rotor_station_feedback(station, 'radioStarted', timestamp, from, batch_id, **kwargs)
  1002. Returns:
  1003. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1004. Raises:
  1005. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1006. """
  1007. return self.rotor_station_feedback(station, 'radioStarted', timestamp, from_=from_, batch_id=batch_id, **kwargs)
  1008. @log
  1009. def rotor_station_feedback_track_started(
  1010. self,
  1011. station: str,
  1012. track_id: Union[str, int],
  1013. batch_id: Optional[str] = None,
  1014. timestamp: TimestampType = None,
  1015. **kwargs: Any,
  1016. ) -> bool:
  1017. """Сокращение для::
  1018. client.rotor_station_feedback(station, 'trackStarted', timestamp, track_id=track_id,
  1019. batch_id=batch_id, **kwargs)
  1020. Returns:
  1021. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1022. Raises:
  1023. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1024. """
  1025. return self.rotor_station_feedback(
  1026. station, 'trackStarted', timestamp, track_id=track_id, batch_id=batch_id, **kwargs
  1027. )
  1028. @log
  1029. def rotor_station_feedback_track_finished(
  1030. self,
  1031. station: str,
  1032. track_id: Union[str, int],
  1033. total_played_seconds: float,
  1034. batch_id: Optional[str] = None,
  1035. timestamp: TimestampType = None,
  1036. **kwargs: Any,
  1037. ) -> bool:
  1038. """Сокращение для::
  1039. client.rotor_station_feedback(station, 'trackFinished', timestamp,
  1040. track_id=track_id, total_played_seconds=total_played_seconds, batch_id=batch_id, **kwargs)
  1041. Returns:
  1042. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1043. Raises:
  1044. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1045. """
  1046. return self.rotor_station_feedback(
  1047. station,
  1048. 'trackFinished',
  1049. timestamp,
  1050. track_id=track_id,
  1051. total_played_seconds=total_played_seconds,
  1052. batch_id=batch_id,
  1053. **kwargs,
  1054. )
  1055. @log
  1056. def rotor_station_feedback_skip(
  1057. self,
  1058. station: str,
  1059. track_id: Union[str, int],
  1060. total_played_seconds: float,
  1061. batch_id: Optional[str] = None,
  1062. timestamp: TimestampType = None,
  1063. **kwargs: Any,
  1064. ) -> bool:
  1065. """Сокращение для::
  1066. client.rotor_station_feedback(station, 'skip', timestamp, track_id=track_id,
  1067. total_played_seconds=total_played_seconds, batch_id=batch_id, **kwargs)
  1068. Returns:
  1069. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1070. Raises:
  1071. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1072. """
  1073. return self.rotor_station_feedback(
  1074. station,
  1075. 'skip',
  1076. timestamp,
  1077. track_id=track_id,
  1078. total_played_seconds=total_played_seconds,
  1079. batch_id=batch_id,
  1080. **kwargs,
  1081. )
  1082. @log
  1083. def rotor_station_info(self, station: str, *args: Any, **kwargs: Any) -> List[StationResult]:
  1084. """Получение информации о станции и пользовательских настроек на неё.
  1085. Args:
  1086. station (:obj:`str`): Станция.
  1087. *args: Произвольные аргументы (будут переданы в запрос).
  1088. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1089. Returns:
  1090. :obj:`list` из :obj:`yandex_music.StationResult` | :obj:`None`: Информация о станции или :obj:`None`.
  1091. Raises:
  1092. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1093. """
  1094. url = f'{self.base_url}/rotor/station/{station}/info'
  1095. result = self._request.get(url, *args, **kwargs)
  1096. return StationResult.de_list(result, self)
  1097. @log
  1098. def rotor_station_settings2(
  1099. self,
  1100. station: str,
  1101. mood_energy: str,
  1102. diversity: str,
  1103. language: str = 'not-russian', # TODO(#555): заменить на any
  1104. type_: str = 'rotor',
  1105. **kwargs: Any,
  1106. ) -> bool:
  1107. """Изменение настроек определённой станции.
  1108. Note:
  1109. Доступные значения для `mood_energy`: `fun`, `active`, `calm`, `sad`, `all`.
  1110. Доступные значения для `diversity`: `favorite`, `popular`, `discover`, `default`.
  1111. Доступные значения для `language`: `not-russian`, `russian`, `any`.
  1112. Доступные значения для `type_`: `rotor`, `generative`.
  1113. У станций в `restrictions` есть Enum'ы, а в них `possible_values` - доступные значения для поля.
  1114. Args:
  1115. station (:obj:`str`): Станция.
  1116. mood_energy (:obj:`str`): Настроение.
  1117. diversity (:obj:`str`): Треки.
  1118. language (:obj:`str`): Язык.
  1119. type_ (:obj:`str`): Тип.
  1120. *args: Произвольные аргументы (будут переданы в запрос).
  1121. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1122. Returns:
  1123. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1124. Raises:
  1125. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1126. """
  1127. url = f'{self.base_url}/rotor/station/{station}/settings3'
  1128. data = {'moodEnergy': mood_energy, 'diversity': diversity, 'type': type_}
  1129. if language:
  1130. data.update({'language': language})
  1131. result = self._request.post(url, json=data, **kwargs)
  1132. return result == 'ok'
  1133. @log
  1134. def rotor_station_tracks(
  1135. self,
  1136. station: str,
  1137. settings2: bool = True,
  1138. queue: Optional[Union[str, int]] = None,
  1139. *args: Any,
  1140. **kwargs: Any,
  1141. ) -> Optional[StationTracksResult]:
  1142. """Получение цепочки треков определённой станции.
  1143. Note:
  1144. Запуск потока по сущности сервиса осуществляется через станцию `<type>:<id>`.
  1145. Например, станцией для запуска потока по треку будет `track:1234`.
  1146. Для продолжения цепочки треков необходимо:
  1147. 1. Передавать `ID` трека, что был до этого (первый в цепочки).
  1148. 2. Отправить фидбек о конце или скипе трека, что был передан в `queue`.
  1149. 3. Отправить фидбек о начале следующего трека (второй в цепочки).
  1150. 4. Выполнить запрос получения треков. В ответе придёт новые треки или произойдёт сдвиг цепочки на 1 элемент.
  1151. Проход по цепочке до конца не изучен. Часто встречаются дубликаты.
  1152. Все официальные клиенты выполняют запросы с `settings2 = True`.
  1153. Args:
  1154. station (:obj:`str`): Станция.
  1155. settings2 (:obj:`bool`, optional): Использовать ли второй набор настроек.
  1156. queue (:obj:`str` | :obj:`int`, optional): Уникальной идентификатор трека, который только что был.
  1157. *args: Произвольные аргументы (будут переданы в запрос).
  1158. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1159. Returns:
  1160. :obj:`yandex_music.StationTracksResult` | :obj:`None`: Последовательность треков станции или :obj:`None`.
  1161. Raises:
  1162. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1163. """
  1164. url = f'{self.base_url}/rotor/station/{station}/tracks'
  1165. params = {}
  1166. if settings2:
  1167. params = {'settings2': str(True)}
  1168. if queue:
  1169. params = {'queue': queue}
  1170. result = self._request.get(url, params, *args, **kwargs)
  1171. return StationTracksResult.de_json(result, self)
  1172. @log
  1173. def artists_brief_info(self, artist_id: Union[str, int], *args: Any, **kwargs: Any) -> Optional[BriefInfo]:
  1174. """Получение информации об артисте.
  1175. Args:
  1176. artist_id (:obj:`str` | :obj:`int`): Уникальный идентификатор исполнителя.
  1177. *args: Произвольные аргументы (будут переданы в запрос).
  1178. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1179. Returns:
  1180. :obj:`yandex_music.BriefInfo` | :obj:`None`: Информация об артисте или :obj:`None`.
  1181. Raises:
  1182. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1183. """
  1184. url = f'{self.base_url}/artists/{artist_id}/brief-info'
  1185. result = self._request.get(url, *args, **kwargs)
  1186. return BriefInfo.de_json(result, self)
  1187. @log
  1188. def artists_tracks(
  1189. self,
  1190. artist_id: Union[str, int],
  1191. page: int = 0,
  1192. page_size: int = 20,
  1193. *args: Any,
  1194. **kwargs: Any,
  1195. ) -> Optional[ArtistTracks]:
  1196. """Получение треков артиста.
  1197. Args:
  1198. artist_id (:obj:`str` | :obj:`int`): Уникальный идентификатор артиста.
  1199. page (:obj:`int`, optional): Номер страницы.
  1200. page_size (:obj:`int`, optional): Количество треков на странице.
  1201. *args: Произвольные аргументы (будут переданы в запрос).
  1202. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1203. Returns:
  1204. :obj:`yandex_music.ArtistsTracks` | :obj:`None`: Страница списка треков артиста или :obj:`None`.
  1205. Raises:
  1206. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1207. """
  1208. url = f'{self.base_url}/artists/{artist_id}/tracks'
  1209. params = {'page': page, 'page-size': page_size}
  1210. result = self._request.get(url, params, *args, **kwargs)
  1211. return ArtistTracks.de_json(result, self)
  1212. @log
  1213. def artists_direct_albums(
  1214. self,
  1215. artist_id: Union[str, int],
  1216. page: int = 0,
  1217. page_size: int = 20,
  1218. sort_by: str = 'year',
  1219. *args: Any,
  1220. **kwargs: Any,
  1221. ) -> Optional[ArtistAlbums]:
  1222. """Получение альбомов артиста.
  1223. Note:
  1224. Известные значения для `sort_by`: `year`, `rating`.
  1225. Args:
  1226. artist_id (:obj:`str` | :obj:`int`): Уникальный идентификатор артиста.
  1227. page (:obj:`int`, optional): Номер страницы.
  1228. page_size (:obj:`int`, optional): Количество альбомов на странице.
  1229. sort_by (:obj:`str`, optional): Параметр для сортировки.
  1230. *args: Произвольные аргументы (будут переданы в запрос).
  1231. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1232. Returns:
  1233. :obj:`yandex_music.ArtistAlbums` | :obj:`None`: Страница списка альбомов артиста или :obj:`None`.
  1234. Raises:
  1235. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1236. """
  1237. url = f'{self.base_url}/artists/{artist_id}/direct-albums'
  1238. params = {'sort-by': sort_by, 'page': page, 'page-size': page_size}
  1239. result = self._request.get(url, params, *args, **kwargs)
  1240. return ArtistAlbums.de_json(result, self)
  1241. def _like_action(
  1242. self,
  1243. object_type: str,
  1244. ids: Union[List[Union[str, int]], str, int],
  1245. remove: bool = False,
  1246. user_id: UserIdType = None,
  1247. *args: Any,
  1248. **kwargs: Any,
  1249. ) -> bool:
  1250. """Действия с отметкой "Мне нравится".
  1251. Note:
  1252. Типы объектов: `track` - трек, `artist` - исполнитель, `playlist` - плейлист, `album` - альбом.
  1253. Идентификатор плейлиста указывается в формате `owner_id:playlist_id`. Где `playlist_id` - идентификатор
  1254. плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста.
  1255. Args:
  1256. object_type (:obj:`str`): Тип объекта.
  1257. ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1258. идентификатор объекта или объектов.
  1259. remove (:obj:`bool`, optional): Если :obj:`True` то снимает отметку, иначе ставит.
  1260. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1261. используется ID текущего пользователя.
  1262. *args: Произвольные аргументы (будут переданы в запрос).
  1263. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1264. Returns:
  1265. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1266. Raises:
  1267. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1268. """
  1269. if user_id is None and self.account_uid is not None:
  1270. user_id = self.account_uid
  1271. action = 'remove' if remove else 'add-multiple'
  1272. url = f'{self.base_url}/users/{user_id}/likes/{object_type}s/{action}'
  1273. result = self._request.post(url, {f'{object_type}-ids': ids}, *args, **kwargs)
  1274. if object_type == 'track':
  1275. return 'revision' in result
  1276. return result == 'ok'
  1277. @log
  1278. def users_likes_tracks_add(
  1279. self,
  1280. track_ids: Union[List[Union[str, int]], str, int],
  1281. user_id: UserIdType = None,
  1282. **kwargs: Any,
  1283. ) -> bool:
  1284. """Поставить отметку "Мне нравится" треку/трекам.
  1285. Note:
  1286. Так же снимает отметку "Не рекомендовать" если она есть.
  1287. Args:
  1288. track_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1289. идентификатор трека или треков.
  1290. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1291. используется ID текущего пользователя.
  1292. *args: Произвольные аргументы (будут переданы в запрос).
  1293. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1294. Returns:
  1295. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1296. Raises:
  1297. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1298. """
  1299. return self._like_action('track', track_ids, remove=False, user_id=user_id, **kwargs)
  1300. @log
  1301. def users_likes_tracks_remove(
  1302. self,
  1303. track_ids: Union[List[Union[str, int]], str, int],
  1304. user_id: UserIdType = None,
  1305. **kwargs: Any,
  1306. ) -> bool:
  1307. """Снять отметку "Мне нравится" у трека/треков.
  1308. Args:
  1309. track_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1310. идентификатор трека или треков.
  1311. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1312. используется ID текущего пользователя.
  1313. *args: Произвольные аргументы (будут переданы в запрос).
  1314. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1315. Returns:
  1316. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1317. Raises:
  1318. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1319. """
  1320. return self._like_action('track', track_ids, remove=True, user_id=user_id, **kwargs)
  1321. @log
  1322. def users_likes_artists_add(
  1323. self,
  1324. artist_ids: Union[List[Union[str, int]], str, int],
  1325. user_id: UserIdType = None,
  1326. **kwargs: Any,
  1327. ) -> bool:
  1328. """Поставить отметку "Мне нравится" исполнителю/исполнителям.
  1329. Args:
  1330. artist_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1331. идентификатор артиста или артистов.
  1332. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1333. используется ID текущего пользователя.
  1334. *args: Произвольные аргументы (будут переданы в запрос).
  1335. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1336. Returns:
  1337. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1338. Raises:
  1339. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1340. """
  1341. return self._like_action('artist', artist_ids, remove=False, user_id=user_id, **kwargs)
  1342. @log
  1343. def users_likes_artists_remove(
  1344. self,
  1345. artist_ids: Union[List[Union[str, int]], str, int],
  1346. user_id: UserIdType = None,
  1347. **kwargs: Any,
  1348. ) -> bool:
  1349. """Снять отметку "Мне нравится" у исполнителя/исполнителей.
  1350. Args:
  1351. artist_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1352. идентификатор артиста или артистов.
  1353. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1354. используется ID текущего пользователя.
  1355. *args: Произвольные аргументы (будут переданы в запрос).
  1356. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1357. Returns:
  1358. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1359. Raises:
  1360. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1361. """
  1362. return self._like_action('artist', artist_ids, remove=True, user_id=user_id, **kwargs)
  1363. @log
  1364. def users_likes_playlists_add(
  1365. self,
  1366. playlist_ids: Union[List[Union[str, int]], str, int],
  1367. user_id: UserIdType = None,
  1368. **kwargs: Any,
  1369. ) -> bool:
  1370. """Поставить отметку "Мне нравится" плейлисту/плейлистам.
  1371. Note:
  1372. Идентификатор плейлиста указывается в формате `owner_id:playlist_id`. Где `playlist_id` - идентификатор
  1373. плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста.
  1374. Args:
  1375. playlist_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1376. идентификатор плейлиста или плейлистов.
  1377. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1378. используется ID текущего пользователя.
  1379. *args: Произвольные аргументы (будут переданы в запрос).
  1380. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1381. Returns:
  1382. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1383. Raises:
  1384. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1385. """
  1386. return self._like_action('playlist', playlist_ids, remove=False, user_id=user_id, **kwargs)
  1387. @log
  1388. def users_likes_playlists_remove(
  1389. self,
  1390. playlist_ids: Union[List[Union[str, int]], str, int],
  1391. user_id: UserIdType = None,
  1392. **kwargs: Any,
  1393. ) -> bool:
  1394. """Снять отметку "Мне нравится" у плейлиста/плейлистов.
  1395. Note:
  1396. Идентификатор плейлиста указывается в формате `owner_id:playlist_id`. Где `playlist_id` - идентификатор
  1397. плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста.
  1398. Args:
  1399. playlist_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1400. идентификатор плейлиста или плейлистов.
  1401. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1402. используется ID текущего пользователя.
  1403. *args: Произвольные аргументы (будут переданы в запрос).
  1404. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1405. Returns:
  1406. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1407. Raises:
  1408. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1409. """
  1410. return self._like_action('playlist', playlist_ids, remove=True, user_id=user_id, **kwargs)
  1411. @log
  1412. def users_likes_albums_add(
  1413. self,
  1414. album_ids: Union[List[Union[str, int]], str, int],
  1415. user_id: UserIdType = None,
  1416. **kwargs: Any,
  1417. ) -> bool:
  1418. """Поставить отметку "Мне нравится" альбому/альбомам.
  1419. Args:
  1420. album_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1421. идентификатор артиста или артистов.
  1422. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1423. используется ID текущего пользователя.
  1424. *args: Произвольные аргументы (будут переданы в запрос).
  1425. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1426. Returns:
  1427. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1428. Raises:
  1429. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1430. """
  1431. return self._like_action('album', album_ids, remove=False, user_id=user_id, **kwargs)
  1432. @log
  1433. def users_likes_albums_remove(
  1434. self,
  1435. album_ids: Union[List[Union[str, int]], str, int],
  1436. user_id: UserIdType = None,
  1437. **kwargs: Any,
  1438. ) -> bool:
  1439. """Снять отметку "Мне нравится" у альбома/альбомов.
  1440. Args:
  1441. album_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1442. идентификатор артиста или артистов.
  1443. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1444. используется ID текущего пользователя.
  1445. *args: Произвольные аргументы (будут переданы в запрос).
  1446. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1447. Returns:
  1448. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1449. Raises:
  1450. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1451. """
  1452. return self._like_action('album', album_ids, remove=True, user_id=user_id, **kwargs)
  1453. def _get_list(
  1454. self,
  1455. object_type: str,
  1456. ids: Union[List[Union[str, int]], int, str],
  1457. params: Optional['JSONType'] = None,
  1458. *args: Any,
  1459. **kwargs: Any,
  1460. ) -> List[Union[Artist, Album, Track, Playlist]]:
  1461. """Получение объекта/объектов.
  1462. Args:
  1463. object_type (:obj:`str`): Тип объекта.
  1464. ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1465. идентификатор объекта или объектов.
  1466. params (:obj:`dict`, optional): Параметры, которые будут переданы в запрос.
  1467. *args: Произвольные аргументы (будут переданы в запрос).
  1468. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1469. Returns:
  1470. :obj:`list` из :obj:`yandex_music.Artist` | :obj:`list` из :obj:`yandex_music.Album` |
  1471. :obj:`list` из :obj:`yandex_music.Track` | :obj:`list` из :obj:`yandex_music.Playlist`: Запрошенный
  1472. объект.
  1473. Raises:
  1474. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1475. """
  1476. if params is None:
  1477. params = {}
  1478. params.update({f'{object_type}-ids': ids})
  1479. url = f'{self.base_url}/{object_type}s' + ('/list' if object_type == 'playlist' else '')
  1480. result = self._request.post(url, params, *args, **kwargs)
  1481. return de_list[object_type](result, self)
  1482. @log
  1483. def artists(self, artist_ids: Union[List[Union[str, int]], int, str], *args: Any, **kwargs: Any) -> List[Artist]:
  1484. """Получение исполнителя/исполнителей.
  1485. Args:
  1486. artist_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1487. идентификатор исполнителя или исполнителей.
  1488. *args: Произвольные аргументы (будут переданы в запрос).
  1489. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1490. Returns:
  1491. :obj:`list` из :obj:`yandex_music.Artist`: Исполнитель или исполнители.
  1492. Raises:
  1493. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1494. """
  1495. return self._get_list('artist', artist_ids, *args, **kwargs)
  1496. @log
  1497. def albums(self, album_ids: Union[List[Union[str, int]], int, str], *args: Any, **kwargs: Any) -> List[Album]:
  1498. """Получение альбома/альбомов.
  1499. Args:
  1500. album_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1501. идентификатор альбома или альбомов.
  1502. *args: Произвольные аргументы (будут переданы в запрос).
  1503. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1504. Returns:
  1505. :obj:`list` из :obj:`yandex_music.Album`: Альбом или альбомы.
  1506. Raises:
  1507. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1508. """
  1509. return self._get_list('album', album_ids, *args, **kwargs)
  1510. @log
  1511. def tracks(
  1512. self,
  1513. track_ids: Union[List[str], List[int], List[Union[str, int]], int, str],
  1514. with_positions: bool = True,
  1515. *args: Any,
  1516. **kwargs: Any,
  1517. ) -> List[Track]:
  1518. """Получение трека/треков.
  1519. Args:
  1520. track_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1521. идентификатор трека или треков.
  1522. with_positions (:obj:`bool`, optional): С позициями TODO.
  1523. *args: Произвольные аргументы (будут переданы в запрос).
  1524. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1525. Returns:
  1526. :obj:`list` из :obj:`yandex_music.Track`: Трек или Треки.
  1527. Raises:
  1528. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1529. """
  1530. return self._get_list('track', track_ids, {'with-positions': str(with_positions)}, *args, **kwargs)
  1531. @log
  1532. def playlists_list(
  1533. self, playlist_ids: Union[List[Union[str, int]], int, str], *args: Any, **kwargs: Any
  1534. ) -> List[Playlist]:
  1535. """Получение плейлиста/плейлистов.
  1536. Note:
  1537. Идентификатор плейлиста указывается в формате `owner_id:playlist_id`. Где `playlist_id` - идентификатор
  1538. плейлиста, `owner_id` - уникальный идентификатор владельца плейлиста.
  1539. Данный метод возвращает сокращенную модель плейлиста для отображения больших список.
  1540. Warning:
  1541. Данный метод не возвращает список треков у плейлиста! Для получения объекта :obj:`yandex_music.Playlist` c
  1542. заполненным полем `tracks` используйте метод :func:`yandex_music.Client.users_playlists` или
  1543. метод :func:`yandex_music.Playlist.fetch_tracks`.
  1544. Args:
  1545. playlist_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1546. идентификатор плейлиста или плейлистов.
  1547. *args: Произвольные аргументы (будут переданы в запрос).
  1548. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1549. Returns:
  1550. :obj:`list` из :obj:`yandex_music.Playlist`: Плейлист или плейлисты.
  1551. Raises:
  1552. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1553. """
  1554. return self._get_list('playlist', playlist_ids, *args, **kwargs)
  1555. @log
  1556. def playlists_collective_join(self, user_id: int, token: str, **kwargs: Any) -> bool:
  1557. """Присоединение к плейлисту как соавтор.
  1558. Note:
  1559. В качестве `user_id` принимается исключительно числовой уникальный идентификатор пользователя, не username.
  1560. Токен можно получить в Web-версии. Для этого, на странице плейлиста нужно нажать на
  1561. "Добавить соавтора". В полученной ссылке GET параметр `token` и будет токеном для присоединения.
  1562. Args:
  1563. user_id (:obj:`int`): Владелец плейлиста.
  1564. token (:obj:`str`): Токен для присоединения.
  1565. **kwargs: Произвольные аргументы (будут переданы в запрос).
  1566. Returns:
  1567. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1568. Raises:
  1569. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1570. """
  1571. url = f'{self.base_url}/playlists/collective/join'
  1572. params = {'uid': user_id, 'token': token}
  1573. result = self._request.post(url, params=params, **kwargs)
  1574. return result == 'ok'
  1575. @log
  1576. def users_playlists_list(self, user_id: UserIdType = None, *args: Any, **kwargs: Any) -> List[Playlist]:
  1577. """Получение списка плейлистов пользователя.
  1578. Args:
  1579. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1580. используется ID текущего пользователя.
  1581. *args: Произвольные аргументы (будут переданы в запрос).
  1582. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1583. Returns:
  1584. :obj:`list` из :obj:`yandex_music.Playlist`: Плейлисты пользователя.
  1585. Raises:
  1586. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1587. """
  1588. if user_id is None and self.account_uid is not None:
  1589. user_id = self.account_uid
  1590. url = f'{self.base_url}/users/{user_id}/playlists/list'
  1591. result = self._request.get(url, *args, **kwargs)
  1592. return Playlist.de_list(result, self)
  1593. def _get_likes(
  1594. self,
  1595. object_type: str,
  1596. user_id: UserIdType = None,
  1597. params: Optional['JSONType'] = None,
  1598. *args: Any,
  1599. **kwargs: Any,
  1600. ) -> Union[List[Like], Optional[TracksList]]:
  1601. """Получение объектов с отметкой "Мне нравится".
  1602. Args:
  1603. object_type (:obj:`str`): Тип объекта.
  1604. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1605. используется ID текущего пользователя.
  1606. params (:obj:`dict`, optional): Параметры, которые будут переданы в запрос.
  1607. *args: Произвольные аргументы (будут переданы в запрос).
  1608. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1609. Returns:
  1610. :obj:`list` из :obj:`yandex_music.Like` | :obj:`yandex_music.TracksList`: Объекты с отметкой "Мне нравится".
  1611. Raises:
  1612. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1613. """
  1614. if user_id is None and self.account_uid is not None:
  1615. user_id = self.account_uid
  1616. url = f'{self.base_url}/users/{user_id}/likes/{object_type}s'
  1617. result = self._request.get(url, params, *args, **kwargs)
  1618. if object_type == 'track':
  1619. return TracksList.de_json(result.get('library'), self)
  1620. return Like.de_list(result, self, object_type)
  1621. @log
  1622. def users_likes_tracks(
  1623. self,
  1624. user_id: UserIdType = None,
  1625. if_modified_since_revision: int = 0,
  1626. *args: Any,
  1627. **kwargs: Any,
  1628. ) -> Optional[TracksList]:
  1629. """Получение треков с отметкой "Мне нравится".
  1630. Args:
  1631. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1632. используется ID текущего пользователя.
  1633. if_modified_since_revision (:obj:`int`, optional): TODO.
  1634. *args: Произвольные аргументы (будут переданы в запрос).
  1635. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1636. Returns:
  1637. :obj:`yandex_music.TracksList`: Треки с отметкой "Мне нравится".
  1638. Raises:
  1639. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1640. """
  1641. return self._get_likes(
  1642. 'track', user_id, {'if-modified-since-revision': if_modified_since_revision}, *args, **kwargs
  1643. )
  1644. @log
  1645. def users_likes_albums(
  1646. self, user_id: UserIdType = None, rich: bool = True, *args: Any, **kwargs: Any
  1647. ) -> List[Like]:
  1648. """Получение альбомов с отметкой "Мне нравится".
  1649. Args:
  1650. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1651. используется ID текущего пользователя.
  1652. rich (:obj:`bool`, optional): Если False, то приходит укороченная версия.
  1653. *args: Произвольные аргументы (будут переданы в запрос).
  1654. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1655. Returns:
  1656. :obj:`list` из :obj:`yandex_music.Like`: Альбомы с отметкой "Мне нравится".
  1657. Raises:
  1658. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1659. """
  1660. return self._get_likes('album', user_id, {'rich': str(rich)}, *args, **kwargs)
  1661. @log
  1662. def users_likes_artists(
  1663. self,
  1664. user_id: UserIdType = None,
  1665. with_timestamps: bool = True,
  1666. *args: Any,
  1667. **kwargs: Any,
  1668. ) -> List[Like]:
  1669. """Получение артистов с отметкой "Мне нравится".
  1670. Args:
  1671. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1672. используется ID текущего пользователя.
  1673. with_timestamps (:obj:`bool`, optional): С временными метками TODO.
  1674. *args: Произвольные аргументы (будут переданы в запрос).
  1675. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1676. Returns:
  1677. :obj:`list` из :obj:`yandex_music.Like`: Артисты с отметкой "Мне нравится".
  1678. Raises:
  1679. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1680. """
  1681. return self._get_likes('artist', user_id, {'with-timestamps': str(with_timestamps)}, *args, **kwargs)
  1682. @log
  1683. def users_likes_playlists(self, user_id: UserIdType = None, *args: Any, **kwargs: Any) -> List[Like]:
  1684. """Получение плейлистов с отметкой "Мне нравится".
  1685. Args:
  1686. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1687. используется ID текущего пользователя.
  1688. *args: Произвольные аргументы (будут переданы в запрос).
  1689. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1690. Returns:
  1691. :obj:`list` из :obj:`yandex_music.Like`: Плейлисты с отметкой "Мне нравится".
  1692. Raises:
  1693. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1694. """
  1695. return self._get_likes('playlist', user_id, *args, **kwargs)
  1696. @log
  1697. def users_dislikes_tracks(
  1698. self,
  1699. user_id: UserIdType = None,
  1700. if_modified_since_revision: int = 0,
  1701. *args: Any,
  1702. **kwargs: Any,
  1703. ) -> Optional[TracksList]:
  1704. """Получение треков с отметкой "Не рекомендовать".
  1705. Args:
  1706. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1707. используется ID текущего пользователя.
  1708. if_modified_since_revision (:obj:`bool`, optional): TODO.
  1709. *args: Произвольные аргументы (будут переданы в запрос).
  1710. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1711. Returns:
  1712. :obj:`list` из :obj:`yandex_music.TracksList`: Треки с отметкой "Не рекомендовать".
  1713. Raises:
  1714. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1715. """
  1716. if user_id is None and self.account_uid is not None:
  1717. user_id = self.account_uid
  1718. url = f'{self.base_url}/users/{user_id}/dislikes/tracks'
  1719. result = self._request.get(url, {'if_modified_since_revision': if_modified_since_revision}, *args, **kwargs)
  1720. return TracksList.de_json(result.get('library'), self)
  1721. def _dislike_action(
  1722. self,
  1723. ids: Union[List[Union[str, int]], str, int],
  1724. remove: bool = False,
  1725. user_id: UserIdType = None,
  1726. *args: Any,
  1727. **kwargs: Any,
  1728. ) -> bool:
  1729. """Действия с отметкой "Не рекомендовать".
  1730. Args:
  1731. ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1732. идентификатор объекта или объектов.
  1733. remove (:obj:`bool`, optional): Если :obj:`True`, то снимает отметку, иначе ставит.
  1734. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1735. используется ID текущего пользователя.
  1736. *args: Произвольные аргументы (будут переданы в запрос).
  1737. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1738. Returns:
  1739. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1740. Raises:
  1741. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1742. """
  1743. if user_id is None and self.account_uid is not None:
  1744. user_id = self.account_uid
  1745. action = 'remove' if remove else 'add-multiple'
  1746. url = f'{self.base_url}/users/{user_id}/dislikes/tracks/{action}'
  1747. result = self._request.post(url, {'track-ids': ids}, *args, **kwargs)
  1748. return 'revision' in result
  1749. @log
  1750. def users_dislikes_tracks_add(
  1751. self,
  1752. track_ids: Union[List[Union[str, int]], str, int],
  1753. user_id: UserIdType = None,
  1754. **kwargs: Any,
  1755. ) -> bool:
  1756. """Поставить отметку "Не рекомендовать" треку/трекам.
  1757. Note:
  1758. Так же снимает отметку "Мне нравится" если она есть.
  1759. Args:
  1760. track_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1761. идентификатор трека или треков.
  1762. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1763. используется ID текущего пользователя.
  1764. *args: Произвольные аргументы (будут переданы в запрос).
  1765. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1766. Returns:
  1767. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1768. Raises:
  1769. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1770. """
  1771. return self._dislike_action(track_ids, remove=False, user_id=user_id, **kwargs)
  1772. @log
  1773. def users_dislikes_tracks_remove(
  1774. self,
  1775. track_ids: Union[List[Union[str, int]], str, int],
  1776. user_id: UserIdType = None,
  1777. **kwargs: Any,
  1778. ) -> bool:
  1779. """Снять отметку "Не рекомендовать" у трека/треков.
  1780. Args:
  1781. track_ids (:obj:`str` | :obj:`int` | :obj:`list` из :obj:`str` | :obj:`list` из :obj:`int`): Уникальный
  1782. идентификатор трека или треков.
  1783. user_id (:obj:`str` | :obj:`int`, optional): Уникальный идентификатор пользователя. Если не указан
  1784. используется ID текущего пользователя.
  1785. *args: Произвольные аргументы (будут переданы в запрос).
  1786. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1787. Returns:
  1788. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1789. Raises:
  1790. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1791. """
  1792. return self._dislike_action(track_ids, remove=True, user_id=user_id, **kwargs)
  1793. @log
  1794. def after_track(
  1795. self,
  1796. next_track_id: Union[str, int],
  1797. context_item: str,
  1798. prev_track_id: Optional[Union[str, int]] = None,
  1799. context: str = 'playlist',
  1800. types: str = 'shot',
  1801. from_: str = 'mobile-landing-origin-default',
  1802. *args: Any,
  1803. **kwargs: Any,
  1804. ) -> Optional[ShotEvent]:
  1805. """Получение рекламы или шота от Алисы после трека.
  1806. Note:
  1807. При получения шота от Алисы `prev_track_id` можно не указывать.
  1808. Если `context = 'playlist'`, то в `context_item` необходимо передать `{OWNER_PLAYLIST}:{ID_PLAYLIST}`.
  1809. Плейлист с Алисой имеет владельца с `id = 940441070`.
  1810. ID плейлиста можно получить из блоков landing'a. Получить шот чужого плейлиста нельзя.
  1811. Известные значения `context`: `playlist`.
  1812. Известные значения `types`: `shot`, `ad`.
  1813. Args:
  1814. prev_track_id (:obj:`str` | :obj:`int`): Уникальный идентификатор предыдущего трека.
  1815. next_track_id (:obj:`str` | :obj:`int`): Уникальный идентификатор следующего трека.
  1816. context_item (:obj:`str`): Уникальный идентификатор контекста.
  1817. context (:obj:`str`, optional): Место, откуда было вызвано получение.
  1818. types (:obj:`str`, optional): Тип того, что вернуть после трека.
  1819. from_ (:obj:`str`, optional): Место, с которого попали в контекст.
  1820. *args: Произвольные аргументы (будут переданы в запрос).
  1821. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1822. Returns:
  1823. :obj:`yandex_music.ShotEvent`: Шот от Алисы или :obj:`None`.
  1824. Raises:
  1825. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1826. """
  1827. url = f'{self.base_url}/after-track'
  1828. params = {
  1829. 'from': from_,
  1830. 'prevTrackId': prev_track_id,
  1831. 'nextTrackId': next_track_id,
  1832. 'context': context,
  1833. 'contextItem': context_item,
  1834. 'types': types,
  1835. }
  1836. result = self._request.get(url, params, *args, **kwargs)
  1837. # TODO (MarshalX) судя по всему ручка ещё возвращает рекламу после треков для пользователей без подписки.
  1838. # https://github.com/MarshalX/yandex-music-api/issues/557
  1839. return ShotEvent.de_json(result.get('shot_event'), self)
  1840. @log
  1841. def queues_list(self, device: Optional[str] = None, *args: Any, **kwargs: Any) -> List[QueueItem]:
  1842. """Получение всех очередей треков с разных устройств для синхронизации между ними.
  1843. Note:
  1844. Именно к `device` привязывается очередь. На одном устройстве может быть создана одна очередь.
  1845. Аргумент `device` имеет следующий формат: `ключ=значение; ключ2=значение2`. Обязательные паля указы в
  1846. значении по умолчанию.
  1847. Args:
  1848. device (:obj:`str`, optional): Содержит информацию об устройстве с которого выполняется запрос.
  1849. *args: Произвольные аргументы (будут переданы в запрос).
  1850. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1851. Returns:
  1852. :obj:`list` из :obj:`yandex_music.QueueItem`: Элементы очереди всех устройств.
  1853. Raises:
  1854. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1855. """
  1856. if not device:
  1857. device = self.device
  1858. url = f'{self.base_url}/queues'
  1859. self._request.headers['X-Yandex-Music-Device'] = device
  1860. result = self._request.get(url, *args, **kwargs)
  1861. return QueueItem.de_list(result.get('queues'), self)
  1862. @log
  1863. def queue(self, queue_id: str, *args: Any, **kwargs: Any) -> Optional[Queue]:
  1864. """Получение информации об очереди треков и самих треков в ней.
  1865. Args:
  1866. queue_id (:obj:`str`): Уникальный идентификатор очереди.
  1867. *args: Произвольные аргументы (будут переданы в запрос).
  1868. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1869. Returns:
  1870. :obj:`yandex_music.Queue`: Очередь или :obj:`None`.
  1871. Raises:
  1872. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1873. """
  1874. url = f'{self.base_url}/queues/{queue_id}'
  1875. result = self._request.get(url, *args, **kwargs)
  1876. return Queue.de_json(result, self)
  1877. @log
  1878. def queue_update_position(self, queue_id: str, current_index: int, device: Optional[str] = None, **kwargs) -> bool:
  1879. """Установка текущего индекса проигрываемого трека в очереди треков.
  1880. Note:
  1881. Изменить можно только у той очереди, которая была создана с переданного `device`!
  1882. Args:
  1883. queue_id (:obj:`str`): Уникальный идентификатор очереди.
  1884. current_index (:obj:`int`): Текущий индекс.
  1885. device (:obj:`str`, optional): Содержит информацию об устройстве с которого выполняется запрос.
  1886. *args: Произвольные аргументы (будут переданы в запрос).
  1887. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1888. Returns:
  1889. :obj:`bool`: :obj:`True` при успешном выполнении запроса, иначе :obj:`False`.
  1890. Raises:
  1891. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1892. """
  1893. if not device:
  1894. device = self.device
  1895. url = f'{self.base_url}/queues/{queue_id}/update-position'
  1896. self._request.headers['X-Yandex-Music-Device'] = device
  1897. result = self._request.post(url, {'isInteractive': False}, params={'currentIndex': current_index}, **kwargs)
  1898. return result.get('status') == 'ok'
  1899. @log
  1900. def queue_create(
  1901. self, queue: Union[Queue, str], device: Optional[str] = None, *args: Any, **kwargs: Any
  1902. ) -> Optional[str]:
  1903. """Создание новой очереди треков.
  1904. Args:
  1905. queue (:obj:`yandex_music.Queue` | :obj:`str`): Объект очереди или JSON строка с этим объектом.
  1906. device (:obj:`str`, optional): Содержит информацию об устройстве с которого выполняется запрос.
  1907. *args: Произвольные аргументы (будут переданы в запрос).
  1908. **kwargs: Произвольные именованные аргументы (будут переданы в запрос).
  1909. Returns:
  1910. :obj:`str`: Вернёт уникальный идентификатор созданной очереди, иначе :obj:`None`.
  1911. Raises:
  1912. :class:`yandex_music.exceptions.YandexMusicError`: Базовое исключение библиотеки.
  1913. """
  1914. if not device:
  1915. device = self.device
  1916. if isinstance(queue, Queue):
  1917. queue = queue.to_json(True)
  1918. url = f'{self.base_url}/queues'
  1919. self._request.headers['X-Yandex-Music-Device'] = device
  1920. result = self._request.post(url, queue, *args, **kwargs)
  1921. return result.get('id')
  1922. # camelCase псевдонимы
  1923. #: Псевдоним для :attr:`account_status`
  1924. accountStatus = account_status
  1925. #: Псевдоним для :attr:`account_settings`
  1926. accountSettings = account_settings
  1927. #: Псевдоним для :attr:`account_settings_set`
  1928. accountSettingsSet = account_settings_set
  1929. #: Псевдоним для :attr:`permission_alerts`
  1930. permissionAlerts = permission_alerts
  1931. #: Псевдоним для :attr:`account_experiments`
  1932. accountExperiments = account_experiments
  1933. #: Псевдоним для :attr:`consume_promo_code`
  1934. consumePromoCode = consume_promo_code
  1935. #: Псевдоним для :attr:`feed_wizard_is_passed`
  1936. feedWizardIsPassed = feed_wizard_is_passed
  1937. #: Псевдоним для :attr:`new_releases`
  1938. newReleases = new_releases
  1939. #: Псевдоним для :attr:`new_playlists`
  1940. newPlaylists = new_playlists
  1941. #: Псевдоним для :attr:`tracks_download_info`
  1942. tracksDownloadInfo = tracks_download_info
  1943. #: Псевдоним для :attr:`track_supplement`
  1944. trackSupplement = track_supplement
  1945. #: Псевдоним для :attr:`tracks_lyrics`
  1946. tracksLyrics = tracks_lyrics
  1947. #: Псевдоним для :attr:`tracks_similar`
  1948. tracksSimilar = tracks_similar
  1949. #: Псевдоним для :attr:`play_audio`
  1950. playAudio = play_audio
  1951. #: Псевдоним для :attr:`albums_with_tracks`
  1952. albumsWithTracks = albums_with_tracks
  1953. #: Псевдоним для :attr:`search_suggest`
  1954. searchSuggest = search_suggest
  1955. #: Псевдоним для :attr:`users_settings`
  1956. usersSettings = users_settings
  1957. #: Псевдоним для :attr:`users_playlists`
  1958. usersPlaylists = users_playlists
  1959. #: Псевдоним для :attr:`users_playlists_recommendations`
  1960. usersPlaylistsRecommendations = users_playlists_recommendations
  1961. #: Псевдоним для :attr:`users_playlists_create`
  1962. usersPlaylistsCreate = users_playlists_create
  1963. #: Псевдоним для :attr:`users_playlists_delete`
  1964. usersPlaylistsDelete = users_playlists_delete
  1965. #: Псевдоним для :attr:`users_playlists_name`
  1966. usersPlaylistsName = users_playlists_name
  1967. #: Псевдоним для :attr:`users_playlists_visibility`
  1968. usersPlaylistsVisibility = users_playlists_visibility
  1969. #: Псевдоним для :attr:`users_playlists_change`
  1970. usersPlaylistsChange = users_playlists_change
  1971. #: Псевдоним для :attr:`users_playlists_insert_track`
  1972. usersPlaylistsInsertTrack = users_playlists_insert_track
  1973. #: Псевдоним для :attr:`users_playlists_delete_track`
  1974. usersPlaylistsDeleteTrack = users_playlists_delete_track
  1975. #: Псевдоним для :attr:`rotor_account_status`
  1976. rotorAccountStatus = rotor_account_status
  1977. #: Псевдоним для :attr:`rotor_stations_dashboard`
  1978. rotorStationsDashboard = rotor_stations_dashboard
  1979. #: Псевдоним для :attr:`rotor_stations_list`
  1980. rotorStationsList = rotor_stations_list
  1981. #: Псевдоним для :attr:`rotor_station_feedback`
  1982. rotorStationFeedback = rotor_station_feedback
  1983. #: Псевдоним для :attr:`rotor_station_feedback_radio_started`
  1984. rotorStationFeedbackRadioStarted = rotor_station_feedback_radio_started
  1985. #: Псевдоним для :attr:`rotor_station_feedback_track_started`
  1986. rotorStationFeedbackTrackStarted = rotor_station_feedback_track_started
  1987. #: Псевдоним для :attr:`rotor_station_feedback_track_finished`
  1988. rotorStationFeedbackTrackFinished = rotor_station_feedback_track_finished
  1989. #: Псевдоним для :attr:`rotor_station_feedback_skip`
  1990. rotorStationFeedbackSkip = rotor_station_feedback_skip
  1991. #: Псевдоним для :attr:`rotor_station_info`
  1992. rotorStationInfo = rotor_station_info
  1993. #: Псевдоним для :attr:`rotor_station_settings2`
  1994. rotorStationSettings2 = rotor_station_settings2
  1995. #: Псевдоним для :attr:`rotor_station_tracks`
  1996. rotorStationTracks = rotor_station_tracks
  1997. #: Псевдоним для :attr:`artists_brief_info`
  1998. artistsBriefInfo = artists_brief_info
  1999. #: Псевдоним для :attr:`artists_tracks`
  2000. artistsTracks = artists_tracks
  2001. #: Псевдоним для :attr:`artists_direct_albums`
  2002. artistsDirectAlbums = artists_direct_albums
  2003. #: Псевдоним для :attr:`users_likes_tracks_add`
  2004. usersLikesTracksAdd = users_likes_tracks_add
  2005. #: Псевдоним для :attr:`users_likes_tracks_remove`
  2006. usersLikesTracksRemove = users_likes_tracks_remove
  2007. #: Псевдоним для :attr:`users_likes_artists_add`
  2008. usersLikesArtistsAdd = users_likes_artists_add
  2009. #: Псевдоним для :attr:`users_likes_artists_remove`
  2010. usersLikesArtistsRemove = users_likes_artists_remove
  2011. #: Псевдоним для :attr:`users_likes_playlists_add`
  2012. usersLikesPlaylistsAdd = users_likes_playlists_add
  2013. #: Псевдоним для :attr:`users_likes_playlists_remove`
  2014. usersLikesPlaylistsRemove = users_likes_playlists_remove
  2015. #: Псевдоним для :attr:`users_likes_albums_add`
  2016. usersLikesAlbumsAdd = users_likes_albums_add
  2017. #: Псевдоним для :attr:`users_likes_albums_remove`
  2018. usersLikesAlbumsRemove = users_likes_albums_remove
  2019. #: Псевдоним для :attr:`playlists_list`
  2020. playlistsList = playlists_list
  2021. #: Псевдоним для :attr:`playlists_collective_join`
  2022. playlistsCollectiveJoin = playlists_collective_join
  2023. #: Псевдоним для :attr:`users_playlists_list`
  2024. usersPlaylistsList = users_playlists_list
  2025. #: Псевдоним для :attr:`users_likes_tracks`
  2026. usersLikesTracks = users_likes_tracks
  2027. #: Псевдоним для :attr:`users_likes_albums`
  2028. usersLikesAlbums = users_likes_albums
  2029. #: Псевдоним для :attr:`users_likes_artists`
  2030. usersLikesArtists = users_likes_artists
  2031. #: Псевдоним для :attr:`users_likes_playlists`
  2032. usersLikesPlaylists = users_likes_playlists
  2033. #: Псевдоним для :attr:`users_dislikes_tracks`
  2034. usersDislikesTracks = users_dislikes_tracks
  2035. #: Псевдоним для :attr:`users_dislikes_tracks_add`
  2036. usersDislikesTracksAdd = users_dislikes_tracks_add
  2037. #: Псевдоним для :attr:`users_dislikes_tracks_remove`
  2038. usersDislikesTracksRemove = users_dislikes_tracks_remove
  2039. #: Псевдоним для :attr:`after_track`
  2040. afterTrack = after_track
  2041. #: Псевдоним для :attr:`queues_list`
  2042. queuesList = queues_list
  2043. #: Псевдоним для :attr:`queue_update_position`
  2044. queueUpdatePosition = queue_update_position
  2045. #: Псевдоним для :attr:`queue_create`
  2046. queueCreate = queue_create