|
5 | 5 |
|
6 | 6 | from vk.logs import LOGGING_CONFIG |
7 | 7 | from vk.utils import stringify_values, json_iter_parse, LoggingSession |
8 | | -from vk.exceptions import VkAuthError, VkAPIMethodError, CAPTCHA_IS_NEEDED, AUTHORIZATION_FAILED |
| 8 | +from vk.exceptions import VkAuthError, VkAPIError, CAPTCHA_IS_NEEDED, AUTHORIZATION_FAILED |
9 | 9 | from vk.mixins import AuthMixin, InteractiveMixin |
10 | 10 |
|
11 | 11 |
|
@@ -60,55 +60,67 @@ def get_access_token(self): |
60 | 60 | logger.debug('API.get_access_token()') |
61 | 61 | return self._access_token |
62 | 62 |
|
63 | | - def make_request(self, method_request, **method_kwargs): |
| 63 | + def make_request(self, method_request, captcha_response=None): |
64 | 64 |
|
65 | 65 | logger.debug('Prepare API Method request') |
66 | 66 |
|
67 | 67 | response = self.send_api_request(method_request) |
| 68 | + # todo Replace with something less exceptional |
68 | 69 | response.raise_for_status() |
69 | 70 |
|
70 | 71 | # there are may be 2 dicts in one JSON |
71 | | - # for example: {'error': ...}{'response': ...} |
72 | | - errors = [] |
73 | | - error_codes = [] |
74 | | - for data in json_iter_parse(response.text): |
75 | | - if 'error' in data: |
76 | | - error_data = data['error'] |
77 | | - if error_data['error_code'] == CAPTCHA_IS_NEEDED: |
78 | | - return self.on_captcha_is_needed(error_data, method_request) |
79 | | - |
80 | | - error_codes.append(error_data['error_code']) |
81 | | - errors.append(error_data) |
82 | | - |
83 | | - if 'response' in data: |
84 | | - for error in errors: |
85 | | - logger.warning(str(error)) |
86 | | - |
87 | | - return data['response'] |
88 | | - |
89 | | - if AUTHORIZATION_FAILED in error_codes: # invalid access token |
90 | | - logger.info('Authorization failed. Access token will be dropped') |
91 | | - self.access_token = None |
92 | | - return self.make_request(method_request) |
93 | | - else: |
94 | | - raise VkAPIMethodError(errors[0]) |
95 | | - |
96 | | - def send_api_request(self, request): |
| 72 | + # for example: "{'error': ...}{'response': ...}" |
| 73 | + for response_or_error in json_iter_parse(response.text): |
| 74 | + if 'response' in response_or_error: |
| 75 | + # todo Can we have error and response simultaneously |
| 76 | + # for error in errors: |
| 77 | + # logger.warning(str(error)) |
| 78 | + |
| 79 | + return response_or_error['response'] |
| 80 | + |
| 81 | + elif 'error' in response_or_error: |
| 82 | + error_data = response_or_error['error'] |
| 83 | + error = VkAPIError(error_data) |
| 84 | + |
| 85 | + if error.is_captcha_needed(): |
| 86 | + captcha_key = self.get_captcha_key(error.captcha_img) |
| 87 | + if not captcha_key: |
| 88 | + raise error |
| 89 | + |
| 90 | + captcha_response = { |
| 91 | + 'sid': error.captcha_sid, |
| 92 | + 'key': captcha_key, |
| 93 | + } |
| 94 | + return self.make_request(method_request, captcha_response=captcha_response) |
| 95 | + |
| 96 | + elif error.is_access_token_incorrect(): |
| 97 | + logger.info('Authorization failed. Access token will be dropped') |
| 98 | + self.access_token = None |
| 99 | + return self.make_request(method_request) |
| 100 | + |
| 101 | + else: |
| 102 | + raise error |
| 103 | + |
| 104 | + def send_api_request(self, request, captcha_response=None): |
97 | 105 | url = self.API_URL + request._method_name |
98 | 106 | method_args = request._api._method_default_args.copy() |
99 | 107 | method_args.update(stringify_values(request._method_args)) |
100 | | - if self.access_token: |
101 | | - method_args['access_token'] = self.access_token |
| 108 | + access_token = self.access_token |
| 109 | + if access_token: |
| 110 | + method_args['access_token'] = access_token |
| 111 | + if captcha_response: |
| 112 | + method_args['captcha_sid'] = captcha_response['sid'] |
| 113 | + method_args['captcha_key'] = captcha_response['key'] |
102 | 114 | timeout = request._api._timeout |
103 | 115 | response = self.requests_session.post(url, method_args, timeout=timeout) |
104 | 116 | return response |
105 | 117 |
|
106 | | - def on_captcha_is_needed(self, error_data, method_request): |
| 118 | + def get_captcha_key(self, captcha_image_url): |
107 | 119 | """ |
108 | 120 | Default behavior on CAPTCHA is to raise exception |
109 | 121 | Reload this in child |
110 | 122 | """ |
111 | | - raise VkAPIMethodError(error_data) |
| 123 | + return None |
112 | 124 |
|
113 | 125 | def auth_code_is_needed(self, content, session): |
114 | 126 | """ |
|
0 commit comments