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

Code before:
            'duration': 1219,
            'channel': 'StarPlus',
            'channel_id': 3,
            'series': 'Ek Bhram - Sarvagun Sampanna',
            'season': 'Chapter 1',
            'season_number': 1,
            'season_id': 6771,
            'episode': 'Janhvi Targets Suman',
            'episode_number': 8,
        },
    }]
    _GEO_BYPASS = False

    def _real_extract(self, url):
        mobj = re.match(self._VALID_URL, url)
        video_id = mobj.group('id')
        video_type = mobj.group('type')
        cookies = self._get_cookies(url)
        if video_type == 'movies':
            video_data = self._call_api('o/v1/movie/detail', video_id)['body']['results']['item']
        elif video_type == 'sports':
            video_data = self._call_api('o/v1/match/detail', video_id)['body']['results']['item']
        elif video_type == 'episode' or video_type == 'tv':
            video_data = self._call_api('o/v1/episode/detail', video_id)['body']['results']['item']
        else:
            video_data = self._call_api('o/v1/content/detail', video_id)['body']['results']['item']

        title = video_data['title']

        if not self.get_param('allow_unplayable_formats') and video_data.get('drmProtected'):
            raise ExtractorError('This video is DRM protected.', expected=True)
        headers = {'Referer': 'https://www.hotstar.com/in'}
        formats = []
        subs = {}
        geo_restricted = False
        # change to v2 in the future
        playback_sets = self._call_api_v2('play/v1/playback', video_id, cookies=cookies)['playBackSets']
        for playback_set in playback_sets:
            if not isinstance(playback_set, dict):
                continue
            format_url = url_or_none(playback_set.get('playbackUrl'))
            if not format_url:
                continue
            format_url = re.sub(
                r'(?<=//staragvod)(\d)', r'web\1', format_url)
            tags = str_or_none(playback_set.get('tagsCombination')) or ''
            if tags and 'encryption:plain' not in tags:
                continue
            ext = determine_ext(format_url)
            try:
                if 'package:hls' in tags or ext == 'm3u8':

Review comment (refactor):
DRY

```py
        ep = {'tv': 'episode', None: 'content', 'movies': 'movie', 'sports': 'match'}  #maybe make this a class property?
        video_type = ep.get(video_type, video_type)
        video_data = self._call_api(f'o/v1/{video_type}/detail', video_id)['body']['results']['item']
```

Code after:
        for playback_set in playback_sets:
            if not isinstance(playback_set, dict):
                continue
            format_url = url_or_none(playback_set.get('playbackUrl'))
            if not format_url:
                continue
            format_url = re.sub(
                r'(?<=//staragvod)(\d)', r'web\1', format_url)
            tags = str_or_none(playback_set.get('tagsCombination')) or ''
            if tags and 'encryption:plain' not in tags:
                continue
            ext = determine_ext(format_url)
            try:
                if 'package:hls' in tags or ext == 'm3u8':
                    hls_formats, hls_subs = self._extract_m3u8_formats_and_subtitles(
                        format_url, video_id, 'mp4',
                        entry_protocol='m3u8_native',
                        m3u8_id='hls', headers=headers)
                    formats.extend(hls_formats)
                    subs = self._merge_subtitles(subs, hls_subs)
                elif 'package:dash' in tags or ext == 'mpd':
                    dash_formats, dash_subs = self._extract_mpd_formats_and_subtitles(
                        format_url, video_id, mpd_id='dash', headers=headers)
                    formats.extend(dash_formats)
                    subs = self._merge_subtitles(subs, dash_subs)
                elif ext == 'f4m':
                    # produce broken files
                    pass
                else:
                    formats.append({
                        'url': format_url,
                        'width': int_or_none(playback_set.get('width')),
                        'height': int_or_none(playback_set.get('height')),
                    })
            except ExtractorError as e:
                if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:
                    geo_restricted = True
                continue
        if not formats and geo_restricted:
            self.raise_geo_restricted(countries=['IN'], metadata_available=True)
        self._sort_formats(formats)

        for f in formats:
            f.setdefault('http_headers', {}).update(headers)

        return {
            'id': video_id,
            'title': title,
            'description': video_data.get('description'),
            'duration': int_or_none(video_data.get('duration')),
            'timestamp': int_or_none(video_data.get('broadcastDate') or video_data.get('startDate')),