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

Code before:
            'http://www.bilibili.tv/video/av%s/' % video_id,
            ie=BiliBiliIE.ie_key(), video_id=video_id)


class BiliIntlBaseIE(InfoExtractor):
    _API_URL = 'https://api.bilibili.tv/intl/gateway'

    def _call_api(self, endpoint, *args, **kwargs):
        return self._download_json(self._API_URL + endpoint, *args, **kwargs)['data']

    def json2srt(self, json):
        data = '\n\n'.join(
            f'{i + 1}\n{srt_subtitles_timecode(line["from"])} --> {srt_subtitles_timecode(line["to"])}\n{line["content"]}'
            for i, line in enumerate(json['body']))
        return data

    def _get_subtitles(self, ep_id):
        sub_json = self._call_api(f'/web/v2/subtitle?episode_id={ep_id}&platform=web', ep_id)
        subtitles = {}
        for sub in sub_json.get('subtitles') or []:
            sub_url = sub.get('url')
            if not sub_url:
                continue
            sub_data = self._download_json(
                sub_url, ep_id,
                note='Downloading subtitles%s' % f' for {sub["lang"]}' if sub.get('lang') else '', errnote='Unable to download subtitles', fatal=False)
            if not sub_data:
                continue
            subtitles.setdefault(sub.get('lang_key', 'en'), []).append({
                'ext': 'srt',
                'data': self.json2srt(sub_data)
            })
        return subtitles

    def _get_formats(self, ep_id):
        video_json = self._call_api(f'/web/playurl?ep_id={ep_id}&platform=web', ep_id,
                                    note='Downloading video formats', errnote='Unable to download video formats')
        if video_json.get('code'):
            if video_json['code'] in (10004004, 10004005, 10023006):
                self.raise_login_required(method='cookies')
            elif video_json['code'] == 10004001:
                self.raise_geo_restricted()
            elif video_json.get('message') and str(video_json['code']) != video_json['message']:
                raise ExtractorError(
                    f'Unable to download video formats: {self.IE_NAME} said: {video_json["message"]}', expected=True)
            else:
                raise ExtractorError('Unable to download video formats')
        video_json = video_json['playurl']
        formats = []
        for vid in video_json.get('video') or []:
            video_res = vid.get('video_resource') or {}

Review comment (suggestion):
```suggestion
            sub_data = self._download_json(
                sub_url, ep_id, errnote='Unable to download subtitles', fatal=False,
                note='Downloading subtitles%s' % f' for {sub["lang"]}' if sub.get('lang') else '')
```

Code after:
            'http://www.bilibili.tv/video/av%s/' % video_id,
            ie=BiliBiliIE.ie_key(), video_id=video_id)


class BiliIntlBaseIE(InfoExtractor):
    _API_URL = 'https://api.bilibili.tv/intl/gateway'

    def _call_api(self, endpoint, *args, **kwargs):
        return self._download_json(self._API_URL + endpoint, *args, **kwargs)['data']

    def json2srt(self, json):
        data = '\n\n'.join(
            f'{i + 1}\n{srt_subtitles_timecode(line["from"])} --> {srt_subtitles_timecode(line["to"])}\n{line["content"]}'
            for i, line in enumerate(json['body']))
        return data

    def _get_subtitles(self, ep_id):
        sub_json = self._call_api(f'/web/v2/subtitle?episode_id={ep_id}&platform=web', ep_id)
        subtitles = {}
        for sub in sub_json.get('subtitles') or []:
            sub_url = sub.get('url')
            if not sub_url:
                continue
            sub_data = self._download_json(
                sub_url, ep_id, errnote='Unable to download subtitles', fatal=False,
                note='Downloading subtitles%s' % f' for {sub["lang"]}' if sub.get('lang') else '')
            if not sub_data:
                continue
            subtitles.setdefault(sub.get('lang_key', 'en'), []).append({
                'ext': 'srt',
                'data': self.json2srt(sub_data)
            })
        return subtitles

    def _get_formats(self, ep_id):
        video_json = self._call_api(f'/web/playurl?ep_id={ep_id}&platform=web', ep_id,
                                    note='Downloading video formats', errnote='Unable to download video formats')
        if video_json.get('code'):
            if video_json['code'] in (10004004, 10004005, 10023006):
                self.raise_login_required(method='cookies')
            elif video_json['code'] == 10004001:
                self.raise_geo_restricted()
            elif video_json.get('message') and str(video_json['code']) != video_json['message']:
                raise ExtractorError(
                    f'Unable to download video formats: {self.IE_NAME} said: {video_json["message"]}', expected=True)
            else:
                raise ExtractorError('Unable to download video formats')
        video_json = video_json['playurl']
        formats = []
        for vid in video_json.get('video') or []:
            video_res = vid.get('video_resource') or {}