def __init__(self, access_token=None): # logger.debug('API.__init__(access_token=%(access_token)r)', {'access_token': access_token}) self.access_token = access_token self.access_token_is_needed = False self.requests_session = LoggingSession() self.requests_session.headers['Accept'] = 'application/json' self.requests_session.headers['Content-Type'] = 'application/x-www-form-urlencoded'
def __init__(self, access_token=None): logger.debug('API.__init__(access_token=%(access_token)r)', {'access_token': access_token}) self.access_token = access_token self.access_token_is_needed = False self.requests_session = LoggingSession() self.requests_session.headers['Accept'] = 'application/json' self.requests_session.headers['Content-Type'] = 'application/x-www-form-urlencoded'
def __init__(self, access_token=None): logger.debug("API.__init__(access_token=%(access_token)r)", {"access_token": access_token}) # self.api_version = api_version # self.default_timeout = default_timeout self.access_token = access_token self.access_token_is_needed = False # self.requests_session = requests.Session() self.requests_session = LoggingSession() self.requests_session.headers["Accept"] = "application/json" self.requests_session.headers["Content-Type"] = "application/x-www-form-urlencoded"
def get_access_token(self): """ Get access token using app id and user login and password. """ logger.debug('AuthMixin.get_access_token()') with LoggingSession() as auth_session: self.auth_session = auth_session self.login() auth_response_url_query = self.oauth2_authorization() if 'access_token' in auth_response_url_query: return auth_response_url_query['access_token'] else: raise VKAuthError('OAuth2 authorization error')
class Session(object): API_URL = 'https://api.vk.com/method/' def __init__(self, access_token=None): # logger.debug('API.__init__(access_token=%(access_token)r)', {'access_token': access_token}) self.access_token = access_token self.access_token_is_needed = False self.requests_session = LoggingSession() self.requests_session.headers['Accept'] = 'application/json' self.requests_session.headers['Content-Type'] = 'application/x-www-form-urlencoded' @property def access_token(self): # logger.debug('Check that we need new access token') if self.access_token_is_needed: # logger.debug('We need new access token. Try to get it.') self.access_token = self.get_access_token() # else: # logger.debug('Use old access token') return self._access_token @access_token.setter def access_token(self, value): self._access_token = value if isinstance(value, str_type) and len(value) >= 12: self.censored_access_token = '{}***{}'.format(value[:4], value[-4:]) else: self.censored_access_token = value # logger.debug('access_token = %r', self.censored_access_token) self.access_token_is_needed = not self._access_token def get_user_login(self): pass # logger.debug('Do nothing to get user login') def get_access_token(self): """ Dummy method """ # logger.debug('API.get_access_token()') return self._access_token def make_request(self, method_request, captcha_response=None): # logger.debug('Prepare API Method request') response = self.send_api_request(method_request, captcha_response=captcha_response) # todo Replace with something less exceptional response.raise_for_status() # there are may be 2 dicts in one JSON # for example: "{'error': ...}{'response': ...}" for response_or_error in json_iter_parse(response.text): if 'response' in response_or_error: # todo Can we have error and response simultaneously # for error in errors: # logger.warning(str(error)) return response_or_error['response'] elif 'error' in response_or_error: error_data = response_or_error['error'] error = VkAPIError(error_data) if error.is_captcha_needed(): captcha_key = self.get_captcha_key(error.captcha_img) if not captcha_key: raise error captcha_response = { 'sid': error.captcha_sid, 'key': captcha_key, } return self.make_request(method_request, captcha_response=captcha_response) elif error.is_access_token_incorrect(): # logger.info('Authorization failed. Access token will be dropped') self.access_token = None return self.make_request(method_request) else: raise error def send_api_request(self, request, captcha_response=None): url = self.API_URL + request._method_name method_args = request._api._method_default_args.copy() method_args.update(stringify_values(request._method_args)) access_token = self.access_token if access_token: method_args['access_token'] = access_token if captcha_response: method_args['captcha_sid'] = captcha_response['sid'] method_args['captcha_key'] = captcha_response['key'] timeout = request._api._timeout response = self.requests_session.post(url, method_args, timeout=timeout) return response def get_captcha_key(self, captcha_image_url): """ Default behavior on CAPTCHA is to raise exception Reload this in child """ return None def auth_code_is_needed(self, content, session): """ Default behavior on 2-AUTH CODE is to raise exception Reload this in child """ raise VkAuthError('Authorization error (2-factor code is needed)') def auth_captcha_is_needed(self, content, session): """ Default behavior on CAPTCHA is to raise exception Reload this in child """ raise VkAuthError('Authorization error (captcha)') def phone_number_is_needed(self, content, session): """ Default behavior on PHONE NUMBER is to raise exception Reload this in child """ # logger.error('Authorization error (phone number is needed)') raise VkAuthError('Authorization error (phone number is needed)')
class Session(object): API_URL = 'https://api.vk.com/method/' def __init__(self, access_token=None): logger.debug('API.__init__(access_token=%(access_token)r)', {'access_token': access_token}) self.access_token = access_token self.access_token_is_needed = False self.requests_session = LoggingSession() self.requests_session.headers['Accept'] = 'application/json' self.requests_session.headers['Content-Type'] = 'application/x-www-form-urlencoded' @property def access_token(self): logger.debug('Check that we need new access token') if self.access_token_is_needed: logger.debug('We need new access token. Try to get it.') self.access_token = self.get_access_token() else: logger.debug('Use old access token') return self._access_token @access_token.setter def access_token(self, value): self._access_token = value if isinstance(value, str_type) and len(value) >= 12: self.censored_access_token = '{}***{}'.format(value[:4], value[-4:]) else: self.censored_access_token = value logger.debug('access_token = %r', self.censored_access_token) self.access_token_is_needed = not self._access_token def get_user_login(self): logger.debug('Do nothing to get user login') def get_access_token(self): """ Dummy method """ logger.debug('API.get_access_token()') return self._access_token def make_request(self, method_request, captcha_response=None): logger.debug('Prepare API Method request') response = self.send_api_request(method_request) # todo Replace with something less exceptional response.raise_for_status() # there are may be 2 dicts in one JSON # for example: "{'error': ...}{'response': ...}" for response_or_error in json_iter_parse(response.text): if 'response' in response_or_error: # todo Can we have error and response simultaneously # for error in errors: # logger.warning(str(error)) return response_or_error['response'] elif 'error' in response_or_error: error_data = response_or_error['error'] error = VkAPIError(error_data) if error.is_captcha_needed(): captcha_key = self.get_captcha_key(error.captcha_img) if not captcha_key: raise error captcha_response = { 'sid': error.captcha_sid, 'key': captcha_key, } return self.make_request(method_request, captcha_response=captcha_response) elif error.is_access_token_incorrect(): logger.info('Authorization failed. Access token will be dropped') self.access_token = None return self.make_request(method_request) else: raise error def send_api_request(self, request, captcha_response=None): url = self.API_URL + request._method_name method_args = request._api._method_default_args.copy() method_args.update(stringify_values(request._method_args)) access_token = self.access_token if access_token: method_args['access_token'] = access_token if captcha_response: method_args['captcha_sid'] = captcha_response['sid'] method_args['captcha_key'] = captcha_response['key'] timeout = request._api._timeout response = self.requests_session.post(url, method_args, timeout=timeout) return response def get_captcha_key(self, captcha_image_url): """ Default behavior on CAPTCHA is to raise exception Reload this in child """ return None def auth_code_is_needed(self, content, session): """ Default behavior on 2-AUTH CODE is to raise exception Reload this in child """ raise VkAuthError('Authorization error (2-factor code is needed)') def auth_captcha_is_needed(self, content, session): """ Default behavior on CAPTCHA is to raise exception Reload this in child """ raise VkAuthError('Authorization error (captcha)') def phone_number_is_needed(self, content, session): """ Default behavior on PHONE NUMBER is to raise exception Reload this in child """ logger.error('Authorization error (phone number is needed)') raise VkAuthError('Authorization error (phone number is needed)')
class Session(object): API_URL = 'https://api.vk.com/method/' def __init__(self, access_token=None): logger.debug('API.__init__(access_token=%(access_token)r)', {'access_token': access_token}) # self.api_version = api_version # self.default_timeout = default_timeout self.access_token = access_token self.access_token_is_needed = False # self.requests_session = requests.Session() self.requests_session = LoggingSession() self.requests_session.headers['Accept'] = 'application/json' self.requests_session.headers[ 'Content-Type'] = 'application/x-www-form-urlencoded' @property def access_token(self): logger.debug('Check that we need new access token') if self.access_token_is_needed: logger.debug('We need new access token. Try to get it.') self.access_token, self._access_token_expires_in = self.get_access_token( ) logger.info('Got new access token') logger.debug('access_token = %r, expires in %s', self.censored_access_token, self._access_token_expires_in) return self._access_token @access_token.setter def access_token(self, value): self._access_token = value self._access_token_expires_in = None self.access_token_is_needed = not self._access_token @property def censored_access_token(self): if self._access_token: return '{}***{}'.format(self._access_token[:4], self._access_token[-4:]) def get_user_login(self): logger.debug('Do nothing to get user login') def get_access_token(self): """ Dummy method """ logger.debug('API.get_access_token()') return self._access_token, self._access_token_expires_in def make_request(self, method_request, **method_kwargs): logger.debug('Prepare API Method request') response = self.send_api_request(method_request) response.raise_for_status() # there are may be 2 dicts in one JSON # for example: {'error': ...}{'response': ...} errors = [] error_codes = [] for data in json_iter_parse(response.text): if 'error' in data: error_data = data['error'] if error_data['error_code'] == CAPTCHA_IS_NEEDED: return self.on_captcha_is_needed(error_data, method_request) error_codes.append(error_data['error_code']) errors.append(error_data) if 'response' in data: for error in errors: logger.warning(str(error)) return data['response'] if AUTHORIZATION_FAILED in error_codes: # invalid access token logger.info('Authorization failed. Access token will be dropped') self.access_token = None return self.make_request(method_request) else: raise VkAPIMethodError(errors[0]) def send_api_request(self, request): url = self.API_URL + request._method_name method_args = request._api._method_default_args.copy() method_args.update(stringify_values(request._method_args)) if self.access_token: method_args['access_token'] = self.access_token timeout = request._api._timeout response = self.requests_session.post(url, method_args, timeout=timeout) return response def on_captcha_is_needed(self, error_data, method_request): """ Default behavior on CAPTCHA is to raise exception Reload this in child """ raise VkAPIMethodError(error_data) def auth_code_is_needed(self, content, session): """ Default behavior on 2-AUTH CODE is to raise exception Reload this in child """ raise VkAuthError('Authorization error (2-factor code is needed)') def auth_captcha_is_needed(self, content, session): """ Default behavior on CAPTCHA is to raise exception Reload this in child """ raise VkAuthError('Authorization error (captcha)') def phone_number_is_needed(self, content, session): """ Default behavior on PHONE NUMBER is to raise exception Reload this in child """ logger.error('Authorization error (phone number is needed)') raise VkAuthError('Authorization error (phone number is needed)')
class Session(object): API_URL = "https://api.vk.com/method/" def __init__(self, access_token=None): logger.debug("API.__init__(access_token=%(access_token)r)", {"access_token": access_token}) # self.api_version = api_version # self.default_timeout = default_timeout self.access_token = access_token self.access_token_is_needed = False # self.requests_session = requests.Session() self.requests_session = LoggingSession() self.requests_session.headers["Accept"] = "application/json" self.requests_session.headers["Content-Type"] = "application/x-www-form-urlencoded" @property def access_token(self): logger.debug("Check that we need new access token") if self.access_token_is_needed: logger.debug("We need new access token. Try to get it.") self.access_token, self._access_token_expires_in = self.get_access_token() logger.info("Got new access token") logger.debug("access_token = %r, expires in %s", self.censored_access_token, self._access_token_expires_in) return self._access_token @access_token.setter def access_token(self, value): self._access_token = value self._access_token_expires_in = None self.access_token_is_needed = not self._access_token @property def censored_access_token(self): if self._access_token: return "{}***{}".format(self._access_token[:4], self._access_token[-4:]) def get_user_login(self): logger.debug("Do nothing to get user login") def get_access_token(self): """ Dummy method """ logger.debug("API.get_access_token()") return self._access_token, self._access_token_expires_in def make_request(self, method_request, **method_kwargs): logger.debug("Prepare API Method request") response = self.send_api_request(method_request) response.raise_for_status() # there are may be 2 dicts in one JSON # for example: {'error': ...}{'response': ...} errors = [] error_codes = [] for data in json_iter_parse(response.text): if "error" in data: error_data = data["error"] if error_data["error_code"] == CAPTCHA_IS_NEEDED: return self.on_captcha_is_needed(error_data, method_request) error_codes.append(error_data["error_code"]) errors.append(error_data) if "response" in data: for error in errors: logger.warning(str(error)) return data["response"] if AUTHORIZATION_FAILED in error_codes: # invalid access token logger.info("Authorization failed. Access token will be dropped") self.access_token = None return self.make_request(method_request) else: raise VkAPIMethodError(errors[0]) def send_api_request(self, request): url = self.API_URL + request._method_name method_args = request._api._method_default_args.copy() method_args.update(stringify_values(request._method_args)) if self.access_token: method_args["access_token"] = self.access_token timeout = request._api._timeout response = self.requests_session.post(url, method_args, timeout=timeout) return response def on_captcha_is_needed(self, error_data, method_request): """ Default behavior on CAPTCHA is to raise exception Reload this in child """ raise VkAPIMethodError(error_data) def auth_code_is_needed(self, content, session): """ Default behavior on 2-AUTH CODE is to raise exception Reload this in child """ raise VkAuthError("Authorization error (2-factor code is needed)") def auth_captcha_is_needed(self, content, session): """ Default behavior on CAPTCHA is to raise exception Reload this in child """ raise VkAuthError("Authorization error (captcha)") def phone_number_is_needed(self, content, session): """ Default behavior on PHONE NUMBER is to raise exception Reload this in child """ logger.error("Authorization error (phone number is needed)") raise VkAuthError("Authorization error (phone number is needed)")