Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix https://vk.com/dev/need_validation #507

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions examples/need_validation_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
import re
import vk_api

import requests
import urllib.parse as urllib
from vk_api.utils import (
search_re
)
from vk_api.exceptions import *

RE_CAPTCHA_SID = re.compile(r'name="captcha_sid" value="(\d+)"')



def return_capcha(url):
key = input("Enter captcha code {0}: ".format(url)).strip()

return key


def need_validation_handler(validation):
""" Обработчик проверки безопасности при запросе API
(https://vk.com/dev/need_validation)

:param validation: исключение
"""
response = None
try:
redirect_uri = validation.get_redirect_uri()
url = redirect_uri.split('?')[0]
query_data = urllib.parse_qs(urllib.urlparse(redirect_uri).query)

# captcha or validate
query_data['act'] = 'captcha' # TODO 'captcha' or 'validate'

response = requests.post(url, data=query_data)
captcha_sid = None
if response.ok:
if query_data['act'] == 'captcha':
captcha_sid = search_re(RE_CAPTCHA_SID, response.text)
captcha_url = validation.get_url(captcha_sid)
elif query_data['act'] == 'validate':
phone = input("Enter phone number: ").strip()
query_data.update({
'act': 'validate_phone',
'phone': '{}'.format(phone)
})
requests.post(url, data=query_data)
else:
return None
else:
return None

if query_data['act'] == 'captcha':
key = return_capcha(captcha_url)
else:
del query_data['phone']
key = input("Enter code: ").strip()
query_data.update({
'act': 'validate_code',
'code': '{}'.format(key)
})
requests.post(url, data=query_data)
response = validation.try_again(key, captcha_sid)

except Exception:
print('error my_need_validation_handler')
return None

return response



def main():
""" Пример обработки валидатора """

login, password = '[email protected]', 'mypassword'
vk_session = vk_api.VkApi(
login, password,
need_validation_handler=need_validation_handler # функция для обработки валидатора
)

try:
vk_session.auth()
except vk_api.AuthError as error_msg:
print(error_msg)
return

# some code
# ...


if __name__ == '__main__':
main()
46 changes: 46 additions & 0 deletions vk_api/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,52 @@ def __str__(self):
return 'Captcha needed'


class Need_Validation(Captcha):

def __init__(self, vk, func, args=None, kwargs=None, response=None):
super(Need_Validation, self).__init__(vk, 0, func, args, kwargs)
self.code = NEED_VALIDATION_CODE
self.response = response

def get_redirect_uri(self):
""" Получить ссылку на необходимую проверку """

if self.response and self.response['redirect_uri']:
return self.response['redirect_uri']

return None

def get_url(self, sid=None):
""" Получить ссылку на изображение капчи """
if sid:
self.sid = sid
if not self.url:
self.url = 'https://api.vk.com/captcha.php?sid={}'.format(self.sid)

return self.url

def try_again(self, key, sid=None):
""" Отправить запрос заново с ответом капчи

:param key: ответ капчи
"""
if key:
self.key = key
self.kwargs.update({
'captcha_key': self.key
})

if sid:
self.sid = sid
self.kwargs.update({
'captcha_sid': self.sid
})

return self.func(*self.args, **self.kwargs)

def __str__(self):
return 'Need_Validation needed'

class VkAudioException(Exception):
pass

Expand Down
14 changes: 11 additions & 3 deletions vk_api/vk_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def __init__(self, login=None, password=None, token=None,
auth_handler=None, captcha_handler=None,
config=jconfig.Config, config_filename='vk_config.v2.json',
api_version='5.92', app_id=6222115, scope=DEFAULT_USER_SCOPE,
client_secret=None, session=None):
client_secret=None, session=None, need_validation_handler=None):

self.login = login
self.password = password
Expand All @@ -113,7 +113,7 @@ def __init__(self, login=None, password=None, token=None,
self.last_request = 0.0

self.error_handlers = {
NEED_VALIDATION_CODE: self.need_validation_handler,
NEED_VALIDATION_CODE: need_validation_handler or self.need_validation_handler,
CAPTCHA_ERROR_CODE: captcha_handler or self.captcha_handler,
TOO_MANY_RPS_CODE: self.too_many_rps_handler,
TWOFACTOR_CODE: auth_handler or self.auth_handler
Expand Down Expand Up @@ -539,7 +539,7 @@ def need_validation_handler(self, error):
:param error: исключение
"""

pass # TODO: write me
raise error

def http_handler(self, error):
""" Обработчик ошибок соединения
Expand Down Expand Up @@ -647,6 +647,14 @@ def method(self, method, values=None, captcha_sid=None, captcha_key=None,
{'values': values, 'raw': raw},
error.error['captcha_img']
)
if error.code == NEED_VALIDATION_CODE:
error = Need_Validation(
self,
self.method,
(method,),
{'values': values, 'raw': raw},
response['error']
)

response = self.error_handlers[error.code](error)

Expand Down