Skip to content

Commit 5c7dab5

Browse files
committed
Merge branch 'dev'
Conflicts: setup.py vk_api/__init__.py
2 parents 1833dba + 78f45f4 commit 5c7dab5

10 files changed

Lines changed: 309 additions & 18 deletions

File tree

examples/capthca_handle.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ def main():
2525
""" Пример: обработка капчи """
2626

2727
login, password = 'python@vk.com', 'mypassword'
28-
vk = vk_api.VkApi(
28+
vk_session = vk_api.VkApi(
2929
login, password,
3030
captcha_handler=captcha_handler # функция для обработки капчи
3131
)
3232

3333
try:
34-
vk.authorization()
34+
vk_session.authorization()
3535
except vk_api.AuthorizationError as error_msg:
3636
print(error_msg)
3737
return

examples/get_full_wall.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ def main():
1212
""" Пример: получение всех постов со стены """
1313

1414
login, password = 'python@vk.com', 'mypassword'
15-
vk = vk_api.VkApi(login, password)
15+
vk_session = vk_api.VkApi(login, password)
1616

1717
try:
18-
vk.authorization()
18+
vk_session.authorization()
1919
except vk_api.AuthorizationError as error_msg:
2020
print(error_msg)
2121
return
2222

23-
tools = vk_api.VkTools(vk)
23+
tools = vk_api.VkTools(vk_session)
2424
"""
2525
VkTools.get_all позволяет получить все итемы, например со стены или
2626
получить все диалоги, или сообщения. При использовании get_all

examples/requests_pool.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
@author: Kirill Python
5+
@contact: https://vk.com/python273
6+
"""
7+
8+
import vk_api
9+
10+
11+
def main():
12+
""" Пример работы с VkRequestsPool """
13+
14+
login, password = 'python@vk.com', 'mypassword'
15+
vk_session = vk_api.VkApi(login, password)
16+
17+
try:
18+
vk_session.authorization()
19+
except vk_api.AuthorizationError as error_msg:
20+
print(error_msg)
21+
return
22+
23+
"""
24+
Позволяет выполнять до 25 запросов к API за один запрос.
25+
Работает через метод execute.
26+
"""
27+
28+
friends = {}
29+
30+
with vk_api.VkRequestsPool(vk_session) as pool:
31+
for user_id in [1, 183433824]:
32+
friends[user_id] = pool.method('friends.get', {'user_id': user_id})
33+
34+
print(friends)
35+
36+
# Same result
37+
with vk_api.VkRequestsPool(vk_session) as pool:
38+
friends = pool.method_one_param(
39+
'friends.get', key='user_id', values=[1, 183433824])
40+
41+
print(friends)
42+
43+
with vk_api.VkRequestsPool(vk_session) as pool:
44+
friends = pool.method('friends.get')
45+
status = pool.method('status.get')
46+
47+
# Обратите внимание, что запрос выполняется после выхода из with
48+
# и к результатам обратиться можно только после выхода из него
49+
50+
print(friends)
51+
print(status)
52+
53+
if __name__ == '__main__':
54+
main()

examples/simple_example.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,23 @@ def main():
1212
""" Пример получения последнего сообщения со стены """
1313

1414
login, password = 'python@vk.com', 'mypassword'
15-
vk = vk_api.VkApi(login, password)
15+
vk_session = vk_api.VkApi(login, password)
1616

1717
try:
18-
vk.authorization()
18+
vk_session.authorization()
1919
except vk_api.AuthorizationError as error_msg:
2020
print(error_msg)
2121
return
2222

23+
vk = vk_session.get_api()
24+
2325
"""
2426
VkApi.method позволяет выполнять запросы к API. В этом примере
2527
используется метод wall.get (https://vk.com/dev/wall.get) с параметром
2628
count = 1, т.е. мы получаем один последний пост со стены текущего
2729
пользователя.
2830
"""
29-
response = vk.method('wall.get', {'count': 1}) # Используем метод wall.get
31+
response = vk.wall.get(count=1) # Используем метод wall.get
3032

3133
if response['items']:
3234
print(response['items'][0])

examples/upload_photo.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ def main():
1212
""" Пример: загрузка фото """
1313

1414
login, password = 'python@vk.com', 'mypassword'
15-
vk = vk_api.VkApi(login, password)
15+
vk_session = vk_api.VkApi(login, password)
1616

1717
try:
18-
vk.authorization()
18+
vk_session.authorization()
1919
except vk_api.AuthorizationError as error_msg:
2020
print(error_msg)
2121
return
@@ -24,7 +24,7 @@ def main():
2424
В VkUpload реализованы методы загрузки файлов в ВК.
2525
(Не все, если что-то понадобится - могу дописать)
2626
"""
27-
upload = vk_api.VkUpload(vk)
27+
upload = vk_api.VkUpload(vk_session)
2828

2929
photo = upload.photo( # Подставьте свои данные
3030
'D:/downloads/tube.jpg',

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='6.7',
17+
version='7.0',
1818
author='Kirill Python',
1919
author_email='python273@ya.ru',
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__ = '6.7'
12+
__version__ = '7.0'
1313
__email__ = 'python273@ya.ru'
1414
__contact__ = 'https://vk.com/python273'
1515

vk_api/vk_api.py

Lines changed: 67 additions & 4 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,9 +35,11 @@
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',
38-
api_version='5.35', app_id=2895443, scope=33554431,
42+
api_version='5.44', app_id=2895443, scope=33554431,
3943
client_secret=None):
4044
"""
4145
:param login: Логин ВКонтакте
@@ -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?
@@ -162,7 +174,7 @@ def vk_login(self, captcha_sid=None, captcha_key=None):
162174
captcha = Captcha(self, captcha_sid, self.vk_login)
163175

164176
if self.error_handlers[CAPTCHA_ERROR_CODE]:
165-
self.error_handlers[CAPTCHA_ERROR_CODE](captcha)
177+
return self.error_handlers[CAPTCHA_ERROR_CODE](captcha)
166178
else:
167179
raise AuthorizationError('Authorization error (capcha)')
168180
elif 'm=1' in response.url:
@@ -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,12 @@ 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+
355+
def get_api(self):
356+
return VkApiMethod(self)
357+
318358
def method(self, method, values=None, captcha_sid=None, captcha_key=None):
319359
""" Использование методов API
320360
@@ -387,6 +427,25 @@ def method(self, method, values=None, captcha_sid=None, captcha_key=None):
387427
return response['response']
388428

389429

430+
class VkApiMethod:
431+
def __init__(self, vk, method=None):
432+
self._vk = vk
433+
self._method = method
434+
435+
def __getattr__(self, method):
436+
if self._method:
437+
self._method += '.' + method
438+
return self
439+
440+
return VkApiMethod(self._vk, method)
441+
442+
def __call__(self, *args, **kwargs):
443+
return self._vk.method(self._method, kwargs)
444+
445+
def get_doc(self):
446+
doc(self._method)
447+
448+
390449
def doc(method=None):
391450
""" Открывает документацию на метод или список всех методов
392451
@@ -444,6 +503,10 @@ class AccountBlocked(AuthorizationError):
444503
pass
445504

446505

506+
class TwoFactorError(AuthorizationError):
507+
pass
508+
509+
447510
class SecurityCheck(AuthorizationError):
448511
def __init__(self, phone_prefix=None, phone_postfix=None, response=None):
449512
self.phone_prefix = phone_prefix

0 commit comments

Comments
 (0)