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

Code before:
        'only_matching': True,
    }, {
        # poll2choice_video card
        'url': 'https://twitter.com/CAF_Online/status/1349365911120195585',
        'only_matching': True,
    }, {
        # 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):
        def filter_tweet(_, obj):
            return obj['entryId'] == f'tweet-{twid}'

        path = ('threaded_conversation_with_injections_v2', 'instructions', 0, 'entries',
                filter_tweet, 'content', 'itemContent', 'tweet_results', 'result')
        result = traverse_obj(data, path, expected_type=dict, default={}, get_all=False)

        if 'tombstone' in result:
            cause = traverse_obj(result, ('tombstone', 'text', 'text'), expected_type=str, default='')
            raise ExtractorError(f'Twitter API says: {cause}', 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,

Review comment (refactor):
```suggestion
            cause = traverse_obj(result, ('tombstone', 'text', 'text'), expected_type=str)
            raise ExtractorError(f'Twitter API says: {cause or "Unknown error"}', expected=True)
```

Code after:
            'id': '1578401165338976258',
            'title': str,
            'description': 'md5:659a6b517a034b4cee5d795381a2dc41',
            'uploader': str,
            'uploader_id': 'primevideouk',
            'timestamp': 1665155137,
            'upload_date': '20221007',
            'age_limit': 0,
            'uploader_url': 'https://twitter.com/primevideouk',
            'comment_count': int,
            'repost_count': int,
            'like_count': int,
            'tags': ['TheRingsOfPower'],
        },
    }, {
        # Twitter Spaces
        'url': 'https://twitter.com/MoniqueCamarra/status/1550101959377551360',
        'info_dict': {
            'id': '1lPJqmBeeNAJb',
            'ext': 'm4a',
            'title': 'EuroFile@6 Ukraine Up-date-Draghi Defenestration-the West',
            'uploader': r're:Monique Camarra.+?',
            'uploader_id': 'MoniqueCamarra',
            'live_status': 'was_live',
            'description': 'md5:acce559345fd49f129c20dbcda3f1201',
            'timestamp': 1658407771464,
        },
        'add_ie': ['TwitterSpaces'],
        'params': {'skip_download': 'm3u8'},
    }, {
        # onion route
        'url': 'https://twitter3e4tixl4xyajtrzo62zg5vztmjuricljdp2c5kshju4avyoid.onion/TwitterBlue/status/1484226494708662273',
        'only_matching': True,
    }, {
        # Twitch Clip Embed
        'url': 'https://twitter.com/GunB1g/status/1163218564784017422',
        'only_matching': True,
    }, {
        # promo_video_website card
        'url': 'https://twitter.com/GunB1g/status/1163218564784017422',
        'only_matching': True,
    }, {
        # promo_video_convo card
        'url': 'https://twitter.com/poco_dandy/status/1047395834013384704',
        'only_matching': True,
    }, {
        # appplayer card
        'url': 'https://twitter.com/poco_dandy/status/1150646424461176832',
        'only_matching': True,
    }, {
        # video_direct_message card