mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-26 20:21:05 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			116 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import json
 | |
| import re
 | |
| import socket
 | |
| 
 | |
| from .common import InfoExtractor
 | |
| from ..utils import (
 | |
|     compat_http_client,
 | |
|     compat_str,
 | |
|     compat_urllib_error,
 | |
|     compat_urllib_request,
 | |
| 
 | |
|     ExtractorError,
 | |
| )
 | |
| 
 | |
| 
 | |
| class MixcloudIE(InfoExtractor):
 | |
|     _WORKING = False # New API, but it seems good http://www.mixcloud.com/developers/documentation/
 | |
|     _VALID_URL = r'^(?:https?://)?(?:www\.)?mixcloud\.com/([\w\d-]+)/([\w\d-]+)'
 | |
|     IE_NAME = u'mixcloud'
 | |
| 
 | |
|     def report_download_json(self, file_id):
 | |
|         """Report JSON download."""
 | |
|         self.to_screen(u'Downloading json')
 | |
| 
 | |
|     def get_urls(self, jsonData, fmt, bitrate='best'):
 | |
|         """Get urls from 'audio_formats' section in json"""
 | |
|         try:
 | |
|             bitrate_list = jsonData[fmt]
 | |
|             if bitrate is None or bitrate == 'best' or bitrate not in bitrate_list:
 | |
|                 bitrate = max(bitrate_list) # select highest
 | |
| 
 | |
|             url_list = jsonData[fmt][bitrate]
 | |
|         except TypeError: # we have no bitrate info.
 | |
|             url_list = jsonData[fmt]
 | |
|         return url_list
 | |
| 
 | |
|     def check_urls(self, url_list):
 | |
|         """Returns 1st active url from list"""
 | |
|         for url in url_list:
 | |
|             try:
 | |
|                 compat_urllib_request.urlopen(url)
 | |
|                 return url
 | |
|             except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error):
 | |
|                 url = None
 | |
| 
 | |
|         return None
 | |
| 
 | |
|     def _print_formats(self, formats):
 | |
|         print('Available formats:')
 | |
|         for fmt in formats.keys():
 | |
|             for b in formats[fmt]:
 | |
|                 try:
 | |
|                     ext = formats[fmt][b][0]
 | |
|                     print('%s\t%s\t[%s]' % (fmt, b, ext.split('.')[-1]))
 | |
|                 except TypeError: # we have no bitrate info
 | |
|                     ext = formats[fmt][0]
 | |
|                     print('%s\t%s\t[%s]' % (fmt, '??', ext.split('.')[-1]))
 | |
|                     break
 | |
| 
 | |
|     def _real_extract(self, url):
 | |
|         mobj = re.match(self._VALID_URL, url)
 | |
|         if mobj is None:
 | |
|             raise ExtractorError(u'Invalid URL: %s' % url)
 | |
|         # extract uploader & filename from url
 | |
|         uploader = mobj.group(1).decode('utf-8')
 | |
|         file_id = uploader + "-" + mobj.group(2).decode('utf-8')
 | |
| 
 | |
|         # construct API request
 | |
|         file_url = 'http://www.mixcloud.com/api/1/cloudcast/' + '/'.join(url.split('/')[-3:-1]) + '.json'
 | |
|         # retrieve .json file with links to files
 | |
|         request = compat_urllib_request.Request(file_url)
 | |
|         try:
 | |
|             self.report_download_json(file_url)
 | |
|             jsonData = compat_urllib_request.urlopen(request).read()
 | |
|         except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err:
 | |
|             raise ExtractorError(u'Unable to retrieve file: %s' % compat_str(err))
 | |
| 
 | |
|         # parse JSON
 | |
|         json_data = json.loads(jsonData)
 | |
|         player_url = json_data['player_swf_url']
 | |
|         formats = dict(json_data['audio_formats'])
 | |
| 
 | |
|         req_format = self._downloader.params.get('format', None)
 | |
| 
 | |
|         if self._downloader.params.get('listformats', None):
 | |
|             self._print_formats(formats)
 | |
|             return
 | |
| 
 | |
|         if req_format is None or req_format == 'best':
 | |
|             for format_param in formats.keys():
 | |
|                 url_list = self.get_urls(formats, format_param)
 | |
|                 # check urls
 | |
|                 file_url = self.check_urls(url_list)
 | |
|                 if file_url is not None:
 | |
|                     break # got it!
 | |
|         else:
 | |
|             if req_format not in formats:
 | |
|                 raise ExtractorError(u'Format is not available')
 | |
| 
 | |
|             url_list = self.get_urls(formats, req_format)
 | |
|             file_url = self.check_urls(url_list)
 | |
|             format_param = req_format
 | |
| 
 | |
|         return [{
 | |
|             'id': file_id.decode('utf-8'),
 | |
|             'url': file_url.decode('utf-8'),
 | |
|             'uploader': uploader.decode('utf-8'),
 | |
|             'upload_date': None,
 | |
|             'title': json_data['name'],
 | |
|             'ext': file_url.split('.')[-1].decode('utf-8'),
 | |
|             'format': (format_param is None and u'NA' or format_param.decode('utf-8')),
 | |
|             'thumbnail': json_data['thumbnail_url'],
 | |
|             'description': json_data['description'],
 | |
|             'player_url': player_url.decode('utf-8'),
 | |
|         }]
 | 
