]>
Raphaël G. Git Repositories - youtubedl/blob - youtube_dl/extractor/viu.py
   2 from __future__ 
import unicode_literals
 
   6 from .common 
import InfoExtractor
 
   7 from ..compat 
import compat_str
 
  14 class ViuBaseIE(InfoExtractor
): 
  15     def _real_initialize(self
): 
  16         viu_auth_res 
= self
._request
_webpage
( 
  17             'https://www.viu.com/api/apps/v2/authenticate', None, 
  18             'Requesting Viu auth', query
={ 
  20                 'appid': 'viu_desktop', 
  23                 'languageid': 'default', 
  24                 'platform': 'desktop', 
  26                 'useridtype': 'guest', 
  28             }, headers
=self
.geo_verification_headers()) 
  29         self
._auth
_token 
= viu_auth_res
.info()['X-VIU-AUTH'] 
  31     def _call_api(self
, path
, *args
, **kwargs
): 
  32         headers 
= self
.geo_verification_headers() 
  34             'X-VIU-AUTH': self
._auth
_token
 
  36         headers
.update(kwargs
.get('headers', {})) 
  37         kwargs
['headers'] = headers
 
  38         response 
= self
._download
_json
( 
  39             'https://www.viu.com/api/' + path
, *args
, **kwargs
)['response'] 
  40         if response
.get('status') != 'success': 
  41             raise ExtractorError('%s said: %s' % ( 
  42                 self
.IE_NAME
, response
['message']), expected
=True) 
  46 class ViuIE(ViuBaseIE
): 
  47     _VALID_URL 
= r
'(?:viu:|https?://www\.viu\.com/[a-z]{2}/media/)(?P<id>\d+)' 
  49         'url': 'https://www.viu.com/en/media/1116705532?containerId=playlist-22168059', 
  53             'title': 'Citizen Khan - Ep 1', 
  54             'description': 'md5:d7ea1604f49e5ba79c212c551ce2110e', 
  57             'skip_download': 'm3u8 download', 
  59         'skip': 'Geo-restricted to India', 
  61         'url': 'https://www.viu.com/en/media/1130599965', 
  65             'title': 'Jealousy Incarnate - Episode 1', 
  66             'description': 'md5:d3d82375cab969415d2720b6894361e9', 
  69             'skip_download': 'm3u8 download', 
  71         'skip': 'Geo-restricted to Indonesia', 
  74     def _real_extract(self
, url
): 
  75         video_id 
= self
._match
_id
(url
) 
  77         video_data 
= self
._call
_api
( 
  78             'clip/load', video_id
, 'Downloading video data', query
={ 
  79                 'appid': 'viu_desktop', 
  84         title 
= video_data
['title'] 
  87         url_path 
= video_data
.get('urlpathd') or video_data
.get('urlpath') 
  88         tdirforwhole 
= video_data
.get('tdirforwhole') 
  89         # #EXT-X-BYTERANGE is not supported by native hls downloader 
  91         # hls_file = video_data.get('hlsfile') 
  92         hls_file 
= video_data
.get('jwhlsfile') 
  93         if url_path 
and tdirforwhole 
and hls_file
: 
  94             m3u8_url 
= '%s/%s/%s' % (url_path
, tdirforwhole
, hls_file
) 
  97             #     r'(/hlsc_)[a-z]+(\d+\.m3u8)', 
  98             #     r'\1whe\2', video_data['href']) 
  99             m3u8_url 
= video_data
['href'] 
 100         formats 
= self
._extract
_m
3u8_formats
(m3u8_url
, video_id
, 'mp4') 
 101         self
._sort
_formats
(formats
) 
 104         for key
, value 
in video_data
.items(): 
 105             mobj 
= re
.match(r
'^subtitle_(?P<lang>[^_]+)_(?P<ext>(vtt|srt))', key
) 
 108             subtitles
.setdefault(mobj
.group('lang'), []).append({ 
 110                 'ext': mobj
.group('ext') 
 116             'description': video_data
.get('description'), 
 117             'series': video_data
.get('moviealbumshowname'), 
 119             'episode_number': int_or_none(video_data
.get('episodeno')), 
 120             'duration': int_or_none(video_data
.get('duration')), 
 122             'subtitles': subtitles
, 
 126 class ViuPlaylistIE(ViuBaseIE
): 
 127     IE_NAME 
= 'viu:playlist' 
 128     _VALID_URL 
= r
'https?://www\.viu\.com/[^/]+/listing/playlist-(?P<id>\d+)' 
 130         'url': 'https://www.viu.com/en/listing/playlist-22461380', 
 133             'title': 'The Good Wife', 
 135         'playlist_count': 16, 
 136         'skip': 'Geo-restricted to Indonesia', 
 139     def _real_extract(self
, url
): 
 140         playlist_id 
= self
._match
_id
(url
) 
 141         playlist_data 
= self
._call
_api
( 
 142             'container/load', playlist_id
, 
 143             'Downloading playlist info', query
={ 
 144                 'appid': 'viu_desktop', 
 146                 'id': 'playlist-' + playlist_id
 
 150         for item 
in playlist_data
.get('item', []): 
 151             item_id 
= item
.get('id') 
 154             item_id 
= compat_str(item_id
) 
 155             entries
.append(self
.url_result( 
 156                 'viu:' + item_id
, 'Viu', item_id
)) 
 158         return self
.playlist_result( 
 159             entries
, playlist_id
, playlist_data
.get('title')) 
 162 class ViuOTTIE(InfoExtractor
): 
 164     _VALID_URL 
= r
'https?://(?:www\.)?viu\.com/ott/(?P<country_code>[a-z]{2})/[a-z]{2}-[a-z]{2}/vod/(?P<id>\d+)' 
 166         'url': 'http://www.viu.com/ott/sg/en-us/vod/3421/The%20Prime%20Minister%20and%20I', 
 170             'title': 'A New Beginning', 
 171             'description': 'md5:1e7486a619b6399b25ba6a41c0fe5b2c', 
 174             'skip_download': 'm3u8 download', 
 176         'skip': 'Geo-restricted to Singapore', 
 178         'url': 'http://www.viu.com/ott/hk/zh-hk/vod/7123/%E5%A4%A7%E4%BA%BA%E5%A5%B3%E5%AD%90', 
 182             'title': '這就是我的生活之道', 
 183             'description': 'md5:4eb0d8b08cf04fcdc6bbbeb16043434f', 
 186             'skip_download': 'm3u8 download', 
 188         'skip': 'Geo-restricted to Hong Kong', 
 191     def _real_extract(self
, url
): 
 192         country_code
, video_id 
= re
.match(self
._VALID
_URL
, url
).groups() 
 194         product_data 
= self
._download
_json
( 
 195             'http://www.viu.com/ott/%s/index.php' % country_code
, video_id
, 
 196             'Downloading video info', query
={ 
 197                 'r': 'vod/ajax-detail', 
 198                 'platform_flag_label': 'web', 
 199                 'product_id': video_id
, 
 202         video_data 
= product_data
.get('current_product') 
 204             raise ExtractorError('This video is not available in your region.', expected
=True) 
 206         stream_data 
= self
._download
_json
( 
 207             'https://d1k2us671qcoau.cloudfront.net/distribute_web_%s.php' % country_code
, 
 208             video_id
, 'Downloading stream info', query
={ 
 209                 'ccs_product_id': video_data
['ccs_product_id'], 
 212         stream_sizes 
= stream_data
.get('size', {}) 
 214         for vid_format
, stream_url 
in stream_data
.get('url', {}).items(): 
 215             height 
= int_or_none(self
._search
_regex
( 
 216                 r
's(\d+)p', vid_format
, 'height', default
=None)) 
 218                 'format_id': vid_format
, 
 222                 'filesize': int_or_none(stream_sizes
.get(vid_format
)) 
 224         self
._sort
_formats
(formats
) 
 227         for sub 
in video_data
.get('subtitle', []): 
 228             sub_url 
= sub
.get('url') 
 231             subtitles
.setdefault(sub
.get('name'), []).append({ 
 236         title 
= video_data
['synopsis'].strip() 
 241             'description': video_data
.get('description'), 
 242             'series': product_data
.get('series', {}).get('name'), 
 244             'episode_number': int_or_none(video_data
.get('number')), 
 245             'duration': int_or_none(stream_data
.get('duration')), 
 246             'thumbnail': video_data
.get('cover_image_url'), 
 248             'subtitles': subtitles
,