+
+
+class ZingMp3LiveRadioIE(ZingMp3BaseIE):
+ IE_NAME = 'zingmp3:liveradio'
+ _VALID_URL = r'https?://(?:mp3\.zing|zingmp3)\.vn/(?P<type>(?:liveradio))/(?P<id>\w+)(?:\.html|\?)'
+ _TESTS = [{
+ 'url': 'https://zingmp3.vn/liveradio/IWZ979UB.html',
+ 'info_dict': {
+ 'id': 'IWZ979UB',
+ 'title': r're:^V\-POP',
+ 'description': 'md5:aa857f8a91dc9ce69e862a809e4bdc10',
+ 'protocol': 'm3u8_native',
+ 'ext': 'mp4',
+ 'view_count': int,
+ 'thumbnail': r're:^https?://.*\.jpg',
+ 'like_count': int,
+ 'live_status': 'is_live',
+ },
+ 'params': {
+ 'skip_download': True,
+ },
+ }, {
+ 'url': 'https://zingmp3.vn/liveradio/IWZ97CWB.html',
+ 'info_dict': {
+ 'id': 'IWZ97CWB',
+ 'title': r're:^Live\s247',
+ 'description': 'md5:d41d8cd98f00b204e9800998ecf8427e',
+ 'protocol': 'm3u8_native',
+ 'ext': 'm4a',
+ 'view_count': int,
+ 'thumbnail': r're:^https?://.*\.jpg',
+ 'like_count': int,
+ 'live_status': 'is_live',
+ },
+ 'params': {
+ 'skip_download': True,
+ },
+ }]
+
+ def _real_extract(self, url):
+ url_type, live_radio_id = self._match_valid_url(url).group('type', 'id')
+ info = self._call_api(url_type, {'id': live_radio_id})
+ manifest_url = info.get('streaming')
+ if not manifest_url:
+ raise ExtractorError('This radio is offline.', expected=True)
+ fmts, subtitles = self._extract_m3u8_formats_and_subtitles(manifest_url, live_radio_id, fatal=False)
+ return {
+ 'id': live_radio_id,
+ 'is_live': True,
+ 'formats': fmts,
+ 'subtitles': subtitles,
+ **traverse_obj(info, {
+ 'title': 'title',
+ 'thumbnail': (('thumbnail', 'thumbnailM', 'thumbnailV', 'thumbnailH'), {url_or_none}),
+ 'view_count': ('activeUsers', {int_or_none}),
+ 'like_count': ('totalReaction', {int_or_none}),
+ 'description': 'description',
+ }, get_all=False),
+ }
+
+
+class ZingMp3PodcastEpisodeIE(ZingMp3BaseIE):
+ IE_NAME = 'zingmp3:podcast-episode'
+ _VALID_URL = ZingMp3BaseIE._VALID_URL_TMPL % 'pgr|cgr'
+ _TESTS = [{
+ 'url': 'https://zingmp3.vn/pgr/Nhac-Moi-Moi-Ngay/68Z9W66B.html',
+ 'info_dict': {
+ 'id': '68Z9W66B',
+ 'title': 'Nhạc Mới Mỗi Ngày',
+ 'description': 'md5:2875dfa951f8e5356742f1610cf20691'
+ },
+ 'playlist_mincount': 20,
+ }, {
+ 'url': 'https://zingmp3.vn/cgr/Am-nhac/IWZ980AO.html',
+ 'info_dict': {
+ 'id': 'IWZ980AO',
+ 'title': 'Âm nhạc'
+ },
+ 'playlist_mincount': 2,
+ }]
+
+ def _fetch_page(self, eps_id, url_type, page):
+ return self._call_api(url_type, {
+ 'id': eps_id,
+ 'page': page,
+ 'count': self._PER_PAGE
+ })
+
+ def _real_extract(self, url):
+ 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)