[youtube:tab] Follow redirect to regional channel (#2884)

Closes #2694
Authored by: coletdjnz
This commit is contained in:
coletdev 2022-03-01 18:08:19 +13:00 committed by GitHub
parent 93c8410d33
commit 7c219ea601
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -3950,12 +3950,13 @@ def _entries(self, tab, item_id, ytcfg, account_syncid, visitor_data):
break break
@staticmethod @staticmethod
def _extract_selected_tab(tabs): def _extract_selected_tab(tabs, fatal=True):
for tab in tabs: for tab in tabs:
renderer = dict_get(tab, ('tabRenderer', 'expandableTabRenderer')) or {} renderer = dict_get(tab, ('tabRenderer', 'expandableTabRenderer')) or {}
if renderer.get('selected') is True: if renderer.get('selected') is True:
return renderer return renderer
else: else:
if fatal:
raise ExtractorError('Unable to find selected tab') raise ExtractorError('Unable to find selected tab')
@classmethod @classmethod
@ -4229,7 +4230,7 @@ def _extract_webpage(self, url, item_id, fatal=True):
self.report_warning(error_to_compat_str(e)) self.report_warning(error_to_compat_str(e))
break break
if dict_get(data, ('contents', 'currentVideoEndpoint')): if dict_get(data, ('contents', 'currentVideoEndpoint', 'onResponseReceivedActions')):
break break
last_error = 'Incomplete yt initial data received' last_error = 'Incomplete yt initial data received'
@ -4248,7 +4249,7 @@ def _extract_data(self, url, item_id, ytcfg=None, fatal=True, webpage_fatal=Fals
ytcfg = ytcfg or self.extract_ytcfg(item_id, webpage) ytcfg = ytcfg or self.extract_ytcfg(item_id, webpage)
# Reject webpage data if redirected to home page without explicitly requesting # Reject webpage data if redirected to home page without explicitly requesting
selected_tab = self._extract_selected_tab(traverse_obj( selected_tab = self._extract_selected_tab(traverse_obj(
data, ('contents', 'twoColumnBrowseResultsRenderer', 'tabs'), expected_type=list, default=[])) or {} data, ('contents', 'twoColumnBrowseResultsRenderer', 'tabs'), expected_type=list, default=[]), fatal=False) or {}
if (url != 'https://www.youtube.com/feed/recommended' if (url != 'https://www.youtube.com/feed/recommended'
and selected_tab.get('tabIdentifier') == 'FEwhat_to_watch' # Home page and selected_tab.get('tabIdentifier') == 'FEwhat_to_watch' # Home page
and 'no-youtube-channel-redirect' not in self.get_param('compat_opts', [])): and 'no-youtube-channel-redirect' not in self.get_param('compat_opts', [])):
@ -4280,7 +4281,7 @@ def _extract_tab_endpoint(self, url, item_id, ytcfg=None, fatal=True, default_cl
return self._extract_response( return self._extract_response(
item_id=item_id, query=params, ep=ep, headers=headers, item_id=item_id, query=params, ep=ep, headers=headers,
ytcfg=ytcfg, fatal=fatal, default_client=default_client, ytcfg=ytcfg, fatal=fatal, default_client=default_client,
check_get_keys=('contents', 'currentVideoEndpoint')) check_get_keys=('contents', 'currentVideoEndpoint', 'onResponseReceivedActions'))
err_note = 'Failed to resolve url (does the playlist exist?)' err_note = 'Failed to resolve url (does the playlist exist?)'
if fatal: if fatal:
raise ExtractorError(err_note, expected=True) raise ExtractorError(err_note, expected=True)
@ -4981,6 +4982,10 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
'skip_download': True, 'skip_download': True,
'extractor_args': {'youtubetab': {'skip': ['webpage']}} 'extractor_args': {'youtubetab': {'skip': ['webpage']}}
}, },
}, {
'note': 'non-standard redirect to regional channel',
'url': 'https://www.youtube.com/channel/UCwVVpHQ2Cs9iGJfpdFngePQ',
'only_matching': True
}] }]
@classmethod @classmethod
@ -5053,6 +5058,16 @@ def get_mobj(url):
data, ytcfg = self._extract_data(url, item_id) data, ytcfg = self._extract_data(url, item_id)
# YouTube may provide a non-standard redirect to the regional channel
# See: https://github.com/yt-dlp/yt-dlp/issues/2694
redirect_url = traverse_obj(
data, ('onResponseReceivedActions', ..., 'navigateAction', 'endpoint', 'commandMetadata', 'webCommandMetadata', 'url'), get_all=False)
if redirect_url and 'no-youtube-channel-redirect' not in compat_opts:
redirect_url = ''.join((
urljoin('https://www.youtube.com', redirect_url), mobj['tab'], mobj['post']))
self.to_screen(f'This playlist is likely not available in your region. Following redirect to regional playlist {redirect_url}')
return self.url_result(redirect_url, ie=YoutubeTabIE.ie_key())
tabs = traverse_obj(data, ('contents', 'twoColumnBrowseResultsRenderer', 'tabs'), expected_type=list) tabs = traverse_obj(data, ('contents', 'twoColumnBrowseResultsRenderer', 'tabs'), expected_type=list)
if tabs: if tabs:
selected_tab = self._extract_selected_tab(tabs) selected_tab = self._extract_selected_tab(tabs)