]>
Commit | Line | Data |
---|---|---|
e452345f RA |
1 | import hashlib |
2 | import random | |
b1742275 | 3 | |
e452345f | 4 | from ..compat import compat_str |
b1742275 | 5 | from .common import InfoExtractor |
e452345f RA |
6 | from ..utils import ( |
7 | clean_html, | |
8 | int_or_none, | |
9 | try_get, | |
10 | ) | |
11 | ||
12 | ||
13 | class JamendoIE(InfoExtractor): | |
3c7da54c S |
14 | _VALID_URL = r'''(?x) |
15 | https?:// | |
16 | (?: | |
17 | licensing\.jamendo\.com/[^/]+| | |
18 | (?:www\.)?jamendo\.com | |
19 | ) | |
e452345f | 20 | /track/(?P<id>[0-9]+)(?:/(?P<display_id>[^/?#&]+))? |
3c7da54c S |
21 | ''' |
22 | _TESTS = [{ | |
b1742275 T |
23 | 'url': 'https://www.jamendo.com/track/196219/stories-from-emona-i', |
24 | 'md5': '6e9e82ed6db98678f171c25a8ed09ffd', | |
25 | 'info_dict': { | |
26 | 'id': '196219', | |
27 | 'display_id': 'stories-from-emona-i', | |
28 | 'ext': 'flac', | |
f7ad7160 | 29 | # 'title': 'Maya Filipič - Stories from Emona I', |
30 | 'title': 'Stories from Emona I', | |
31 | # 'artist': 'Maya Filipič', | |
3cbecdd1 S |
32 | 'track': 'Stories from Emona I', |
33 | 'duration': 210, | |
e452345f RA |
34 | 'thumbnail': r're:^https?://.*\.jpg', |
35 | 'timestamp': 1217438117, | |
36 | 'upload_date': '20080730', | |
f7ad7160 | 37 | 'license': 'by-nc-nd', |
38 | 'view_count': int, | |
39 | 'like_count': int, | |
40 | 'average_rating': int, | |
41 | 'tags': ['piano', 'peaceful', 'newage', 'strings', 'upbeat'], | |
b1742275 | 42 | } |
3c7da54c S |
43 | }, { |
44 | 'url': 'https://licensing.jamendo.com/en/track/1496667/energetic-rock', | |
45 | 'only_matching': True, | |
46 | }] | |
b1742275 | 47 | |
f7ad7160 | 48 | def _call_api(self, resource, resource_id): |
49 | path = '/api/%ss' % resource | |
50 | rand = compat_str(random.random()) | |
51 | return self._download_json( | |
52 | 'https://www.jamendo.com' + path, resource_id, query={ | |
53 | 'id[]': resource_id, | |
54 | }, headers={ | |
55 | 'X-Jam-Call': '$%s*%s~' % (hashlib.sha1((path + rand).encode()).hexdigest(), rand) | |
56 | })[0] | |
57 | ||
b1742275 | 58 | def _real_extract(self, url): |
bdbafb39 | 59 | track_id, display_id = self._match_valid_url(url).groups() |
f7ad7160 | 60 | # webpage = self._download_webpage( |
61 | # 'https://www.jamendo.com/track/' + track_id, track_id) | |
62 | # models = self._parse_json(self._html_search_regex( | |
63 | # r"data-bundled-models='([^']+)", | |
64 | # webpage, 'bundled models'), track_id) | |
65 | # track = models['track']['models'][0] | |
66 | track = self._call_api('track', track_id) | |
e452345f | 67 | title = track_name = track['name'] |
f7ad7160 | 68 | # get_model = lambda x: try_get(models, lambda y: y[x]['models'][0], dict) or {} |
69 | # artist = get_model('artist') | |
70 | # artist_name = artist.get('name') | |
71 | # if artist_name: | |
72 | # title = '%s - %s' % (artist_name, title) | |
73 | # album = get_model('album') | |
d3b6b3b9 S |
74 | |
75 | formats = [{ | |
76 | 'url': 'https://%s.jamendo.com/?trackid=%s&format=%s&from=app-97dab294' | |
77 | % (sub_domain, track_id, format_id), | |
78 | 'format_id': format_id, | |
79 | 'ext': ext, | |
80 | 'quality': quality, | |
81 | } for quality, (format_id, sub_domain, ext) in enumerate(( | |
82 | ('mp31', 'mp3l', 'mp3'), | |
83 | ('mp32', 'mp3d', 'mp3'), | |
84 | ('ogg1', 'ogg', 'ogg'), | |
85 | ('flac', 'flac', 'flac'), | |
86 | ))] | |
87 | self._sort_formats(formats) | |
88 | ||
e452345f RA |
89 | urls = [] |
90 | thumbnails = [] | |
f7ad7160 | 91 | for covers in (track.get('cover') or {}).values(): |
e452345f RA |
92 | for cover_id, cover_url in covers.items(): |
93 | if not cover_url or cover_url in urls: | |
94 | continue | |
95 | urls.append(cover_url) | |
96 | size = int_or_none(cover_id.lstrip('size')) | |
97 | thumbnails.append({ | |
98 | 'id': cover_id, | |
99 | 'url': cover_url, | |
100 | 'width': size, | |
101 | 'height': size, | |
102 | }) | |
103 | ||
104 | tags = [] | |
f7ad7160 | 105 | for tag in (track.get('tags') or []): |
e452345f RA |
106 | tag_name = tag.get('name') |
107 | if not tag_name: | |
108 | continue | |
109 | tags.append(tag_name) | |
110 | ||
111 | stats = track.get('stats') or {} | |
f7ad7160 | 112 | license = track.get('licenseCC') or [] |
b1742275 | 113 | |
b1742275 T |
114 | return { |
115 | 'id': track_id, | |
116 | 'display_id': display_id, | |
e452345f | 117 | 'thumbnails': thumbnails, |
b1742275 | 118 | 'title': title, |
e452345f RA |
119 | 'description': track.get('description'), |
120 | 'duration': int_or_none(track.get('duration')), | |
f7ad7160 | 121 | # 'artist': artist_name, |
e452345f | 122 | 'track': track_name, |
f7ad7160 | 123 | # 'album': album.get('name'), |
e452345f | 124 | 'formats': formats, |
f7ad7160 | 125 | 'license': '-'.join(license) if license else None, |
e452345f RA |
126 | 'timestamp': int_or_none(track.get('dateCreated')), |
127 | 'view_count': int_or_none(stats.get('listenedAll')), | |
128 | 'like_count': int_or_none(stats.get('favorited')), | |
129 | 'average_rating': int_or_none(stats.get('averageNote')), | |
130 | 'tags': tags, | |
b1742275 T |
131 | } |
132 | ||
133 | ||
f7ad7160 | 134 | class JamendoAlbumIE(JamendoIE): |
e452345f | 135 | _VALID_URL = r'https?://(?:www\.)?jamendo\.com/album/(?P<id>[0-9]+)' |
f7ad7160 | 136 | _TESTS = [{ |
b1742275 T |
137 | 'url': 'https://www.jamendo.com/album/121486/duck-on-cover', |
138 | 'info_dict': { | |
139 | 'id': '121486', | |
e452345f RA |
140 | 'title': 'Duck On Cover', |
141 | 'description': 'md5:c2920eaeef07d7af5b96d7c64daf1239', | |
b1742275 | 142 | }, |
d3b6b3b9 S |
143 | 'playlist': [{ |
144 | 'md5': 'e1a2fcb42bda30dfac990212924149a8', | |
145 | 'info_dict': { | |
146 | 'id': '1032333', | |
147 | 'ext': 'flac', | |
3cbecdd1 S |
148 | 'title': 'Shearer - Warmachine', |
149 | 'artist': 'Shearer', | |
150 | 'track': 'Warmachine', | |
e452345f RA |
151 | 'timestamp': 1368089771, |
152 | 'upload_date': '20130509', | |
d3b6b3b9 S |
153 | } |
154 | }, { | |
155 | 'md5': '1f358d7b2f98edfe90fd55dac0799d50', | |
156 | 'info_dict': { | |
157 | 'id': '1032330', | |
158 | 'ext': 'flac', | |
3cbecdd1 S |
159 | 'title': 'Shearer - Without Your Ghost', |
160 | 'artist': 'Shearer', | |
161 | 'track': 'Without Your Ghost', | |
e452345f RA |
162 | 'timestamp': 1368089771, |
163 | 'upload_date': '20130509', | |
b1742275 | 164 | } |
d3b6b3b9 | 165 | }], |
b1742275 T |
166 | 'params': { |
167 | 'playlistend': 2 | |
168 | } | |
f7ad7160 | 169 | }] |
e452345f | 170 | |
b1742275 | 171 | def _real_extract(self, url): |
e452345f RA |
172 | album_id = self._match_id(url) |
173 | album = self._call_api('album', album_id) | |
174 | album_name = album.get('name') | |
175 | ||
176 | entries = [] | |
f7ad7160 | 177 | for track in (album.get('tracks') or []): |
e452345f RA |
178 | track_id = track.get('id') |
179 | if not track_id: | |
180 | continue | |
181 | track_id = compat_str(track_id) | |
182 | entries.append({ | |
183 | '_type': 'url_transparent', | |
184 | 'url': 'https://www.jamendo.com/track/' + track_id, | |
185 | 'ie_key': JamendoIE.ie_key(), | |
186 | 'id': track_id, | |
187 | 'album': album_name, | |
188 | }) | |
189 | ||
190 | return self.playlist_result( | |
191 | entries, album_id, album_name, | |
192 | clean_html(try_get(album, lambda x: x['description']['en'], compat_str))) |