]> jfr.im git - yt-dlp.git/blobdiff - yt_dlp/extractor/sevenplus.py
[ie/crunchyroll] Fix stream extraction (#10005)
[yt-dlp.git] / yt_dlp / extractor / sevenplus.py
index 9f15bd7ccc122987dc8cf9955b57017c0cb4214a..6c688d1505ed5a718a53b55bb2d757f458d2aab6 100644 (file)
@@ -1,13 +1,9 @@
-# coding: utf-8
-from __future__ import unicode_literals
-
+import json
 import re
 
-from .brightcove import BrightcoveNewIE
-from ..compat import (
-    compat_HTTPError,
-    compat_str,
-)
+from .brightcove import BrightcoveNewBaseIE
+from ..compat import compat_str
+from ..networking.exceptions import HTTPError
 from ..utils import (
     ExtractorError,
     try_get,
@@ -15,7 +11,7 @@
 )
 
 
-class SevenPlusIE(BrightcoveNewIE):
+class SevenPlusIE(BrightcoveNewBaseIE):
     IE_NAME = '7plus'
     _VALID_URL = r'https?://(?:www\.)?7plus\.com\.au/(?P<path>[^?]+\?.*?\bepisode-id=(?P<id>[^&#]+))'
     _TESTS = [{
@@ -34,7 +30,6 @@ class SevenPlusIE(BrightcoveNewIE):
             'episode': 'Wind Surf',
         },
         'params': {
-            'format': 'bestvideo',
             'skip_download': True,
         }
     }, {
@@ -42,9 +37,52 @@ class SevenPlusIE(BrightcoveNewIE):
         'only_matching': True,
     }]
 
+    def _real_initialize(self):
+        self.token = None
+
+        cookies = self._get_cookies('https://7plus.com.au')
+        api_key = next((x for x in cookies if x.startswith('glt_')), '')[4:]
+        if not api_key:  # Cookies are signed out, skip login
+            return
+
+        login_resp = self._download_json(
+            'https://login.7plus.com.au/accounts.getJWT', None, 'Logging in', fatal=False,
+            query={
+                'APIKey': api_key,
+                'sdk': 'js_latest',
+                'login_token': cookies[f'glt_{api_key}'].value,
+                'authMode': 'cookie',
+                'pageURL': 'https://7plus.com.au/',
+                'sdkBuild': '12471',
+                'format': 'json',
+            }) or {}
+
+        if 'errorMessage' in login_resp:
+            self.report_warning(f'Unable to login: 7plus said: {login_resp["errorMessage"]}')
+            return
+        id_token = login_resp.get('id_token')
+        if not id_token:
+            self.report_warning('Unable to login: Could not extract id token')
+            return
+
+        token_resp = self._download_json(
+            'https://7plus.com.au/auth/token', None, 'Getting auth token', fatal=False,
+            headers={'Content-Type': 'application/json'}, data=json.dumps({
+                'idToken': id_token,
+                'platformId': 'web',
+                'regSource': '7plus',
+            }).encode('utf-8')) or {}
+        self.token = token_resp.get('token')
+        if not self.token:
+            self.report_warning('Unable to log in: Could not extract auth token')
+
     def _real_extract(self, url):
         path, episode_id = self._match_valid_url(url).groups()
 
+        headers = {}
+        if self.token:
+            headers['Authorization'] = f'Bearer {self.token}'
+
         try:
             media = self._download_json(
                 'https://videoservice.swm.digital/playback', episode_id, query={
@@ -55,11 +93,11 @@ def _real_extract(self, url):
                     'referenceId': 'ref:' + episode_id,
                     'deliveryId': 'csai',
                     'videoType': 'vod',
-                })['media']
+                }, headers=headers)['media']
         except ExtractorError as e:
-            if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:
+            if isinstance(e.cause, HTTPError) and e.cause.status == 403:
                 raise ExtractorError(self._parse_json(
-                    e.cause.read().decode(), episode_id)[0]['error_code'], expected=True)
+                    e.cause.response.read().decode(), episode_id)[0]['error_code'], expected=True)
             raise
 
         for source in media.get('sources', {}):