Skip to content

Commit 84986a2

Browse files
committed
Fix two-factor authentication merge conflicts
2 parents 7c7c7f6 + 744a4ef commit 84986a2

1 file changed

Lines changed: 43 additions & 2 deletions

File tree

vk_api/vk_api.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
CAPTCHA_ERROR_CODE = 14
2121
NEED_VALIDATION_CODE = 17
2222
HTTP_ERROR_CODE = -1
23+
TWOFACTOR_CODE = -2
2324

2425
RE_LOGIN_HASH = re.compile(r'name="lg_h" value="([a-z0-9]+)"')
2526
RE_CAPTCHAID = re.compile(r'sid=(\d+)')
2627
RE_NUMBER_HASH = re.compile(r"al_page: '3', hash: '([a-z0-9]+)'")
28+
RE_AUTH_HASH = re.compile(r"hash: '([a-z_0-9]+)'")
2729
RE_TOKEN_URL = re.compile(r'location\.href = "(.*?)"\+addr;')
2830

2931
RE_PHONE_PREFIX = re.compile(r'phone_number">(.*?)<')
@@ -33,7 +35,9 @@
3335

3436
class VkApi(object):
3537
def __init__(self, login=None, password=None, number=None, sec_number=None,
36-
token=None, proxies=None, captcha_handler=None,
38+
token=None,
39+
proxies=None,
40+
auth_handler=None, captcha_handler=None,
3741
config_filename='vk_config.json',
3842
api_version='5.35', app_id=2895443, scope=33554431,
3943
client_secret=None):
@@ -51,6 +55,9 @@ def __init__(self, login=None, password=None, number=None, sec_number=None,
5155
:param proxies: proxy server
5256
{'http': 'http://127.0.0.1:8888/',
5357
'https': 'https://127.0.0.1:8888/'}
58+
:param auth_handler: Функция для обработки двухфакторной аутентификации,
59+
обязана возвращать строку с кодом для
60+
прохождения аутентификации
5461
:param captcha_handler: Функция для обработки капчи
5562
:param config_filename: Расположение config файла
5663
@@ -88,7 +95,8 @@ def __init__(self, login=None, password=None, number=None, sec_number=None,
8895
self.error_handlers = {
8996
NEED_VALIDATION_CODE: self.need_validation_handler,
9097
CAPTCHA_ERROR_CODE: captcha_handler or self.captcha_handler,
91-
TOO_MANY_RPS_CODE: self.too_many_rps_handler
98+
TOO_MANY_RPS_CODE: self.too_many_rps_handler,
99+
TWOFACTOR_CODE: auth_handler or self.auth_handler
92100
}
93101

94102
def authorization(self, reauth=False):
@@ -139,6 +147,10 @@ def vk_login(self, captcha_sid=None, captcha_key=None):
139147

140148
remixsid = None
141149

150+
if 'act=authcheck' in response.url:
151+
code = self.error_handlers[TWOFACTOR_CODE]()
152+
response = self.twofactor(response, code)
153+
142154
if 'remixsid' in self.http.cookies:
143155
remixsid = self.http.cookies['remixsid']
144156
elif 'remixsid6' in self.http.cookies: # ipv6?
@@ -176,6 +188,28 @@ def vk_login(self, captcha_sid=None, captcha_key=None):
176188
if 'act=blocked' in response.url:
177189
raise AccountBlocked('Account is blocked')
178190

191+
def twofactor(self, response, code):
192+
""" Двухфакторная аутентификация
193+
:param reponse: запрос, содержащий страницу с приглашением к аутентификации
194+
:param code: код, который необходимо ввести для успешной аутентификации
195+
"""
196+
assert code != None, "Empty code doesn't acceptable"
197+
assert len(code) == 6, "Length of code cannot be other than 6."
198+
199+
auth_hash = search_re(RE_AUTH_HASH, response.text)
200+
url = 'https://vk.com/al_login.php'
201+
if auth_hash:
202+
values = {
203+
'act': 'a_authcheck_code',
204+
'code': code,
205+
'remember': 0, # TODO: Fix me(device remembering)
206+
'hash': auth_hash,
207+
}
208+
response = self.http.post(url, values, cookies=response.cookies)
209+
if url not in response.url:
210+
return response
211+
raise TwoFactorError('Incorrect code: %s' % code)
212+
179213
def security_check(self, url=None, response=None):
180214
if url:
181215
response = self.http.get(url)
@@ -315,6 +349,9 @@ def too_many_rps_handler(self, error):
315349
time.sleep(0.5)
316350
return error.try_method()
317351

352+
def auth_handler(self):
353+
raise AuthorizationError("No handler for two-factor authorization.")
354+
318355
def method(self, method, values=None, captcha_sid=None, captcha_key=None):
319356
""" Использование методов API
320357
@@ -444,6 +481,10 @@ class AccountBlocked(AuthorizationError):
444481
pass
445482

446483

484+
class TwoFactorError(AuthorizationError):
485+
pass
486+
487+
447488
class SecurityCheck(AuthorizationError):
448489
def __init__(self, phone_prefix=None, phone_postfix=None, response=None):
449490
self.phone_prefix = phone_prefix

0 commit comments

Comments
 (0)