1010
1111import re
1212import time
13+ import threading
1314
1415import requests
1516
@@ -39,7 +40,7 @@ def __init__(self, login=None, password=None, number=None, sec_number=None,
3940 proxies = None ,
4041 auth_handler = None , captcha_handler = None ,
4142 config_filename = 'vk_config.json' ,
42- api_version = '5.44 ' , app_id = 2895443 , scope = 33554431 ,
43+ api_version = '5.52 ' , app_id = 2895443 , scope = 33554431 ,
4344 client_secret = None ):
4445 """
4546 :param login: Логин ВКонтакте
@@ -56,8 +57,9 @@ def __init__(self, login=None, password=None, number=None, sec_number=None,
5657 {'http': 'http://127.0.0.1:8888/',
5758 'https': 'https://127.0.0.1:8888/'}
5859 :param auth_handler: Функция для обработки двухфакторной аутентификации,
59- обязана возвращать строку с кодом для
60- прохождения аутентификации
60+ обязана возвращать строку с кодом и булевое значение,
61+ означающее, стоит ли вк запомнить это устройство, для
62+ прохождения аутентификации.
6163 :param captcha_handler: Функция для обработки капчи
6264 :param config_filename: Расположение config файла
6365
@@ -85,10 +87,10 @@ def __init__(self, login=None, password=None, number=None, sec_number=None,
8587
8688 self .http = requests .Session ()
8789 self .http .proxies = proxies # Ставим прокси
88- self .http .headers = { # Притворимся браузером
90+ self .http .headers . update ( { # Притворимся браузером
8991 'User-agent' : 'Mozilla/5.0 (Windows NT 6.1; rv:40.0) '
9092 'Gecko/20100101 Firefox/40.0'
91- }
93+ })
9294
9395 self .last_request = 0.0
9496
@@ -99,10 +101,12 @@ def __init__(self, login=None, password=None, number=None, sec_number=None,
99101 TWOFACTOR_CODE : auth_handler or self .auth_handler
100102 }
101103
104+ self .lock = threading .Lock ()
105+
102106 def authorization (self , reauth = False ):
103107 """ Полная авторизация с получением токена
104108
105- :param reauth: Позволяет переавторизиваться, игнорируя сохраненные
109+ :param reauth: Позволяет переавторизиваться, игнорируя сохраненные
106110 куки и токен
107111 """
108112
@@ -148,8 +152,8 @@ def vk_login(self, captcha_sid=None, captcha_key=None):
148152 remixsid = None
149153
150154 if 'act=authcheck' in response .url :
151- code = self .error_handlers [TWOFACTOR_CODE ]()
152- response = self .twofactor (response , code )
155+ code , remember_device = self .error_handlers [TWOFACTOR_CODE ]()
156+ response = self .twofactor (response , code , remember_device )
153157
154158 if 'remixsid' in self .http .cookies :
155159 remixsid = self .http .cookies ['remixsid' ]
@@ -188,21 +192,27 @@ def vk_login(self, captcha_sid=None, captcha_key=None):
188192 if 'act=blocked' in response .url :
189193 raise AccountBlocked ('Account is blocked' )
190194
191- def twofactor (self , response , code ):
195+ def twofactor (self , response , code , remember_device = False ):
192196 """ Двухфакторная аутентификация
193197 :param reponse: запрос, содержащий страницу с приглашением к аутентификации
194198 :param code: код, который необходимо ввести для успешной аутентификации
199+ :param remember_device: параметр, означающий,
200+ стоит ли запоминать это устройство в целях
201+ избежания повторного ввода кода(default: False)
195202 """
196- assert code != None , "Empty code doesn't acceptable"
197- assert len (code ) == 6 , "Length of code cannot be other than 6."
203+
204+ if code == None :
205+ raise TwoFactorError ("Empty code doesn't acceptable" )
206+ if len (code ) != 6 :
207+ raise TwoFactorError ("Length of code cannot be other than 6." )
198208
199209 auth_hash = search_re (RE_AUTH_HASH , response .text )
200210 url = 'https://vk.com/al_login.php'
201211 if auth_hash :
202212 values = {
203213 'act' : 'a_authcheck_code' ,
204214 'code' : code ,
205- 'remember' : 0 , # TODO: Fix me(device remembering)
215+ 'remember' : int ( remember_device ),
206216 'hash' : auth_hash ,
207217 }
208218 response = self .http .post (url , values , cookies = response .cookies )
@@ -383,14 +393,15 @@ def method(self, method, values=None, captcha_sid=None, captcha_key=None):
383393 'captcha_key' : captcha_key
384394 })
385395
386- # Ограничение 3 запроса в секунду
387- delay = DELAY - (time .time () - self .last_request )
396+ with self .lock :
397+ # Ограничение 3 запроса в секунду
398+ delay = DELAY - (time .time () - self .last_request )
388399
389- if delay > 0 :
390- time .sleep (delay )
400+ if delay > 0 :
401+ time .sleep (delay )
391402
392- response = self .http .post (url , values )
393- self .last_request = time .time ()
403+ response = self .http .post (url , values )
404+ self .last_request = time .time ()
394405
395406 if response .ok :
396407 response = response .json ()
@@ -574,6 +585,7 @@ def __init__(self, vk, captcha_sid,
574585
575586 self .key = None
576587 self .url = url
588+ self .image = None
577589
578590 def get_url (self ):
579591 """ Возвращает ссылку на изображение капчи
@@ -585,6 +597,14 @@ def get_url(self):
585597
586598 return self .url
587599
600+ def get_image (self ):
601+ """ Возвращает бинарное изображение капчи, получаемое по get_url()
602+ """
603+
604+ if not self .image :
605+ self .image = self .vk .http .get (self .get_url ()).content
606+ return self .image
607+
588608 def try_again (self , key ):
589609 """ Отправляет запрос заново с ответом капчи
590610
0 commit comments