youtube-dl

Another place where youtube-dl lives on
git clone git://git.oshgnacknak.de/youtube-dl.git
Log | Files | Refs | README | LICENSE

commit 9303ce3e6969b5818982d6214a8d0ff4e3c95286
parent 06c085ab6e87b46630d291b3f1e991760e0cdc32
Author: reddraggone9 <cljenkins9@gmail.com>
Date:   Thu, 13 Aug 2015 22:11:11 -0500

[youtube] Fix two-factor authentication

Diffstat:
Myoutube_dl/extractor/youtube.py | 40++++++++++++++++++----------------------
1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py @@ -46,7 +46,7 @@ from ..utils import ( class YoutubeBaseInfoExtractor(InfoExtractor): """Provide base functions for Youtube extractors""" _LOGIN_URL = 'https://accounts.google.com/ServiceLogin' - _TWOFACTOR_URL = 'https://accounts.google.com/SecondFactor' + _TWOFACTOR_URL = 'https://accounts.google.com/signin/challenge' _NETRC_MACHINE = 'youtube' # If True it will raise an error if no login info is provided _LOGIN_REQUIRED = False @@ -128,7 +128,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor): # Two-Factor # TODO add SMS and phone call support - these require making a request and then prompting the user - if re.search(r'(?i)<form[^>]* id="gaia_secondfactorform"', login_results) is not None: + if re.search(r'(?i)<form[^>]* id="challenge"', login_results) is not None: tfa_code = self._get_tfa_info() if tfa_code is None: @@ -136,31 +136,27 @@ class YoutubeBaseInfoExtractor(InfoExtractor): self._downloader.report_warning('(Note that only TOTP (Google Authenticator App) codes work at this time.)') return False - # Unlike the first login form, secTok and timeStmp are both required for the TFA form + def find_value(element_id): + match = re.search(r'id="%s"\s+value="(.+?)">' % element_id, login_results, re.M | re.U) + if match is None: + self._downloader.report_warning('Failed to get %s - did the page structure change?' % id) + return match.group(1) - match = re.search(r'id="secTok"\n\s+value=\'(.+)\'/>', login_results, re.M | re.U) - if match is None: - self._downloader.report_warning('Failed to get secTok - did the page structure change?') - secTok = match.group(1) - match = re.search(r'id="timeStmp"\n\s+value=\'(.+)\'/>', login_results, re.M | re.U) - if match is None: - self._downloader.report_warning('Failed to get timeStmp - did the page structure change?') - timeStmp = match.group(1) + challengeId = find_value('challengeId') + challengeType = find_value('challengeType') + gxf = find_value('gxf') tfa_form_strs = { + 'challengeId': challengeId, + 'challengeType': challengeType, # This doesn't appear to change 'continue': 'https://www.youtube.com/signin?action_handle_signin=true&feature=sign_in_button&hl=en_US&nomobiletemp=1', - 'smsToken': '', - 'smsUserPin': tfa_code, - 'smsVerifyPin': 'Verify', - - 'PersistentCookie': 'yes', - 'checkConnection': '', - 'checkedDomains': 'youtube', - 'pstMsg': '1', - 'secTok': secTok, - 'timeStmp': timeStmp, 'service': 'youtube', 'hl': 'en_US', + 'checkedDomains': 'youtube', + 'pstMsg': '0', + 'gxf': gxf, + 'Pin': tfa_code, + 'TrustDevice': 'on', } tfa_form = dict((k.encode('utf-8'), v.encode('utf-8')) for k, v in tfa_form_strs.items()) tfa_data = compat_urllib_parse.urlencode(tfa_form).encode('ascii') @@ -173,7 +169,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor): if tfa_results is False: return False - if re.search(r'(?i)<form[^>]* id="gaia_secondfactorform"', tfa_results) is not None: + if re.search(r'(?i)<form[^>]* id="challenge"', tfa_results) is not None: self._downloader.report_warning('Two-factor code expired. Please try again, or use a one-use backup code instead.') return False if re.search(r'(?i)<form[^>]* id="gaia_loginform"', tfa_results) is not None: