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