| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  | # coding: utf-8 | 
					
						
							|  |  |  | from __future__ import unicode_literals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import re | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from .common import InfoExtractor | 
					
						
							|  |  |  | from ..utils import ( | 
					
						
							|  |  |  |     clean_html, | 
					
						
							| 
									
										
										
										
											2014-12-13 12:24:42 +01:00
										 |  |  |     ExtractorError, | 
					
						
							| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  |     float_or_none, | 
					
						
							|  |  |  |     parse_iso8601, | 
					
						
							| 
									
										
										
										
											2015-11-21 22:18:17 +06:00
										 |  |  |     sanitized_Request, | 
					
						
							| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TapelyIE(InfoExtractor): | 
					
						
							| 
									
										
										
										
											2015-10-03 16:25:33 +03:00
										 |  |  |     _VALID_URL = r'https?://(?:www\.)?(?:tape\.ly|tapely\.com)/(?P<id>[A-Za-z0-9\-_]+)(?:/(?P<songnr>\d+))?' | 
					
						
							| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  |     _API_URL = 'http://tape.ly/showtape?id={0:}' | 
					
						
							|  |  |  |     _S3_SONG_URL = 'http://mytape.s3.amazonaws.com/{0:}' | 
					
						
							| 
									
										
										
										
											2014-10-01 21:53:45 +03:00
										 |  |  |     _SOUNDCLOUD_SONG_URL = 'http://api.soundcloud.com{0:}' | 
					
						
							| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  |     _TESTS = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             'url': 'http://tape.ly/my-grief-as-told-by-water', | 
					
						
							|  |  |  |             'info_dict': { | 
					
						
							|  |  |  |                 'id': 23952, | 
					
						
							|  |  |  |                 'title': 'my grief as told by water', | 
					
						
							|  |  |  |                 'thumbnail': 're:^https?://.*\.png$', | 
					
						
							|  |  |  |                 'uploader_id': 16484, | 
					
						
							|  |  |  |                 'timestamp': 1411848286, | 
					
						
							|  |  |  |                 'description': 'For Robin and Ponkers, whom the tides of life have taken out to sea.', | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             'playlist_count': 13, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             'url': 'http://tape.ly/my-grief-as-told-by-water/1', | 
					
						
							|  |  |  |             'md5': '79031f459fdec6530663b854cbc5715c', | 
					
						
							|  |  |  |             'info_dict': { | 
					
						
							|  |  |  |                 'id': 258464, | 
					
						
							|  |  |  |                 'title': 'Dreaming Awake  (My Brightest Diamond)', | 
					
						
							|  |  |  |                 'ext': 'm4a', | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2015-10-03 16:25:33 +03:00
										 |  |  |         { | 
					
						
							|  |  |  |             'url': 'https://tapely.com/my-grief-as-told-by-water', | 
					
						
							|  |  |  |             'only_matching': True, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _real_extract(self, url): | 
					
						
							|  |  |  |         mobj = re.match(self._VALID_URL, url) | 
					
						
							|  |  |  |         display_id = mobj.group('id') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         playlist_url = self._API_URL.format(display_id) | 
					
						
							| 
									
										
										
										
											2015-11-21 22:18:17 +06:00
										 |  |  |         request = sanitized_Request(playlist_url) | 
					
						
							| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  |         request.add_header('X-Requested-With', 'XMLHttpRequest') | 
					
						
							|  |  |  |         request.add_header('Accept', 'application/json') | 
					
						
							| 
									
										
										
										
											2014-11-09 15:01:12 +02:00
										 |  |  |         request.add_header('Referer', url) | 
					
						
							| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         playlist = self._download_json(request, display_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tape = playlist['tape'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         entries = [] | 
					
						
							|  |  |  |         for s in tape['songs']: | 
					
						
							|  |  |  |             song = s['song'] | 
					
						
							|  |  |  |             entry = { | 
					
						
							|  |  |  |                 'id': song['id'], | 
					
						
							|  |  |  |                 'duration': float_or_none(song.get('songduration'), 1000), | 
					
						
							|  |  |  |                 'title': song['title'], | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if song['source'] == 'S3': | 
					
						
							|  |  |  |                 entry.update({ | 
					
						
							|  |  |  |                     'url': self._S3_SONG_URL.format(song['filename']), | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |                 entries.append(entry) | 
					
						
							|  |  |  |             elif song['source'] == 'YT': | 
					
						
							| 
									
										
										
										
											2014-10-01 21:53:45 +03:00
										 |  |  |                 self.to_screen('YouTube video detected') | 
					
						
							|  |  |  |                 yt_id = song['filename'].replace('/youtube/', '') | 
					
						
							| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  |                 entry.update(self.url_result(yt_id, 'Youtube', video_id=yt_id)) | 
					
						
							|  |  |  |                 entries.append(entry) | 
					
						
							| 
									
										
										
										
											2014-10-01 21:53:45 +03:00
										 |  |  |             elif song['source'] == 'SC': | 
					
						
							|  |  |  |                 self.to_screen('SoundCloud song detected') | 
					
						
							|  |  |  |                 sc_url = self._SOUNDCLOUD_SONG_URL.format(song['filename']) | 
					
						
							|  |  |  |                 entry.update(self.url_result(sc_url, 'Soundcloud')) | 
					
						
							|  |  |  |                 entries.append(entry) | 
					
						
							| 
									
										
										
										
											2014-10-01 17:26:09 +03:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 self.report_warning('Unknown song source: %s' % song['source']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if mobj.group('songnr'): | 
					
						
							|  |  |  |             songnr = int(mobj.group('songnr')) - 1 | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 return entries[songnr] | 
					
						
							|  |  |  |             except IndexError: | 
					
						
							|  |  |  |                 raise ExtractorError( | 
					
						
							|  |  |  |                     'No song with index: %s' % mobj.group('songnr'), | 
					
						
							|  |  |  |                     expected=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             '_type': 'playlist', | 
					
						
							|  |  |  |             'id': tape['id'], | 
					
						
							|  |  |  |             'display_id': display_id, | 
					
						
							|  |  |  |             'title': tape['name'], | 
					
						
							|  |  |  |             'entries': entries, | 
					
						
							|  |  |  |             'thumbnail': tape.get('image_url'), | 
					
						
							|  |  |  |             'description': clean_html(tape.get('subtext')), | 
					
						
							|  |  |  |             'like_count': tape.get('likescount'), | 
					
						
							|  |  |  |             'uploader_id': tape.get('user_id'), | 
					
						
							|  |  |  |             'timestamp': parse_iso8601(tape.get('published_at')), | 
					
						
							|  |  |  |         } |