1919HTTP_ERROR_CODE = - 1
2020
2121RE_CAPTCHAID = re .compile (r'sid=(\d+)' )
22- RE_NUMBER_HASH = re .compile (r'security_check.*? hash: \'(.*?)\'\};' )
22+ RE_NUMBER_HASH = re .compile (r"al_page: '3', hash: '([a-z0-9]+)'" )
2323RE_TOKEN_URL = re .compile (r'location\.href = "(.*?)"\+addr;' )
24+
2425RE_PHONE_PREFIX = re .compile (r'phone_number">(.*?)<' )
25- RE_PHONE_POSTFIX = re .compile (r'phone_postfix">(.*?)<' )
26+ RE_PHONE_PREFIX_2 = re .compile (r'label ta_r">\+(\d+)' )
27+ RE_PHONE_POSTFIX = re .compile (r'phone_postfix">.*?(\d+).*?<' )
2628
2729
2830class VkApi (object ):
2931
30- def __init__ (self , login = None , password = None , number = None , token = None ,
32+ def __init__ (self , login = None , password = None , number = None , sec_number = None ,
33+ token = None ,
3134 proxies = None , captcha_handler = None , config_filename = None ,
3235 api_version = '5.24' , app_id = 2895443 , scope = 2097151 ):
3336 """
3437 :param login: Логин ВКонтакте
3538 :param password: Пароль ВКонтакте
3639 :param number: Номер для проверке безопасности (указывать, если
3740 в качестве логина используется не номер)
41+ :param sec_number:
3842
3943 :param token: access_token
4044 :param proxies: proxy server
@@ -51,6 +55,7 @@ def __init__(self, login=None, password=None, number=None, token=None,
5155 self .login = login
5256 self .password = password
5357 self .number = number
58+ self .sec_number = sec_number
5459
5560 self .sid = None
5661 self .token = {'access_token' : token }
@@ -70,7 +75,6 @@ def __init__(self, login=None, password=None, number=None, token=None,
7075 'User-agent' : 'Mozilla/5.0 (Windows NT 6.1; rv:31.0)'
7176 ' Gecko/20100101 Firefox/31.0'
7277 }
73- self .http .verify = False
7478
7579 self .last_request = 0.0
7680
@@ -137,24 +141,34 @@ def vk_login(self, captcha_sid=None, captcha_key=None):
137141 self .error_handlers [CAPTCHA_ERROR_CODE ](captcha )
138142 else :
139143 raise AuthorizationError ('Authorization error (capcha)' )
140- else :
144+ elif 'm=1' in response . url :
141145 raise BadPassword ('Bad password' )
146+ else :
147+ raise AuthorizationError ('Unknown error. Please send bugreport.' )
142148
143149 if 'security_check' in response .url :
144150 self .security_check (response = response )
145151
152+ if 'act=blocked' in response .url :
153+ raise AccountBlocked ('Account is blocked' )
154+
146155 def security_check (self , url = None , response = None ):
147156 if url :
148157 response = self .http .get (url )
149158 if 'security_check' not in response .url :
150159 return
151160
152- phone_prefix = search_re (RE_PHONE_PREFIX , response .text ).strip ()
153- phone_postfix = search_re (RE_PHONE_POSTFIX , response .text ).strip ()
161+ phone_prefix = search_re (RE_PHONE_PREFIX , response .text )
162+ if not phone_prefix :
163+ phone_prefix = search_re (RE_PHONE_PREFIX_2 , response .text )
154164
155- if self .number :
165+ phone_postfix = search_re (RE_PHONE_POSTFIX , response .text )
166+
167+ if self .sec_number :
168+ code = self .sec_number
169+ elif self .number :
156170 code = code_from_number (phone_prefix , phone_postfix , self .number )
157- else :
171+ elif self . login :
158172 code = code_from_number (phone_prefix , phone_postfix , self .login )
159173
160174 if code :
@@ -174,7 +188,10 @@ def security_check(self, url=None, response=None):
174188 if response .text .split ('<!>' )[4 ] == '4' :
175189 return True
176190
177- raise SecurityCheck (phone_prefix , phone_postfix )
191+ if phone_prefix and phone_postfix :
192+ raise SecurityCheck (phone_prefix , phone_postfix )
193+ else :
194+ raise SecurityCheck (response = response )
178195
179196 def check_sid (self ):
180197 """ Прверка Cookies remixsid на валидность """
@@ -338,22 +355,24 @@ def doc(method=None):
338355
339356def search_re (reg , string ):
340357 """ Поиск по регулярке """
341- m = reg .search (string )
342- groups = m .groups ()
358+ s = reg .search (string )
343359
344- if groups :
360+ if s :
361+ groups = s .groups ()
345362 return groups [0 ]
346363
347364
348365def code_from_number (phone_prefix , phone_postfix , number ):
349366 prefix_len = len (phone_prefix )
350367 postfix_len = len (phone_postfix )
351368
369+ if number [0 ] == '+' :
370+ number = number [1 :]
371+
352372 if (prefix_len + postfix_len ) >= len (number ):
353373 return
354374
355375 # Сравниваем начало номера
356- # TODO: ignore "+" symbole
357376 if not number [:prefix_len ] == phone_prefix :
358377 return
359378
@@ -372,16 +391,25 @@ class BadPassword(AuthorizationError):
372391 pass
373392
374393
394+ class AccountBlocked (AuthorizationError ):
395+ pass
396+
397+
375398class SecurityCheck (AuthorizationError ):
376399
377- def __init__ (self , phone_prefix , phone_postfix ):
400+ def __init__ (self , phone_prefix , phone_postfix , response = None ):
378401 self .phone_prefix = phone_prefix
379402 self .phone_postfix = phone_postfix
403+ self .response = response
380404
381405 def __str__ (self ):
382- return 'Security check. Enter number: {} ... {}' .format (
383- self .phone_prefix , self .phone_postfix
384- )
406+ if self .phone_prefix and self .phone_postfix :
407+ return 'Security check. Enter number: {} ... {}' .format (
408+ self .phone_prefix , self .phone_postfix
409+ )
410+ else :
411+ return ('Security check. Phone prefix and postfix not detected. '
412+ 'Please send bugreport. Response in self.response' )
385413
386414
387415class ApiError (Exception ):
@@ -405,7 +433,7 @@ def __str__(self):
405433 self .error ['error_msg' ])
406434
407435
408- class ApiHttpError (object ):
436+ class ApiHttpError (Exception ):
409437
410438 def __init__ (self , vk , method , values , response ):
411439 self .vk = vk
0 commit comments