0
0
Fork 0
mirror of https://github.com/yt-dlp/yt-dlp.git synced 2024-11-26 02:55:17 +00:00

[extractor] Add _perform_login function (#2943)

* Adds new functions `_initialize_pre_login` and `_perform_login` as part of the extractor API
* Adds `ie.supports_login` to the public API
This commit is contained in:
pukkandan 2022-03-19 02:23:33 +05:30 committed by GitHub
parent 028f6437f1
commit 52efa4b312
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 253 additions and 569 deletions

View file

@ -12,11 +12,6 @@
from yt_dlp.extractor import IqiyiIE from yt_dlp.extractor import IqiyiIE
class IqiyiIEWithCredentials(IqiyiIE):
def _get_login_info(self):
return 'foo', 'bar'
class WarningLogger(object): class WarningLogger(object):
def __init__(self): def __init__(self):
self.messages = [] self.messages = []
@ -40,8 +35,8 @@ def test_iqiyi_sdk_interpreter(self):
If `sign` is incorrect, /validate call throws an HTTP 556 error If `sign` is incorrect, /validate call throws an HTTP 556 error
''' '''
logger = WarningLogger() logger = WarningLogger()
ie = IqiyiIEWithCredentials(FakeYDL({'logger': logger})) ie = IqiyiIE(FakeYDL({'logger': logger}))
ie._login() ie._perform_login('foo', 'bar')
self.assertTrue('unable to log in:' in logger.messages[0]) self.assertTrue('unable to log in:' in logger.messages[0])

View file

@ -7,18 +7,19 @@
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from yt_dlp.extractor import ( from yt_dlp.extractor import gen_extractor_classes
gen_extractors, from yt_dlp.extractor.common import InfoExtractor
)
NO_LOGIN = InfoExtractor._perform_login
class TestNetRc(unittest.TestCase): class TestNetRc(unittest.TestCase):
def test_netrc_present(self): def test_netrc_present(self):
for ie in gen_extractors(): for ie in gen_extractor_classes():
if not hasattr(ie, '_login'): if ie._perform_login is NO_LOGIN:
continue continue
self.assertTrue( self.assertTrue(
hasattr(ie, '_NETRC_MACHINE'), ie._NETRC_MACHINE,
'Extractor %s supports login, but is missing a _NETRC_MACHINE property' % ie.IE_NAME) 'Extractor %s supports login, but is missing a _NETRC_MACHINE property' % ie.IE_NAME)

View file

@ -291,15 +291,7 @@ def _get_media_token(self, invalidate=False, to_show=True):
return self._MEDIATOKEN return self._MEDIATOKEN
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
# No authentication to be performed
if not username:
return True
if '@' in username: # don't strictly check if it's email address or not if '@' in username: # don't strictly check if it's email address or not
ep, method = 'user/email', 'email' ep, method = 'user/email', 'email'
else: else:

View file

@ -126,10 +126,7 @@ def _get_subtitles(self, sub_url, video_id):
}]) }])
return subtitles return subtitles
def _real_initialize(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if not username:
return
try: try:
access_token = (self._download_json( access_token = (self._download_json(
self._API_BASE_URL + 'authentication/login', None, self._API_BASE_URL + 'authentication/login', None,

View file

@ -184,14 +184,7 @@ def parse_video_key(key):
video_key['part'] = int(m.group('part')) video_key['part'] = int(m.group('part'))
return video_key return video_key
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
login_form = { login_form = {
'szWork': 'login', 'szWork': 'login',
'szType': 'json', 'szType': 'json',

View file

@ -74,14 +74,7 @@ def _real_extract(self, url):
"formats": formats "formats": formats
} }
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
pass
login_page = self._download_webpage( login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login popup') self._LOGIN_URL, None, 'Downloading login popup')

View file

@ -15,25 +15,21 @@
class AnimeLabBaseIE(InfoExtractor): class AnimeLabBaseIE(InfoExtractor):
_LOGIN_REQUIRED = True
_LOGIN_URL = 'https://www.animelab.com/login' _LOGIN_URL = 'https://www.animelab.com/login'
_NETRC_MACHINE = 'animelab' _NETRC_MACHINE = 'animelab'
_LOGGED_IN = False
def _login(self): def _is_logged_in(self, login_page=None):
def is_logged_in(login_webpage): if not self._LOGGED_IN:
return 'Sign In' not in login_webpage if not login_page:
login_page = self._download_webpage(self._LOGIN_URL, None, 'Downloading login page')
AnimeLabBaseIE._LOGGED_IN = 'Sign In' not in login_page
return self._LOGGED_IN
login_page = self._download_webpage( def _perform_login(self, username, password):
self._LOGIN_URL, None, 'Downloading login page') if self._is_logged_in():
# Check if already logged in
if is_logged_in(login_page):
return return
(username, password) = self._get_login_info()
if username is None and self._LOGIN_REQUIRED:
self.raise_login_required('Login is required to access any AnimeLab content')
login_form = { login_form = {
'email': username, 'email': username,
'password': password, 'password': password,
@ -47,17 +43,14 @@ def is_logged_in(login_webpage):
except ExtractorError as e: except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 400: if isinstance(e.cause, compat_HTTPError) and e.cause.code == 400:
raise ExtractorError('Unable to log in (wrong credentials?)', expected=True) raise ExtractorError('Unable to log in (wrong credentials?)', expected=True)
else: raise
raise
# if login was successful if not self._is_logged_in(response):
if is_logged_in(response): raise ExtractorError('Unable to login (cannot verify if logged in)')
return
raise ExtractorError('Unable to login (cannot verify if logged in)')
def _real_initialize(self): def _real_initialize(self):
self._login() if not self._is_logged_in():
self.raise_login_required('Login is required to access any AnimeLab content')
class AnimeLabIE(AnimeLabBaseIE): class AnimeLabIE(AnimeLabBaseIE):

View file

@ -53,11 +53,7 @@ class AnimeOnDemandIE(InfoExtractor):
'only_matching': True, 'only_matching': True,
}] }]
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
login_page = self._download_webpage( login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page') self._LOGIN_URL, None, 'Downloading login page')
@ -93,9 +89,6 @@ def _login(self):
raise ExtractorError('Unable to login: %s' % error, expected=True) raise ExtractorError('Unable to login: %s' % error, expected=True)
raise ExtractorError('Unable to log in') raise ExtractorError('Unable to log in')
def _real_initialize(self):
self._login()
def _real_extract(self, url): def _real_extract(self, url):
anime_id = self._match_id(url) anime_id = self._match_id(url)

View file

@ -37,9 +37,6 @@ class AtresPlayerIE(InfoExtractor):
] ]
_API_BASE = 'https://api.atresplayer.com/' _API_BASE = 'https://api.atresplayer.com/'
def _real_initialize(self):
self._login()
def _handle_error(self, e, code): def _handle_error(self, e, code):
if isinstance(e.cause, compat_HTTPError) and e.cause.code == code: if isinstance(e.cause, compat_HTTPError) and e.cause.code == code:
error = self._parse_json(e.cause.read(), None) error = self._parse_json(e.cause.read(), None)
@ -48,11 +45,7 @@ def _handle_error(self, e, code):
raise ExtractorError(error['error_description'], expected=True) raise ExtractorError(error['error_description'], expected=True)
raise raise
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
self._request_webpage( self._request_webpage(
self._API_BASE + 'login', None, 'Downloading login page') self._API_BASE + 'login', None, 'Downloading login page')

View file

@ -264,11 +264,7 @@ class BBCCoUkIE(InfoExtractor):
'only_matching': True, 'only_matching': True,
}] }]
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
login_page = self._download_webpage( login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading signin page') self._LOGIN_URL, None, 'Downloading signin page')
@ -294,9 +290,6 @@ def _login(self):
'Unable to login: %s' % error, expected=True) 'Unable to login: %s' % error, expected=True)
raise ExtractorError('Unable to log in') raise ExtractorError('Unable to log in')
def _real_initialize(self):
self._login()
class MediaSelectionError(Exception): class MediaSelectionError(Exception):
def __init__(self, id): def __init__(self, id):
self.id = id self.id = id

View file

@ -821,11 +821,7 @@ def _extract_ep_info(self, episode_data, ep_id):
'extractor_key': BiliIntlIE.ie_key(), 'extractor_key': BiliIntlIE.ie_key(),
} }
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
try: try:
from Cryptodome.PublicKey import RSA from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_v1_5 from Cryptodome.Cipher import PKCS1_v1_5
@ -856,9 +852,6 @@ def _login(self):
else: else:
raise ExtractorError('Unable to log in') raise ExtractorError('Unable to log in')
def _real_initialize(self):
self._login()
class BiliIntlIE(BiliIntlBaseIE): class BiliIntlIE(BiliIntlBaseIE):
_VALID_URL = r'https?://(?:www\.)?bili(?:bili\.tv|intl\.com)/(?:[a-z]{2}/)?play/(?P<season_id>\d+)/(?P<id>\d+)' _VALID_URL = r'https?://(?:www\.)?bili(?:bili\.tv|intl\.com)/(?:[a-z]{2}/)?play/(?P<season_id>\d+)/(?P<id>\d+)'

View file

