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

Code before:
                resp = self._parse_json(e.cause.read().decode(), None, fatal=False)
                if resp:
                    error = resp.get('extra_info') or resp.get('error_description') or resp.get('error')
                    if error:
                        msg += ': ' + error
            raise ExtractorError('Unable to log in: ' + msg)

    def _real_initialize(self):
        self._login()

    def _real_extract(self, url):
        MAX_TITLE_LENGTH = 128
        language, video_id = re.match(self._VALID_URL, url).groups()
        if not language:
            language = 'en'
        self.debug_out("url: " + url + " video_id: " + video_id + " language: " + language)
        webpage = self._download_webpage(url, video_id)
        playlist_title = self._html_search_regex(r'<title>(.+?)</title>', webpage, 'title') or \
            self._og_search_title(webpage)
        self.debug_out("playlist_title: " + playlist_title)

        # use the API to get other information about the concert
        vid_info_dict = self._download_json(
            'https://api.digitalconcerthall.com/v2/concert/'
            + video_id, video_id, headers={'Accept': 'application/json',
                                           'Accept-Language': language})
        embedded = vid_info_dict.get('_embedded')
        entries = []
        for embed_type in embedded:
            # embed_type should be either 'work' or 'interview'
            # 'work' will be an array of one or more works
            for item in embedded.get(embed_type):
                if embed_type == 'interview':
                    item['is_interview'] = 1
                else:
                    item['is_interview'] = 0
                stream_href = item.get('_links').get('streams').get('href')
                self.debug_out("JSON URL: " + 'https:' + stream_href)
                test_dict = self._download_json('https:' + stream_href, video_id,
                    headers={'Accept': 'application/json',
                    'Authorization': 'Bearer ' + self._ACCCESS_TOKEN,
                    'Accept-Language': language})
                m3u8_url = test_dict['channel']['vod_mixed_hls_h264_hevc_abr_uhd']['stream'][0]['url']
                self.debug_out('stream URL: ' + m3u8_url)

                formats = self._extract_m3u8_formats(
                    m3u8_url, video_id, 'mp4', 'm3u8_native', fatal=False)
                self._sort_formats(formats)

                if item.get('is_interview') == 1:
                    title = "Interview - " + item.get('title', "unknown interview title")

Review comment (refactor):
```suggestion
        vid_info_dict = self._download_json(
            f'https://api.digitalconcerthall.com/v2/concert/{video_id}', video_id, headers={
                'Accept': 'application/json',
                'Accept-Language': language
            })
```
Also, change the var name to something else. We use `info_dict` generally to refer to the return value of extractors. So this is a bit confusing

Code after:

            yield {
                'id': video_id,
                'title': item.get('title'),
                'composer': item.get('name_composer'),
                'url': m3u8_url,
                'formats': formats,
                'duration': item.get('duration_total'),
                'timestamp': traverse_obj(item, ('date', 'published')),
                'description': item.get('short_description') or stream_info.get('short_description'),
                **kwargs,
                'chapters': [{
                    'start_time': chapter.get('time'),
                    'end_time': try_get(chapter, lambda x: x['time'] + x['duration']),
                    'title': chapter.get('text'),
                } for chapter in item['cuepoints']] if item.get('cuepoints') else None,
            }

    def _real_extract(self, url):
        language, video_id = self._match_valid_url(url).group('language', 'id')
        if not language:
            language = 'en'

        thumbnail_url = self._html_search_regex(
            r'(https?://images\.digitalconcerthall\.com/cms/thumbnails/.*\.jpg)',
            self._download_webpage(url, video_id), 'thumbnail')
        thumbnails = [{
            'url': thumbnail_url,
            **parse_resolution(thumbnail_url)
        }]

        vid_info = self._download_json(
            f'https://api.digitalconcerthall.com/v2/concert/{video_id}', video_id, headers={
                'Accept': 'application/json',
                'Accept-Language': language
            })
        album_artist = ' / '.join(traverse_obj(vid_info, ('_links', 'artist', ..., 'name')) or '')

        return {
            '_type': 'playlist',
            'id': video_id,
            'title': vid_info.get('title'),
            'entries': self._entries(traverse_obj(vid_info, ('_embedded', ..., ...)), language,
                                     thumbnails=thumbnails, album_artist=album_artist),
            'thumbnails': thumbnails,
            'album_artist': album_artist,
        }