Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/twitter.py (Python)

Code before:
            },
            'features': {
                'graphql_is_translatable_rweb_tweet_is_translatable_enabled': False,
                'interactive_text_enabled': True,
                'responsive_web_edit_tweet_api_enabled': True,
                'responsive_web_enhance_cards_enabled': True,
                'responsive_web_graphql_timeline_navigation_enabled': False,
                'responsive_web_text_conversations_enabled': False,
                'responsive_web_uc_gql_enabled': True,
                'standardized_nudges_misinfo': True,
                'tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled': False,
                'tweetypie_unmention_optimization_enabled': True,
                'unified_cards_ad_metadata_container_dynamic_card_content_query_enabled': True,
                'verified_phone_label_enabled': False,
                'vibe_api_enabled': True,
            },
        }

    def _real_extract(self, url):
        twid = self._match_id(url)
        use_graphql = self.is_logged_in()

        force_graphql = bool(self._configuration_arg('force_graphql', ie_key=self.ie_key()))
        if force_graphql and not use_graphql:
            self.report_warning('Forced usage of GraphQL API', only_once=True)
            use_graphql = True

        if use_graphql:
            result = self._call_graphql_api('zZXycP0V6H7m-2r0mOnFcA/TweetDetail', twid)
            status = self._graphql_to_legacy(result, twid)

        else:
            status = self._call_api(f'statuses/show/{twid}.json', twid, {
                'cards_platform': 'Web-12',
                'include_cards': 1,
                'include_reply_count': 1,
                'include_user_entities': 0,
                'tweet_mode': 'extended',
            })

        title = description = status['full_text'].replace('\n', ' ')
        # strip  'https -_t.co_BJYgOjSeGA' junk from filenames
        title = re.sub(r'\s+(https?://[^ ]+)', '', title)
        user = status.get('user') or {}
        uploader = user.get('name')
        if uploader:
            title = f'{uploader} - {title}'
        uploader_id = user.get('screen_name')

        tags = []
        for hashtag in (try_get(status, lambda x: x['entities']['hashtags'], list) or []):

Review comment (bug):
warning is unnecessary. If you need the message, put it in debug/stdout
```suggestion
        if not use_graphql and self._configuration_arg('force_graphql'):
            self.write_debug('Forced usage of GraphQL API')
            use_graphql = True
```

Code after:
    }, {
        # poll3choice_video card
        'url': 'https://twitter.com/SamsungMobileSA/status/1348609186725289984',
        'only_matching': True,
    }, {
        # poll4choice_video card
        'url': 'https://twitter.com/SouthamptonFC/status/1347577658079641604',
        'only_matching': True,
    }]

    def _graphql_to_legacy(self, data, twid):
        result = traverse_obj(data, (
            'threaded_conversation_with_injections_v2', 'instructions', 0, 'entries',
            lambda _, v: v['entryId'] == f'tweet-{twid}', 'content', 'itemContent',
            'tweet_results', 'result'
        ), expected_type=dict, default={}, get_all=False)

        if 'tombstone' in result:
            cause = traverse_obj(result, ('tombstone', 'text', 'text'), expected_type=str)
            raise ExtractorError(f'Twitter API says: {cause or "Unknown error"}', expected=True)

        status = result.get('legacy', {})
        status.update(traverse_obj(result, {
            'user': ('core', 'user_results', 'result', 'legacy'),
            'card': ('card', 'legacy'),
            'quoted_status': ('quoted_status_result', 'result', 'legacy'),
        }, expected_type=dict, default={}))

        # extra transformation is needed since result does not match legacy format
        binding_values = {
            binding_value.get('key'): binding_value.get('value')
            for binding_value in traverse_obj(status, ('card', 'binding_values', ...), expected_type=dict)
        }
        if binding_values:
            status['card']['binding_values'] = binding_values

        return status

    def _build_graphql_query(self, media_id):
        return {
            'variables': {
                'focalTweetId': media_id,
                'includePromotedContent': True,
                'with_rux_injections': False,
                'withBirdwatchNotes': True,
                'withCommunity': True,
                'withDownvotePerspective': False,
                'withQuickPromoteEligibilityTweetFields': True,
                'withReactionsMetadata': False,
                'withReactionsPerspective': False,
                'withSuperFollowsTweetFields': True,