3434RE_NUMBER_HASH = re .compile (r"al_page: '3', hash: '([a-z0-9]+)'" )
3535RE_AUTH_HASH = re .compile (r"Authcheck\.init\('([a-z_0-9]+)'" )
3636RE_TOKEN_URL = re .compile (r'location\.href = "(.*?)"\+addr;' )
37+ RE_AUTH_TOKEN_URL = re .compile (r'window\.init = ({.*?});' )
3738
3839RE_PHONE_PREFIX = re .compile (r'label ta_r">\+(.*?)<' )
3940RE_PHONE_POSTFIX = re .compile (r'phone_postfix">.*?(\d+).*?<' )
@@ -342,7 +343,7 @@ def _vk_login(self, captcha_sid=None, captcha_key=None):
342343 if 'act=blocked' in response .url :
343344 raise AccountBlocked ('Account is blocked' )
344345
345- def _pass_twofactor (self , auth_response ):
346+ def _pass_twofactor (self , auth_response , captcha_sid = None , captcha_key = None ):
346347 """ Двухфакторная аутентификация
347348
348349 :param auth_response: страница с приглашением к аутентификации
@@ -361,6 +362,15 @@ def _pass_twofactor(self, auth_response):
361362 'hash' : auth_hash ,
362363 'remember' : int (remember_device ),
363364 }
365+ if captcha_sid and captcha_key :
366+ self .logger .info (
367+ 'Using captcha code: {}: {}' .format (
368+ captcha_sid ,
369+ captcha_key
370+ )
371+ )
372+ values ['captcha_sid' ] = captcha_sid
373+ values ['captcha_key' ] = captcha_key
364374
365375 response = self .http .post (
366376 'https://vk.com/al_login.php?act=a_authcheck_code' ,
@@ -377,6 +387,14 @@ def _pass_twofactor(self, auth_response):
377387 return self ._pass_twofactor (auth_response )
378388
379389 elif status == '2' :
390+ if data ['payload' ][1 ][1 ] != 2 :
391+ # Regular captcha
392+ self .logger .info ('Captcha code is required' )
393+
394+ captcha_sid = data ['payload' ][1 ][0 ][1 :- 1 ]
395+ captcha = Captcha (self , captcha_sid , self ._pass_twofactor , (auth_response ,))
396+
397+ return self .error_handlers [CAPTCHA_ERROR_CODE ](captcha )
380398 raise TwoFactorError ('Recaptcha required' )
381399
382400 raise TwoFactorError (get_unknown_exc_str ('2FA; unknown status' ))
@@ -435,13 +453,15 @@ def check_sid(self):
435453 self .logger .info ('No remixsid' )
436454 return
437455
438- response = self .http .get ('https://vk.com/feed2.php' ).json ()
456+ feed_url = 'https://vk.com/feed.php'
457+ response = self .http .get (feed_url )
439458
440- if response [ 'user' ][ 'id' ] != - 1 :
441- self .logger .info ('remixsid is valid' )
442- return response
459+ if response . url != feed_url :
460+ self .logger .info ('remixsid is not valid' )
461+ return False
443462
444- self .logger .info ('remixsid is not valid' )
463+ self .logger .info ('remixsid is valid' )
464+ return True
445465
446466 def _api_login (self ):
447467 """ Получение токена через Desktop приложение """
@@ -469,6 +489,51 @@ def _api_login(self):
469489
470490 if url :
471491 response = self .http .get (url )
492+ elif 'redirect_uri' in response .url :
493+ response = self .http .get (response .url )
494+ auth_json = json .loads (search_re (RE_AUTH_TOKEN_URL , response .text ))
495+ return_auth_hash = auth_json ['data' ]['hash' ]['return_auth' ]
496+ response = self .http .post (
497+ 'https://login.vk.com/?act=connect_internal' ,
498+ {
499+ 'uuid' : '' ,
500+ 'service_group' : '' ,
501+ 'return_auth_hash' : return_auth_hash ,
502+ 'version' : 1 ,
503+ 'app_id' : self .app_id ,
504+ },
505+ headers = {'Origin' : 'https://id.vk.com' }
506+ )
507+ connect_data = response .json ()
508+ if connect_data ['type' ] != 'okay' :
509+ raise AuthError ('Unknown API auth error' )
510+ auth_token = connect_data ['data' ]['access_token' ]
511+ response = self .http .post (
512+ 'https://api.vk.com/method/auth.getOauthToken' ,
513+ {
514+ 'hash' : return_auth_hash ,
515+ 'app_id' : self .app_id ,
516+ 'client_id' : self .app_id ,
517+ 'scope' : self .scope ,
518+ 'access_token' : auth_token ,
519+ 'is_seamless_auth' : 1 ,
520+ 'v' : '5.207'
521+ }
522+ )
523+
524+ self .token = response .json ()['response' ]
525+
526+ self .storage .setdefault (
527+ 'token' , {}
528+ ).setdefault (
529+ 'app' + str (self .app_id ), {}
530+ )['scope_' + str (self .scope )] = self .token
531+
532+ self .storage .save ()
533+
534+ self .logger .info ('Got access_token' )
535+ return
536+
472537
473538 if 'access_token' in response .url :
474539 parsed_url = urllib .parse .urlparse (response .url )
0 commit comments