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

Code before:
class ZingMp3ChartMusicVideoIE(ZingMp3BaseIE):
    _VALID_URL = r'https?://(?:mp3\.zing|zingmp3)\.vn/(?P<type>the-loai-video)/.+?/(?P<id>[^\.]+)'
    IE_NAME = 'zingmp3:chart-music-video'
    _TESTS = [{
        'url': 'https://zingmp3.vn/the-loai-video/Viet-Nam/IWZ9Z08I.html',
        'info_dict': {
            '_type': 'playlist',
            'id': 'IWZ9Z08I',
            'title': 'zing-chart-video',
            'description': 'zing-chart-video',
        },
        'playlist_mincount': 400,
    }]

    def _fetch_page(self, song_id, type_url, page):
        page += 1
        api = self.get_api_with_signature(name_api=self._SLUG_API[type_url], param={
            'id': song_id,
            'type': 'genre',
            'page': page,
            'count': self._PER_PAGE
        })
        data = self._download_json(api, song_id)['data']
        items = data.get('items')
        if items:
            return self._entries(items)

    def _real_extract(self, url):
        song_id, type_url = self._match_valid_url(url).group('id', 'type')
        entries = OnDemandPagedList(functools.partial(self._fetch_page, song_id, type_url), self._PER_PAGE)
        return self.playlist_result(entries, song_id, 'zing-chart-video', 'zing-chart-video')


class ZingMp3UserIE(ZingMp3BaseIE):
    _VALID_URL = r'''(?x)
                        https?://
                            (?:mp3\.zing|zingmp3)\.vn/
                            (?P<user>[^/]+)
                            (?:/
                                (?P<type>bai-hat|single|album|video)
                            )
                            /?(?:[?#].*)?$
                    '''
    IE_NAME = 'zingmp3:user'
    _TESTS = [{
        'url': 'https://zingmp3.vn/Mr-Siro/bai-hat',
        'info_dict': {
            'id': 'IWZ98609',
            'title': 'Mr. Siro - bai-hat',
            'description': 'md5:85ab29bd7b21725c12bf76fd1d6922e5',
        },

Review comment (suggestion):
```suggestion
        return self._entries(data.get('items'))
```
see above comment

Code after:
        },
        'playlist_mincount': 400,
    }, {
        'url': 'https://zingmp3.vn/the-loai-video/Au-My/IWZ9Z08O.html',
        'info_dict': {
            'id': 'IWZ9Z08O',
            'title': 'the-loai-video_Au-My',
        },
        'playlist_mincount': 40,
    }, {
        'url': 'https://zingmp3.vn/the-loai-video/Han-Quoc/IWZ9Z08W.html',
        'info_dict': {
            'id': 'IWZ9Z08W',
            'title': 'the-loai-video_Han-Quoc',
        },
        'playlist_mincount': 30,
    }, {
        'url': 'https://zingmp3.vn/the-loai-video/Khong-Loi/IWZ9Z086.html',
        'info_dict': {
            'id': 'IWZ9Z086',
            'title': 'the-loai-video_Khong-Loi',
        },
        'playlist_mincount': 10,
    }]

    def _fetch_page(self, song_id, type_url, page):
        page += 1
        api = self.get_api_with_signature(name_api=self._SLUG_API[type_url], param={
            'id': song_id,
            'type': 'genre',
            'page': page,
            'count': self._PER_PAGE
        })
        data = self._download_json(api, song_id)['data']
        return self._entries(data.get('items'))

    def _real_extract(self, url):
        song_id, regions, type_url = self._match_valid_url(url).group('id', 'regions', 'type')
        entries = OnDemandPagedList(functools.partial(self._fetch_page, song_id, type_url), self._PER_PAGE)
        return self.playlist_result(entries, song_id, f'{type_url}_{regions}')


class ZingMp3UserIE(ZingMp3BaseIE):
    _VALID_URL = r'''(?x)
                        https?://
                            (?:mp3\.zing|zingmp3)\.vn/
                            (?P<user>[^/]+)
                            (?:
                                /(?P<type>bai-hat|single|album|video)
                            )
                            /?(?:[?#]|$)