]>
Raphaël G. Git Repositories - youtubedl/blob - youtube_dl/extractor/viu.py
5cf93591cd0d863bb1f62968a0c25ea86e4cc744
   2 from __future__ 
import unicode_literals
 
   6 from .common 
import InfoExtractor
 
  17 class ViuBaseIE(InfoExtractor
): 
  18     def _real_initialize(self
): 
  19         viu_auth_res 
= self
._request
_webpage
( 
  20             'https://www.viu.com/api/apps/v2/authenticate', None, 
  21             'Requesting Viu auth', query
={ 
  23                 'appid': 'viu_desktop', 
  26                 'languageid': 'default', 
  27                 'platform': 'desktop', 
  29                 'useridtype': 'guest', 
  31             }, headers
=self
.geo_verification_headers()) 
  32         self
._auth
_token 
= viu_auth_res
.info()['X-VIU-AUTH'] 
  34     def _call_api(self
, path
, *args
, **kwargs
): 
  35         headers 
= self
.geo_verification_headers() 
  37             'X-VIU-AUTH': self
._auth
_token
 
  39         headers
.update(kwargs
.get('headers', {})) 
  40         kwargs
['headers'] = headers
 
  41         response 
= self
._download
_json
( 
  42             'https://www.viu.com/api/' + path
, *args
, 
  43             **compat_kwargs(kwargs
))['response'] 
  44         if response
.get('status') != 'success': 
  45             raise ExtractorError('%s said: %s' % ( 
  46                 self
.IE_NAME
, response
['message']), expected
=True) 
  50 class ViuIE(ViuBaseIE
): 
  51     _VALID_URL 
= r
'(?:viu:|https?://[^/]+\.viu\.com/[a-z]{2}/media/)(?P<id>\d+)' 
  53         'url': 'https://www.viu.com/en/media/1116705532?containerId=playlist-22168059', 
  57             'title': 'Citizen Khan - Ep 1', 
  58             'description': 'md5:d7ea1604f49e5ba79c212c551ce2110e', 
  61             'skip_download': 'm3u8 download', 
  63         'skip': 'Geo-restricted to India', 
  65         'url': 'https://www.viu.com/en/media/1130599965', 
  69             'title': 'Jealousy Incarnate - Episode 1', 
  70             'description': 'md5:d3d82375cab969415d2720b6894361e9', 
  73             'skip_download': 'm3u8 download', 
  75         'skip': 'Geo-restricted to Indonesia', 
  77         'url': 'https://india.viu.com/en/media/1126286865', 
  78         'only_matching': True, 
  81     def _real_extract(self
, url
): 
  82         video_id 
= self
._match
_id
(url
) 
  84         video_data 
