ronantakizawa/codereview-bench huggingface dataset:
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/elevensports.py (Python)

Code before:
            'upload_date': '20230521',
            'timestamp': 1684684800,
            'thumbnail': r're:^https?://.*\.(?:jpg|png)',
        },
        'params': {'skip_download': 'm3u8'}
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        nextjs_info = self._search_nextjs_data(webpage, video_id)
        event_id = traverse_obj(nextjs_info, ('props', 'pageProps', 'event', 'mclsEventId'), default={})
        event_data = self._download_json(
            f'https://mcls-api.mycujoo.tv/bff/events/v1beta1/{event_id}', video_id, headers={"Authorization": "Bearer FBVKACGN37JQC5SFA0OVK8KKSIOP153G"})
        formats, subtitles = self._extract_m3u8_formats_and_subtitles(
            event_data['streams'][0]['full_url'], video_id, 'mp4', m3u8_id='hls', fatal=False
        )

        return {
            'id': video_id,
            'formats': formats,
            'subtitles': subtitles,
            **traverse_obj(event_data, {
                'title': ('title', {str}),
                'description': ('description', {str}),
                'upload_date': ('start_time', {unified_strdate}),
                'timestamp': ('start_time', {parse_iso8601}),
                'thumbnail': ('thumbnail_url', {url_or_none}),
            }),
        }


Review comment (refactor):
`upload_date` will be calculated from `timestamp`, you don't need to extract the same value twice
```suggestion
```

Code after:
            'timestamp': 1684684800,
            'thumbnail': r're:^https?://.*\.(?:jpg|png)',
        },
        'params': {'skip_download': 'm3u8'}
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        event_id = self._search_nextjs_data(webpage, video_id)['props']['pageProps']['event']['mclsEventId']
        event_data = self._download_json(
            f'https://mcls-api.mycujoo.tv/bff/events/v1beta1/{event_id}', video_id,
            headers={'Authorization': 'Bearer FBVKACGN37JQC5SFA0OVK8KKSIOP153G'})
        formats, subtitles = self._extract_m3u8_formats_and_subtitles(
            event_data['streams'][0]['full_url'], video_id, 'mp4', m3u8_id='hls')

        return {
            'id': video_id,
            'formats': formats,
            'subtitles': subtitles,
            **traverse_obj(event_data, {
                'title': ('title', {str}),
                'description': ('description', {str}),
                'timestamp': ('start_time', {parse_iso8601}),
                'thumbnail': ('thumbnail_url', {url_or_none}),
            }),
        }
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/elevensports.py (Python)

Code before:
from .common import InfoExtractor
from ..utils import (
    parse_iso8601,
    traverse_obj,
    unified_strdate,
    url_or_none,
)


