]>
Commit | Line | Data |
---|---|---|
5c19d18c AB |
1 | from __future__ import unicode_literals |
2 | ||
3 | import re | |
4 | ||
5 | from .common import InfoExtractor | |
ae67d082 | 6 | from ..utils import int_or_none |
5c19d18c AB |
7 | |
8 | # 22Tracks regularly replace the audio tracks that can be streamed on their | |
9 | # site. The tracks usually expire after 1 months, so we can't add tests. | |
10 | ||
11 | ||
12 | class TwentyTwoTracksIE(InfoExtractor): | |
ae67d082 S |
13 | _VALID_URL = r'https?://22tracks\.com/(?P<city>[a-z]+)/(?P<genre>[\da-z]+)/(?P<id>\d+)' |
14 | IE_NAME = '22tracks:track' | |
5c19d18c | 15 | |
ae67d082 | 16 | _API_BASE = 'http://22tracks.com/api' |
5c19d18c | 17 | |
ae67d082 S |
18 | def _extract_info(self, city, genre_name, track_id=None): |
19 | item_id = track_id if track_id else genre_name | |
5c19d18c AB |
20 | |
21 | cities = self._download_json( | |
ae67d082 S |
22 | '%s/cities' % self._API_BASE, item_id, |
23 | 'Downloading cities info', | |
24 | 'Unable to download cities info') | |
25 | city_id = [x['id'] for x in cities if x['slug'] == city][0] | |
5c19d18c AB |
26 | |
27 | genres = self._download_json( | |
ae67d082 S |
28 | '%s/genres/%s' % (self._API_BASE, city_id), item_id, |
29 | 'Downloading %s genres info' % city, | |
30 | 'Unable to download %s genres info' % city) | |
31 | genre = [x for x in genres if x['slug'] == genre_name][0] | |
32 | genre_id = genre['id'] | |
5c19d18c AB |
33 | |
34 | tracks = self._download_json( | |
ae67d082 S |
35 | '%s/tracks/%s' % (self._API_BASE, genre_id), item_id, |
36 | 'Downloading %s genre tracks info' % genre_name, | |
37 | 'Unable to download track info') | |
5c19d18c | 38 | |
ae67d082 | 39 | return [x for x in tracks if x['id'] == item_id][0] if track_id else [genre['title'], tracks] |
5c19d18c | 40 | |
ae67d082 | 41 | def _get_track_url(self, filename, track_id): |
5c19d18c | 42 | token = self._download_json( |
ae67d082 S |
43 | 'http://22tracks.com/token.php?desktop=true&u=/128/%s' % filename, |
44 | track_id, 'Downloading token', 'Unable to download token') | |
45 | return 'http://audio.22tracks.com%s?st=%s&e=%d' % (token['filename'], token['st'], token['e']) | |
5c19d18c | 46 | |
ae67d082 S |
47 | def _extract_track_info(self, track_info, track_id): |
48 | download_url = self._get_track_url(track_info['filename'], track_id) | |
49 | title = '%s - %s' % (track_info['artist'].strip(), track_info['title'].strip()) | |
5c19d18c AB |
50 | return { |
51 | 'id': track_id, | |
52 | 'url': download_url, | |
53 | 'ext': 'mp3', | |
54 | 'title': title, | |
ae67d082 S |
55 | 'duration': int_or_none(track_info.get('duration')), |
56 | 'timestamp': int_or_none(track_info.get('published_at') or track_info.get('created')) | |
5c19d18c AB |
57 | } |
58 | ||
ae67d082 S |
59 | def _real_extract(self, url): |
60 | mobj = re.match(self._VALID_URL, url) | |
61 | ||
62 | city = mobj.group('city') | |
63 | genre = mobj.group('genre') | |
64 | track_id = mobj.group('id') | |
65 | ||
66 | track_info = self._extract_info(city, genre, track_id) | |
67 | return self._extract_track_info(track_info, track_id) | |
68 | ||
5c19d18c AB |
69 | |
70 | class TwentyTwoTracksGenreIE(TwentyTwoTracksIE): | |
ae67d082 S |
71 | _VALID_URL = r'https?://22tracks\.com/(?P<city>[a-z]+)/(?P<genre>[\da-z]+)/?$' |
72 | IE_NAME = '22tracks:genre' | |
5c19d18c AB |
73 | |
74 | def _real_extract(self, url): | |
75 | mobj = re.match(self._VALID_URL, url) | |
76 | ||
ae67d082 S |
77 | city = mobj.group('city') |
78 | genre = mobj.group('genre') | |
5c19d18c | 79 | |
ae67d082 | 80 | genre_title, tracks = self._extract_info(city, genre) |
5c19d18c | 81 | |
ae67d082 S |
82 | entries = [ |
83 | self._extract_track_info(track_info, track_info['id']) | |
84 | for track_info in tracks] | |
5c19d18c | 85 | |
ae67d082 | 86 | return self.playlist_result(entries, genre, genre_title) |