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

Code before:
        data = {
            'password': password,
            'grant_type': 'password',
            'username': username,
        }
        if self.get_param('twofactor'):
            data['tfa_token'] = self.get_param('twofactor')

        def _call_login():
            return self._download_json(
                self._OAUTH_URL, None, 'Logging in',
                data=urlencode_postdata(data),
                headers={
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Authorization': f'Bearer {self._ACCESS_TOKEN}',
                },
                errnote='Login failed', fatal=False,
                expected_status=lambda s: s == 200 or 400 <= s < 500)

        response = _call_login()
        if response.get('error') == 'tfa_required':
            data['tfa_token'] = self._get_tfa_info()
            response = _call_login()
        if response.get('error'):
            self.report_warning('API returned error {}: {}'.format(
                response.get('error'), response.get('error_description')))

    def _real_extract(self, url):
        blog_1, blog_2, video_id = self._match_valid_url(url).groups()
        blog = blog_2 or blog_1

        url = f'http://{blog}.tumblr.com/post/{video_id}'
        # whatsapp ua makes iab tcf shut the fuck up
        webpage, urlh = self._download_webpage_handle(url, video_id, headers={
            'User-Agent': 'WhatsApp/2.0'})

        redirect_url = urlh.geturl()

        api_only = bool(self._search_regex(
            r'(tumblr.com|^)/(safe-mode|login_required|blog/view)',
            redirect_url, 'redirect', default=None))

        if api_only and not self._ACCESS_TOKEN:
            raise ExtractorError('Cannot get data for dashboard-only post without access token')

        post_json = {}
        if self._ACCESS_TOKEN:
            post_json = traverse_obj(
                self._download_json(
                    f'https://www.tumblr.com/api/v2/blog/{blog}/posts/{video_id}/permalink',
                    video_id, headers={'Authorization': f'Bearer {self._ACCESS_TOKEN}'}, fatal=False),

Review comment (refactor):
IMO we should raise here
```suggestion
            raise ExtractorError(
                f'API returned error {': '.join(traverse_obj(response, (("error", "error_description"), {str})))}')
```

Code after:
                r'"API_TOKEN":\s*"(\w+)"', login_page, 'API access token', fatal=False)
        if not self._ACCESS_TOKEN:
            self.report_warning('Failed to get access token; metadata will be missing and some videos may not work')

    def _perform_login(self, username, password):
        if not self._ACCESS_TOKEN:
            return

        data = {
            'password': password,
            'grant_type': 'password',
            'username': username,
        }
        if self.get_param('twofactor'):
            data['tfa_token'] = self.get_param('twofactor')

        def _call_login():
            return self._download_json(
                self._OAUTH_URL, None, 'Logging in',
                data=urlencode_postdata(data),
                headers={
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Authorization': f'Bearer {self._ACCESS_TOKEN}',
                },
                errnote='Login failed', fatal=False,
                expected_status=lambda s: 400 <= s < 500)

        response = _call_login()
        if traverse_obj(response, 'error') == 'tfa_required':
            data['tfa_token'] = self._get_tfa_info()
            response = _call_login()
        if traverse_obj(response, 'error'):
            raise ExtractorError(
                f'API returned error {": ".join(traverse_obj(response, (("error", "error_description"), {str})))}')

    def _real_extract(self, url):
        blog_1, blog_2, video_id = self._match_valid_url(url).groups()
        blog = blog_2 or blog_1

        url = f'http://{blog}.tumblr.com/post/{video_id}'
        webpage, urlh = self._download_webpage_handle(
            url, video_id, headers={'User-Agent': 'WhatsApp/2.0'})  # whatsapp ua bypasses problems

        redirect_url = urlh.url

        api_only = bool(self._search_regex(
            r'(tumblr.com|^)/(safe-mode|login_required|blog/view)',
            redirect_url, 'redirect', default=None))

        if api_only and not self._ACCESS_TOKEN:
            raise ExtractorError('Cannot get data for dashboard-only post without access token')