diff options
| -rw-r--r-- | test/test_utils.py | 1 | ||||
| -rw-r--r-- | youtube_dl/extractor/extractors.py | 1 | ||||
| -rw-r--r-- | youtube_dl/extractor/tennistv.py | 113 | ||||
| -rw-r--r-- | youtube_dl/utils.py | 5 | 
4 files changed, 120 insertions, 0 deletions
diff --git a/test/test_utils.py b/test/test_utils.py index f92c65b59..a1fe6fdb2 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -352,6 +352,7 @@ class TestUtil(unittest.TestCase):          self.assertEqual(unified_timestamp('2017-03-30T17:52:41Q'), 1490896361)          self.assertEqual(unified_timestamp('Sep 11, 2013 | 5:49 AM'), 1378878540)          self.assertEqual(unified_timestamp('December 15, 2017 at 7:49 am'), 1513324140) +        self.assertEqual(unified_timestamp('2018-03-14T08:32:43.1493874+00:00'), 1521016363)      def test_determine_ext(self):          self.assertEqual(determine_ext('http://example.com/foo/bar.mp4/?download'), 'mp4') diff --git a/youtube_dl/extractor/extractors.py b/youtube_dl/extractor/extractors.py index 6d6ae89f8..3bde40eb3 100644 --- a/youtube_dl/extractor/extractors.py +++ b/youtube_dl/extractor/extractors.py @@ -1062,6 +1062,7 @@ from .telequebec import (  )  from .teletask import TeleTaskIE  from .telewebion import TelewebionIE +from .tennistv import TennisTVIE  from .testurl import TestURLIE  from .tf1 import TF1IE  from .tfo import TFOIE diff --git a/youtube_dl/extractor/tennistv.py b/youtube_dl/extractor/tennistv.py new file mode 100644 index 000000000..601a17e57 --- /dev/null +++ b/youtube_dl/extractor/tennistv.py @@ -0,0 +1,113 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import json + +from .common import InfoExtractor + +from ..utils import ( +    ExtractorError, +    unified_timestamp, +) + + +class TennisTVIE(InfoExtractor): +    _VALID_URL = r'https?://(?:www\.)?tennistv\.com/videos/(?P<id>[-a-z0-9]+)' +    _TEST = { +        'url': 'https://www.tennistv.com/videos/indian-wells-2018-verdasco-fritz', +        'info_dict': { +            'id': 'indian-wells-2018-verdasco-fritz', +            'ext': 'mp4', +            'title': 'Fernando Verdasco v Taylor Fritz', +            'description': 're:^After his stunning victory.{174}$', +            'thumbnail': 'https://atp-prod.akamaized.net/api/images/v1/images/112831/landscape/1242/0', +            'timestamp': 1521017381, +            'upload_date': '20180314', +        }, +        'params': { +            'skip_download': True, +        }, +        'skip': 'Requires email and password of a subscribed account', +    } +    _NETRC_MACHINE = 'tennistv' + +    def _login(self): +        (username, password) = self._get_login_info() +        if not username or not password: +            raise ExtractorError('No login info available, needed for using %s.' % self.IE_NAME, expected=True) + +        login_form = { +            'Email': username, +            'Password': password, +        } +        login_json = json.dumps(login_form) +        headers = { +            'content-type': 'application/json', +            'Referer': 'https://www.tennistv.com/login', +            'Origin': 'https://www.tennistv.com', +        } + +        login_result = self._download_json( +            'https://www.tennistv.com/api/users/v1/login', None, +            note='Logging in', +            errnote='Login failed (wrong password?)', +            headers=headers, +            data=login_json) + +        if login_result['error']['errorCode']: +            raise ExtractorError('Login failed, %s said: %r' % (self.IE_NAME, login_result['error']['errorMessage'])) + +        if login_result['entitlement'] != 'SUBSCRIBED': +            self.report_warning('%s may not be subscribed to %s.' % (username, self.IE_NAME)) + +        self._session_token = login_result['sessionToken'] + +    def _real_initialize(self): +        self._login() + +    def _real_extract(self, url): +        video_id = self._match_id(url) +        webpage = self._download_webpage(url, video_id) + +        internal_id = self._search_regex(r'video=([0-9]+)', webpage, 'internal video id') + +        headers = { +            'Origin': 'https://www.tennistv.com', +            'authorization': 'ATP %s' % self._session_token, +            'content-type': 'application/json', +            'Referer': url, +        } +        check_data = { +            'videoID': internal_id, +            'VideoUrlType': 'HLSV3', +        } +        check_json = json.dumps(check_data) +        check_result = self._download_json( +            'https://www.tennistv.com/api/users/v1/entitlementchecknondiva', +            video_id, note='Checking video authorization', headers=headers, data=check_json) +        formats = self._extract_m3u8_formats(check_result['contentUrl'], video_id, ext='mp4') + +        vdata_url = 'https://www.tennistv.com/api/channels/v1/de/none/video/%s' % video_id +        vdata = self._download_json(vdata_url, video_id) + +        timestamp = unified_timestamp(vdata['timestamp']) +        thumbnail = vdata['video']['thumbnailUrl'] +        description = vdata['displayText']['description'] +        title = vdata['video']['title'] + +        series = vdata['tour'] +        venue = vdata['displayText']['venue'] +        round_str = vdata['seo']['round'] + +        return { +            'id': video_id, +            'title': title, +            'description': description, +            'formats': formats, +            'timestamp': timestamp, +            'thumbnail': thumbnail, +            'timestamp': timestamp, +            'series': series, +            'season': venue, +            'episode': round_str, +        } diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index a21455f70..027d12785 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1211,6 +1211,11 @@ def unified_timestamp(date_str, day_first=True):      if m:          date_str = date_str[:-len(m.group('tz'))] +    # Python only supports microseconds, so remove nanoseconds +    m = re.search(r'^([0-9]{4,}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\.[0-9]{6})[0-9]+$', date_str) +    if m: +        date_str = m.group(1) +      for expression in date_formats(day_first):          try:              dt = datetime.datetime.strptime(date_str, expression) - timezone + datetime.timedelta(hours=pm_delta)  | 
