]>
Commit | Line | Data |
---|---|---|
f226880c PH |
1 | # coding: utf-8 |
2 | from __future__ import unicode_literals | |
3 | ||
4 | import json | |
5 | ||
6 | from .common import InfoExtractor | |
7 | ||
8 | from ..utils import ( | |
9 | ExtractorError, | |
10 | unified_timestamp, | |
11 | ) | |
12 | ||
13 | ||
14 | class TennisTVIE(InfoExtractor): | |
15 | _VALID_URL = r'https?://(?:www\.)?tennistv\.com/videos/(?P<id>[-a-z0-9]+)' | |
16 | _TEST = { | |
17 | 'url': 'https://www.tennistv.com/videos/indian-wells-2018-verdasco-fritz', | |
18 | 'info_dict': { | |
19 | 'id': 'indian-wells-2018-verdasco-fritz', | |
20 | 'ext': 'mp4', | |
21 | 'title': 'Fernando Verdasco v Taylor Fritz', | |
22 | 'description': 're:^After his stunning victory.{174}$', | |
23 | 'thumbnail': 'https://atp-prod.akamaized.net/api/images/v1/images/112831/landscape/1242/0', | |
24 | 'timestamp': 1521017381, | |
25 | 'upload_date': '20180314', | |
26 | }, | |
27 | 'params': { | |
28 | 'skip_download': True, | |
29 | }, | |
30 | 'skip': 'Requires email and password of a subscribed account', | |
31 | } | |
32 | _NETRC_MACHINE = 'tennistv' | |
52efa4b3 | 33 | _session_token = None |
f226880c | 34 | |
52efa4b3 | 35 | def _perform_login(self, username, password): |
f226880c PH |
36 | |
37 | login_form = { | |
38 | 'Email': username, | |
39 | 'Password': password, | |
40 | } | |
e6e68069 | 41 | login_json = json.dumps(login_form).encode('utf-8') |
f226880c PH |
42 | headers = { |
43 | 'content-type': 'application/json', | |
44 | 'Referer': 'https://www.tennistv.com/login', | |
45 | 'Origin': 'https://www.tennistv.com', | |
46 | } | |
47 | ||
48 | login_result = self._download_json( | |
49 | 'https://www.tennistv.com/api/users/v1/login', None, | |
50 | note='Logging in', | |
51 | errnote='Login failed (wrong password?)', | |
52 | headers=headers, | |
53 | data=login_json) | |
54 | ||
55 | if login_result['error']['errorCode']: | |
56 | raise ExtractorError('Login failed, %s said: %r' % (self.IE_NAME, login_result['error']['errorMessage'])) | |
57 | ||
58 | if login_result['entitlement'] != 'SUBSCRIBED': | |
59 | self.report_warning('%s may not be subscribed to %s.' % (username, self.IE_NAME)) | |
60 | ||
61 | self._session_token = login_result['sessionToken'] | |
62 | ||
63 | def _real_initialize(self): | |
52efa4b3 | 64 | if not self._session_token: |
65 | raise self.raise_login_required('Login info is needed for this website', method='password') | |
f226880c PH |
66 | |
67 | def _real_extract(self, url): | |
68 | video_id = self._match_id(url) | |
69 | webpage = self._download_webpage(url, video_id) | |
70 | ||
c8d83a22 | 71 | internal_id = self._search_regex(r'video=([\w-]+)', webpage, 'internal video id') |
f226880c PH |
72 | |
73 | headers = { | |
74 | 'Origin': 'https://www.tennistv.com', | |
75 | 'authorization': 'ATP %s' % self._session_token, | |
76 | 'content-type': 'application/json', | |
77 | 'Referer': url, | |
78 | } | |
79 | check_data = { | |
80 | 'videoID': internal_id, | |
c8d83a22 | 81 | 'VideoUrlType': 'HLS', |
f226880c | 82 | } |
e6e68069 | 83 | check_json = json.dumps(check_data).encode('utf-8') |
f226880c PH |
84 | check_result = self._download_json( |
85 | 'https://www.tennistv.com/api/users/v1/entitlementchecknondiva', | |
86 | video_id, note='Checking video authorization', headers=headers, data=check_json) | |
87 | formats = self._extract_m3u8_formats(check_result['contentUrl'], video_id, ext='mp4') | |
bce8cbb0 | 88 | self._sort_formats(formats) |
f226880c | 89 | |
c8d83a22 | 90 | vdata = self._download_json( |
91 | 'https://www.tennistv.com/api/en/v2/none/common/video/%s' % video_id, | |
92 | video_id, headers=headers) | |
f226880c PH |
93 | |
94 | timestamp = unified_timestamp(vdata['timestamp']) | |
95 | thumbnail = vdata['video']['thumbnailUrl'] | |
96 | description = vdata['displayText']['description'] | |
97 | title = vdata['video']['title'] | |
98 | ||
99 | series = vdata['tour'] | |
100 | venue = vdata['displayText']['venue'] | |
101 | round_str = vdata['seo']['round'] | |
102 | ||
103 | return { | |
104 | 'id': video_id, | |
105 | 'title': title, | |
106 | 'description': description, | |
107 | 'formats': formats, | |
f226880c PH |
108 | 'thumbnail': thumbnail, |
109 | 'timestamp': timestamp, | |
110 | 'series': series, | |
111 | 'season': venue, | |
112 | 'episode': round_str, | |
113 | } |