diff --git a/examples/need_validation_handler.py b/examples/need_validation_handler.py new file mode 100644 index 0000000..0beaa6c --- /dev/null +++ b/examples/need_validation_handler.py @@ -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 = 'python@vk.com', '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() diff --git a/vk_api/exceptions.py b/vk_api/exceptions.py index b645f93..5c44497 100644 --- a/vk_api/exceptions.py +++ b/vk_api/exceptions.py @@ -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 diff --git a/vk_api/vk_api.py b/vk_api/vk_api.py index 0c164dc..328cba2 100644 --- a/vk_api/vk_api.py +++ b/vk_api/vk_api.py @@ -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 @@ -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 @@ -539,7 +539,7 @@ def need_validation_handler(self, error): :param error: исключение """ - pass # TODO: write me + raise error def http_handler(self, error): """ Обработчик ошибок соединения @@ -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)