- last_error = None
- for bearer_token in self._TOKENS:
- for first_attempt in (True, False):
- headers['Authorization'] = f'Bearer {bearer_token}'
-
- if not self.is_logged_in:
- if not self._TOKENS[bearer_token]:
- headers.pop('x-guest-token', None)
- guest_token_response = self._download_json(
- self._API_BASE + 'guest/activate.json', video_id,
- 'Downloading guest token', data=b'', headers=headers)
-
- self._TOKENS[bearer_token] = guest_token_response.get('guest_token')
- if not self._TOKENS[bearer_token]:
- raise ExtractorError('Could not retrieve guest token')
-
- headers['x-guest-token'] = self._TOKENS[bearer_token]
-
- try:
- allowed_status = {400, 403, 404} if graphql else {403}
- result = self._download_json(
- (self._GRAPHQL_API_BASE if graphql else self._API_BASE) + path,
- video_id, headers=headers, query=query, expected_status=allowed_status)
-
- except ExtractorError as e:
- if last_error:
- raise last_error
-
- if not isinstance(e.cause, urllib.error.HTTPError) or e.cause.code != 404:
- raise
-
- last_error = e
- self.report_warning(
- 'Twitter API gave 404 response, retrying with deprecated auth token. '
- 'Only one media item can be extracted')
- break # continue outer loop with next bearer_token
-
- if result.get('errors'):
- errors = traverse_obj(result, ('errors', ..., 'message'), expected_type=str)
- if first_attempt and any('bad guest token' in error.lower() for error in errors):
- self.to_screen('Guest token has expired. Refreshing guest token')
- self._TOKENS[bearer_token] = None
- continue
+ for first_attempt in (True, False):
+ if not self.is_logged_in and not self._guest_token:
+ headers.pop('x-guest-token', None)
+ self._guest_token = traverse_obj(self._download_json(
+ f'{self._API_BASE}guest/activate.json', video_id,
+ 'Downloading guest token', data=b'', headers=headers), 'guest_token')
+ if self._guest_token:
+ headers['x-guest-token'] = self._guest_token
+ elif not self.is_logged_in:
+ raise ExtractorError('Could not retrieve guest token')
+
+ allowed_status = {400, 401, 403, 404} if graphql else {403}
+ result = self._download_json(
+ (self._GRAPHQL_API_BASE if graphql else self._API_BASE) + path,
+ video_id, headers=headers, query=query, expected_status=allowed_status,
+ note=f'Downloading {"GraphQL" if graphql else "legacy API"} JSON')
+
+ if result.get('errors'):
+ errors = ', '.join(set(traverse_obj(result, ('errors', ..., 'message', {str}))))
+ if not self.is_logged_in and first_attempt and 'bad guest token' in errors.lower():
+ self.to_screen('Guest token has expired. Refreshing guest token')
+ self._guest_token = None
+ continue