From 2415e66f889f38503b73e8ebc5f43ca342390e5c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 18:49:24 +0200 Subject: Adding upstream version 2024.03.10. Signed-off-by: Daniel Baumann --- yt_dlp/extractor/jiosaavn.py | 105 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 yt_dlp/extractor/jiosaavn.py (limited to 'yt_dlp/extractor/jiosaavn.py') diff --git a/yt_dlp/extractor/jiosaavn.py b/yt_dlp/extractor/jiosaavn.py new file mode 100644 index 0000000..a592098 --- /dev/null +++ b/yt_dlp/extractor/jiosaavn.py @@ -0,0 +1,105 @@ +from .common import InfoExtractor +from ..utils import ( + int_or_none, + js_to_json, + url_or_none, + urlencode_postdata, + urljoin, +) +from ..utils.traversal import traverse_obj + + +class JioSaavnBaseIE(InfoExtractor): + def _extract_initial_data(self, url, audio_id): + webpage = self._download_webpage(url, audio_id) + return self._search_json( + r'window\.__INITIAL_DATA__\s*=', webpage, + 'init json', audio_id, transform_source=js_to_json) + + +class JioSaavnSongIE(JioSaavnBaseIE): + _VALID_URL = r'https?://(?:www\.)?(?:jiosaavn\.com/song/[^/?#]+/|saavn\.com/s/song/(?:[^/?#]+/){3})(?P[^/?#]+)' + _TESTS = [{ + 'url': 'https://www.jiosaavn.com/song/leja-re/OQsEfQFVUXk', + 'md5': '3b84396d15ed9e083c3106f1fa589c04', + 'info_dict': { + 'id': 'OQsEfQFVUXk', + 'ext': 'mp4', + 'title': 'Leja Re', + 'album': 'Leja Re', + 'thumbnail': 'https://c.saavncdn.com/258/Leja-Re-Hindi-2018-20181124024539-500x500.jpg', + 'duration': 205, + 'view_count': int, + 'release_year': 2018, + }, + }, { + 'url': 'https://www.saavn.com/s/song/hindi/Saathiya/O-Humdum-Suniyo-Re/KAMiazoCblU', + 'only_matching': True, + }] + + _VALID_BITRATES = ('16', '32', '64', '128', '320') + + def _real_extract(self, url): + audio_id = self._match_id(url) + extract_bitrates = self._configuration_arg('bitrate', ['128', '320'], ie_key='JioSaavn') + if invalid_bitrates := [br for br in extract_bitrates if br not in self._VALID_BITRATES]: + raise ValueError( + f'Invalid bitrate(s): {", ".join(invalid_bitrates)}. ' + + f'Valid bitrates are: {", ".join(self._VALID_BITRATES)}') + + song_data = self._extract_initial_data(url, audio_id)['song']['song'] + formats = [] + for bitrate in extract_bitrates: + media_data = self._download_json( + 'https://www.jiosaavn.com/api.php', audio_id, f'Downloading format info for {bitrate}', + fatal=False, data=urlencode_postdata({ + '__call': 'song.generateAuthToken', + '_format': 'json', + 'bitrate': bitrate, + 'url': song_data['encrypted_media_url'], + })) + if not media_data.get('auth_url'): + self.report_warning(f'Unable to extract format info for {bitrate}') + continue + formats.append({ + 'url': media_data['auth_url'], + 'ext': media_data.get('type'), + 'format_id': bitrate, + 'abr': int(bitrate), + 'vcodec': 'none', + }) + + return { + 'id': audio_id, + 'formats': formats, + **traverse_obj(song_data, { + 'title': ('title', 'text'), + 'album': ('album', 'text'), + 'thumbnail': ('image', 0, {url_or_none}), + 'duration': ('duration', {int_or_none}), + 'view_count': ('play_count', {int_or_none}), + 'release_year': ('year', {int_or_none}), + }), + } + + +class JioSaavnAlbumIE(JioSaavnBaseIE): + _VALID_URL = r'https?://(?:www\.)?(?:jio)?saavn\.com/album/[^/?#]+/(?P[^/?#]+)' + _TESTS = [{ + 'url': 'https://www.jiosaavn.com/album/96/buIOjYZDrNA_', + 'info_dict': { + 'id': 'buIOjYZDrNA_', + 'title': '96', + }, + 'playlist_count': 10, + }] + + def _real_extract(self, url): + album_id = self._match_id(url) + album_view = self._extract_initial_data(url, album_id)['albumView'] + + return self.playlist_from_matches( + traverse_obj(album_view, ( + 'modules', lambda _, x: x['key'] == 'list', 'data', ..., 'title', 'action', {str})), + album_id, traverse_obj(album_view, ('album', 'title', 'text', {str})), ie=JioSaavnSongIE, + getter=lambda x: urljoin('https://www.jiosaavn.com/', x)) -- cgit v1.2.3