class ElevenSportsIE(InfoExtractor):
    _VALID_URL = r'https://elevensports\.com/view/event/(?P<id>[a-z0-9]+)'
    _TESTS = [{
        'url': 'https://elevensports.com/view/event/clf46yr3kenn80jgrqsjmwefk',
        'md5': 'c0958d9ff90e4503a75544358758921d',
        'info_dict': {
            'id': 'clf46yr3kenn80jgrqsjmwefk',
            'title': 'Cleveland SC vs Lionsbridge FC',
            'ext': 'mp4',
            'description': 'md5:03b5238d6549f4ea1fddadf69b5e0b58',
            'upload_date': '20230323',
            'timestamp': 1679612400,
            'thumbnail': r're:^https?://.*\.(?:jpg|png)',
        },
        'params': {'skip_download': 'm3u8'}
    }, {
        'url': 'https://elevensports.com/view/event/clhpyd53b06160jez74qhgkmf',
        'md5': 'c0958d9ff90e4503a75544358758921d',
        'info_dict': {
            'id': 'clhpyd53b06160jez74qhgkmf',
            'title': 'AJNLF vs ARRAF',
            'ext': 'mp4',
            'description': 'md5:c8c5e75c78f37c6d15cd6c475e43a8c1',
            'upload_date': '20230521',
            'timestamp': 1684684800,
            'thumbnail': r're:^https?://.*\.(?:jpg|png)',
        },

Review comment (suggestion):
```suggestion
    _VALID_URL = r'https?://(?:www\.)?elevensports\.com/view/event/(?P<id>\w+)'
```

Code after:
from .common import InfoExtractor
from ..utils import (
    parse_iso8601,
    traverse_obj,
    url_or_none,
)


class ElevenSportsIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?elevensports\.com/view/event/(?P<id>\w+)'
    _TESTS = [{
        'url': 'https://elevensports.com/view/event/clf46yr3kenn80jgrqsjmwefk',
        'md5': 'c0958d9ff90e4503a75544358758921d',
        'info_dict': {
            'id': 'clf46yr3kenn80jgrqsjmwefk',
            'title': 'Cleveland SC vs Lionsbridge FC',
            'ext': 'mp4',
            'description': 'md5:03b5238d6549f4ea1fddadf69b5e0b58',
            'upload_date': '20230323',
            'timestamp': 1679612400,
            'thumbnail': r're:^https?://.*\.(?:jpg|png)',
        },
        'params': {'skip_download': 'm3u8'}
    }, {
        'url': 'https://elevensports.com/view/event/clhpyd53b06160jez74qhgkmf',
        'md5': 'c0958d9ff90e4503a75544358758921d',
        'info_dict': {
            'id': 'clhpyd53b06160jez74qhgkmf',
            'title': 'AJNLF vs ARRAF',
            'ext': 'mp4',
            'description': 'md5:c8c5e75c78f37c6d15cd6c475e43a8c1',
            'upload_date': '20230521',
            'timestamp': 1684684800,
            'thumbnail': r're:^https?://.*\.(?:jpg|png)',
        },
        'params': {'skip_download': 'm3u8'}
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/zingmp3.py (Python)

Code before:
import hashlib
import hmac
import itertools
import json
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    traverse_obj,
    ExtractorError,
    int_or_none,
    try_call,
    urljoin
)


class ZingMp3BaseIE(InfoExtractor):
    _VALID_URL_TMPL = r'https?://(?:mp3\.zing|zingmp3)\.vn/(?P<type>(?:%s))/[^/?#]+/(?P<id>\w+)(?:\.html|\?)'
    _GEO_COUNTRIES = ['VN']
    _DOMAIN = 'https://zingmp3.vn'
    _PER_PAGE = 50
    _API_SLUGS = {
        # Audio/video
        'bai-hat': '/api/v2/page/get/song',
        'embed': '/api/v2/page/get/song',
        'video-clip': '/api/v2/page/get/video',
        'lyric': '/api/v2/lyric/get/lyric',
        'song-streaming': '/api/v2/song/get/streaming',
        'liveradio': '/api/v2/livestream/get/info',
        'eps': '/api/v2/page/get/podcast-episode',
        'episode-streaming': '/api/v2/podcast/episode/get/streaming',
        # Playlist
        'playlist': '/api/v2/page/get/playlist',
        'album': '/api/v2/page/get/playlist',
        'pgr': '/api/v2/page/get/podcast-program',
        'pgr-list': '/api/v2/podcast/episode/get/list',
        'cgr': '/api/v2/page/get/podcast-category',
        'cgr-list': '/api/v2/podcast/program/get/list-by-cate',
        'cgrs': '/api/v2/page/get/podcast-categories',

Review comment (refactor):
Ran isort
```suggestion
from ..utils import (
    ExtractorError,
    int_or_none,
    try_call,
    urljoin,
)
from ..utils.traversal import traverse_obj
```

Code after:
import hashlib
import hmac
import itertools
import json
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    int_or_none,
    join_nonempty,
    try_call,
    urljoin,
    url_or_none
)
from ..utils.traversal import traverse_obj


class ZingMp3BaseIE(InfoExtractor):
    _VALID_URL_TMPL = r'https?://(?:mp3\.zing|zingmp3)\.vn/(?P<type>(?:%s))/[^/?#]+/(?P<id>\w+)(?:\.html|\?)'
    _GEO_COUNTRIES = ['VN']
    _DOMAIN = 'https://zingmp3.vn'
    _PER_PAGE = 50
    _API_SLUGS = {
        # Audio/video
        'bai-hat': '/api/v2/page/get/song',
        'embed': '/api/v2/page/get/song',
        'video-clip': '/api/v2/page/get/video',
        'lyric': '/api/v2/lyric/get/lyric',
        'song-streaming': '/api/v2/song/get/streaming',
        'liveradio': '/api/v2/livestream/get/info',
        'eps': '/api/v2/page/get/podcast-episode',
        'episode-streaming': '/api/v2/podcast/episode/get/streaming',
        # Playlist
        'playlist': '/api/v2/page/get/playlist',
        'album': '/api/v2/page/get/playlist',
        'pgr': '/api/v2/page/get/podcast-program',
        'pgr-list': '/api/v2/podcast/episode/get/list',
        'cgr': '/api/v2/page/get/podcast-category',
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/zingmp3.py (Python)

Code before:
        return self.playlist_result(
            entries, post_cast_id, post_cast_info.get('title'), post_cast_info.get('description'))


class ZingMp3PostCastCategoriesIE(ZingMp3BaseIE):
    IE_NAME = 'zingmp3:postcast-categories'
    _VALID_URL = r'https?://(?:mp3\.zing|zingmp3)\.vn/(?P<id>(?:cgr|top-podcast))/?(?:[#?]|$)'
    _TESTS = [{
        'url': 'https://zingmp3.vn/cgr',
        'info_dict': {
            'id': 'cgr',
        },
        'playlist_mincount': 5,
    }, {
        'url': 'https://zingmp3.vn/top-podcast',
        'info_dict': {
            'id': 'top-podcast',
        },
        'playlist_mincount': 50,
    }]

    def _real_extract(self, url):
        url_type = self._match_id(url)
        data = self._call_api('cgrs' if url_type == 'cgr' else url_type, {'id': url_type})
        items = traverse_obj(data, 'items')
        return self.playlist_result(self._parse_items(items), url_type)


class ZingMp3PostCastNewIE(ZingMp3BaseIE):
    IE_NAME = 'zingmp3:postcast-new'
    _VALID_URL = r'https?://(?:mp3\.zing|zingmp3)\.vn/(?P<id>podcast-new)/?(?:[#?]|$)'
    _TESTS = [{
        'url': 'https://zingmp3.vn/podcast-new',
        'info_dict': {
            'id': 'podcast-new',
        },
        'playlist_mincount': 5,
    }]

    def _real_extract(self, url):
        url_type = self._match_id(url)
        data = self._call_api('podcast-discover', {'id': url_type, 'type': 'new'})
        items = traverse_obj(data, 'items')
        return self.playlist_result(self._parse_items(items), url_type)


Review comment (suggestion):
```suggestion
        return self.playlist_result(self._parse_items(data.get('items')), url_type)
```

Code after:
        podcast_id, url_type = self._match_valid_url(url).group('id', 'type')
        podcast_info = self._call_api(url_type, {'id': podcast_id})
        entries = self._paged_list(podcast_id, 'pgr-list' if url_type == 'pgr' else 'cgr-list')
        return self.playlist_result(
            entries, podcast_id, podcast_info.get('title'), podcast_info.get('description'))


class ZingMp3PodcastIE(ZingMp3BaseIE):
    IE_NAME = 'zingmp3:podcast'
    _VALID_URL = r'https?://(?:mp3\.zing|zingmp3)\.vn/(?P<id>(?:cgr|top-podcast|podcast-new))/?(?:[#?]|$)'
    _TESTS = [{
        'url': 'https://zingmp3.vn/cgr',
        'info_dict': {
            'id': 'cgr',
        },
        'playlist_mincount': 5,
    }, {
        'url': 'https://zingmp3.vn/top-podcast',
        'info_dict': {
            'id': 'top-podcast',
        },
        'playlist_mincount': 7,
    }, {
        'url': 'https://zingmp3.vn/podcast-new',
        'info_dict': {
            'id': 'podcast-new',
        },
        'playlist_mincount': 4,
    }]

    def _real_extract(self, url):
        url_type = self._match_id(url)
        params = {'id': url_type}
        if url_type == 'podcast-new':
            params['type'] = 'new'
        items = self._call_api('cgrs' if url_type == 'cgr' else url_type, params)['items']
        return self.playlist_result(self._parse_items(items), url_type)
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/motherless.py (Python)

Code before:
    }, {
        'url': 'http://motherless.com/g/sex_must_be_funny',
        'info_dict': {
            'id': 'sex_must_be_funny',
            'title': 'Sex must be funny',
        },
        'playlist_count': 0,
    }, {
        'url': 'https://motherless.com/gv/beautiful_cock',
        'info_dict': {
            'id': 'beautiful_cock',
            'title': 'Beautiful Cock',
        },
        'playlist_mincount': 2040,
    }]

    @classmethod
    def suitable(cls, url):
        return False if MotherlessIE.suitable(url) else super(MotherlessGroupIE, cls).suitable(url)

    def _correct_path(self, url, item_id):
        return urllib.parse.urljoin(url, f'/gv/{item_id}')


class MotherlessGalleryIE(MotherlessPaginatedIE):
    _VALID_URL = r'https?://(?:www\.)?motherless\.com/G[VIG]?(?P<id>[A-F0-9]+)'
    _TESTS = [{
        'url': 'https://motherless.com/GV338999F',
        'info_dict': {
            'id': '338999F',
            'title': 'Random',
        },
        'playlist_mincount': 190,
    }, {
        'url': 'https://motherless.com/GVABD6213',
        'info_dict': {
            'id': 'ABD6213',
            'title': 'Cuties',
        },
        'playlist_mincount': 2,
    }, {
        'url': 'https://motherless.com/GVBCF7622',
        'info_dict': {
            'id': 'BCF7622',
            'title': 'Vintage',
        },
        'playlist_count': 0,
    }, {
        'url': 'https://motherless.com/G035DE2F',
        'info_dict': {
            'id': '035DE2F',

Review comment (suggestion):
same as above, instead of redefining `suitable`, I think this would work:
```suggestion
    _VALID_URL = r'https?://(?:www\.)?motherless\.com/G[VIG]?(?P<id>[A-F0-9]+)/?(?:$|[#?])'
```

Code after:
        'playlist_count': 0,
    }, {
        'url': 'https://motherless.com/gv/beautiful_cock',
        'info_dict': {
            'id': 'beautiful_cock',
            'title': 'Beautiful Cock',
        },
        'playlist_mincount': 2040,
    }]

    def _correct_path(self, url, item_id):
        return urllib.parse.urljoin(url, f'/gv/{item_id}')


class MotherlessGalleryIE(MotherlessPaginatedIE):
    _VALID_URL = r'https?://(?:www\.)?motherless\.com/G[VIG]?(?P<id>[A-F0-9]+)/?(?:$|[#?])'
    _TESTS = [{
        'url': 'https://motherless.com/GV338999F',
        'info_dict': {
            'id': '338999F',
            'title': 'Random',
        },
        'playlist_mincount': 190,
    }, {
        'url': 'https://motherless.com/GVABD6213',
        'info_dict': {
            'id': 'ABD6213',
            'title': 'Cuties',
        },
        'playlist_mincount': 2,
    }, {
        'url': 'https://motherless.com/GVBCF7622',
        'info_dict': {
            'id': 'BCF7622',
            'title': 'Vintage',
        },
        'playlist_count': 0,
    }, {
        'url': 'https://motherless.com/G035DE2F',
        'info_dict': {
            'id': '035DE2F',
            'title': 'General',
        },
        'playlist_mincount': 420,
    }]

    def _correct_path(self, url, item_id):
        return urllib.parse.urljoin(url, f'/GV{item_id}')
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/motherless.py (Python)

Code before:
import datetime
import re
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    OnDemandPagedList,
    str_to_int,
    unified_strdate,
    remove_end,
)


class MotherlessIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?motherless\.com/(?:g/[a-z0-9_]+/|G[VIG]?[A-F0-9]+/)?(?P<id>[A-F0-9]+)'
    _TESTS = [{
        'url': 'http://motherless.com/EE97006',
        'info_dict': {
            'id': 'EE97006',
            'ext': 'mp4',
            'title': 'Dogging blond Brit getting glazed (comp)',
            'categories': ['UK', 'slag', 'whore', 'dogging', 'cunt', 'cumhound', 'big tits', 'Pearl Necklace'],
            'upload_date': '20230519',
            'uploader_id': 'deathbird',
            'thumbnail': r're:https?://.*\.jpg',
            'age_limit': 18,
            'comment_count': int,
            'view_count': int,
            'like_count': int,
        },
        'params': {
            # Downloads are currently broken because of an incomplete cert chain
            'skip_download': True,
        },
    }, {

Review comment (suggestion):
sort
```suggestion
    remove_end,
    str_to_int,
    unified_strdate,
```

Code after:
import datetime
import re
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    OnDemandPagedList,
    remove_end,
    str_to_int,
    unified_strdate,
)


class MotherlessIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?motherless\.com/(?:g/[a-z0-9_]+/|G[VIG]?[A-F0-9]+/)?(?P<id>[A-F0-9]+)'
    _TESTS = [{
        'url': 'http://motherless.com/EE97006',
        'md5': 'cb5e7438f7a3c4e886b7bccc1292a3bc',
        'info_dict': {
            'id': 'EE97006',
            'ext': 'mp4',
            'title': 'Dogging blond Brit getting glazed (comp)',
            'categories': ['UK', 'slag', 'whore', 'dogging', 'cunt', 'cumhound', 'big tits', 'Pearl Necklace'],
            'upload_date': '20230519',
            'uploader_id': 'deathbird',
            'thumbnail': r're:https?://.*\.jpg',
            'age_limit': 18,
            'comment_count': int,
            'view_count': int,
            'like_count': int,
        },
        'params': {
            # Incomplete cert chains
            'nocheckcertificate': True,
        },
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/zaiko.py (Python)

Code before:
import json
import html
import re

from .common import InfoExtractor
from ..utils import traverse_obj


class ZaikoIE(InfoExtractor):
    _VALID_URL = r'https://zaiko\.io/event/(?P<id>\d+)/stream(?:/\d+)+'
    _TESTS = [{
        'url': 'https://zaiko.io/event/324868/stream/20571/20571',
        'info_dict': {
            'id': 324868,
            'ext': 'mp4',
            'title': 'ZAIKO STREAMING TEST',
            'uploader_id': 454,
            'timestamp': 1583809200,
        }
    }]

    def _parse_vue_element_attr(self, name, string):
        page_elem = self._search_regex(r'<' + name + '([^>]+)>', string, name)
        attr = {}
        for m in re.finditer(r'(:?[\w\-_]+)="([^"]+)"', page_elem):
            key, value = m.groups()
            if key[0] == ':':
                key = key[1:]
                value = json.loads(html.unescape(value))
            attr[key] = value
        return attr

    def _real_extract(self, url):
        video_id = self._match_id(url)


Review comment (suggestion):
Match `http` and `www.` too since they work/redirect in browser
```suggestion
    _VALID_URL = r'https?://(?:www\.)?zaiko\.io/event/(?P<id>\d+)/stream(?:/\d+)+'
```

Code after:
from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    extract_attributes,
    int_or_none,
    str_or_none,
    traverse_obj,
    unescapeHTML,
    url_or_none,
)


class ZaikoIE(InfoExtractor):
    _VALID_URL = r'https?://(?:[\w-]+\.)?zaiko\.io/event/(?P<id>\d+)/stream(?:/\d+)+'
    _TESTS = [{
        'url': 'https://zaiko.io/event/324868/stream/20571/20571',
        'info_dict': {
            'id': '324868',
            'ext': 'mp4',
            'title': 'ZAIKO STREAMING TEST',
            'alt_title': '[VOD] ZAIKO STREAMING TEST_20210603(Do Not Delete)',
            'uploader_id': '454',
            'uploader': 'ZAIKO ZERO',
            'release_timestamp': 1583809200,
            'thumbnail': r're:https://[a-z0-9]+.cloudfront.net/[a-z0-9_]+/[a-z0-9_]+',
            'release_date': '20200310',
            'categories': ['Tech House'],
            'live_status': 'was_live',
        },
        'params': {'skip_download': 'm3u8'},
    }]

    def _parse_vue_element_attr(self, name, string, video_id):
        page_elem = self._search_regex(rf'(<{name}[^>]+>)', string, name)
        attrs = {}
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/zaiko.py (Python)

Code before:
from .common import InfoExtractor
from ..utils import (
    traverse_obj,
    extract_attributes,
    remove_start,
    unescapeHTML,
    url_or_none,
    str_or_none,
    int_or_none,
)


class ZaikoIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?zaiko\.io/event/(?P<id>\d+)/stream(?:/\d+)+'
    _TESTS = [{
        'url': 'https://zaiko.io/event/324868/stream/20571/20571',
        'info_dict': {
            'id': '324868',
            'ext': 'mp4',
            'title': 'ZAIKO STREAMING TEST',

            'alt_title': '[VOD] ZAIKO STREAMING TEST_20210603(Do Not Delete)',
            'uploader_id': '454',
            'uploader': 'ZAIKO ZERO',
            'timestamp': 1583809200,
            'thumbnail': r're:https://[a-z0-9]+.cloudfront.net/[a-z0-9_]+/[a-z0-9_]+',
            'upload_date': '20200310',
            'categories': ['Tech House'],
        }
    }]

    def _parse_vue_element_attr(self, name, string, video_id):
        page_elem = self._search_regex(rf'(<{name}[^>]+>)', string, name)
        attrs = {}
        for key, value in extract_attributes(page_elem).items():

Review comment (security):
sort (and remove `remove_start` if applying suggestion below)
```suggestion
from ..utils import (
    extract_attributes,
    int_or_none,
    str_or_none,
    traverse_obj,
    unescapeHTML,
    url_or_none,
)
```

Code after:
from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    extract_attributes,
    int_or_none,
    str_or_none,
    traverse_obj,
    unescapeHTML,
    url_or_none,
)


class ZaikoIE(InfoExtractor):
    _VALID_URL = r'https?://(?:[\w-]+\.)?zaiko\.io/event/(?P<id>\d+)/stream(?:/\d+)+'
    _TESTS = [{
        'url': 'https://zaiko.io/event/324868/stream/20571/20571',
        'info_dict': {
            'id': '324868',
            'ext': 'mp4',
            'title': 'ZAIKO STREAMING TEST',
            'alt_title': '[VOD] ZAIKO STREAMING TEST_20210603(Do Not Delete)',
            'uploader_id': '454',
            'uploader': 'ZAIKO ZERO',
            'release_timestamp': 1583809200,
            'thumbnail': r're:https://[a-z0-9]+.cloudfront.net/[a-z0-9_]+/[a-z0-9_]+',
            'release_date': '20200310',
            'categories': ['Tech House'],
            'live_status': 'was_live',
        },
        'params': {'skip_download': 'm3u8'},
    }]

    def _parse_vue_element_attr(self, name, string, video_id):
        page_elem = self._search_regex(rf'(<{name}[^>]+>)', string, name)
        attrs = {}
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/zaiko.py (Python)

Code before:
from .common import InfoExtractor
from ..utils import (
    extract_attributes,
    int_or_none,
    str_or_none,
    traverse_obj,
    unescapeHTML,
    url_or_none,
)


class ZaikoIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?zaiko\.io/event/(?P<id>\d+)/stream(?:/\d+)+'
    _TESTS = [{
        'url': 'https://zaiko.io/event/324868/stream/20571/20571',
        'info_dict': {
            'id': '324868',
            'ext': 'mp4',
            'title': 'ZAIKO STREAMING TEST',
            'alt_title': '[VOD] ZAIKO STREAMING TEST_20210603(Do Not Delete)',
            'uploader_id': '454',
            'uploader': 'ZAIKO ZERO',
            'timestamp': 1583809200,
            'thumbnail': r're:https://[a-z0-9]+.cloudfront.net/[a-z0-9_]+/[a-z0-9_]+',
            'upload_date': '20200310',
            'categories': ['Tech House'],
        }
    }]


Review comment (refactor):
need this for later
```suggestion
    ExtractorError,
    extract_attributes,
```

Code after:
from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    extract_attributes,
    int_or_none,
    str_or_none,
    traverse_obj,
    unescapeHTML,
    url_or_none,
)


class ZaikoIE(InfoExtractor):
    _VALID_URL = r'https?://(?:[\w-]+\.)?zaiko\.io/event/(?P<id>\d+)/stream(?:/\d+)+'
    _TESTS = [{
        'url': 'https://zaiko.io/event/324868/stream/20571/20571',
        'info_dict': {
            'id': '324868',
            'ext': 'mp4',
            'title': 'ZAIKO STREAMING TEST',
            'alt_title': '[VOD] ZAIKO STREAMING TEST_20210603(Do Not Delete)',
            'uploader_id': '454',
            'uploader': 'ZAIKO ZERO',
            'release_timestamp': 1583809200,
            'thumbnail': r're:https://[a-z0-9]+.cloudfront.net/[a-z0-9_]+/[a-z0-9_]+',
            'release_date': '20200310',
            'categories': ['Tech House'],
            'live_status': 'was_live',
        },