|
|
|
@ -4986,6 +4986,10 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
|
|
|
|
|
for item in grid_renderer['items']:
|
|
|
|
|
if not isinstance(item, dict):
|
|
|
|
|
continue
|
|
|
|
|
if lockup_view_model := traverse_obj(item, ('lockupViewModel', {dict})):
|
|
|
|
|
if entry := self._extract_lockup_view_model(lockup_view_model):
|
|
|
|
|
yield entry
|
|
|
|
|
continue
|
|
|
|
|
renderer = self._extract_basic_item_renderer(item)
|
|
|
|
|
if not isinstance(renderer, dict):
|
|
|
|
|
continue
|
|
|
|
@ -5084,10 +5088,30 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
|
|
|
|
|
continue
|
|
|
|
|
yield self._extract_video(renderer)
|
|
|
|
|
|
|
|
|
|
def _extract_lockup_view_model(self, view_model):
|
|
|
|
|
content_id = view_model.get('contentId')
|
|
|
|
|
if not content_id:
|
|
|
|
|
return
|
|
|
|
|
content_type = view_model.get('contentType')
|
|
|
|
|
if content_type not in ('LOCKUP_CONTENT_TYPE_PLAYLIST', 'LOCKUP_CONTENT_TYPE_PODCAST'):
|
|
|
|
|
self.report_warning(
|
|
|
|
|
f'Unsupported lockup view model content type "{content_type}"{bug_reports_message()}', only_once=True)
|
|
|
|
|
return
|
|
|
|
|
return self.url_result(
|
|
|
|
|
f'https://www.youtube.com/playlist?list={content_id}', ie=YoutubeTabIE, video_id=content_id,
|
|
|
|
|
title=traverse_obj(view_model, (
|
|
|
|
|
'metadata', 'lockupMetadataViewModel', 'title', 'content', {str})),
|
|
|
|
|
thumbnails=self._extract_thumbnails(view_model, (
|
|
|
|
|
'contentImage', 'collectionThumbnailViewModel', 'primaryThumbnail', 'thumbnailViewModel', 'image'), final_key='sources'))
|
|
|
|
|
|
|
|
|
|
def _rich_entries(self, rich_grid_renderer):
|
|
|
|
|
if lockup_view_model := traverse_obj(rich_grid_renderer, ('content', 'lockupViewModel', {dict})):
|
|
|
|
|
if entry := self._extract_lockup_view_model(lockup_view_model):
|
|
|
|
|
yield entry
|
|
|
|
|
return
|
|
|
|
|
renderer = traverse_obj(
|
|
|
|
|
rich_grid_renderer,
|
|
|
|
|
('content', ('videoRenderer', 'reelItemRenderer', 'playlistRenderer', 'shortsLockupViewModel', 'lockupViewModel'), any)) or {}
|
|
|
|
|
('content', ('videoRenderer', 'reelItemRenderer', 'playlistRenderer', 'shortsLockupViewModel'), any)) or {}
|
|
|
|
|
video_id = renderer.get('videoId')
|
|
|
|
|
if video_id:
|
|
|
|
|
yield self._extract_video(renderer)
|
|
|
|
@ -5114,18 +5138,6 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
|
|
|
|
|
})),
|
|
|
|
|
thumbnails=self._extract_thumbnails(renderer, 'thumbnail', final_key='sources'))
|
|
|
|
|
return
|
|
|
|
|
# lockupViewModel extraction
|
|
|
|
|
content_id = renderer.get('contentId')
|
|
|
|
|
if content_id and renderer.get('contentType') == 'LOCKUP_CONTENT_TYPE_PODCAST':
|
|
|
|
|
yield self.url_result(
|
|
|
|
|
f'https://www.youtube.com/playlist?list={content_id}',
|
|
|
|
|
ie=YoutubeTabIE, video_id=content_id,
|
|
|
|
|
**traverse_obj(renderer, {
|
|
|
|
|
'title': ('metadata', 'lockupMetadataViewModel', 'title', 'content', {str}),
|
|
|
|
|
}),
|
|
|
|
|
thumbnails=self._extract_thumbnails(renderer, (
|
|
|
|
|
'contentImage', 'collectionThumbnailViewModel', 'primaryThumbnail', 'thumbnailViewModel', 'image'), final_key='sources'))
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
def _video_entry(self, video_renderer):
|
|
|
|
|
video_id = video_renderer.get('videoId')
|
|
|
|
@ -5794,7 +5806,7 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
|
|
|
|
|
'info_dict': {
|
|
|
|
|
'id': 'UCYO_jab_esuFRV4b17AJtAw',
|
|
|
|
|
'title': '3Blue1Brown - Playlists',
|
|
|
|
|
'description': 'md5:4d1da95432004b7ba840ebc895b6b4c9',
|
|
|
|
|
'description': 'md5:602e3789e6a0cb7d9d352186b720e395',
|
|
|
|
|
'channel_url': 'https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw',
|
|
|
|
|
'channel': '3Blue1Brown',
|
|
|
|
|
'channel_id': 'UCYO_jab_esuFRV4b17AJtAw',
|
|
|
|
|