Skip to content

Commit fefd264

Browse files
committed
Merge branch 'dev'
2 parents 886b071 + 73c707d commit fefd264

5 files changed

Lines changed: 129 additions & 118 deletions

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
setup(
1616
name='vk_api',
17-
version='7.3',
17+
version='7.4',
1818
author='Kirill Python',
1919
author_email='whoami@python273.pw',
2020
url='https://github.com/python273/vk_api',

vk_api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"""
1010

1111
__author__ = 'Kirill Python'
12-
__version__ = '7.3'
12+
__version__ = '7.4'
1313
__email__ = 'python273@ya.ru'
1414
__contact__ = 'https://vk.com/python273'
1515

vk_api/utils.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
@author: Kirill Python
5+
@contact: https://vk.com/python273
6+
@license Apache License, Version 2.0, see LICENSE file
7+
8+
Copyright (C) 2016
9+
"""
10+
11+
12+
def search_re(reg, string):
13+
""" Поиск по регулярке """
14+
s = reg.search(string)
15+
16+
if s:
17+
groups = s.groups()
18+
return groups[0]
19+
20+
21+
def clean_string(s):
22+
if s:
23+
return s.strip().replace(' ', '')
24+
25+
26+
def code_from_number(prefix, postfix, number):
27+
prefix_len = len(prefix)
28+
postfix_len = len(postfix)
29+
30+
if number[0] == '+':
31+
number = number[1:]
32+
33+
if (prefix_len + postfix_len) >= len(number):
34+
return
35+
36+
# Сравниваем начало номера
37+
if number[:prefix_len] != prefix:
38+
return
39+
40+
# Сравниваем конец номера
41+
if number[-postfix_len:] != postfix:
42+
return
43+
44+
return number[prefix_len:-postfix_len]

vk_api/vk_api.py

Lines changed: 52 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
"""
1010

1111
import re
12-
import time
1312
import threading
13+
import time
1414

1515
import requests
1616

1717
import jconfig
18+
from .utils import code_from_number, search_re, clean_string
19+
1820

1921
DELAY = 0.34 # ~3 requests per second
2022
TOO_MANY_RPS_CODE = 6
@@ -29,8 +31,7 @@
2931
RE_AUTH_HASH = re.compile(r"hash: '([a-z_0-9]+)'")
3032
RE_TOKEN_URL = re.compile(r'location\.href = "(.*?)"\+addr;')
3133

32-
RE_PHONE_PREFIX = re.compile(r'phone_number">(.*?)<')
33-
RE_PHONE_PREFIX_2 = re.compile(r'label ta_r">\+(\d+)')
34+
RE_PHONE_PREFIX = re.compile(r'label ta_r">\+(.*?)<')
3435
RE_PHONE_POSTFIX = re.compile(r'phone_postfix">.*?(\d+).*?<')
3536

3637

@@ -134,6 +135,7 @@ def vk_login(self, captcha_sid=None, captcha_key=None):
134135
response = self.http.get('https://vk.com/')
135136

136137
values = {
138+
'act': 'login',
137139
'role': 'al_frame',
138140
'_origin': 'https://vk.com',
139141
'utf8': '1',
@@ -148,18 +150,26 @@ def vk_login(self, captcha_sid=None, captcha_key=None):
148150
'captcha_key': captcha_key
149151
})
150152

151-
response = self.http.post('https://login.vk.com/?act=login', values)
153+
response = self.http.post('https://login.vk.com/', values)
154+
155+
if 'onLoginCaptcha(' in response.text:
156+
captcha_sid = search_re(RE_CAPTCHAID, response.text)
157+
captcha = Captcha(self, captcha_sid, self.vk_login)
158+
159+
return self.error_handlers[CAPTCHA_ERROR_CODE](captcha)
160+
161+
if 'onLoginFailed(4' in response.text:
162+
raise BadPassword('Bad password')
152163

153-
remixsid = None
164+
if 'act=authcheck' in response.text:
165+
response = self.http.get('https://vk.com/login?act=authcheck')
154166

155-
if 'act=authcheck' in response.url: # TODO: test/fix
156-
code, remember_device = self.error_handlers[TWOFACTOR_CODE]()
157-
response = self.twofactor(response, code, remember_device)
167+
self.twofactor(response)
158168

159-
if 'remixsid' in self.http.cookies:
160-
remixsid = self.http.cookies['remixsid']
161-
elif 'remixsid6' in self.http.cookies: # ipv6?
162-
remixsid = self.http.cookies['remixsid6']
169+
remixsid = (
170+
self.http.cookies.get('remixsid') or
171+
self.http.cookies.get('remixsid6')
172+
)
163173

164174
if remixsid:
165175
self.settings.remixsid = remixsid
@@ -173,66 +183,51 @@ def vk_login(self, captcha_sid=None, captcha_key=None):
173183
self.settings.save()
174184

175185
self.sid = remixsid
176-
177-
elif 'onLoginCaptcha(' in response.text:
178-
captcha_sid = search_re(RE_CAPTCHAID, response.text)
179-
captcha = Captcha(self, captcha_sid, self.vk_login)
180-
181-
if self.error_handlers[CAPTCHA_ERROR_CODE]:
182-
return self.error_handlers[CAPTCHA_ERROR_CODE](captcha)
183-
else:
184-
raise AuthorizationError('Authorization error (capcha)')
185-
elif 'onLoginFailed(4' in response.text:
186-
raise BadPassword('Bad password')
187186
else:
188187
raise AuthorizationError(
189188
'Unknown error. Please send bugreport: https://vk.com/python273'
190189
)
191190

192-
self.security_check()
191+
response = self.security_check()
193192

194-
if 'act=blocked' in response.url: # TODO: text/fix
193+
if 'act=blocked' in response.url:
195194
raise AccountBlocked('Account is blocked')
196195

197-
def twofactor(self, response, code, remember_device=False):
196+
def twofactor(self, auth_response):
198197
""" Двухфакторная аутентификация
199-
:param reponse: запрос, содержащий страницу с приглашением к аутентификации
200-
:param code: код, который необходимо ввести для успешной аутентификации
201-
:param remember_device: параметр, означающий,
202-
стоит ли запоминать это устройство в целях
203-
избежания повторного ввода кода(default: False)
198+
:param auth_response: страница с приглашением к аутентификации
204199
"""
200+
code, remember_device = self.error_handlers[TWOFACTOR_CODE]()
205201

206-
if code == None:
207-
raise TwoFactorError("Empty code doesn't acceptable")
208-
if len(code) != 6:
209-
raise TwoFactorError("Length of code cannot be other than 6.")
202+
auth_hash = search_re(RE_AUTH_HASH, auth_response.text)
210203

211-
auth_hash = search_re(RE_AUTH_HASH, response.text)
212-
url = 'https://vk.com/al_login.php'
213-
if auth_hash:
214-
values = {
215-
'act': 'a_authcheck_code',
216-
'code': code,
217-
'remember': int(remember_device),
218-
'hash': auth_hash,
219-
}
220-
response = self.http.post(url, values, cookies=response.cookies)
221-
if url not in response.url:
222-
return response
223-
raise TwoFactorError('Incorrect code: %s' % code)
204+
values = {
205+
'act': 'a_authcheck_code',
206+
'al': '1',
207+
'code': code,
208+
'remember': int(remember_device),
209+
'hash': auth_hash,
210+
}
211+
212+
response = self.http.post('https://vk.com/al_login.php', values)
213+
response_parsed = response.text.split('<!>')
214+
215+
if response_parsed[4] == '4': # OK
216+
return self.http.get('https://vk.com/' + response_parsed[5])
217+
218+
elif response_parsed[4] == '8': # Incorrect code
219+
return self.twofactor(auth_response)
220+
221+
raise TwoFactorError('Two factor authentication failed')
224222

225223
def security_check(self, response=None):
226224
if response is None:
227225
response = self.http.get('https://vk.com/settings')
228226
if 'security_check' not in response.url:
229-
return
230-
231-
phone_prefix = search_re(RE_PHONE_PREFIX, response.text)
232-
if not phone_prefix:
233-
phone_prefix = search_re(RE_PHONE_PREFIX_2, response.text)
227+
return response
234228

235-
phone_postfix = search_re(RE_PHONE_POSTFIX, response.text)
229+
phone_prefix = clean_string(search_re(RE_PHONE_PREFIX, response.text))
230+
phone_postfix = clean_string(search_re(RE_PHONE_POSTFIX, response.text))
236231

237232
code = None
238233
if self.sec_number:
@@ -257,12 +252,12 @@ def security_check(self, response=None):
257252
response = self.http.post('https://vk.com/login.php', values)
258253

259254
if response.text.split('<!>')[4] == '4':
260-
return True
255+
return response
261256

262257
if phone_prefix and phone_postfix:
263258
raise SecurityCheck(phone_prefix, phone_postfix)
264-
else:
265-
raise SecurityCheck(response=response)
259+
260+
raise SecurityCheck(response=response)
266261

267262
def check_sid(self):
268263
""" Проверка Cookies remixsid на валидность """
@@ -457,54 +452,6 @@ def __getattr__(self, method):
457452
def __call__(self, *args, **kwargs):
458453
return self._vk.method(self._method, kwargs)
459454

460-
def get_doc(self):
461-
doc(self._method)
462-
463-
464-
def doc(method=None):
465-
""" Открывает документацию на метод или список всех методов
466-
467-
:param method: метод
468-
"""
469-
470-
if not method:
471-
method = 'methods'
472-
473-
url = 'https://vk.com/dev/{}'.format(method)
474-
475-
import webbrowser
476-
webbrowser.open(url)
477-
478-
479-
def search_re(reg, string):
480-
""" Поиск по регулярке """
481-
s = reg.search(string)
482-
483-
if s:
484-
groups = s.groups()
485-
return groups[0]
486-
487-
488-
def code_from_number(phone_prefix, phone_postfix, number):
489-
prefix_len = len(phone_prefix)
490-
postfix_len = len(phone_postfix)
491-
492-
if number[0] == '+':
493-
number = number[1:]
494-
495-
if (prefix_len + postfix_len) >= len(number):
496-
return
497-
498-
# Сравниваем начало номера
499-
if not number[:prefix_len] == phone_prefix:
500-
return
501-
502-
# Сравниваем конец номера
503-
if not number[-postfix_len:] == phone_postfix:
504-
return
505-
506-
return number[prefix_len:-postfix_len]
507-
508455

509456
class AuthorizationError(Exception):
510457
pass

0 commit comments

Comments
 (0)