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

Code before:
            'upload_date': '20170411',
            'timestamp': 1491929865,
            'duration': 213,
        },
        'params': {
            'skip_download': True,
        },
    }, {
        # adult content
        'url': 'https://vod.sooplive.co.kr/player/97267690',
        'info_dict': {
            'id': '20180327_27901457_202289533_1',
            'ext': 'mp4',
            'title': '[생]빨개요♥ (part 1)',
            'thumbnail': 're:^https?://(?:video|st)img.sooplive.co.kr/.*$',
            'uploader': '[SA]서아',
            'uploader_id': 'bjdyrksu',
            'upload_date': '20180327',
            'duration': 3601,
        },
        'params': {
            'skip_download': True,
        },
        'skip': 'The VOD does not exist',
    }, {
        'url': 'http://www.sooplive.co.kr/player/Player.swf?szType=szBjId=djleegoon&nStationNo=11273158&nBbsNo=13161095&nTitleNo=36327652',
        'only_matching': True,
    }, {
        'url': 'https://vod.sooplive.co.kr/player/96753363',
        'info_dict': {
            'id': '20230108_9FF5BEE1_244432674_1',
            'ext': 'mp4',
            'uploader_id': 'rlantnghks',
            'uploader': '페이즈으',
            'duration': 10840,
            'thumbnail': r're:https?://videoimg\.sooplive\.co/.kr/.+',
            'upload_date': '20230108',
            'timestamp': 1673218805,
            'title': '젠지 페이즈',
        },
        'params': {
            'skip_download': True,
        },
    }, {
        # adult content
        'url': 'https://vod.sooplive.co.kr/player/70395877',
        'only_matching': True,
    }, {
        # subscribers only
        'url': 'https://vod.sooplive.co.kr/player/104647403',
        'only_matching': True,

Review comment (suggestion):
```suggestion
        'url': 'http://www.afreecatv.com/player/Player.swf?szType=szBjId=djleegoon&nStationNo=11273158&nBbsNo=13161095&nTitleNo=36327652',
```

Code after:
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        data = self._call_api(
            'station/video/a/view', video_id, headers={'Referer': url},
            data=urlencode_postdata({
                'nTitleNo': video_id,
                'nApiLevel': 10,
            }))['data']

        error_code = traverse_obj(data, ('code', {int}))
        if error_code == -6221:
            raise ExtractorError('The VOD does not exist', expected=True)
        elif error_code == -6205:
            raise ExtractorError('This VOD is private', expected=True)

        common_info = traverse_obj(data, {
            'title': ('title', {str}),
            'uploader': ('writer_nick', {str}),
            'uploader_id': ('bj_id', {str}),
            'duration': ('total_file_duration', {functools.partial(int_or_none, scale=1000)}),
            'thumbnail': ('thumb', {url_or_none}),
        })

        entries = []
        for file_num, file_element in enumerate(
                traverse_obj(data, ('files', lambda _, v: url_or_none(v['file']))), start=1):
            file_url = file_element['file']
            if determine_ext(file_url) == 'm3u8':
                formats = self._extract_m3u8_formats(
                    file_url, video_id, 'mp4', m3u8_id='hls',
                    note=f'Downloading part {file_num} m3u8 information')
            else:
                formats = [{
                    'url': file_url,
                    'format_id': 'http',
                }]

            entries.append({
                **common_info,
                'id': file_element.get('file_info_key') or f'{video_id}_{file_num}',
                'title': f'{common_info.get("title") or "Untitled"} (part {file_num})',
                'formats': formats,
                **traverse_obj(file_element, {
                    'duration': ('duration', {functools.partial(int_or_none, scale=1000)}),
                    'timestamp': ('file_start', {unified_timestamp}),
                }),
            })

        if traverse_obj(data, ('adult_status', {str})) == 'notLogin':