error = response.get('error')
if error:
raise ExtractorError(error, expected=True)
+ if response.get('type') == 'captcha' or 'captcha' in response:
+ YandexMusicBaseIE._raise_captcha()
+
+ @staticmethod
+ def _raise_captcha():
+ raise ExtractorError(
+ 'YandexMusic has considered youtube-dl requests automated and '
+ 'asks you to solve a CAPTCHA. You can either wait for some '
+ 'time until unblocked and optionally use --sleep-interval '
+ 'in future or alternatively you can go to https://music.yandex.ru/ '
+ 'solve CAPTCHA, then export cookies and pass cookie file to '
+ 'youtube-dl with --cookies',
+ expected=True)
def _download_webpage(self, *args, **kwargs):
webpage = super(YandexMusicBaseIE, self)._download_webpage(*args, **kwargs)
if 'Нам очень жаль, но запросы, поступившие с вашего IP-адреса, похожи на автоматические.' in webpage:
- raise ExtractorError(
- 'YandexMusic has considered youtube-dl requests automated and '
- 'asks you to solve a CAPTCHA. You can either wait for some '
- 'time until unblocked and optionally use --sleep-interval '
- 'in future or alternatively you can go to https://music.yandex.ru/ '
- 'solve CAPTCHA, then export cookies and pass cookie file to '
- 'youtube-dl with --cookies',
- expected=True)
+ self._raise_captcha()
return webpage
def _download_json(self, *args, **kwargs):
% storage_dir,
track_id, 'Downloading track location JSON')
+ # Each string is now wrapped in a list, this is probably only temporarily thus
+ # supporting both scenarios (see https://github.com/rg3/youtube-dl/issues/10193)
+ for k, v in data.items():
+ if v and isinstance(v, list):
+ data[k] = v[0]
+
key = hashlib.md5(('XGRlBW9FXlekgbPrRHuSiA' + data['path'][1:] + data['s']).encode('utf-8')).hexdigest()
storage = storage_dir.split('.')