@ -274,14 +274,7 @@ class VrtNUIE(GigyaBaseIE):
_APIKEY = '3_0Z2HujMtiWq_pkAjgnS2Md2E11a1AwZjYiBETtwNE-EoEHDINgtnvcAOpNgmrVGy' _APIKEY = '3_0Z2HujMtiWq_pkAjgnS2Md2E11a1AwZjYiBETtwNE-EoEHDINgtnvcAOpNgmrVGy'
_CONTEXT_ID = 'R3595707040' _CONTEXT_ID = 'R3595707040'
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
auth_info = self._gigya_login({ auth_info = self._gigya_login({
'APIKey': self._APIKEY, 'APIKey': self._APIKEY,
'targetEnv': 'jssdk', 'targetEnv': 'jssdk',

View file

@ -432,7 +432,15 @@ class InfoExtractor(object):
Subclasses may also override suitable() if necessary, but ensure the function Subclasses may also override suitable() if necessary, but ensure the function
signature is preserved and that this function imports everything it needs signature is preserved and that this function imports everything it needs
(except other extractors), so that lazy_extractors works correctly (except other extractors), so that lazy_extractors works correctly.
To support username + password (or netrc) login, the extractor must define a
_NETRC_MACHINE and re-define _perform_login(username, password) and
(optionally) _initialize_pre_login() methods. The _perform_login method will
be called between _initialize_pre_login and _real_initialize if credentials
are passed by the user. In cases where it is necessary to have the login
process as part of the extraction rather than initialization, _perform_login
can be left undefined.
_GEO_BYPASS attribute may be set to False in order to disable _GEO_BYPASS attribute may be set to False in order to disable
geo restriction bypass mechanisms for a particular extractor. geo restriction bypass mechanisms for a particular extractor.
@ -460,9 +468,10 @@ class InfoExtractor(object):
_GEO_COUNTRIES = None _GEO_COUNTRIES = None
_GEO_IP_BLOCKS = None _GEO_IP_BLOCKS = None
_WORKING = True _WORKING = True
_NETRC_MACHINE = None
_LOGIN_HINTS = { _LOGIN_HINTS = {
'any': 'Use --cookies, --username and --password, or --netrc to provide account credentials', 'any': 'Use --cookies, --cookies-from-browser, --username and --password, or --netrc to provide account credentials',
'cookies': ( 'cookies': (
'Use --cookies-from-browser or --cookies for the authentication. ' 'Use --cookies-from-browser or --cookies for the authentication. '
'See https://github.com/ytdl-org/youtube-dl#how-do-i-pass-cookies-to-youtube-dl for how to manually pass cookies'), 'See https://github.com/ytdl-org/youtube-dl#how-do-i-pass-cookies-to-youtube-dl for how to manually pass cookies'),
@ -512,6 +521,10 @@ def working(cls):
"""Getter method for _WORKING.""" """Getter method for _WORKING."""
return cls._WORKING return cls._WORKING
@classmethod
def supports_login(cls):
return bool(cls._NETRC_MACHINE)
def initialize(self): def initialize(self):
"""Initializes an instance (authentication, etc).""" """Initializes an instance (authentication, etc)."""
self._printed_messages = set() self._printed_messages = set()
@ -520,6 +533,13 @@ def initialize(self):
'ip_blocks': self._GEO_IP_BLOCKS, 'ip_blocks': self._GEO_IP_BLOCKS,
}) })
if not self._ready: if not self._ready:
self._initialize_pre_login()
if self.supports_login():
username, password = self._get_login_info()
if username:
self._perform_login(username, password)
elif self.get_param('username') and False not in (self.IE_DESC, self._NETRC_MACHINE):
self.report_warning(f'Login with password is not supported for this website. {self._LOGIN_HINTS["cookies"]}')
self._real_initialize() self._real_initialize()
self._ready = True self._ready = True
@ -665,6 +685,14 @@ def set_downloader(self, downloader):
"""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
def _initialize_pre_login(self):
""" Intialization before login. Redefine in subclasses."""
pass
def _perform_login(self, username, password):
""" Login with username and password. Redefine in subclasses."""
pass
def _real_initialize(self): def _real_initialize(self):
"""Real initialization process. Redefine in subclasses.""" """Real initialization process. Redefine in subclasses."""
pass pass
@ -1098,12 +1126,15 @@ def report_login(self):
def raise_login_required( def raise_login_required(
self, msg='This video is only available for registered users', self, msg='This video is only available for registered users',
metadata_available=False, method='any'): metadata_available=False, method=NO_DEFAULT):
if metadata_available and ( if metadata_available and (
self.get_param('ignore_no_formats_error') or self.get_param('wait_for_video')): self.get_param('ignore_no_formats_error') or self.get_param('wait_for_video')):
self.report_warning(msg) self.report_warning(msg)
return return
if method is NO_DEFAULT:
method = 'any' if self.supports_login() else 'cookies'
if method is not None: if method is not None:
assert method in self._LOGIN_HINTS, 'Invalid login method'
msg = '%s. %s' % (msg, self._LOGIN_HINTS[method]) msg = '%s. %s' % (msg, self._LOGIN_HINTS[method])
raise ExtractorError(msg, expected=True) raise ExtractorError(msg, expected=True)
@ -3680,9 +3711,8 @@ def _get_automatic_captions(self, *args, **kwargs):
def mark_watched(self, *args, **kwargs): def mark_watched(self, *args, **kwargs):
if not self.get_param('mark_watched', False): if not self.get_param('mark_watched', False):
return return
if (hasattr(self, '_NETRC_MACHINE') and self._get_login_info()[0] is not None if (self.supports_login() and self._get_login_info()[0] is not None
or self.get_param('cookiefile') or self.get_param('cookiefile') or self.get_param('cookiesfrombrowser')):
or self.get_param('cookiesfrombrowser')):
self._mark_watched(*args, **kwargs) self._mark_watched(*args, **kwargs)
def _mark_watched(self, *args, **kwargs): def _mark_watched(self, *args, **kwargs):

View file

@ -57,10 +57,7 @@ def _call_rpc_api(self, method, video_id, note=None, data=None):
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
}) })
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
if self._get_cookies(self._LOGIN_URL).get('etp_rt'): if self._get_cookies(self._LOGIN_URL).get('etp_rt'):
return return
@ -89,9 +86,6 @@ def _login(self):
if not self._get_cookies(self._LOGIN_URL).get('etp_rt'): if not self._get_cookies(self._LOGIN_URL).get('etp_rt'):
raise ExtractorError('Login succeeded but did not set etp_rt cookie') raise ExtractorError('Login succeeded but did not set etp_rt cookie')
def _real_initialize(self):
self._login()
@staticmethod @staticmethod
def _add_skip_wall(url): def _add_skip_wall(url):
parsed_url = compat_urlparse.urlparse(url) parsed_url = compat_urlparse.urlparse(url)

View file

@ -33,14 +33,11 @@ def _call_api(self, path, video_id, query=None):
self._handle_errors(result) self._handle_errors(result)
return result['data'] return result['data']
def _real_initialize(self): def _perform_login(self, username, password):
email, password = self._get_login_info()
if email is None:
return
result = self._download_json( result = self._download_json(
'https://api.curiositystream.com/v1/login', None, 'https://api.curiositystream.com/v1/login', None,
note='Logging in', data=urlencode_postdata({ note='Logging in', data=urlencode_postdata({
'email': email, 'email': username,
'password': password, 'password': password,
})) }))
self._handle_errors(result) self._handle_errors(result)

View file

@ -45,10 +45,7 @@ class DigitalConcertHallIE(InfoExtractor):
'playlist_count': 3, 'playlist_count': 3,
}] }]
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if not username:
self.raise_login_required()
token_response = self._download_json( token_response = self._download_json(
self._OAUTH_URL, self._OAUTH_URL,
None, 'Obtaining token', errnote='Unable to obtain token', data=urlencode_postdata({ None, 'Obtaining token', errnote='Unable to obtain token', data=urlencode_postdata({
@ -78,7 +75,8 @@ def _login(self):
self.raise_login_required(msg='Login info incorrect') self.raise_login_required(msg='Login info incorrect')
def _real_initialize(self): def _real_initialize(self):
self._login() if not self._ACCESS_TOKEN:
self.raise_login_required(method='password')
def _entries(self, items, language, **kwargs): def _entries(self, items, language, **kwargs):
for item in items: for item in items:

View file

@ -39,11 +39,7 @@ class EroProfileIE(InfoExtractor):
'skip': 'Requires login', 'skip': 'Requires login',
}] }]
def _login(self): def _perform_login(self, username, password):
(username, password) = self._get_login_info()
if username is None:
return
query = compat_urllib_parse_urlencode({ query = compat_urllib_parse_urlencode({
'username': username, 'username': username,
'password': password, 'password': password,
@ -62,9 +58,6 @@ def _login(self):
r'<script[^>]+?src="([^"]+)"', login_page, 'login redirect url') r'<script[^>]+?src="([^"]+)"', login_page, 'login redirect url')
self._download_webpage(redirect_url, None, False) self._download_webpage(redirect_url, None, False)
def _real_initialize(self):
self._login()
def _real_extract(self, url): def _real_extract(self, url):
display_id = self._match_id(url) display_id = self._match_id(url)

View file

@ -329,11 +329,7 @@ def _extract_urls(webpage):
urls.append(mobj.group('url')) urls.append(mobj.group('url'))
return urls return urls
def _login(self): def _perform_login(self, username, password):
useremail, password = self._get_login_info()
if useremail is None:
return
login_page_req = sanitized_Request(self._LOGIN_URL) login_page_req = sanitized_Request(self._LOGIN_URL)
self._set_cookie('facebook.com', 'locale', 'en_US') self._set_cookie('facebook.com', 'locale', 'en_US')
login_page = self._download_webpage(login_page_req, None, login_page = self._download_webpage(login_page_req, None,
@ -345,7 +341,7 @@ def _login(self):
lgnrnd = self._search_regex(r'name="lgnrnd" value="([^"]*?)"', login_page, 'lgnrnd') lgnrnd = self._search_regex(r'name="lgnrnd" value="([^"]*?)"', login_page, 'lgnrnd')
login_form = { login_form = {
'email': useremail, 'email': username,
'pass': password, 'pass': password,
'lsd': lsd, 'lsd': lsd,
'lgnrnd': lgnrnd, 'lgnrnd': lgnrnd,
@ -392,9 +388,6 @@ def _login(self):
self.report_warning('unable to log in: %s' % error_to_compat_str(err)) self.report_warning('unable to log in: %s' % error_to_compat_str(err))
return return
def _real_initialize(self):
self._login()
def _extract_from_url(self, url, video_id): def _extract_from_url(self, url, video_id):
webpage = self._download_webpage( webpage = self._download_webpage(
url.replace('://m.facebook.com/', '://www.facebook.com/'), video_id) url.replace('://m.facebook.com/', '://www.facebook.com/'), video_id)

View file

@ -49,30 +49,26 @@ class FancodeVodIE(InfoExtractor):
'referer': 'https://fancode.com', 'referer': 'https://fancode.com',
} }
def _login(self): def _perform_login(self, username, password):
# Access tokens are shortlived, so get them using the refresh token. # Access tokens are shortlived, so get them using the refresh token.
username, password = self._get_login_info() if username != 'refresh':
if username == 'refresh' and password is not None:
self.report_login()
data = '''{
"query":"mutation RefreshToken($refreshToken: String\\u0021) { refreshToken(refreshToken: $refreshToken) { accessToken }}",
"variables":{
"refreshToken":"%s"
},
"operationName":"RefreshToken"
}''' % password
token_json = self.download_gql('refresh token', data, "Getting the Access token")
self._ACCESS_TOKEN = try_get(token_json, lambda x: x['data']['refreshToken']['accessToken'])
if self._ACCESS_TOKEN is None:
self.report_warning('Failed to get Access token')
else:
self.headers.update({'Authorization': 'Bearer %s' % self._ACCESS_TOKEN})
elif username is not None:
self.report_warning(f'Login using username and password is not currently supported. {self._LOGIN_HINT}') self.report_warning(f'Login using username and password is not currently supported. {self._LOGIN_HINT}')
def _real_initialize(self): self.report_login()
self._login() data = '''{
"query":"mutation RefreshToken($refreshToken: String\\u0021) { refreshToken(refreshToken: $refreshToken) { accessToken }}",
"variables":{
"refreshToken":"%s"
},
"operationName":"RefreshToken"
}''' % password
token_json = self.download_gql('refresh token', data, "Getting the Access token")
self._ACCESS_TOKEN = try_get(token_json, lambda x: x['data']['refreshToken']['accessToken'])
if self._ACCESS_TOKEN is None:
self.report_warning('Failed to get Access token')
else:
self.headers.update({'Authorization': 'Bearer %s' % self._ACCESS_TOKEN})
def _check_login_required(self, is_available, is_premium): def _check_login_required(self, is_available, is_premium):
msg = None msg = None

View file

@ -28,14 +28,7 @@ class FrontendMastersBaseIE(InfoExtractor):
'high': {'width': 1920, 'height': 1080} 'high': {'width': 1920, 'height': 1080}
} }
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
(username, password) = self._get_login_info()
if username is None:
return
login_page = self._download_webpage( login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page') self._LOGIN_URL, None, 'Downloading login page')

View file

@ -36,9 +36,8 @@ def _get_region(self):
note='Checking geo-location', errnote='Unable to fetch geo-location information'), note='Checking geo-location', errnote='Unable to fetch geo-location information'),
'region') or 'US' 'region') or 'US'
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info() if self._TOKEN:
if username is None:
return return
try: try:
data = self._download_json( data = self._download_json(
@ -47,7 +46,7 @@ def _login(self):
'username': username, 'username': username,
'password': password, 'password': password,
})) }))
return data['token'] FunimationBaseIE._TOKEN = data['token']
except ExtractorError as e: except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 401: if isinstance(e.cause, compat_HTTPError) and e.cause.code == 401:
error = self._parse_json(e.cause.read().decode(), None)['error'] error = self._parse_json(e.cause.read().decode(), None)['error']
@ -90,8 +89,6 @@ class FunimationPageIE(FunimationBaseIE):
def _real_initialize(self): def _real_initialize(self):
if not self._REGION: if not self._REGION:
FunimationBaseIE._REGION = self._get_region() FunimationBaseIE._REGION = self._get_region()
if not self._TOKEN:
FunimationBaseIE._TOKEN = self._login()
def _real_extract(self, url): def _real_extract(self, url):
locale, show, episode = self._match_valid_url(url).group('lang', 'show', 'episode') locale, show, episode = self._match_valid_url(url).group('lang', 'show', 'episode')
@ -154,10 +151,6 @@ class FunimationIE(FunimationBaseIE):
}, },
}] }]
def _real_initialize(self):
if not self._TOKEN:
FunimationBaseIE._TOKEN = self._login()
@staticmethod @staticmethod
def _get_experiences(episode): def _get_experiences(episode):
for lang, lang_data in episode.get('languages', {}).items(): for lang, lang_data in episode.get('languages', {}).items():

View file

@ -56,24 +56,22 @@ class GaiaIE(InfoExtractor):
def _real_initialize(self): def _real_initialize(self):
auth = self._get_cookies('https://www.gaia.com/').get('auth') auth = self._get_cookies('https://www.gaia.com/').get('auth')
if auth: if auth:
auth = self._parse_json( auth = self._parse_json(compat_urllib_parse_unquote(auth.value), None, fatal=False)
compat_urllib_parse_unquote(auth.value),
None, fatal=False)
if not auth:
username, password = self._get_login_info()
if username is None:
return
auth = self._download_json(
'https://auth.gaia.com/v1/login',
None, data=urlencode_postdata({
'username': username,
'password': password
}))
if auth.get('success') is False:
raise ExtractorError(', '.join(auth['messages']), expected=True)
if auth:
self._jwt = auth.get('jwt') self._jwt = auth.get('jwt')
def _perform_login(self, username, password):
if self._jwt:
return
auth = self._download_json(
'https://auth.gaia.com/v1/login',
None, data=urlencode_postdata({
'username': username,
'password': password
}))
if auth.get('success') is False:
raise ExtractorError(', '.join(auth['messages']), expected=True)
self._jwt = auth.get('jwt')
def _real_extract(self, url): def _real_extract(self, url):
display_id, vtype = self._match_valid_url(url).groups() display_id, vtype = self._match_valid_url(url).groups()
node_id = self._download_json( node_id = self._download_json(

View file

@ -153,6 +153,7 @@ class GenericIE(InfoExtractor):
IE_DESC = 'Generic downloader that works on some sites' IE_DESC = 'Generic downloader that works on some sites'
_VALID_URL = r'.*' _VALID_URL = r'.*'
IE_NAME = 'generic' IE_NAME = 'generic'
_NETRC_MACHINE = False # Supress username warning
_TESTS = [ _TESTS = [
# Direct link to a video # Direct link to a video
{ {

View file

@ -35,18 +35,14 @@ class HiDiveIE(InfoExtractor):
'skip': 'Requires Authentication', 'skip': 'Requires Authentication',
}] }]
def _real_initialize(self): def _perform_login(self, username, password):
email, password = self._get_login_info()
if email is None:
return
webpage = self._download_webpage(self._LOGIN_URL, None) webpage = self._download_webpage(self._LOGIN_URL, None)
form = self._search_regex( form = self._search_regex(
r'(?s)<form[^>]+action="/account/login"[^>]*>(.+?)</form>', r'(?s)<form[^>]+action="/account/login"[^>]*>(.+?)</form>',
webpage, 'login form') webpage, 'login form')
data = self._hidden_inputs(form) data = self._hidden_inputs(form)
data.update({ data.update({
'Email': email, 'Email': username,
'Password': password, 'Password': password,
}) })
self._download_webpage( self._download_webpage(

View file

@ -27,8 +27,9 @@ class HRTiBaseIE(InfoExtractor):
_APP_VERSION = '1.1' _APP_VERSION = '1.1'
_APP_PUBLICATION_ID = 'all_in_one' _APP_PUBLICATION_ID = 'all_in_one'
_API_URL = 'http://clientapi.hrt.hr/client_api.php/config/identify/format/json' _API_URL = 'http://clientapi.hrt.hr/client_api.php/config/identify/format/json'
_token = None
def _initialize_api(self): def _initialize_pre_login(self):
init_data = { init_data = {
'application_publication_id': self._APP_PUBLICATION_ID 'application_publication_id': self._APP_PUBLICATION_ID
} }
@ -64,12 +65,7 @@ def _initialize_api(self):
self._logout_url = modules['user']['resources']['logout']['uri'] self._logout_url = modules['user']['resources']['logout']['uri']
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
# TODO: figure out authentication with cookies
if username is None or password is None:
self.raise_login_required()
auth_data = { auth_data = {
'username': username, 'username': username,
'password': password, 'password': password,
@ -94,8 +90,9 @@ def _login(self):
self._token = auth_info['secure_streaming_token'] self._token = auth_info['secure_streaming_token']
def _real_initialize(self): def _real_initialize(self):
self._initialize_api() if not self._token:
self._login() # TODO: figure out authentication with cookies
self.raise_login_required(method='password')
class HRTiIE(HRTiBaseIE): class HRTiIE(HRTiBaseIE):

View file

@ -21,25 +21,26 @@ class ImgGamingBaseIE(InfoExtractor):
_REALM = None _REALM = None
_VALID_URL_TEMPL = r'https?://(?P<domain>%s)/(?P<type>live|playlist|video)/(?P<id>\d+)(?:\?.*?\bplaylistId=(?P<playlist_id>\d+))?' _VALID_URL_TEMPL = r'https?://(?P<domain>%s)/(?P<type>live|playlist|video)/(?P<id>\d+)(?:\?.*?\bplaylistId=(?P<playlist_id>\d+))?'
def _real_initialize(self): def _initialize_pre_login(self):
self._HEADERS = { self._HEADERS = {
'Realm': 'dce.' + self._REALM, 'Realm': 'dce.' + self._REALM,
'x-api-key': self._API_KEY, 'x-api-key': self._API_KEY,
} }
email, password = self._get_login_info() def _perform_login(self, username, password):
if email is None:
self.raise_login_required()
p_headers = self._HEADERS.copy() p_headers = self._HEADERS.copy()
p_headers['Content-Type'] = 'application/json' p_headers['Content-Type'] = 'application/json'
self._HEADERS['Authorization'] = 'Bearer ' + self._download_json( self._HEADERS['Authorization'] = 'Bearer ' + self._download_json(
self._API_BASE + 'login', self._API_BASE + 'login',
None, 'Logging in', data=json.dumps({ None, 'Logging in', data=json.dumps({
'id': email, 'id': username,
'secret': password, 'secret': password,
}).encode(), headers=p_headers)['authorisationToken'] }).encode(), headers=p_headers)['authorisationToken']
def _real_initialize(self):
if not self._HEADERS.get('Authorization'):
self.raise_login_required(method='password')
def _call_api(self, path, media_id): def _call_api(self, path, media_id):
return self._download_json( return self._download_json(
self._API_BASE + path + media_id, media_id, headers=self._HEADERS) self._API_BASE + path + media_id, media_id, headers=self._HEADERS)

View file

@ -29,9 +29,8 @@ class InstagramBaseIE(InfoExtractor):
_NETRC_MACHINE = 'instagram' _NETRC_MACHINE = 'instagram'
_IS_LOGGED_IN = False _IS_LOGGED_IN = False
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info() if self._IS_LOGGED_IN:
if username is None or self._IS_LOGGED_IN:
return return
login_webpage = self._download_webpage( login_webpage = self._download_webpage(
@ -72,9 +71,6 @@ def _login(self):
raise ExtractorError('Unable to login') raise ExtractorError('Unable to login')
InstagramBaseIE._IS_LOGGED_IN = True InstagramBaseIE._IS_LOGGED_IN = True
def _real_initialize(self):
self._login()
def _get_count(self, media, kind, *keys): def _get_count(self, media, kind, *keys):
return traverse_obj( return traverse_obj(
media, (kind, 'count'), *((f'edge_media_{key}', 'count') for key in keys), media, (kind, 'count'), *((f'edge_media_{key}', 'count') for key in keys),

View file

@ -65,11 +65,9 @@ class IPrimaIE(InfoExtractor):
'only_matching': True, 'only_matching': True,
}] }]
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info() if self.access_token:
return
if username is None or password is None:
self.raise_login_required('Login is required to access any iPrima content', method='password')
login_page = self._download_webpage( login_page = self._download_webpage(
self._LOGIN_URL, None, note='Downloading login page', self._LOGIN_URL, None, note='Downloading login page',
@ -105,16 +103,16 @@ def _login(self):
if self.access_token is None: if self.access_token is None:
raise ExtractorError('Getting token failed', expected=True) raise ExtractorError('Getting token failed', expected=True)
def _real_initialize(self):
if not self.access_token:
self.raise_login_required('Login is required to access any iPrima content', method='password')
def _raise_access_error(self, error_code): def _raise_access_error(self, error_code):
if error_code == 'PLAY_GEOIP_DENIED': if error_code == 'PLAY_GEOIP_DENIED':
self.raise_geo_restricted(countries=['CZ'], metadata_available=True) self.raise_geo_restricted(countries=['CZ'], metadata_available=True)
elif error_code is not None: elif error_code is not None:
self.raise_no_formats('Access to stream infos forbidden', expected=True) self.raise_no_formats('Access to stream infos forbidden', expected=True)
def _real_initialize(self):
if not self.access_token:
self._login()
def _real_extract(self, url): def _real_extract(self, url):
video_id = self._match_id(url) video_id = self._match_id(url)

View file

@ -241,9 +241,6 @@ class IqiyiIE(InfoExtractor):
'18': 7, # 1080p '18': 7, # 1080p
} }
def _real_initialize(self):
self._login()
@staticmethod @staticmethod
def _rsa_fun(data): def _rsa_fun(data):
# public key extracted from http://static.iqiyi.com/js/qiyiV2/20160129180840/jobs/i18n/i18nIndex.js # public key extracted from http://static.iqiyi.com/js/qiyiV2/20160129180840/jobs/i18n/i18nIndex.js
@ -252,12 +249,7 @@ def _rsa_fun(data):
return ohdave_rsa_encrypt(data, e, N) return ohdave_rsa_encrypt(data, e, N)
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
# No authentication to be performed
if not username:
return True
data = self._download_json( data = self._download_json(
'http://kylin.iqiyi.com/get_token', None, 'http://kylin.iqiyi.com/get_token', None,

View file

@ -22,14 +22,7 @@ class LecturioBaseIE(InfoExtractor):
_LOGIN_URL = 'https://app.lecturio.com/en/login' _LOGIN_URL = 'https://app.lecturio.com/en/login'
_NETRC_MACHINE = 'lecturio' _NETRC_MACHINE = 'lecturio'
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
# Sets some cookies # Sets some cookies
_, urlh = self._download_webpage_handle( _, urlh = self._download_webpage_handle(
self._LOGIN_URL, None, 'Downloading login popup') self._LOGIN_URL, None, 'Downloading login popup')

View file

@ -25,12 +25,9 @@ class LinkedInBaseIE(InfoExtractor):
_NETRC_MACHINE = 'linkedin' _NETRC_MACHINE = 'linkedin'
_logged_in = False _logged_in = False
def _real_initialize(self): def _perform_login(self, username, password):
if self._logged_in: if self._logged_in:
return return
email, password = self._get_login_info()
if email is None:
return
login_page = self._download_webpage( login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page') self._LOGIN_URL, None, 'Downloading login page')
@ -39,7 +36,7 @@ def _real_initialize(self):
default='https://www.linkedin.com/uas/login-submit', group='url')) default='https://www.linkedin.com/uas/login-submit', group='url'))
data = self._hidden_inputs(login_page) data = self._hidden_inputs(login_page)
data.update({ data.update({
'session_key': email, 'session_key': username,
'session_password': password, 'session_password': password,
}) })
login_submit_page = self._download_webpage( login_submit_page = self._download_webpage(

View file

@ -75,14 +75,7 @@ class LinuxAcademyIE(InfoExtractor):
_CLIENT_ID = 'KaWxNn1C2Gc7n83W9OFeXltd8Utb5vvx' _CLIENT_ID = 'KaWxNn1C2Gc7n83W9OFeXltd8Utb5vvx'
_NETRC_MACHINE = 'linuxacademy' _NETRC_MACHINE = 'linuxacademy'
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def random_string(): def random_string():
return ''.join([ return ''.join([
random.choice('0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._~') random.choice('0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._~')

View file

@ -21,9 +21,6 @@ class LyndaBaseIE(InfoExtractor):
_ACCOUNT_CREDENTIALS_HINT = 'Use --username and --password options to provide lynda.com account credentials.' _ACCOUNT_CREDENTIALS_HINT = 'Use --username and --password options to provide lynda.com account credentials.'
_NETRC_MACHINE = 'lynda' _NETRC_MACHINE = 'lynda'
def _real_initialize(self):
self._login()
@staticmethod @staticmethod
def _check_error(json_string, key_or_keys): def _check_error(json_string, key_or_keys):
keys = [key_or_keys] if isinstance(key_or_keys, compat_str) else key_or_keys keys = [key_or_keys] if isinstance(key_or_keys, compat_str) else key_or_keys
@ -32,7 +29,7 @@ def _check_error(json_string, key_or_keys):
if error: if error:
raise ExtractorError('Unable to login: %s' % error, expected=True) raise ExtractorError('Unable to login: %s' % error, expected=True)
def _login_step(self, form_html, fallback_action_url, extra_form_data, note, referrer_url): def _perform_login_step(self, form_html, fallback_action_url, extra_form_data, note, referrer_url):
action_url = self._search_regex( action_url = self._search_regex(
r'<form[^>]+action=(["\'])(?P<url>.+?)\1', form_html, r'<form[^>]+action=(["\'])(?P<url>.+?)\1', form_html,
'post url', default=fallback_action_url, group='url') 'post url', default=fallback_action_url, group='url')
@ -55,11 +52,7 @@ def _login_step(self, form_html, fallback_action_url, extra_form_data, note, ref
return response, action_url return response, action_url
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
# Step 1: download signin page # Step 1: download signin page
signin_page = self._download_webpage( signin_page = self._download_webpage(
self._SIGNIN_URL, None, 'Downloading signin page') self._SIGNIN_URL, None, 'Downloading signin page')

View file

@ -148,14 +148,12 @@ def _build_video_info(self, episode):
'creator': episode['channel_title'], 'creator': episode['channel_title'],
} }
def _login(self): def _perform_login(self, username=None, password=None):
# FIXME: username should be passed from here to inner functions
self._nebula_api_token = self._retrieve_nebula_api_token() self._nebula_api_token = self._retrieve_nebula_api_token()
self._nebula_bearer_token = self._fetch_nebula_bearer_token() self._nebula_bearer_token = self._fetch_nebula_bearer_token()
self._zype_access_token = self._fetch_zype_access_token() self._zype_access_token = self._fetch_zype_access_token()
def _real_initialize(self):
self._login()
class NebulaIE(NebulaBaseIE): class NebulaIE(NebulaBaseIE):
_VALID_URL = r'https?://(?:www\.)?(?:watchnebula\.com|nebula\.app)/videos/(?P<id>[-\w]+)' _VALID_URL = r'https?://(?:www\.)?(?:watchnebula\.com|nebula\.app)/videos/(?P<id>[-\w]+)'

View file

@ -183,16 +183,7 @@ class NiconicoIE(InfoExtractor):
'Origin': 'https://www.nicovideo.jp', 'Origin': 'https://www.nicovideo.jp',
} }
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
# No authentication to be performed
if not username:
return True
# Log in
login_ok = True login_ok = True
login_form_strs = { login_form_strs = {
'mail_tel': username, 'mail_tel': username,

View file

@ -43,15 +43,7 @@ class NJPWWorldIE(InfoExtractor):
_LOGIN_URL = 'https://front.njpwworld.com/auth/login' _LOGIN_URL = 'https://front.njpwworld.com/auth/login'
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
# No authentication to be performed
if not username:
return True
# Setup session (will set necessary cookies) # Setup session (will set necessary cookies)
self._request_webpage( self._request_webpage(
'https://njpwworld.com/', None, note='Setting up session') 'https://njpwworld.com/', None, note='Setting up session')

View file

@ -61,14 +61,7 @@ class NocoIE(InfoExtractor):
} }
] ]
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
login = self._download_json( login = self._download_json(
self._LOGIN_URL, None, 'Logging in', self._LOGIN_URL, None, 'Logging in',
data=urlencode_postdata({ data=urlencode_postdata({

View file

@ -47,10 +47,7 @@ class PacktPubIE(PacktPubBaseIE):
_NETRC_MACHINE = 'packtpub' _NETRC_MACHINE = 'packtpub'
_TOKEN = None _TOKEN = None
def _real_initialize(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
try: try:
self._TOKEN = self._download_json( self._TOKEN = self._download_json(
'https://services.packtpub.com/auth-v1/users/tokens', None, 'https://services.packtpub.com/auth-v1/users/tokens', None,

View file

@ -88,11 +88,7 @@ class PatreonIE(InfoExtractor):
# Currently Patreon exposes download URL via hidden CSS, so login is not # Currently Patreon exposes download URL via hidden CSS, so login is not
# needed. Keeping this commented for when this inevitably changes. # needed. Keeping this commented for when this inevitably changes.
''' '''
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
login_form = { login_form = {
'redirectUrl': 'http://www.patreon.com/', 'redirectUrl': 'http://www.patreon.com/',
'email': username, 'email': username,
@ -108,8 +104,6 @@ def _login(self):
if re.search(r'onLoginFailed', login_page): if re.search(r'onLoginFailed', login_page):
raise ExtractorError('Unable to login, incorrect username and/or password', expected=True) raise ExtractorError('Unable to login, incorrect username and/or password', expected=True)
def _real_initialize(self):
self._login()
''' '''
def _real_extract(self, url): def _real_extract(self, url):

View file

@ -29,13 +29,9 @@ class PiaproIE(InfoExtractor):
} }
}] }]
def _real_initialize(self): _login_status = False
self._login_status = self._login()
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if not username:
return False
login_ok = True login_ok = True
login_form_strs = { login_form_strs = {
'_username': username, '_username': username,
@ -57,7 +53,7 @@ def _login(self):
if not login_ok: if not login_ok:
self.report_warning( self.report_warning(
'unable to log in: bad username or password') 'unable to log in: bad username or password')
return login_ok self._login_status = login_ok
def _real_extract(self, url): def _real_extract(self, url):
video_id = self._match_id(url) video_id = self._match_id(url)

View file

@ -22,14 +22,7 @@ class PlatziBaseIE(InfoExtractor):
_LOGIN_URL = 'https://platzi.com/login/' _LOGIN_URL = 'https://platzi.com/login/'
_NETRC_MACHINE = 'platzi' _NETRC_MACHINE = 'platzi'
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
login_page = self._download_webpage( login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page') self._LOGIN_URL, None, 'Downloading login page')

View file

@ -38,14 +38,10 @@ def _call_api(self, resource, video_id=None, query=None):
'Authorization': 'Bearer ' + self._token, 'Authorization': 'Bearer ' + self._token,
}, query=query) }, query=query)
def _real_initialize(self): def _perform_login(self, username, password):
email, password = self._get_login_info()
if email is None:
self.raise_login_required()
req = PUTRequest( req = PUTRequest(
'https://api.playplus.tv/api/web/login', json.dumps({ 'https://api.playplus.tv/api/web/login', json.dumps({
'email': email, 'email': username,
'password': password, 'password': password,
}).encode(), { }).encode(), {
'Content-Type': 'application/json; charset=utf-8', 'Content-Type': 'application/json; charset=utf-8',
@ -61,6 +57,10 @@ def _real_initialize(self):
self._profile = self._call_api('Profiles')['list'][0]['_id'] self._profile = self._call_api('Profiles')['list'][0]['_id']
def _real_initialize(self):
if not self._token:
self.raise_login_required(method='password')
def _real_extract(self, url): def _real_extract(self, url):
project_id, media_id = self._match_valid_url(url).groups() project_id, media_id = self._match_valid_url(url).groups()
media = self._call_api( media = self._call_api(

View file

@ -162,14 +162,7 @@ class PluralsightIE(PluralsightBaseIE):
} }
}''' }'''
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
login_page = self._download_webpage( login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page') self._LOGIN_URL, None, 'Downloading login page')

View file

@ -15,11 +15,9 @@ class PokerGoBaseIE(InfoExtractor):
_AUTH_TOKEN = None _AUTH_TOKEN = None
_PROPERTY_ID = '1dfb3940-7d53-4980-b0b0-f28b369a000d' _PROPERTY_ID = '1dfb3940-7d53-4980-b0b0-f28b369a000d'
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info() if self._AUTH_TOKEN:
if not username: return
self.raise_login_required(method='password')
self.report_login() self.report_login()
PokerGoBaseIE._AUTH_TOKEN = self._download_json( PokerGoBaseIE._AUTH_TOKEN = self._download_json(
f'https://subscription.pokergo.com/properties/{self._PROPERTY_ID}/sign-in', None, f'https://subscription.pokergo.com/properties/{self._PROPERTY_ID}/sign-in', None,
@ -30,7 +28,7 @@ def _login(self):
def _real_initialize(self): def _real_initialize(self):
if not self._AUTH_TOKEN: if not self._AUTH_TOKEN:
self._login() self.raise_login_required(method='password')
class PokerGoIE(PokerGoBaseIE): class PokerGoIE(PokerGoBaseIE):

View file

@ -21,10 +21,7 @@ class RoosterTeethBaseIE(InfoExtractor):
_API_BASE = 'https://svod-be.roosterteeth.com' _API_BASE = 'https://svod-be.roosterteeth.com'
_API_BASE_URL = f'{_API_BASE}/api/v1' _API_BASE_URL = f'{_API_BASE}/api/v1'
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
if self._get_cookies(self._API_BASE_URL).get('rt_access_token'): if self._get_cookies(self._API_BASE_URL).get('rt_access_token'):
return return
@ -47,9 +44,6 @@ def _login(self):
msg += ': ' + error msg += ': ' + error
self.report_warning(msg) self.report_warning(msg)
def _real_initialize(self):
self._login()
def _extract_video_info(self, data): def _extract_video_info(self, data):
thumbnails = [] thumbnails = []
for image in traverse_obj(data, ('included', 'images')): for image in traverse_obj(data, ('included', 'images')):

View file

@ -25,14 +25,7 @@ class SafariBaseIE(InfoExtractor):
LOGGED_IN = False LOGGED_IN = False
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
_, urlh = self._download_webpage_handle( _, urlh = self._download_webpage_handle(
'https://learning.oreilly.com/accounts/login-check/', None, 'https://learning.oreilly.com/accounts/login-check/', None,
'Downloading login page') 'Downloading login page')

View file

@ -14,14 +14,7 @@ class SCTEBaseIE(InfoExtractor):
_LOGIN_URL = 'https://www.scte.org/SCTE/Sign_In.aspx' _LOGIN_URL = 'https://www.scte.org/SCTE/Sign_In.aspx'
_NETRC_MACHINE = 'scte' _NETRC_MACHINE = 'scte'
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
login_popup = self._download_webpage( login_popup = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login popup') self._LOGIN_URL, None, 'Downloading login popup')

View file

@ -79,16 +79,12 @@ class ShahidIE(ShahidBaseIE):
'only_matching': True 'only_matching': True
}] }]
def _real_initialize(self): def _perform_login(self, username, password):
email, password = self._get_login_info()
if email is None:
return
try: try:
user_data = self._download_json( user_data = self._download_json(
'https://shahid.mbc.net/wd/service/users/login', 'https://shahid.mbc.net/wd/service/users/login',
None, 'Logging in', data=json.dumps({ None, 'Logging in', data=json.dumps({
'email': email, 'email': username,
'password': password, 'password': password,
'basic': 'false', 'basic': 'false',
}).encode('utf-8'), headers={ }).encode('utf-8'), headers={

View file

@ -75,9 +75,12 @@ def _get_device_id(self):
t[i] = '{:x}'.format(3 & n | 8) t[i] = '{:x}'.format(3 & n | 8)
return ''.join(t) + '-' + str(int(time.time() * 1000)) return ''.join(t) + '-' + str(int(time.time() * 1000))
def _login(self, username, password): def _perform_login(self, username, password):
self._HEADERS['device_id'] = self._get_device_id()
self._HEADERS['content-type'] = 'application/json'
if username.lower() == 'token' and len(password) > 1198: if username.lower() == 'token' and len(password) > 1198:
return password self._HEADERS['authorization'] = password
elif len(username) != 10 or not username.isdigit(): elif len(username) != 10 or not username.isdigit():
raise ExtractorError(f'Invalid username/password; {self._LOGIN_HINT}') raise ExtractorError(f'Invalid username/password; {self._LOGIN_HINT}')
@ -99,7 +102,7 @@ def _login(self, username, password):
None, note='Verifying OTP', data=data.encode(), headers=self._HEADERS) None, note='Verifying OTP', data=data.encode(), headers=self._HEADERS)
if otp_verify_json['resultCode'] == 'KO': if otp_verify_json['resultCode'] == 'KO':
raise ExtractorError(otp_request_json['message'], expected=True) raise ExtractorError(otp_request_json['message'], expected=True)
return otp_verify_json['resultObj']['accessToken'] self._HEADERS['authorization'] = otp_verify_json['resultObj']['accessToken']
def _call_api(self, version, path, video_id): def _call_api(self, version, path, video_id):
try: try:
@ -118,13 +121,8 @@ def _call_api(self, version, path, video_id):
raise ExtractorError(message) raise ExtractorError(message)
raise raise
def _real_initialize(self): def _initialize_pre_login(self):
self._HEADERS['security_token'] = self._call_api('1.4', 'ALL/GETTOKEN', None) self._HEADERS['security_token'] = self._call_api('1.4', 'ALL/GETTOKEN', None)
username, password = self._get_login_info()
if username:
self._HEADERS['device_id'] = self._get_device_id()
self._HEADERS['content-type'] = 'application/json'
self._HEADERS['authorization'] = self._login(username, password)
def _real_extract(self, url): def _real_extract(self, url):
video_id = self._match_id(url) video_id = self._match_id(url)

View file

@ -107,30 +107,24 @@ def _download_json(self, *args, **kwargs):
return False return False
raise raise
def _real_initialize(self): def _initialize_pre_login(self):
self._CLIENT_ID = self._downloader.cache.load('soundcloud', 'client_id') or 'a3e059563d7fd3372b49b37f00a00bcf' self._CLIENT_ID = self._downloader.cache.load('soundcloud', 'client_id') or 'a3e059563d7fd3372b49b37f00a00bcf'
self._login()
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info() if username != 'oauth':
if username is None:
return
if username == 'oauth' and password is not None:
self._access_token = password
query = self._API_AUTH_QUERY_TEMPLATE % self._CLIENT_ID
payload = {'session': {'access_token': self._access_token}}
token_verification = sanitized_Request(self._API_VERIFY_AUTH_TOKEN % query, json.dumps(payload).encode('utf-8'))
response = self._download_json(token_verification, None, note='Verifying login token...', fatal=False)
if response is not False:
self._HEADERS = {'Authorization': 'OAuth ' + self._access_token}
self.report_login()
else:
self.report_warning('Provided authorization token seems to be invalid. Continue as guest')
elif username is not None:
self.report_warning( self.report_warning(
'Login using username and password is not currently supported. ' 'Login using username and password is not currently supported. '
'Use "--username oauth --password <oauth_token>" to login using an oauth token') 'Use "--username oauth --password <oauth_token>" to login using an oauth token')
self._access_token = password
query = self._API_AUTH_QUERY_TEMPLATE % self._CLIENT_ID
payload = {'session': {'access_token': self._access_token}}
token_verification = sanitized_Request(self._API_VERIFY_AUTH_TOKEN % query, json.dumps(payload).encode('utf-8'))
response = self._download_json(token_verification, None, note='Verifying login token...', fatal=False)
if response is not False:
self._HEADERS = {'Authorization': 'OAuth ' + self._access_token}
self.report_login()
else:
self.report_warning('Provided authorization token seems to be invalid. Continue as guest')
r''' r'''
def genDevId(): def genDevId():

View file

@ -40,8 +40,7 @@ def _login(self, site):
if self._logged_in: if self._logged_in:
return return
username, password = self._get_login_info( username, password = self._get_login_info(netrc_machine=self._SITES.get(site, site))
netrc_machine=self._SITES.get(site, site))
if username is None: if username is None:
return return

View file

@ -51,17 +51,14 @@ class TeamTreeHouseIE(InfoExtractor):
}] }]
_NETRC_MACHINE = 'teamtreehouse' _NETRC_MACHINE = 'teamtreehouse'
def _real_initialize(self): def _perform_login(self, username, password):
email, password = self._get_login_info()
if email is None:
return
signin_page = self._download_webpage( signin_page = self._download_webpage(
'https://teamtreehouse.com/signin', 'https://teamtreehouse.com/signin',
None, 'Downloading signin page') None, 'Downloading signin page')
data = self._form_hidden_inputs('new_user_session', signin_page) data = self._form_hidden_inputs('new_user_session', signin_page)
data.update({ data.update({
'user_session[email]': email, 'user_session[email]': username,
'user_session[password]': password, 'user_session[password]': password,
}) })
error_message = get_element_by_class('error-message', self._download_webpage( error_message = get_element_by_class('error-message', self._download_webpage(

View file

@ -30,11 +30,9 @@ class TennisTVIE(InfoExtractor):
'skip': 'Requires email and password of a subscribed account', 'skip': 'Requires email and password of a subscribed account',
} }
_NETRC_MACHINE = 'tennistv' _NETRC_MACHINE = 'tennistv'
_session_token = None
def _login(self): def _perform_login(self, username, password):
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 = { login_form = {
'Email': username, 'Email': username,
@ -63,7 +61,8 @@ def _login(self):
self._session_token = login_result['sessionToken'] self._session_token = login_result['sessionToken']
def _real_initialize(self): def _real_initialize(self):
self._login() if not self._session_token:
raise self.raise_login_required('Login info is needed for this website', method='password')
def _real_extract(self, url): def _real_extract(self, url):
video_id = self._match_id(url) video_id = self._match_id(url)

View file

@ -40,17 +40,14 @@ class TouTvIE(RadioCanadaIE):
}] }]
_CLIENT_KEY = '90505c8d-9c34-4f34-8da1-3a85bdc6d4f4' _CLIENT_KEY = '90505c8d-9c34-4f34-8da1-3a85bdc6d4f4'
def _real_initialize(self): def _perform_login(self, username, password):
email, password = self._get_login_info()
if email is None:
return
try: try:
self._access_token = self._download_json( self._access_token = self._download_json(
'https://services.radio-canada.ca/toutv/profiling/accounts/login', 'https://services.radio-canada.ca/toutv/profiling/accounts/login',
None, 'Logging in', data=json.dumps({ None, 'Logging in', data=json.dumps({
'ClientId': self._CLIENT_KEY, 'ClientId': self._CLIENT_KEY,
'ClientSecret': '34026772-244b-49b6-8b06-317b30ac9a20', 'ClientSecret': '34026772-244b-49b6-8b06-317b30ac9a20',
'Email': email, 'Email': username,
'Password': password, 'Password': password,
'Scope': 'id.write media-validation.read', 'Scope': 'id.write media-validation.read',
}).encode(), headers={ }).encode(), headers={

View file

@ -54,10 +54,7 @@ class TubiTvIE(InfoExtractor):
}, },
}] }]
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
self.report_login() self.report_login()
form_data = { form_data = {
'username': username, 'username': username,
@ -72,9 +69,6 @@ def _login(self):
raise ExtractorError( raise ExtractorError(
'Login failed (invalid username/password)', expected=True) 'Login failed (invalid username/password)', expected=True)
def _real_initialize(self):
self._login()
def _real_extract(self, url): def _real_extract(self, url):
video_id = self._match_id(url) video_id = self._match_id(url)
video_data = self._download_json( video_data = self._download_json(

View file

@ -247,11 +247,7 @@ class TumblrIE(InfoExtractor):
_ACCESS_TOKEN = None _ACCESS_TOKEN = None
def _real_initialize(self): def _initialize_pre_login(self):
self.get_access_token()
self._login()
def get_access_token(self):
login_page = self._download_webpage( login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page', fatal=False) self._LOGIN_URL, None, 'Downloading login page', fatal=False)
if login_page: if login_page:
@ -260,11 +256,7 @@ def get_access_token(self):
if not self._ACCESS_TOKEN: if not self._ACCESS_TOKEN:
self.report_warning('Failed to get access token; metadata will be missing and some videos may not work') self.report_warning('Failed to get access token; metadata will be missing and some videos may not work')
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if not username:
return
if not self._ACCESS_TOKEN: if not self._ACCESS_TOKEN:
return return

View file

@ -57,14 +57,7 @@ class TwitchBaseIE(InfoExtractor):
'VideoPlayer_ChapterSelectButtonVideo': '8d2793384aac3773beab5e59bd5d6f585aedb923d292800119e03d40cd0f9b41', 'VideoPlayer_ChapterSelectButtonVideo': '8d2793384aac3773beab5e59bd5d6f585aedb923d292800119e03d40cd0f9b41',
} }
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def fail(message): def fail(message):
raise ExtractorError( raise ExtractorError(
'Unable to login. Twitch said: %s' % message, expected=True) 'Unable to login. Twitch said: %s' % message, expected=True)

View file

@ -168,14 +168,7 @@ def _download_json(self, url_or_request, *args, **kwargs):
self._handle_error(response) self._handle_error(response)
return response return response
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
login_popup = self._download_webpage( login_popup = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login popup') self._LOGIN_URL, None, 'Downloading login popup')

View file

@ -23,11 +23,7 @@ class VidioBaseIE(InfoExtractor):
_LOGIN_URL = 'https://www.vidio.com/users/login' _LOGIN_URL = 'https://www.vidio.com/users/login'
_NETRC_MACHINE = 'vidio' _NETRC_MACHINE = 'vidio'
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
def is_logged_in(): def is_logged_in():
res = self._download_json( res = self._download_json(
'https://www.vidio.com/interactions.json', None, 'Checking if logged in', fatal=False) or {} 'https://www.vidio.com/interactions.json', None, 'Checking if logged in', fatal=False) or {}
@ -63,10 +59,9 @@ def is_logged_in():
'Unable to log in: %s. %s' % (reason, clean_html(subreason)), expected=True) 'Unable to log in: %s. %s' % (reason, clean_html(subreason)), expected=True)
raise ExtractorError('Unable to log in') raise ExtractorError('Unable to log in')
def _real_initialize(self): def _initialize_pre_login(self):
self._api_key = self._download_json( self._api_key = self._download_json(
'https://www.vidio.com/auth', None, data=b'')['api_key'] 'https://www.vidio.com/auth', None, data=b'')['api_key']
self._login()
def _call_api(self, url, video_id, note=None): def _call_api(self, url, video_id, note=None):
return self._download_json(url, video_id, note=note, headers={ return self._download_json(url, video_id, note=note, headers={

View file

@ -36,9 +36,6 @@ class ViewLiftBaseIE(InfoExtractor):
def _fetch_token(self, site, url): def _fetch_token(self, site, url):
if self._TOKENS.get(site): if self._TOKENS.get(site):
return return
email, password = self._get_login_info(netrc_machine=site)
if email:
self.report_warning('Logging in using username and password is broken. %s' % self._LOGIN_HINTS['cookies'])
cookies = self._get_cookies(url) cookies = self._get_cookies(url)
if cookies and cookies.get('token'): if cookies and cookies.get('token'):

View file

@ -99,14 +99,7 @@ def _check_errors(self, data):
self.raise_login_required(message) self.raise_login_required(message)
self._raise_error(message) self._raise_error(message)
def _real_initialize(self): def _perform_login(self, username, password):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
self._token = self._call_api( self._token = self._call_api(
'sessions.json', None, 'Logging in', fatal=False, 'sessions.json', None, 'Logging in', fatal=False,
data={'username': username, 'password': password}).get('token') data={'username': username, 'password': password}).get('token')

View file

@ -44,12 +44,7 @@ class VimeoBaseInfoExtractor(InfoExtractor):
_LOGIN_REQUIRED = False _LOGIN_REQUIRED = False
_LOGIN_URL = 'https://vimeo.com/log_in' _LOGIN_URL = 'https://vimeo.com/log_in'
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
if self._LOGIN_REQUIRED:
raise ExtractorError('No login info available, needed for using %s.' % self.IE_NAME, expected=True)
return
webpage = self._download_webpage( webpage = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page') self._LOGIN_URL, None, 'Downloading login page')
token, vuid = self._extract_xsrft_and_vuid(webpage) token, vuid = self._extract_xsrft_and_vuid(webpage)
@ -75,6 +70,10 @@ def _login(self):
expected=True) expected=True)
raise ExtractorError('Unable to log in') raise ExtractorError('Unable to log in')
def _real_initialize(self):
if self._LOGIN_REQUIRED and not self._get_cookies('https://vimeo.com').get('vuid'):
self._raise_login_required()
def _get_video_password(self): def _get_video_password(self):
password = self.get_param('videopassword') password = self.get_param('videopassword')
if password is None: if password is None:
@ -701,9 +700,6 @@ def _verify_player_video_password(self, url, video_id, headers):
raise ExtractorError('Wrong video password', expected=True) raise ExtractorError('Wrong video password', expected=True)
return checked return checked
def _real_initialize(self):
self._login()
def _extract_from_api(self, video_id, unlisted_hash=None): def _extract_from_api(self, video_id, unlisted_hash=None):
token = self._download_json( token = self._download_json(
'https://vimeo.com/_rv/jwt', video_id, headers={ 'https://vimeo.com/_rv/jwt', video_id, headers={
@ -1231,9 +1227,6 @@ class VimeoReviewIE(VimeoBaseInfoExtractor):
'skip': 'video gone', 'skip': 'video gone',
}] }]
def _real_initialize(self):
self._login()
def _real_extract(self, url): def _real_extract(self, url):
page_url, video_id = self._match_valid_url(url).groups() page_url, video_id = self._match_valid_url(url).groups()
data = self._download_json( data = self._download_json(
@ -1275,9 +1268,6 @@ class VimeoWatchLaterIE(VimeoChannelIE):
'only_matching': True, 'only_matching': True,
}] }]
def _real_initialize(self):
self._login()
def _page_url(self, base_url, pagenum): def _page_url(self, base_url, pagenum):
url = '%s/page:%d/' % (base_url, pagenum) url = '%s/page:%d/' % (base_url, pagenum)
request = sanitized_Request(url) request = sanitized_Request(url)

View file

@ -29,11 +29,7 @@
class VKBaseIE(InfoExtractor): class VKBaseIE(InfoExtractor):
_NETRC_MACHINE = 'vk' _NETRC_MACHINE = 'vk'
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info()
if username is None:
return
login_page, url_handle = self._download_webpage_handle( login_page, url_handle = self._download_webpage_handle(
'https://vk.com', None, 'Downloading login page') 'https://vk.com', None, 'Downloading login page')
@ -57,9 +53,6 @@ def _login(self):
raise ExtractorError( raise ExtractorError(
'Unable to login, incorrect username and/or password', expected=True) 'Unable to login, incorrect username and/or password', expected=True)
def _real_initialize(self):
self._login()
def _download_payload(self, path, video_id, data, fatal=True): def _download_payload(self, path, video_id, data, fatal=True):
data['al'] = 1 data['al'] = 1
code, payload = self._download_json( code, payload = self._download_json(

View file

@ -26,22 +26,16 @@ class VLiveBaseIE(NaverBaseIE):
_NETRC_MACHINE = 'vlive' _NETRC_MACHINE = 'vlive'
_logged_in = False _logged_in = False
def _real_initialize(self): def _perform_login(self, username, password):
if not self._logged_in: if self._logged_in:
VLiveBaseIE._logged_in = self._login() return
def _login(self):
email, password = self._get_login_info()
if email is None:
return False
LOGIN_URL = 'https://www.vlive.tv/auth/email/login' LOGIN_URL = 'https://www.vlive.tv/auth/email/login'
self._request_webpage( self._request_webpage(
LOGIN_URL, None, note='Downloading login cookies') LOGIN_URL, None, note='Downloading login cookies')
self._download_webpage( self._download_webpage(
LOGIN_URL, None, note='Logging in', LOGIN_URL, None, note='Logging in',
data=urlencode_postdata({'email': email, 'pwd': password}), data=urlencode_postdata({'email': username, 'pwd': password}),
headers={ headers={
'Referer': LOGIN_URL, 'Referer': LOGIN_URL,
'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/x-www-form-urlencoded'
@ -54,7 +48,7 @@ def _login(self):
if not try_get(login_info, lambda x: x['message']['login'], bool): if not try_get(login_info, lambda x: x['message']['login'], bool):
raise ExtractorError('Unable to log in', expected=True) raise ExtractorError('Unable to log in', expected=True)
return True VLiveBaseIE._logged_in = True
def _call_api(self, path_template, video_id, fields=None, query_add={}, note=None): def _call_api(self, path_template, video_id, fields=None, query_add={}, note=None):
if note is None: if note is None:

View file

@ -85,7 +85,7 @@ def _get_cms_resource(self, resource_key, video_id):
'resource_key': resource_key, 'resource_key': resource_key,
})['__links__']['cms_resource']['href'] })['__links__']['cms_resource']['href']
def _real_initialize(self): def _initialize_pre_login(self):
webpage = self._download_webpage( webpage = self._download_webpage(
'https://vrv.co/', None, headers=self.geo_verification_headers()) 'https://vrv.co/', None, headers=self.geo_verification_headers())
self._API_PARAMS = self._parse_json(self._search_regex( self._API_PARAMS = self._parse_json(self._search_regex(
@ -124,16 +124,10 @@ class VRVIE(VRVBaseIE):
}] }]
_NETRC_MACHINE = 'vrv' _NETRC_MACHINE = 'vrv'
def _real_initialize(self): def _perform_login(self, username, password):
super(VRVIE, self)._real_initialize()
email, password = self._get_login_info()
if email is None:
return
token_credentials = self._call_api( token_credentials = self._call_api(
'authenticate/by:credentials', None, 'Token Credentials', data={ 'authenticate/by:credentials', None, 'Token Credentials', data={
'email': email, 'email': username,
'password': password, 'password': password,
}) })
self._TOKEN = token_credentials['oauth_token'] self._TOKEN = token_credentials['oauth_token']

View file

@ -263,7 +263,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
_PLAYLIST_ID_RE = r'(?:(?:PL|LL|EC|UU|FL|RD|UL|TL|PU|OLAK5uy_)[0-9A-Za-z-_]{10,}|RDMM|WL|LL|LM)' _PLAYLIST_ID_RE = r'(?:(?:PL|LL|EC|UU|FL|RD|UL|TL|PU|OLAK5uy_)[0-9A-Za-z-_]{10,}|RDMM|WL|LL|LM)'
_NETRC_MACHINE = 'youtube' # _NETRC_MACHINE = 'youtube'
# If True it will raise an error if no login info is provided # If True it will raise an error if no login info is provided
_LOGIN_REQUIRED = False _LOGIN_REQUIRED = False
@ -334,21 +334,6 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
r'(?:www\.)?hpniueoejy4opn7bc4ftgazyqjoeqwlvh2uiku2xqku6zpoa4bf5ruid\.onion', r'(?:www\.)?hpniueoejy4opn7bc4ftgazyqjoeqwlvh2uiku2xqku6zpoa4bf5ruid\.onion',
) )
def _login(self):
"""
Attempt to log in to YouTube.
If _LOGIN_REQUIRED is set and no authentication was provided, an error is raised.
"""
if (self._LOGIN_REQUIRED
and self.get_param('cookiefile') is None
and self.get_param('cookiesfrombrowser') is None):
self.raise_login_required(
'Login details are needed to download this content', method='cookies')
username, password = self._get_login_info()
if username:
self.report_warning(f'Cannot login to YouTube using username and password. {self._LOGIN_HINTS["cookies"]}')
def _initialize_consent(self): def _initialize_consent(self):
cookies = self._get_cookies('https://www.youtube.com/') cookies = self._get_cookies('https://www.youtube.com/')
if cookies.get('__Secure-3PSID'): if cookies.get('__Secure-3PSID'):
@ -379,7 +364,10 @@ def _initialize_pref(self):
def _real_initialize(self): def _real_initialize(self):
self._initialize_pref() self._initialize_pref()
self._initialize_consent() self._initialize_consent()
self._login() if (self._LOGIN_REQUIRED
and self.get_param('cookiefile') is None
and self.get_param('cookiesfrombrowser') is None):
self.raise_login_required('Login details are needed to download this content', method='cookies')
_YT_INITIAL_DATA_RE = r'(?:window\s*\[\s*["\']ytInitialData["\']\s*\]|ytInitialData)\s*=\s*({.+?})\s*;' _YT_INITIAL_DATA_RE = r'(?:window\s*\[\s*["\']ytInitialData["\']\s*\]|ytInitialData)\s*=\s*({.+?})\s*;'
_YT_INITIAL_PLAYER_RESPONSE_RE = r'ytInitialPlayerResponse\s*=\s*({.+?})\s*;' _YT_INITIAL_PLAYER_RESPONSE_RE = r'ytInitialPlayerResponse\s*=\s*({.+?})\s*;'
@ -3928,6 +3916,7 @@ def _rich_grid_entries(self, contents):
if entry: if entry:
yield entry yield entry
''' '''
def _extract_entries(self, parent_renderer, continuation_list): def _extract_entries(self, parent_renderer, continuation_list):
# continuation_list is modified in-place with continuation_list = [continuation_token] # continuation_list is modified in-place with continuation_list = [continuation_token]
continuation_list[:] = [None] continuation_list[:] = [None]

View file

@ -25,13 +25,11 @@ class ZattooPlatformBaseIE(InfoExtractor):
def _host_url(self): def _host_url(self):
return 'https://%s' % (self._API_HOST if hasattr(self, '_API_HOST') else self._HOST) return 'https://%s' % (self._API_HOST if hasattr(self, '_API_HOST') else self._HOST)
def _login(self): def _real_initialize(self):
username, password = self._get_login_info() if not self._power_guide_hash:
if not username or not password: self.raise_login_required('An account is needed to access this media', method='password')
self.raise_login_required(
'A valid %s account is needed to access this media.'
% self._NETRC_MACHINE)
def _perform_login(self, username, password):
try: try:
data = self._download_json( data = self._download_json(
'%s/zapi/v2/account/login' % self._host_url(), None, 'Logging in', '%s/zapi/v2/account/login' % self._host_url(), None, 'Logging in',
@ -52,7 +50,7 @@ def _login(self):
self._power_guide_hash = data['session']['power_guide_hash'] self._power_guide_hash = data['session']['power_guide_hash']
def _real_initialize(self): def _initialize_pre_login(self):
webpage = self._download_webpage( webpage = self._download_webpage(
self._host_url(), None, 'Downloading app token') self._host_url(), None, 'Downloading app token')
app_token = self._html_search_regex( app_token = self._html_search_regex(
@ -72,8 +70,6 @@ def _real_initialize(self):
'format': 'json', 'format': 'json',
})) }))
self._login()
def _extract_cid(self, video_id, channel_name): def _extract_cid(self, video_id, channel_name):
channel_groups = self._download_json( channel_groups = self._download_json(
'%s/zapi/v2/cached/channels/%s' % (self._host_url(), '%s/zapi/v2/cached/channels/%s' % (self._host_url(),

View file

@ -93,32 +93,27 @@ class Zee5IE(InfoExtractor):
_NETRC_MACHINE = 'zee5' _NETRC_MACHINE = 'zee5'
_GEO_COUNTRIES = ['IN'] _GEO_COUNTRIES = ['IN']
def _login(self): def _perform_login(self, username, password):
username, password = self._get_login_info() if len(username) == 10 and username.isdigit() and self._USER_TOKEN is None:
if username: self.report_login()
if len(username) == 10 and username.isdigit() and self._USER_TOKEN is None: otp_request_json = self._download_json('https://b2bapi.zee5.com/device/sendotp_v1.php?phoneno=91{}'.format(username),
self.report_login() None, note='Sending OTP')
otp_request_json = self._download_json('https://b2bapi.zee5.com/device/sendotp_v1.php?phoneno=91{}'.format(username), if otp_request_json['code'] == 0:
None, note='Sending OTP') self.to_screen(otp_request_json['message'])
if otp_request_json['code'] == 0:
self.to_screen(otp_request_json['message'])
else:
raise ExtractorError(otp_request_json['message'], expected=True)
otp_code = self._get_tfa_info('OTP')
otp_verify_json = self._download_json('https://b2bapi.zee5.com/device/verifyotp_v1.php?phoneno=91{}&otp={}&guest_token={}&platform=web'.format(username, otp_code, self._DEVICE_ID),
None, note='Verifying OTP', fatal=False)
if not otp_verify_json:
raise ExtractorError('Unable to verify OTP.', expected=True)
self._USER_TOKEN = otp_verify_json.get('token')
if not self._USER_TOKEN:
raise ExtractorError(otp_request_json['message'], expected=True)
elif username.lower() == 'token' and len(password) > 1198:
self._USER_TOKEN = password
else: else:
raise ExtractorError(self._LOGIN_HINT, expected=True) raise ExtractorError(otp_request_json['message'], expected=True)
otp_code = self._get_tfa_info('OTP')
def _real_initialize(self): otp_verify_json = self._download_json('https://b2bapi.zee5.com/device/verifyotp_v1.php?phoneno=91{}&otp={}&guest_token={}&platform=web'.format(username, otp_code, self._DEVICE_ID),
self._login() None, note='Verifying OTP', fatal=False)
if not otp_verify_json:
raise ExtractorError('Unable to verify OTP.', expected=True)
self._USER_TOKEN = otp_verify_json.get('token')
if not self._USER_TOKEN:
raise ExtractorError(otp_request_json['message'], expected=True)
elif username.lower() == 'token' and len(password) > 1198:
self._USER_TOKEN = password
else:
raise ExtractorError(self._LOGIN_HINT, expected=True)
def _real_extract(self, url): def _real_extract(self, url):
video_id, display_id = self._match_valid_url(url).group('id', 'display_id') video_id, display_id = self._match_valid_url(url).group('id', 'display_id')