[Youtube] Extract alerts from continuation (#144)

Related: #143

Authored by: colethedj
This commit is contained in:
Matthew 2021-03-05 10:07:32 +00:00 committed by GitHub
parent 9e631877f8
commit f3eaa8dd1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2796,7 +2796,11 @@ def extract_entries(parent_renderer): # this needs to called again for continua
# See: https://github.com/ytdl-org/youtube-dl/issues/28194 # See: https://github.com/ytdl-org/youtube-dl/issues/28194
if response.get('continuationContents') or response.get('onResponseReceivedActions'): if response.get('continuationContents') or response.get('onResponseReceivedActions'):
break break
last_error = 'Incomplete data recieved'
# Youtube may send alerts if there was an issue with the continuation page
self._extract_alerts(response, expected=False)
last_error = 'Incomplete data received'
if count >= retries: if count >= retries:
self._downloader.report_error(last_error) self._downloader.report_error(last_error)
@ -2982,23 +2986,35 @@ def _extract_from_playlist(self, item_id, url, data, playlist):
self._extract_mix_playlist(playlist, playlist_id), self._extract_mix_playlist(playlist, playlist_id),
playlist_id=playlist_id, playlist_title=title) playlist_id=playlist_id, playlist_title=title)
@staticmethod def _extract_alerts(self, data, expected=False):
def _extract_alerts(data):
for alert_dict in try_get(data, lambda x: x['alerts'], list) or []: def _real_extract_alerts():
if not isinstance(alert_dict, dict): for alert_dict in try_get(data, lambda x: x['alerts'], list) or []:
continue if not isinstance(alert_dict, dict):
for renderer in alert_dict:
alert = alert_dict[renderer]
alert_type = alert.get('type')
if not alert_type:
continue continue
message = try_get(alert, lambda x: x['text']['simpleText'], compat_str) for alert in alert_dict.values():
if message: alert_type = alert.get('type')
yield alert_type, message if not alert_type:
for run in try_get(alert, lambda x: x['text']['runs'], list) or []: continue
message = try_get(run, lambda x: x['text'], compat_str) message = try_get(alert, lambda x: x['text']['simpleText'], compat_str)
if message: if message:
yield alert_type, message yield alert_type, message
for run in try_get(alert, lambda x: x['text']['runs'], list) or []:
message = try_get(run, lambda x: x['text'], compat_str)
if message:
yield alert_type, message
err_msg = None
for alert_type, alert_message in _real_extract_alerts():
if alert_type.lower() == 'error':
if err_msg:
self._downloader.report_warning('YouTube said: %s - %s' % ('ERROR', err_msg))
err_msg = alert_message
else:
self._downloader.report_warning('YouTube said: %s - %s' % (alert_type, alert_message))
if err_msg:
raise ExtractorError('YouTube said: %s' % err_msg, expected=expected)
def _extract_identity_token(self, webpage, item_id): def _extract_identity_token(self, webpage, item_id):
ytcfg = self._extract_ytcfg(item_id, webpage) ytcfg = self._extract_ytcfg(item_id, webpage)
@ -3024,16 +3040,7 @@ def _extract_webpage(self, url, item_id):
url, item_id, url, item_id,
'Downloading webpage%s' % (' (retry #%d)' % count if count else '')) 'Downloading webpage%s' % (' (retry #%d)' % count if count else ''))
data = self._extract_yt_initial_data(item_id, webpage) data = self._extract_yt_initial_data(item_id, webpage)
err_msg = None self._extract_alerts(data, expected=True)
for alert_type, alert_message in self._extract_alerts(data):
if alert_type.lower() == 'error':
if err_msg:
self._downloader.report_warning('YouTube said: %s - %s' % ('ERROR', err_msg))
err_msg = alert_message
else:
self._downloader.report_warning('YouTube said: %s - %s' % (alert_type, alert_message))
if err_msg:
raise ExtractorError('YouTube said: %s' % err_msg, expected=True)
if data.get('contents') or data.get('currentVideoEndpoint'): if data.get('contents') or data.get('currentVideoEndpoint'):
break break
if count >= retries: if count >= retries: