]>
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?://[^/]+\.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', 
  73         'url': 'https://india.viu.com/en/media/1126286865', 
  74         'only_matching': True, 
  77     def _real_extract(self
, url
): 
  78         video_id 
= self
._match
_id
(url
) 
  80         video_data 
= self
._call
_api
( 
  81             'clip/load', video_id
, 'Downloading video data', query
={ 
  82                 'appid': 'viu_desktop', 
  87         title 
= video_data
['title'] 
  90         url_path 
= video_data
.get('urlpathd') or video_data
.get('urlpath') 
  91         tdirforwhole 
= video_data
.get('tdirforwhole') 
  92         # #EXT-X-BYTERANGE is not supported by native hls downloader 
  94         # hls_file = video_data.get('hlsfile') 
  95         hls_file 
= video_data
.get('jwhlsfile') 
  96         if url_path 
and tdirforwhole 
and hls_file
: 
  97             m3u8_url 
= '%s/%s/%s' % (url_path
, tdirforwhole
, hls_file
) 
 100             #     r'(/hlsc_)[a-z]+(\d+\.m3u8)', 
 101             #     r'\1whe\2', video_data['href']) 
 102             m3u8_url 
= video_data
['href'] 
 103         formats 
= self
._extract
_m
3u8_formats
(m3u8_url
, video_id
, 'mp4') 
 104         self
._sort
_formats
(formats
) 
 107         for key
, value 
in video_data
.items(): 
 108             mobj 
= re
.match(r
'^subtitle_(?P<lang>[^_]+)_(?P<ext>(vtt|srt))', key
) 
 111             subtitles
.setdefault(mobj
.group('lang'), []).append({ 
 113                 'ext': mobj
.group('ext') 
 119             'description': video_data
.get('description'), 
 120             'series': video_data
.get('moviealbumshowname'), 
 122             'episode_number': int_or_none(video_data
.get('episodeno')), 
 123             'duration': int_or_none(video_data
.get('duration')), 
 125             'subtitles': subtitles
, 
 129 class ViuPlaylistIE(ViuBaseIE
): 
 130     IE_NAME 
= 'viu:playlist' 
 131     _VALID_URL 
= r
'https?://www\.viu\.com/[^/]+/listing/playlist-(?P<id>\d+)' 
 133         'url': 'https://www.viu.com/en/listing/playlist-22461380', 
 136             'title': 'The Good Wife', 
 138         'playlist_count': 16, 
 139         'skip': 'Geo-restricted to Indonesia', 
 142     def _real_extract(self
, url
): 
 143         playlist_id 
= self
._match
_id
(url
) 
 144         playlist_data 
= self
._call
_api
( 
 145             'container/load', playlist_id
, 
 146             'Downloading playlist info', query
={ 
 147                 'appid': 'viu_desktop', 
 149                 'id': 'playlist-' + playlist_id
 
 153         for item 
in playlist_data
.get('item', []): 
 154             item_id 
= item
.get('id') 
 157             item_id 
= compat_str(item_id
) 
 158             entries
.append(self
.url_result( 
 159                 'viu:' + item_id
, 'Viu', item_id
)) 
 161         return self
.playlist_result( 
 162             entries
, playlist_id
, playlist_data
.get('title')) 
 165 class ViuOTTIE(InfoExtractor
): 
 167     _VALID_URL 
= r
'https?://(?:www\.)?viu\.com/ott/(?P<country_code>[a-z]{2})/[a-z]{2}-[a-z]{2}/vod/(?P<id>\d+)' 
 169         'url': 'http://www.viu.com/ott/sg/en-us/vod/3421/The%20Prime%20Minister%20and%20I', 
 173             'title': 'A New Beginning', 
 174             'description': 'md5:1e7486a619b6399b25ba6a41c0fe5b2c', 
 177             'skip_download': 'm3u8 download', 
 179         'skip': 'Geo-restricted to Singapore', 
 181         'url': 'http://www.viu.com/ott/hk/zh-hk/vod/7123/%E5%A4%A7%E4%BA%BA%E5%A5%B3%E5%AD%90', 
 185             'title': '這就是我的生活之道', 
 186             'description': 'md5:4eb0d8b08cf04fcdc6bbbeb16043434f', 
 189             'skip_download': 'm3u8 download', 
 191         'skip': 'Geo-restricted to Hong Kong', 
 194     def _real_extract(self
, url
): 
 195         country_code
, video_id 
= re
.match(self
._VALID
_URL
, url
).groups() 
 197         product_data 
= self
._download
_json
( 
 198             'http://www.viu.com/ott/%s/index.php' % country_code
, video_id
, 
 199             'Downloading video info', query
={ 
 200                 'r': 'vod/ajax-detail', 
 201                 'platform_flag_label': 'web', 
 202                 'product_id': video_id
, 
 205         video_data 
= product_data
.get('current_product') 
 207             raise ExtractorError('This video is not available in your region.', expected
=True) 
 209         stream_data 
= self
._download
_json
( 
 210             'https://d1k2us671qcoau.cloudfront.net/distribute_web_%s.php' % country_code
, 
 211             video_id
, 'Downloading stream info', query
={ 
 212                 'ccs_product_id': video_data
['ccs_product_id'], 
 215         stream_sizes 
= stream_data
.get('size', {}) 
 217         for vid_format
, stream_url 
in stream_data
.get('url', {}).items(): 
 218             height 
= int_or_none(self
._search
_regex
( 
 219                 r
's(\d+)p', vid_format
, 'height', default
=None)) 
 221                 'format_id': vid_format
, 
 225                 'filesize': int_or_none(stream_sizes
.get(vid_format
)) 
 227         self
._sort
_formats
(formats
) 
 230         for sub 
in video_data
.get('subtitle', []): 
 231             sub_url 
= sub
.get('url') 
 234             subtitles
.setdefault(sub
.get('name'), []).append({ 
 239         title 
= video_data
['synopsis'].strip() 
 244             'description': video_data
.get('description'), 
 245             'series': product_data
.get('series', {}).get('name'), 
 247             'episode_number': int_or_none(video_data
.get('number')), 
 248             'duration': int_or_none(stream_data
.get('duration')), 
 249             'thumbnail': video_data
.get('cover_image_url'), 
 251             'subtitles': subtitles
,