]>
Commit | Line | Data |
---|---|---|
d2ac0467 RA |
1 | # coding: utf-8 |
2 | from __future__ import unicode_literals | |
3 | ||
4 | import time | |
5 | import hashlib | |
6 | import json | |
7 | ||
818ac213 | 8 | from .adobepass import AdobePassIE |
d2ac0467 RA |
9 | from ..compat import compat_HTTPError |
10 | from ..utils import ( | |
11 | int_or_none, | |
12 | parse_age_limit, | |
13 | str_or_none, | |
14 | parse_duration, | |
15 | ExtractorError, | |
16 | extract_attributes, | |
17 | ) | |
18 | ||
19 | ||
818ac213 | 20 | class VicelandIE(AdobePassIE): |
d2ac0467 RA |
21 | _VALID_URL = r'https?://(?:www\.)?viceland\.com/[^/]+/video/[^/]+/(?P<id>[a-f0-9]+)' |
22 | _TEST = { | |
d2ac0467 RA |
23 | 'url': 'https://www.viceland.com/en_us/video/cyberwar-trailer/57608447973ee7705f6fbd4e', |
24 | 'info_dict': { | |
25 | 'id': '57608447973ee7705f6fbd4e', | |
26 | 'ext': 'mp4', | |
9fa57892 RA |
27 | 'title': 'CYBERWAR (Trailer)', |
28 | 'description': 'Tapping into the geopolitics of hacking and surveillance, Ben Makuch travels the world to meet with hackers, government officials, and dissidents to investigate the ecosystem of cyberwarfare.', | |
29 | 'age_limit': 14, | |
30 | 'timestamp': 1466008539, | |
31 | 'upload_date': '20160615', | |
32 | 'uploader_id': '11', | |
33 | 'uploader': 'Viceland', | |
d2ac0467 RA |
34 | }, |
35 | 'params': { | |
36 | # m3u8 download | |
37 | 'skip_download': True, | |
38 | }, | |
24eb13b1 | 39 | 'add_ie': ['UplynkPreplay'], |
d2ac0467 RA |
40 | } |
41 | ||
42 | def _real_extract(self, url): | |
43 | video_id = self._match_id(url) | |
44 | ||
45 | webpage = self._download_webpage(url, video_id) | |
46 | watch_hub_data = extract_attributes(self._search_regex( | |
47 | r'(?s)(<watch-hub\s*.+?</watch-hub>)', webpage, 'watch hub')) | |
48 | video_id = watch_hub_data['vms-id'] | |
49 | title = watch_hub_data['video-title'] | |
50 | ||
51 | query = {} | |
52 | if watch_hub_data.get('video-locked') == '1': | |
53 | resource = self._get_mvpd_resource( | |
54 | 'VICELAND', title, video_id, | |
55 | watch_hub_data.get('video-rating')) | |
56 | query['tvetoken'] = self._extract_mvpd_auth(url, video_id, 'VICELAND', resource) | |
57 | ||
58 | # signature generation algorithm is reverse engineered from signatureGenerator in | |
59 | # webpack:///../shared/~/vice-player/dist/js/vice-player.js in | |
60 | # https://www.viceland.com/assets/common/js/web.vendor.bundle.js | |
61 | exp = int(time.time()) + 14400 | |
62 | query.update({ | |
63 | 'exp': exp, | |
64 | 'sign': hashlib.sha512(('%s:GET:%d' % (video_id, exp)).encode()).hexdigest(), | |
65 | }) | |
66 | ||
67 | try: | |
68 | preplay = self._download_json('https://www.viceland.com/en_us/preplay/%s' % video_id, video_id, query=query) | |
69 | except ExtractorError as e: | |
70 | if isinstance(e.cause, compat_HTTPError) and e.cause.code == 400: | |
71 | error = json.loads(e.cause.read().decode()) | |
72 | raise ExtractorError('%s said: %s' % (self.IE_NAME, error['details']), expected=True) | |
e811bcf8 | 73 | raise |
d2ac0467 RA |
74 | |
75 | video_data = preplay['video'] | |
76 | base = video_data['base'] | |
77 | uplynk_preplay_url = preplay['preplayURL'] | |
78 | episode = video_data.get('episode', {}) | |
79 | channel = video_data.get('channel', {}) | |
80 | ||
81 | subtitles = {} | |
82 | cc_url = preplay.get('ccURL') | |
83 | if cc_url: | |
84 | subtitles['en'] = [{ | |
85 | 'url': cc_url, | |
86 | }] | |
87 | ||
88 | return { | |
89 | '_type': 'url_transparent', | |
90 | 'url': uplynk_preplay_url, | |
91 | 'id': video_id, | |
92 | 'title': title, | |
93 | 'description': base.get('body'), | |
94 | 'thumbnail': watch_hub_data.get('cover-image') or watch_hub_data.get('thumbnail'), | |
95 | 'duration': parse_duration(video_data.get('video_duration') or watch_hub_data.get('video-duration')), | |
96 | 'timestamp': int_or_none(video_data.get('created_at')), | |
97 | 'age_limit': parse_age_limit(video_data.get('video_rating')), | |
98 | 'series': video_data.get('show_title') or watch_hub_data.get('show-title'), | |
99 | 'episode_number': int_or_none(episode.get('episode_number') or watch_hub_data.get('episode')), | |
100 | 'episode_id': str_or_none(episode.get('id') or video_data.get('episode_id')), | |
101 | 'season_number': int_or_none(watch_hub_data.get('season')), | |
102 | 'season_id': str_or_none(episode.get('season_id')), | |
103 | 'uploader': channel.get('base', {}).get('title') or watch_hub_data.get('channel-title'), | |
104 | 'uploader_id': str_or_none(channel.get('id')), | |
105 | 'subtitles': subtitles, | |
106 | 'ie_key': 'UplynkPreplay', | |
107 | } |