mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-15 21:53:21 +00:00
Compare commits
No commits in common. "9809740ba5cc5daf53e690d104a37aa6545e53f9" and "0c36dc00d7b9f43238bacb0e03730f31117d0b38" have entirely different histories.
9809740ba5
...
0c36dc00d7
@ -109,7 +109,7 @@ class AbemaLicenseHandler(compat_urllib_request.BaseHandler):
|
|||||||
self.ie = ie
|
self.ie = ie
|
||||||
|
|
||||||
def _get_videokey_from_ticket(self, ticket):
|
def _get_videokey_from_ticket(self, ticket):
|
||||||
to_show = self.ie.get_param('verbose', False)
|
to_show = self.ie._downloader.params.get('verbose', False)
|
||||||
media_token = self.ie._get_media_token(to_show=to_show)
|
media_token = self.ie._get_media_token(to_show=to_show)
|
||||||
|
|
||||||
license_response = self.ie._download_json(
|
license_response = self.ie._download_json(
|
||||||
|
@ -1431,7 +1431,7 @@ class AdobePassIE(InfoExtractor):
|
|||||||
guid = xml_text(resource, 'guid') if '<' in resource else resource
|
guid = xml_text(resource, 'guid') if '<' in resource else resource
|
||||||
count = 0
|
count = 0
|
||||||
while count < 2:
|
while count < 2:
|
||||||
requestor_info = self.cache.load(self._MVPD_CACHE, requestor_id) or {}
|
requestor_info = self._downloader.cache.load(self._MVPD_CACHE, requestor_id) or {}
|
||||||
authn_token = requestor_info.get('authn_token')
|
authn_token = requestor_info.get('authn_token')
|
||||||
if authn_token and is_expired(authn_token, 'simpleTokenExpires'):
|
if authn_token and is_expired(authn_token, 'simpleTokenExpires'):
|
||||||
authn_token = None
|
authn_token = None
|
||||||
@ -1726,12 +1726,12 @@ class AdobePassIE(InfoExtractor):
|
|||||||
raise_mvpd_required()
|
raise_mvpd_required()
|
||||||
raise
|
raise
|
||||||
if '<pendingLogout' in session:
|
if '<pendingLogout' in session:
|
||||||
self.cache.store(self._MVPD_CACHE, requestor_id, {})
|
self._downloader.cache.store(self._MVPD_CACHE, requestor_id, {})
|
||||||
count += 1
|
count += 1
|
||||||
continue
|
continue
|
||||||
authn_token = unescapeHTML(xml_text(session, 'authnToken'))
|
authn_token = unescapeHTML(xml_text(session, 'authnToken'))
|
||||||
requestor_info['authn_token'] = authn_token
|
requestor_info['authn_token'] = authn_token
|
||||||
self.cache.store(self._MVPD_CACHE, requestor_id, requestor_info)
|
self._downloader.cache.store(self._MVPD_CACHE, requestor_id, requestor_info)
|
||||||
|
|
||||||
authz_token = requestor_info.get(guid)
|
authz_token = requestor_info.get(guid)
|
||||||
if authz_token and is_expired(authz_token, 'simpleTokenTTL'):
|
if authz_token and is_expired(authz_token, 'simpleTokenTTL'):
|
||||||
@ -1747,14 +1747,14 @@ class AdobePassIE(InfoExtractor):
|
|||||||
'userMeta': '1',
|
'userMeta': '1',
|
||||||
}), headers=mvpd_headers)
|
}), headers=mvpd_headers)
|
||||||
if '<pendingLogout' in authorize:
|
if '<pendingLogout' in authorize:
|
||||||
self.cache.store(self._MVPD_CACHE, requestor_id, {})
|
self._downloader.cache.store(self._MVPD_CACHE, requestor_id, {})
|
||||||
count += 1
|
count += 1
|
||||||
continue
|
continue
|
||||||
if '<error' in authorize:
|
if '<error' in authorize:
|
||||||
raise ExtractorError(xml_text(authorize, 'details'), expected=True)
|
raise ExtractorError(xml_text(authorize, 'details'), expected=True)
|
||||||
authz_token = unescapeHTML(xml_text(authorize, 'authzToken'))
|
authz_token = unescapeHTML(xml_text(authorize, 'authzToken'))
|
||||||
requestor_info[guid] = authz_token
|
requestor_info[guid] = authz_token
|
||||||
self.cache.store(self._MVPD_CACHE, requestor_id, requestor_info)
|
self._downloader.cache.store(self._MVPD_CACHE, requestor_id, requestor_info)
|
||||||
|
|
||||||
mvpd_headers.update({
|
mvpd_headers.update({
|
||||||
'ap_19': xml_text(authn_token, 'simpleSamlNameID'),
|
'ap_19': xml_text(authn_token, 'simpleSamlNameID'),
|
||||||
@ -1770,7 +1770,7 @@ class AdobePassIE(InfoExtractor):
|
|||||||
'hashed_guid': 'false',
|
'hashed_guid': 'false',
|
||||||
}), headers=mvpd_headers)
|
}), headers=mvpd_headers)
|
||||||
if '<pendingLogout' in short_authorize:
|
if '<pendingLogout' in short_authorize:
|
||||||
self.cache.store(self._MVPD_CACHE, requestor_id, {})
|
self._downloader.cache.store(self._MVPD_CACHE, requestor_id, {})
|
||||||
count += 1
|
count += 1
|
||||||
continue
|
continue
|
||||||
return short_authorize
|
return short_authorize
|
||||||
|
@ -600,9 +600,9 @@ class BrightcoveNewIE(AdobePassIE):
|
|||||||
account_id, player_id, embed, content_type, video_id = self._match_valid_url(url).groups()
|
account_id, player_id, embed, content_type, video_id = self._match_valid_url(url).groups()
|
||||||
|
|
||||||
policy_key_id = '%s_%s' % (account_id, player_id)
|
policy_key_id = '%s_%s' % (account_id, player_id)
|
||||||
policy_key = self.cache.load('brightcove', policy_key_id)
|
policy_key = self._downloader.cache.load('brightcove', policy_key_id)
|
||||||
policy_key_extracted = False
|
policy_key_extracted = False
|
||||||
store_pk = lambda x: self.cache.store('brightcove', policy_key_id, x)
|
store_pk = lambda x: self._downloader.cache.store('brightcove', policy_key_id, x)
|
||||||
|
|
||||||
def extract_policy_key():
|
def extract_policy_key():
|
||||||
base_url = 'http://players.brightcove.net/%s/%s_%s/' % (account_id, player_id, embed)
|
base_url = 'http://players.brightcove.net/%s/%s_%s/' % (account_id, player_id, embed)
|
||||||
|
@ -304,13 +304,13 @@ class CBCGemIE(InfoExtractor):
|
|||||||
def _get_claims_token(self, email, password):
|
def _get_claims_token(self, email, password):
|
||||||
if not self.claims_token_valid():
|
if not self.claims_token_valid():
|
||||||
self._claims_token = self._new_claims_token(email, password)
|
self._claims_token = self._new_claims_token(email, password)
|
||||||
self.cache.store(self._NETRC_MACHINE, 'claims_token', self._claims_token)
|
self._downloader.cache.store(self._NETRC_MACHINE, 'claims_token', self._claims_token)
|
||||||
return self._claims_token
|
return self._claims_token
|
||||||
|
|
||||||
def _real_initialize(self):
|
def _real_initialize(self):
|
||||||
if self.claims_token_valid():
|
if self.claims_token_valid():
|
||||||
return
|
return
|
||||||
self._claims_token = self.cache.load(self._NETRC_MACHINE, 'claims_token')
|
self._claims_token = self._downloader.cache.load(self._NETRC_MACHINE, 'claims_token')
|
||||||
|
|
||||||
def _find_secret_formats(self, formats, video_id):
|
def _find_secret_formats(self, formats, video_id):
|
||||||
""" Find a valid video url and convert it to the secret variant """
|
""" Find a valid video url and convert it to the secret variant """
|
||||||
|
@ -695,14 +695,6 @@ class InfoExtractor:
|
|||||||
"""Sets a YoutubeDL instance as the downloader for this IE."""
|
"""Sets a YoutubeDL instance as the downloader for this IE."""
|
||||||
self._downloader = downloader
|
self._downloader = downloader
|
||||||
|
|
||||||
@property
|
|
||||||
def cache(self):
|
|
||||||
return self._downloader.cache
|
|
||||||
|
|
||||||
@property
|
|
||||||
def cookiejar(self):
|
|
||||||
return self._downloader.cookiejar
|
|
||||||
|
|
||||||
def _initialize_pre_login(self):
|
def _initialize_pre_login(self):
|
||||||
""" Intialization before login. Redefine in subclasses."""
|
""" Intialization before login. Redefine in subclasses."""
|
||||||
pass
|
pass
|
||||||
@ -3601,7 +3593,7 @@ class InfoExtractor:
|
|||||||
0, name, value, port, port is not None, domain, True,
|
0, name, value, port, port is not None, domain, True,
|
||||||
domain.startswith('.'), path, True, secure, expire_time,
|
domain.startswith('.'), path, True, secure, expire_time,
|
||||||
discard, None, None, rest)
|
discard, None, None, rest)
|
||||||
self.cookiejar.set_cookie(cookie)
|
self._downloader.cookiejar.set_cookie(cookie)
|
||||||
|
|
||||||
def _get_cookies(self, url):
|
def _get_cookies(self, url):
|
||||||
""" Return a compat_cookies_SimpleCookie with the cookies for the url """
|
""" Return a compat_cookies_SimpleCookie with the cookies for the url """
|
||||||
|
@ -78,7 +78,7 @@ class FC2IE(InfoExtractor):
|
|||||||
webpage = None
|
webpage = None
|
||||||
if not url.startswith('fc2:'):
|
if not url.startswith('fc2:'):
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
self.cookiejar.clear_session_cookies() # must clear
|
self._downloader.cookiejar.clear_session_cookies() # must clear
|
||||||
self._login()
|
self._login()
|
||||||
|
|
||||||
title, thumbnail, description = None, None, None
|
title, thumbnail, description = None, None, None
|
||||||
|
@ -31,7 +31,7 @@ class FoxgayIE(InfoExtractor):
|
|||||||
description = get_element_by_id('inf_tit', webpage)
|
description = get_element_by_id('inf_tit', webpage)
|
||||||
|
|
||||||
# The default user-agent with foxgay cookies leads to pages without videos
|
# The default user-agent with foxgay cookies leads to pages without videos
|
||||||
self.cookiejar.clear('.foxgay.com')
|
self._downloader.cookiejar.clear('.foxgay.com')
|
||||||
# Find the URL for the iFrame which contains the actual video.
|
# Find the URL for the iFrame which contains the actual video.
|
||||||
iframe_url = self._html_search_regex(
|
iframe_url = self._html_search_regex(
|
||||||
r'<iframe[^>]+src=([\'"])(?P<url>[^\'"]+)\1', webpage,
|
r'<iframe[^>]+src=([\'"])(?P<url>[^\'"]+)\1', webpage,
|
||||||
|
@ -264,7 +264,7 @@ class GoogleDriveIE(InfoExtractor):
|
|||||||
subtitles_id = ttsurl.encode('utf-8').decode(
|
subtitles_id = ttsurl.encode('utf-8').decode(
|
||||||
'unicode_escape').split('=')[-1]
|
'unicode_escape').split('=')[-1]
|
||||||
|
|
||||||
self.cookiejar.clear(domain='.google.com', path='/', name='NID')
|
self._downloader.cookiejar.clear(domain='.google.com', path='/', name='NID')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': video_id,
|
'id': video_id,
|
||||||
|
@ -521,7 +521,7 @@ class IqIE(InfoExtractor):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
def _extract_vms_player_js(self, webpage, video_id):
|
def _extract_vms_player_js(self, webpage, video_id):
|
||||||
player_js_cache = self.cache.load('iq', 'player_js')
|
player_js_cache = self._downloader.cache.load('iq', 'player_js')
|
||||||
if player_js_cache:
|
if player_js_cache:
|
||||||
return player_js_cache
|
return player_js_cache
|
||||||
webpack_js_url = self._proto_relative_url(self._search_regex(
|
webpack_js_url = self._proto_relative_url(self._search_regex(
|
||||||
@ -534,7 +534,7 @@ class IqIE(InfoExtractor):
|
|||||||
f'https://stc.iqiyipic.com/_next/static/chunks/{webpack_map1.get(module_index, module_index)}.{webpack_map2[module_index]}.js',
|
f'https://stc.iqiyipic.com/_next/static/chunks/{webpack_map1.get(module_index, module_index)}.{webpack_map2[module_index]}.js',
|
||||||
video_id, note=f'Downloading #{module_index} module JS', errnote='Unable to download module JS', fatal=False) or ''
|
video_id, note=f'Downloading #{module_index} module JS', errnote='Unable to download module JS', fatal=False) or ''
|
||||||
if 'vms request' in module_js:
|
if 'vms request' in module_js:
|
||||||
self.cache.store('iq', 'player_js', module_js)
|
self._downloader.cache.store('iq', 'player_js', module_js)
|
||||||
return module_js
|
return module_js
|
||||||
raise ExtractorError('Unable to extract player JS')
|
raise ExtractorError('Unable to extract player JS')
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ class PhantomJSwrapper:
|
|||||||
os.remove(self._TMP_FILES[name].name)
|
os.remove(self._TMP_FILES[name].name)
|
||||||
|
|
||||||
def _save_cookies(self, url):
|
def _save_cookies(self, url):
|
||||||
cookies = cookie_jar_to_list(self.extractor.cookiejar)
|
cookies = cookie_jar_to_list(self.extractor._downloader.cookiejar)
|
||||||
for cookie in cookies:
|
for cookie in cookies:
|
||||||
if 'path' not in cookie:
|
if 'path' not in cookie:
|
||||||
cookie['path'] = '/'
|
cookie['path'] = '/'
|
||||||
|
@ -43,7 +43,7 @@ class RadikoBaseIE(InfoExtractor):
|
|||||||
}).split(',')[0]
|
}).split(',')[0]
|
||||||
|
|
||||||
auth_data = (auth_token, area_id)
|
auth_data = (auth_token, area_id)
|
||||||
self.cache.store('radiko', 'auth_data', auth_data)
|
self._downloader.cache.store('radiko', 'auth_data', auth_data)
|
||||||
return auth_data
|
return auth_data
|
||||||
|
|
||||||
def _extract_full_key(self):
|
def _extract_full_key(self):
|
||||||
@ -150,7 +150,7 @@ class RadikoIE(RadikoBaseIE):
|
|||||||
vid_int = unified_timestamp(video_id, False)
|
vid_int = unified_timestamp(video_id, False)
|
||||||
prog, station_program, ft, radio_begin, radio_end = self._find_program(video_id, station, vid_int)
|
prog, station_program, ft, radio_begin, radio_end = self._find_program(video_id, station, vid_int)
|
||||||
|
|
||||||
auth_cache = self.cache.load('radiko', 'auth_data')
|
auth_cache = self._downloader.cache.load('radiko', 'auth_data')
|
||||||
for attempt in range(2):
|
for attempt in range(2):
|
||||||
auth_token, area_id = (not attempt and auth_cache) or self._auth_client()
|
auth_token, area_id = (not attempt and auth_cache) or self._auth_client()
|
||||||
formats = self._extract_formats(
|
formats = self._extract_formats(
|
||||||
|
@ -360,7 +360,7 @@ class RokfinSearchIE(SearchInfoExtractor):
|
|||||||
_db_access_key = None
|
_db_access_key = None
|
||||||
|
|
||||||
def _real_initialize(self):
|
def _real_initialize(self):
|
||||||
self._db_url, self._db_access_key = self.cache.load(self.ie_key(), 'auth', default=(None, None))
|
self._db_url, self._db_access_key = self._downloader.cache.load(self.ie_key(), 'auth', default=(None, None))
|
||||||
if not self._db_url:
|
if not self._db_url:
|
||||||
self._get_db_access_credentials()
|
self._get_db_access_credentials()
|
||||||
|
|
||||||
@ -405,6 +405,6 @@ class RokfinSearchIE(SearchInfoExtractor):
|
|||||||
|
|
||||||
self._db_url = url_or_none(f'{auth_data["ENDPOINT_BASE"]}/api/as/v1/engines/rokfin-search/search.json')
|
self._db_url = url_or_none(f'{auth_data["ENDPOINT_BASE"]}/api/as/v1/engines/rokfin-search/search.json')
|
||||||
self._db_access_key = f'Bearer {auth_data["SEARCH_KEY"]}'
|
self._db_access_key = f'Bearer {auth_data["SEARCH_KEY"]}'
|
||||||
self.cache.store(self.ie_key(), 'auth', (self._db_url, self._db_access_key))
|
self._downloader.cache.store(self.ie_key(), 'auth', (self._db_url, self._db_access_key))
|
||||||
return
|
return
|
||||||
raise ExtractorError('Unable to extract access credentials')
|
raise ExtractorError('Unable to extract access credentials')
|
||||||
|
@ -67,7 +67,7 @@ class SoundcloudBaseIE(InfoExtractor):
|
|||||||
_HEADERS = {}
|
_HEADERS = {}
|
||||||
|
|
||||||
def _store_client_id(self, client_id):
|
def _store_client_id(self, client_id):
|
||||||
self.cache.store('soundcloud', 'client_id', client_id)
|
self._downloader.cache.store('soundcloud', 'client_id', client_id)
|
||||||
|
|
||||||
def _update_client_id(self):
|
def _update_client_id(self):
|
||||||
webpage = self._download_webpage('https://soundcloud.com/', None)
|
webpage = self._download_webpage('https://soundcloud.com/', None)
|
||||||
@ -104,7 +104,7 @@ class SoundcloudBaseIE(InfoExtractor):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def _initialize_pre_login(self):
|
def _initialize_pre_login(self):
|
||||||
self._CLIENT_ID = self.cache.load('soundcloud', 'client_id') or 'a3e059563d7fd3372b49b37f00a00bcf'
|
self._CLIENT_ID = self._downloader.cache.load('soundcloud', 'client_id') or 'a3e059563d7fd3372b49b37f00a00bcf'
|
||||||
|
|
||||||
def _perform_login(self, username, password):
|
def _perform_login(self, username, password):
|
||||||
if username != 'oauth':
|
if username != 'oauth':
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
import urllib.parse
|
import json
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
|
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
random_uuidv4,
|
|
||||||
unified_timestamp,
|
unified_timestamp,
|
||||||
urlencode_postdata,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TennisTVIE(InfoExtractor):
|
class TennisTVIE(InfoExtractor):
|
||||||
_VALID_URL = r'https?://(?:www\.)?tennistv\.com/videos/(?P<id>[-a-z0-9]+)'
|
_VALID_URL = r'https?://(?:www\.)?tennistv\.com/videos/(?P<id>[-a-z0-9]+)'
|
||||||
_TESTS = [{
|
_TEST = {
|
||||||
'url': 'https://www.tennistv.com/videos/indian-wells-2018-verdasco-fritz',
|
'url': 'https://www.tennistv.com/videos/indian-wells-2018-verdasco-fritz',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'indian-wells-2018-verdasco-fritz',
|
'id': 'indian-wells-2018-verdasco-fritz',
|
||||||
@ -26,132 +25,86 @@ class TennisTVIE(InfoExtractor):
|
|||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
},
|
},
|
||||||
'skip': 'Requires email and password of a subscribed account',
|
'skip': 'Requires email and password of a subscribed account',
|
||||||
}, {
|
|
||||||
'url': 'https://www.tennistv.com/videos/2650480/best-matches-of-2022-part-5',
|
|
||||||
'info_dict': {
|
|
||||||
'id': '2650480',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'title': 'Best Matches of 2022 - Part 5',
|
|
||||||
'description': 'md5:36dec3bfae7ed74bd79e48045b17264c',
|
|
||||||
'thumbnail': 'https://open.http.mp.streamamg.com/p/3001482/sp/300148200/thumbnail/entry_id/0_myef18pd/version/100001/height/1920',
|
|
||||||
},
|
|
||||||
'params': {'skip_download': 'm3u8'},
|
|
||||||
'skip': 'Requires email and password of a subscribed account',
|
|
||||||
}]
|
|
||||||
_NETRC_MACHINE = 'tennistv'
|
|
||||||
|
|
||||||
access_token, refresh_token = None, None
|
|
||||||
_PARTNER_ID = 3001482
|
|
||||||
_FORMAT_URL = 'https://open.http.mp.streamamg.com/p/{partner}/sp/{partner}00/playManifest/entryId/{entry}/format/applehttp/protocol/https/a.m3u8?ks={session}'
|
|
||||||
_AUTH_BASE_URL = 'https://sso.tennistv.com/auth/realms/TennisTV/protocol/openid-connect'
|
|
||||||
_HEADERS = {
|
|
||||||
'origin': 'https://www.tennistv.com',
|
|
||||||
'referer': 'https://www.tennistv.com/',
|
|
||||||
'content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
}
|
}
|
||||||
|
_NETRC_MACHINE = 'tennistv'
|
||||||
|
_session_token = None
|
||||||
|
|
||||||
def _perform_login(self, username, password):
|
def _perform_login(self, username, password):
|
||||||
login_page = self._download_webpage(
|
|
||||||
f'{self._AUTH_BASE_URL}/auth', None, 'Downloading login page',
|
|
||||||
query={
|
|
||||||
'client_id': 'tennis-tv-web',
|
|
||||||
'redirect_uri': 'https://tennistv.com',
|
|
||||||
'response_mode': 'fragment',
|
|
||||||
'response_type': 'code',
|
|
||||||
'scope': 'openid'
|
|
||||||
})
|
|
||||||
|
|
||||||
post_url = self._html_search_regex(r'action=["\']([^"\']+?)["\']\s+method=["\']post["\']', login_page, 'login POST url')
|
login_form = {
|
||||||
temp_page = self._download_webpage(
|
'Email': username,
|
||||||
post_url, None, 'Sending login data', 'Unable to send login data',
|
'Password': password,
|
||||||
headers=self._HEADERS, data=urlencode_postdata({
|
}
|
||||||
'username': username,
|
login_json = json.dumps(login_form).encode('utf-8')
|
||||||
'password': password,
|
headers = {
|
||||||
'submitAction': 'Log In'
|
'content-type': 'application/json',
|
||||||
}))
|
'Referer': 'https://www.tennistv.com/login',
|
||||||
if 'Your username or password was incorrect' in temp_page:
|
'Origin': 'https://www.tennistv.com',
|
||||||
raise ExtractorError('Your username or password was incorrect', expected=True)
|
}
|
||||||
|
|
||||||
handle = self._request_webpage(
|
login_result = self._download_json(
|
||||||
f'{self._AUTH_BASE_URL}/auth', None, 'Logging in', headers=self._HEADERS,
|
'https://www.tennistv.com/api/users/v1/login', None,
|
||||||
query={
|
note='Logging in',
|
||||||
'client_id': 'tennis-tv-web',
|
errnote='Login failed (wrong password?)',
|
||||||
'redirect_uri': 'https://www.tennistv.com/resources/v1.1.10/html/silent-check-sso.html',
|
headers=headers,
|
||||||
'state': random_uuidv4(),
|
data=login_json)
|
||||||
'response_mode': 'fragment',
|
|
||||||
'response_type': 'code',
|
|
||||||
'scope': 'openid',
|
|
||||||
'nonce': random_uuidv4(),
|
|
||||||
'prompt': 'none'
|
|
||||||
})
|
|
||||||
|
|
||||||
self.get_token(None, {
|
if login_result['error']['errorCode']:
|
||||||
'code': urllib.parse.parse_qs(handle.geturl())['code'][-1],
|
raise ExtractorError('Login failed, %s said: %r' % (self.IE_NAME, login_result['error']['errorMessage']))
|
||||||
'grant_type': 'authorization_code',
|
|
||||||
'client_id': 'tennis-tv-web',
|
|
||||||
'redirect_uri': 'https://www.tennistv.com/resources/v1.1.10/html/silent-check-sso.html'
|
|
||||||
})
|
|
||||||
|
|
||||||
def get_token(self, video_id, payload):
|
if login_result['entitlement'] != 'SUBSCRIBED':
|
||||||
res = self._download_json(
|
self.report_warning('%s may not be subscribed to %s.' % (username, self.IE_NAME))
|
||||||
f'{self._AUTH_BASE_URL}/token', video_id, 'Fetching tokens',
|
|
||||||
'Unable to fetch tokens', headers=self._HEADERS, data=urlencode_postdata(payload))
|
|
||||||
|
|
||||||
self.access_token = res.get('access_token') or self.access_token
|
self._session_token = login_result['sessionToken']
|
||||||
self.refresh_token = res.get('refresh_token') or self.refresh_token
|
|
||||||
|
|
||||||
def _real_initialize(self):
|
def _real_initialize(self):
|
||||||
if self.access_token and self.refresh_token:
|
if not self._session_token:
|
||||||
return
|
raise self.raise_login_required('Login info is needed for this website', method='password')
|
||||||
|
|
||||||
cookies = self._get_cookies('https://www.tennistv.com/')
|
|
||||||
if not cookies.get('access_token') or not cookies.get('refresh_token'):
|
|
||||||
self.raise_login_required()
|
|
||||||
self.access_token, self.refresh_token = cookies['access_token'].value, cookies['refresh_token'].value
|
|
||||||
|
|
||||||
def _download_session_json(self, video_id, entryid,):
|
|
||||||
return self._download_json(
|
|
||||||
f'https://atppayments.streamamg.com/api/v1/session/ksession/?lang=en&apijwttoken={self.access_token}&entryId={entryid}',
|
|
||||||
video_id, 'Downloading ksession token', 'Failed to download ksession token', headers=self._HEADERS)
|
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
video_id = self._match_id(url)
|
video_id = self._match_id(url)
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
entryid = self._search_regex(r'data-entry-id=["\']([^"\']+)', webpage, 'entryID')
|
internal_id = self._search_regex(r'video=([\w-]+)', webpage, 'internal video id')
|
||||||
session_json = self._download_session_json(video_id, entryid)
|
|
||||||
|
|
||||||
k_session = session_json.get('KSession')
|
|
||||||
if k_session is None:
|
|
||||||
self.get_token(video_id, {
|
|
||||||
'grant_type': 'refresh_token',
|
|
||||||
'refresh_token': self.refresh_token,
|
|
||||||
'client_id': 'tennis-tv-web'
|
|
||||||
})
|
|
||||||
k_session = self._download_session_json(video_id, entryid).get('KSession')
|
|
||||||
if k_session is None:
|
|
||||||
raise ExtractorError('Failed to get KSession, possibly a premium video', expected=True)
|
|
||||||
|
|
||||||
if session_json.get('ErrorMessage'):
|
|
||||||
self.report_warning(session_json['ErrorMessage'])
|
|
||||||
|
|
||||||
formats, subtitles = self._extract_m3u8_formats_and_subtitles(
|
|
||||||
self._FORMAT_URL.format(partner=self._PARTNER_ID, entry=entryid, session=k_session), 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': 'HLS',
|
||||||
|
}
|
||||||
|
check_json = json.dumps(check_data).encode('utf-8')
|
||||||
|
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')
|
||||||
self._sort_formats(formats)
|
self._sort_formats(formats)
|
||||||
|
|
||||||
|
vdata = self._download_json(
|
||||||
|
'https://www.tennistv.com/api/en/v2/none/common/video/%s' % video_id,
|
||||||
|
video_id, headers=headers)
|
||||||
|
|
||||||
|
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 {
|
return {
|
||||||
'id': video_id,
|
'id': video_id,
|
||||||
'title': self._html_extract_title(webpage) or self._og_search_title(webpage),
|
'title': title,
|
||||||
'description': self._html_search_regex(
|
'description': description,
|
||||||
(r'<span itemprop="description" content=["\']([^"\']+)["\']>', *self._og_regexes('description')),
|
|
||||||
webpage, 'description', fatal=False),
|
|
||||||
'thumbnail': f'https://open.http.mp.streamamg.com/p/{self._PARTNER_ID}/sp/{self._PARTNER_ID}00/thumbnail/entry_id/{entryid}/version/100001/height/1920',
|
|
||||||
'timestamp': unified_timestamp(self._html_search_regex(
|
|
||||||
r'<span itemprop="description" content=["\']([^"\']+)["\']>', webpage, 'upload time')),
|
|
||||||
'series': self._html_search_regex(r'data-series\s*?=\s*?"(.*?)"', webpage, 'series', fatal=False) or None,
|
|
||||||
'season': self._html_search_regex(r'data-tournament-city\s*?=\s*?"(.*?)"', webpage, 'season', fatal=False) or None,
|
|
||||||
'episode': self._html_search_regex(r'data-round\s*?=\s*?"(.*?)"', webpage, 'round', fatal=False) or None,
|
|
||||||
'formats': formats,
|
'formats': formats,
|
||||||
'subtitles': subtitles,
|
'thumbnail': thumbnail,
|
||||||
|
'timestamp': timestamp,
|
||||||
|
'series': series,
|
||||||
|
'season': venue,
|
||||||
|
'episode': round_str,
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ class UdemyIE(InfoExtractor):
|
|||||||
'X-Udemy-Snail-Case': 'true',
|
'X-Udemy-Snail-Case': 'true',
|
||||||
'X-Requested-With': 'XMLHttpRequest',
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
}
|
}
|
||||||
for cookie in self.cookiejar:
|
for cookie in self._downloader.cookiejar:
|
||||||
if cookie.name == 'client_id':
|
if cookie.name == 'client_id':
|
||||||
headers['X-Udemy-Client-Id'] = cookie.value
|
headers['X-Udemy-Client-Id'] = cookie.value
|
||||||
elif cookie.name == 'access_token':
|
elif cookie.name == 'access_token':
|
||||||
|
@ -20,7 +20,7 @@ class WPPilotBaseIE(InfoExtractor):
|
|||||||
|
|
||||||
def _get_channel_list(self, cache=True):
|
def _get_channel_list(self, cache=True):
|
||||||
if cache is True:
|
if cache is True:
|
||||||
cache_res = self.cache.load('wppilot', 'channel-list')
|
cache_res = self._downloader.cache.load('wppilot', 'channel-list')
|
||||||
if cache_res:
|
if cache_res:
|
||||||
return cache_res, True
|
return cache_res, True
|
||||||
webpage = self._download_webpage('https://pilot.wp.pl/tv/', None, 'Downloading webpage')
|
webpage = self._download_webpage('https://pilot.wp.pl/tv/', None, 'Downloading webpage')
|
||||||
@ -35,7 +35,7 @@ class WPPilotBaseIE(InfoExtractor):
|
|||||||
channel_list = try_get(qhash_content, lambda x: x['data']['allChannels']['nodes'])
|
channel_list = try_get(qhash_content, lambda x: x['data']['allChannels']['nodes'])
|
||||||
if channel_list is None:
|
if channel_list is None:
|
||||||
continue
|
continue
|
||||||
self.cache.store('wppilot', 'channel-list', channel_list)
|
self._downloader.cache.store('wppilot', 'channel-list', channel_list)
|
||||||
return channel_list, False
|
return channel_list, False
|
||||||
raise ExtractorError('Unable to find the channel list')
|
raise ExtractorError('Unable to find the channel list')
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ class WPPilotIE(WPPilotBaseIE):
|
|||||||
channel = self._get_channel(video_id)
|
channel = self._get_channel(video_id)
|
||||||
video_id = str(channel['id'])
|
video_id = str(channel['id'])
|
||||||
|
|
||||||
is_authorized = next((c for c in self.cookiejar if c.name == 'netviapisessid'), None)
|
is_authorized = next((c for c in self._downloader.cookiejar if c.name == 'netviapisessid'), None)
|
||||||
# cookies starting with "g:" are assigned to guests
|
# cookies starting with "g:" are assigned to guests
|
||||||
is_authorized = True if is_authorized is not None and not is_authorized.value.startswith('g:') else False
|
is_authorized = True if is_authorized is not None and not is_authorized.value.startswith('g:') else False
|
||||||
|
|
||||||
|
@ -2475,7 +2475,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
func_id = f'js_{player_id}_{self._signature_cache_id(example_sig)}'
|
func_id = f'js_{player_id}_{self._signature_cache_id(example_sig)}'
|
||||||
assert os.path.basename(func_id) == func_id
|
assert os.path.basename(func_id) == func_id
|
||||||
|
|
||||||
cache_spec = self.cache.load('youtube-sigfuncs', func_id)
|
cache_spec = self._downloader.cache.load('youtube-sigfuncs', func_id)
|
||||||
if cache_spec is not None:
|
if cache_spec is not None:
|
||||||
return lambda s: ''.join(s[i] for i in cache_spec)
|
return lambda s: ''.join(s[i] for i in cache_spec)
|
||||||
|
|
||||||
@ -2487,7 +2487,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
cache_res = res(test_string)
|
cache_res = res(test_string)
|
||||||
cache_spec = [ord(c) for c in cache_res]
|
cache_spec = [ord(c) for c in cache_res]
|
||||||
|
|
||||||
self.cache.store('youtube-sigfuncs', func_id, cache_spec)
|
self._downloader.cache.store('youtube-sigfuncs', func_id, cache_spec)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _print_sig_code(self, func, example_sig):
|
def _print_sig_code(self, func, example_sig):
|
||||||
@ -2602,7 +2602,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
|
|
||||||
def _extract_n_function(self, video_id, player_url):
|
def _extract_n_function(self, video_id, player_url):
|
||||||
player_id = self._extract_player_info(player_url)
|
player_id = self._extract_player_info(player_url)
|
||||||
func_code = self.cache.load('youtube-nsig', player_id)
|
func_code = self._downloader.cache.load('youtube-nsig', player_id)
|
||||||
|
|
||||||
if func_code:
|
if func_code:
|
||||||
jsi = JSInterpreter(func_code)
|
jsi = JSInterpreter(func_code)
|
||||||
@ -2611,7 +2611,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
funcname = self._extract_n_function_name(jscode)
|
funcname = self._extract_n_function_name(jscode)
|
||||||
jsi = JSInterpreter(jscode)
|
jsi = JSInterpreter(jscode)
|
||||||
func_code = jsi.extract_function_code(funcname)
|
func_code = jsi.extract_function_code(funcname)
|
||||||
self.cache.store('youtube-nsig', player_id, func_code)
|
self._downloader.cache.store('youtube-nsig', player_id, func_code)
|
||||||
|
|
||||||
if self.get_param('youtube_print_sig_code'):
|
if self.get_param('youtube_print_sig_code'):
|
||||||
self.to_screen(f'Extracted nsig function from {player_id}:\n{func_code[1]}\n')
|
self.to_screen(f'Extracted nsig function from {player_id}:\n{func_code[1]}\n')
|
||||||
|
@ -347,7 +347,6 @@ class FFmpegPostProcessor(PostProcessor):
|
|||||||
_, stderr, returncode = Popen.run(
|
_, stderr, returncode = Popen.run(
|
||||||
cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
|
cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
|
||||||
if returncode not in variadic(expected_retcodes):
|
if returncode not in variadic(expected_retcodes):
|
||||||
self.write_debug(stderr)
|
|
||||||
raise FFmpegPostProcessorError(stderr.strip().splitlines()[-1])
|
raise FFmpegPostProcessorError(stderr.strip().splitlines()[-1])
|
||||||
for out_path, _ in output_path_opts:
|
for out_path, _ in output_path_opts:
|
||||||
if out_path:
|
if out_path:
|
||||||
|
Loading…
Reference in New Issue
Block a user