= self
._call
_api
( 
  85             'clip/load', video_id
, 'Downloading video data', query
={ 
  86                 'appid': 'viu_desktop', 
  91         title 
= video_data
['title'] 
  94         url_path 
= video_data
.get('urlpathd') or video_data
.get('urlpath') 
  95         tdirforwhole 
= video_data
.get('tdirforwhole') 
  96         # #EXT-X-BYTERANGE is not supported by native hls downloader 
  98         # hls_file = video_data.get('hlsfile') 
  99         hls_file 
= video_data
.get('jwhlsfile') 
 100         if url_path 
and tdirforwhole 
and hls_file
: 
 101             m3u8_url 
= '%s/%s/%s' % (url_path
, tdirforwhole
, hls_file
) 
 104             #     r'(/hlsc_)[a-z]+(\d+\.m3u8)', 
 105             #     r'\1whe\2', video_data['href']) 
 106             m3u8_url 
= video_data
['href'] 
 107         formats 
= self
._extract
_m
3u8_formats
(m3u8_url
, video_id
, 'mp4') 
 108         self
._sort
_formats
(formats
) 
 111         for key
, value 
in video_data
.items(): 
 112             mobj 
= re
.match(r
'^subtitle_(?P<lang>[^_]+)_(?P<ext>(vtt|srt))', key
) 
 115             subtitles
.setdefault(mobj
.group('lang'), []).append({ 
 117                 'ext': mobj
.group('ext') 
 123             'description': video_data
.get('description'), 
 124             'series': video_data
.get('moviealbumshowname'), 
 126             'episode_number': int_or_none(video_data
.get('episodeno')), 
 127             'duration': int_or_none(video_data
.get('duration')), 
 129             'subtitles': subtitles
, 
 133 class ViuPlaylistIE(ViuBaseIE
): 
 134     IE_NAME 
= 'viu:playlist' 
 135     _VALID_URL 
= r
'https?://www\.viu\.com/[^/]+/listing/playlist-(?P<id>\d+)' 
 137         'url': 'https://www.viu.com/en/listing/playlist-22461380', 
 140             'title': 'The Good Wife', 
 142         'playlist_count': 16, 
 143         'skip': 'Geo-restricted to Indonesia', 
 146     def _real_extract(self
, url
): 
 147         playlist_id 
= self
._match
_id
(url
) 
 148         playlist_data 
= self
._call
_api
( 
 149             'container/load', playlist_id
, 
 150             'Downloading playlist info', query
={ 
 151                 'appid': 'viu_desktop', 
 153                 'id': 'playlist-' + playlist_id
 
 157         for item 
in playlist_data
.get('item', []): 
 158             item_id 
= item
.get('id') 
 161             item_id 
= compat_str(item_id
) 
 162             entries
.append(self
.url_result( 
 163                 'viu:' + item_id
, 'Viu', item_id
)) 
 165         return self
.playlist_result( 
 166             entries
, playlist_id
, playlist_data
.get('title')) 
 169 class ViuOTTIE(InfoExtractor
): 
 171     _VALID_URL 
= r
'https?://(?:www\.)?viu\.com/ott/(?P<country_code>[a-z]{2})/[a-z]{2}-[a-z]{2}/vod/(?P<id>\d+)' 
 173         'url': 'http://www.viu.com/ott/sg/en-us/vod/3421/The%20Prime%20Minister%20and%20I', 
 177             'title': 'A New Beginning', 
 178             'description': 'md5:1e7486a619b6399b25ba6a41c0fe5b2c', 
 181             'skip_download': 'm3u8 download', 
 183         'skip': 'Geo-restricted to Singapore', 
 185         'url': 'http://www.viu.com/ott/hk/zh-hk/vod/7123/%E5%A4%A7%E4%BA%BA%E5%A5%B3%E5%AD%90', 
 189             'title': '這就是我的生活之道', 
 190             'description': 'md5:4eb0d8b08cf04fcdc6bbbeb16043434f', 
 193             'skip_download': 'm3u8 download', 
 195         'skip': 'Geo-restricted to Hong Kong', 
 198     def _real_extract(self
, url
): 
 199         country_code
, video_id 
= re
.match(self
._VALID
_URL
, url
).groups() 
 201         product_data 
= self
._download
_json
( 
 202             'http://www.viu.com/ott/%s/index.php' % country_code
, video_id
, 
 203             'Downloading video info', query
={ 
 204                 'r': 'vod/ajax-detail', 
 205                 'platform_flag_label': 'web', 
 206                 'product_id': video_id
, 
 209         video_data 
= product_data
.get('current_product') 
 211             raise ExtractorError('This video is not available in your region.', expected
=True) 
 213         stream_data 
= self
._download
_json
( 
 214             'https://d1k2us671qcoau.cloudfront.net/distribute_web_%s.php' % country_code
, 
 215             video_id
, 'Downloading stream info', query
={ 
 216                 'ccs_product_id': video_data
['ccs_product_id'], 
 219         stream_sizes 
= stream_data
.get('size', {}) 
 221         for vid_format
, stream_url 
in stream_data
.get('url', {}).items(): 
 222             height 
= int_or_none(self
._search
_regex
( 
 223                 r
's(\d+)p', vid_format
, 'height', default
=None)) 
 225                 'format_id': vid_format
, 
 229                 'filesize': int_or_none(stream_sizes
.get(vid_format
)) 
 231         self
._sort
_formats
(formats
) 
 234         for sub 
in video_data
.get('subtitle', []): 
 235             sub_url 
= sub
.get('url') 
 238             subtitles
.setdefault(sub
.get('name'), []).append({ 
 243         title 
= video_data
['synopsis'].strip() 
 248             'description': video_data
.get('description'), 
 249             'series': product_data
.get('series', {}).get('name'), 
 251             'episode_number': int_or_none(video_data
.get('number')), 
 252             'duration': int_or_none(stream_data
.get('duration')), 
 253             'thumbnail': video_data
.get('cover_image_url'), 
 255             'subtitles': subtitles
,