|
@ -0,0 +1,111 @@ |
|
|
|
|
|
from __future__ import unicode_literals |
|
|
|
|
|
|
|
|
|
|
|
import re |
|
|
|
|
|
|
|
|
|
|
|
from .common import InfoExtractor |
|
|
|
|
|
|
|
|
|
|
|
# 22Tracks regularly replace the audio tracks that can be streamed on their |
|
|
|
|
|
# site. The tracks usually expire after 1 months, so we can't add tests. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TwentyTwoTracksIE(InfoExtractor): |
|
|
|
|
|
_VALID_URL = r'http://22tracks\.com/([a-z]+)/([a-z]+[2]*)/(\d+)' |
|
|
|
|
|
IE_NAME = 'TwentyTwoTracks:Tracks' |
|
|
|
|
|
|
|
|
|
|
|
def _extract_info(self, city, genre, track=''): |
|
|
|
|
|
self._base_url = "http://22tracks.com/api/" |
|
|
|
|
|
|
|
|
|
|
|
if track == '': |
|
|
|
|
|
itemid = genre |
|
|
|
|
|
else: |
|
|
|
|
|
itemid = track |
|
|
|
|
|
|
|
|
|
|
|
cities = self._download_json( |
|
|
|
|
|
self._base_url + 'cities', itemid, |
|
|
|
|
|
'Downloading city info', 'Cannot download city info') |
|
|
|
|
|
city_id = [x['id'] for x in cities if x['slug'] == city] |
|
|
|
|
|
|
|
|
|
|
|
genres = self._download_json( |
|
|
|
|
|
self._base_url + 'genres/' + str(city_id[0]), itemid, |
|
|
|
|
|
'Downloading genre info', 'Cannot download genre info') |
|
|
|
|
|
genre_id = [x['id'] for x in genres if x['slug'] == genre] |
|
|
|
|
|
|
|
|
|
|
|
tracks = self._download_json( |
|
|
|
|
|
self._base_url + 'tracks/' + str(genre_id[0]), |
|
|
|
|
|
itemid, 'Downloading track info', 'Cannot download track info') |
|
|
|
|
|
|
|
|
|
|
|
if track == '': |
|
|
|
|
|
return [[x['title'] for x in genres if x['slug'] == genre][0], |
|
|
|
|
|
tracks] |
|
|
|
|
|
else: |
|
|
|
|
|
return [x for x in tracks if x['id'] == itemid][0] |
|
|
|
|
|
|
|
|
|
|
|
def _get_token(self, filename, track_id): |
|
|
|
|
|
token = self._download_json( |
|
|
|
|
|
'http://22tracks.com/token.php?desktop=true&u=%2F128%2f{0}'.format( |
|
|
|
|
|
filename), track_id, 'Finding download link...') |
|
|
|
|
|
|
|
|
|
|
|
down_url = 'http://audio.22tracks.com{0}?st={1}&e={2}'.format( |
|
|
|
|
|
token['filename'], |
|
|
|
|
|
token['st'], |
|
|
|
|
|
token['e']) |
|
|
|
|
|
|
|
|
|
|
|
return down_url |
|
|
|
|
|
|
|
|
|
|
|
def _real_extract(self, url): |
|
|
|
|
|
mobj = re.match(self._VALID_URL, url) |
|
|
|
|
|
|
|
|
|
|
|
city_id = mobj.group(1) |
|
|
|
|
|
genre_id = mobj.group(2) |
|
|
|
|
|
track_id = mobj.group(3) |
|
|
|
|
|
|
|
|
|
|
|
self.to_screen(':: Track ID found! - Downloading single track') |
|
|
|
|
|
|
|
|
|
|
|
track_info = self._extract_info(city_id, genre_id, track_id) |
|
|
|
|
|
|
|
|
|
|
|
download_url = self._get_token(track_info['filename'], track_id) |
|
|
|
|
|
title = '{0}-{1}'.format( |
|
|
|
|
|
track_info['artist'].strip(), track_info['title'].strip()) |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
'id': track_id, |
|
|
|
|
|
'url': download_url, |
|
|
|
|
|
'ext': 'mp3', |
|
|
|
|
|
'title': title, |
|
|
|
|
|
'duration': track_info['duration'] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TwentyTwoTracksGenreIE(TwentyTwoTracksIE): |
|
|
|
|
|
_VALID_URL = r'http://22tracks\.com/([a-z]+)/([a-z]+[2]*)/?' |
|
|
|
|
|
IE_NAME = 'TwentyTwoTracks:Genre' |
|
|
|
|
|
|
|
|
|
|
|
def _real_extract(self, url): |
|
|
|
|
|
mobj = re.match(self._VALID_URL, url) |
|
|
|
|
|
|
|
|
|
|
|
city_id = mobj.group(1) |
|
|
|
|
|
genre_id = mobj.group(2) |
|
|
|
|
|
|
|
|
|
|
|
self.to_screen(':: Track ID not found! - Downloading entire genre') |
|
|
|
|
|
|
|
|
|
|
|
playlist_info = self._extract_info(city_id, genre_id) |
|
|
|
|
|
|
|
|
|
|
|
entries = [] |
|
|
|
|
|
for track in playlist_info[1]: |
|
|
|
|
|
title = '{0}-{1}'.format( |
|
|
|
|
|
track['artist'].strip(), track['title'].strip()) |
|
|
|
|
|
entries.append({ |
|
|
|
|
|
'id': track['id'], |
|
|
|
|
|
'url': self._get_token(track['filename'], track['id']), |
|
|
|
|
|
'ext': 'mp3', |
|
|
|
|
|
'title': title |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
self.to_screen(':: Links found - Downloading Playlist') |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
'_type': 'playlist', |
|
|
|
|
|
'id': genre_id, |
|
|
|
|
|
'title': playlist_info[0], |
|
|
|
|
|
'entries': entries |
|
|
|
|
|
} |