mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-31 14:45:14 +00:00 
			
		
		
		
	[Youtube] Fix private feeds/playlists on multi-channel accounts (#143)
Authored by: colethedj
This commit is contained in:
		| @@ -301,7 +301,6 @@ class YoutubeBaseInfoExtractor(InfoExtractor): | |||||||
|         auth = self._generate_sapisidhash_header() |         auth = self._generate_sapisidhash_header() | ||||||
|         if auth is not None: |         if auth is not None: | ||||||
|             headers.update({'Authorization': auth, 'X-Origin': 'https://www.youtube.com'}) |             headers.update({'Authorization': auth, 'X-Origin': 'https://www.youtube.com'}) | ||||||
|  |  | ||||||
|         return self._download_json( |         return self._download_json( | ||||||
|             'https://www.youtube.com/youtubei/v1/%s' % ep, |             'https://www.youtube.com/youtubei/v1/%s' % ep, | ||||||
|             video_id=video_id, fatal=fatal, note=note, errnote=errnote, |             video_id=video_id, fatal=fatal, note=note, errnote=errnote, | ||||||
| @@ -2704,7 +2703,7 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor): | |||||||
|             ctp = continuation_ep.get('clickTrackingParams') |             ctp = continuation_ep.get('clickTrackingParams') | ||||||
|             return YoutubeTabIE._build_continuation_query(continuation, ctp) |             return YoutubeTabIE._build_continuation_query(continuation, ctp) | ||||||
|  |  | ||||||
|     def _entries(self, tab, identity_token, item_id): |     def _entries(self, tab, item_id, identity_token, account_syncid): | ||||||
|  |  | ||||||
|         def extract_entries(parent_renderer):  # this needs to called again for continuation to work with feeds |         def extract_entries(parent_renderer):  # this needs to called again for continuation to work with feeds | ||||||
|             contents = try_get(parent_renderer, lambda x: x['contents'], list) or [] |             contents = try_get(parent_renderer, lambda x: x['contents'], list) or [] | ||||||
| @@ -2764,6 +2763,10 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor): | |||||||
|         if identity_token: |         if identity_token: | ||||||
|             headers['x-youtube-identity-token'] = identity_token |             headers['x-youtube-identity-token'] = identity_token | ||||||
|  |  | ||||||
|  |         if account_syncid: | ||||||
|  |             headers['X-Goog-PageId'] = account_syncid | ||||||
|  |             headers['X-Goog-AuthUser'] = 0 | ||||||
|  |  | ||||||
|         for page_num in itertools.count(1): |         for page_num in itertools.count(1): | ||||||
|             if not continuation: |             if not continuation: | ||||||
|                 break |                 break | ||||||
| @@ -2883,7 +2886,7 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor): | |||||||
|                         try_get(owner, lambda x: x['navigationEndpoint']['browseEndpoint']['canonicalBaseUrl'], compat_str)) |                         try_get(owner, lambda x: x['navigationEndpoint']['browseEndpoint']['canonicalBaseUrl'], compat_str)) | ||||||
|         return {k: v for k, v in uploader.items() if v is not None} |         return {k: v for k, v in uploader.items() if v is not None} | ||||||
|  |  | ||||||
|     def _extract_from_tabs(self, item_id, webpage, data, tabs, identity_token): |     def _extract_from_tabs(self, item_id, webpage, data, tabs): | ||||||
|         playlist_id = title = description = channel_url = channel_name = channel_id = None |         playlist_id = title = description = channel_url = channel_name = channel_id = None | ||||||
|         thumbnails_list = tags = [] |         thumbnails_list = tags = [] | ||||||
|  |  | ||||||
| @@ -2947,7 +2950,10 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor): | |||||||
|             'channel_id': metadata['uploader_id'], |             'channel_id': metadata['uploader_id'], | ||||||
|             'channel_url': metadata['uploader_url']}) |             'channel_url': metadata['uploader_url']}) | ||||||
|         return self.playlist_result( |         return self.playlist_result( | ||||||
|             self._entries(selected_tab, identity_token, playlist_id), |             self._entries( | ||||||
|  |                 selected_tab, playlist_id, | ||||||
|  |                 self._extract_identity_token(webpage, item_id), | ||||||
|  |                 self._extract_account_syncid(data)), | ||||||
|             **metadata) |             **metadata) | ||||||
|  |  | ||||||
|     def _extract_mix_playlist(self, playlist, playlist_id): |     def _extract_mix_playlist(self, playlist, playlist_id): | ||||||
| @@ -3026,6 +3032,17 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor): | |||||||
|             r'\bID_TOKEN["\']\s*:\s*["\'](.+?)["\']', webpage, |             r'\bID_TOKEN["\']\s*:\s*["\'](.+?)["\']', webpage, | ||||||
|             'identity token', default=None) |             'identity token', default=None) | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def _extract_account_syncid(data): | ||||||
|  |         """Extract syncId required to download private playlists of secondary channels""" | ||||||
|  |         sync_ids = ( | ||||||
|  |             try_get(data, lambda x: x['responseContext']['mainAppWebResponseContext']['datasyncId'], compat_str) | ||||||
|  |             or '').split("||") | ||||||
|  |         if len(sync_ids) >= 2 and sync_ids[1]: | ||||||
|  |             # datasyncid is of the form "channel_syncid||user_syncid" for secondary channel | ||||||
|  |             # and just "user_syncid||" for primary channel. We only want the channel_syncid | ||||||
|  |             return sync_ids[0] | ||||||
|  |  | ||||||
|     def _extract_webpage(self, url, item_id): |     def _extract_webpage(self, url, item_id): | ||||||
|         retries = self._downloader.params.get('extractor_retries', 3) |         retries = self._downloader.params.get('extractor_retries', 3) | ||||||
|         count = -1 |         count = -1 | ||||||
| @@ -3085,8 +3102,7 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor): | |||||||
|         tabs = try_get( |         tabs = try_get( | ||||||
|             data, lambda x: x['contents']['twoColumnBrowseResultsRenderer']['tabs'], list) |             data, lambda x: x['contents']['twoColumnBrowseResultsRenderer']['tabs'], list) | ||||||
|         if tabs: |         if tabs: | ||||||
|             identity_token = self._extract_identity_token(webpage, item_id) |             return self._extract_from_tabs(item_id, webpage, data, tabs) | ||||||
|             return self._extract_from_tabs(item_id, webpage, data, tabs, identity_token) |  | ||||||
|  |  | ||||||
|         playlist = try_get( |         playlist = try_get( | ||||||
|             data, lambda x: x['contents']['twoColumnWatchNextResults']['playlist']['playlist'], dict) |             data, lambda x: x['contents']['twoColumnWatchNextResults']['playlist']['playlist'], dict) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Matthew
					Matthew