def get_access_token(self): """ Get access token using app id and user login and password if no stored token provided else use stored token as access token """ if not all([self.app_id, self._login, self._password ]) and not self._stored_token: raise ValueError( 'app_id=%s, login=%s password=%s (masked) must be given' % (self.app_id, self._login, bool(self._password))) logger.info("Getting access token for user '%s'" % self._login) with VerboseHTTPSession() as s: if self._stored_token: url_query_params = {'access_token': self._stored_token} self._stored_token = None else: self.do_login(session=s) url_query_params = self.do_oauth2_authorization(session=s) logger.debug('url_query_params: %s', url_query_params) if 'access_token' in url_query_params: logger.info('Done') return url_query_params['access_token'] else: raise VkAuthError('OAuth2 authorization error')
def http_session(self): """HTTP Session property :return: vk_requests.utils.VerboseHTTPSession instance """ if self._http_session is None: session = VerboseHTTPSession() session.headers.update(self.DEFAULT_HTTP_HEADERS) self._http_session = session return self._http_session
def __init__(self, app_id=None, user_login=None, user_password=None, phone_number=None, auth_api_cls=None, **api_kwargs): self.auth_api_cls = auth_api_cls or self.DEFAULT_AUTH_API_CLS self.auth_api = self.get_auth_api(app_id=app_id, login=user_login, password=user_password, phone_number=phone_number, **api_kwargs) self.censored_access_token = None # requests.Session subclass instance self.http_session = VerboseHTTPSession() self.http_session.headers['Accept'] = 'application/json' self.http_session.headers['Content-Type'] = \ 'application/x-www-form-urlencoded'
class VKSession(object): API_URL = 'https://api.vk.com/method/' DEFAULT_AUTH_API_CLS = AuthAPI def __init__(self, app_id=None, user_login=None, user_password=None, phone_number=None, auth_api_cls=None, **api_kwargs): self.auth_api_cls = auth_api_cls or self.DEFAULT_AUTH_API_CLS self.auth_api = self.get_auth_api(app_id=app_id, login=user_login, password=user_password, phone_number=phone_number, **api_kwargs) self.censored_access_token = None # requests.Session subclass instance self.http_session = VerboseHTTPSession() self.http_session.headers['Accept'] = 'application/json' self.http_session.headers['Content-Type'] = \ 'application/x-www-form-urlencoded' def get_auth_api(self, app_id, login, password, phone_number, **api_kwargs): """Get auth api instance""" if not issubclass(self.auth_api_cls, BaseAuthAPI): raise TypeError('Wrong AUTH_API_CLS %s, must be subclass of %s' % ( self.auth_api_cls, BaseAuthAPI.__name__, )) return self.auth_api_cls(app_id=app_id, user_login=login, user_password=password, phone_number=phone_number, **api_kwargs) @property def access_token(self): return self.auth_api.access_token @access_token.setter def access_token(self, value): self.auth_api._access_token = value if isinstance(value, six.string_types) 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) def make_request(self, request_obj, captcha_response=None): logger.debug('Prepare API Method request %r', request_obj) response = self.send_api_request(request=request_obj, captcha_response=captcha_response) 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 'error' in response_or_error: error_data = response_or_error['error'] vk_error = VkAPIError(error_data) if vk_error.is_captcha_needed(): captcha_key = self.auth_api.get_captcha_key( vk_error.captcha_img) if not captcha_key: raise vk_error captcha_response = { 'sid': vk_error.captcha_sid, 'key': captcha_key, } return self.make_request(request_obj, captcha_response=captcha_response) elif vk_error.is_access_token_incorrect(): logger.info( 'Authorization failed. Access token will be dropped') self.access_token = None return self.make_request(request_obj) else: raise vk_error elif 'execute_errors' in response_or_error: # can take place while running .execute vk method # See more: https://vk.com/dev/execute raise VkAPIError(response_or_error['execute_errors'][0]) elif 'response' in response_or_error: return response_or_error['response'] def send_api_request(self, request, captcha_response=None): url = self.API_URL + request.get_method_name() vk_api = request.get_api() # Prepare request arguments method_kwargs = {'v': self.auth_api.api_version} for values in (vk_api.get_default_kwargs(), request.get_method_args()): method_kwargs.update(stringify_values(values)) if self.auth_api.is_token_required(): # Auth api call if access_token weren't be got earlier method_kwargs['access_token'] = self.access_token if captcha_response: method_kwargs['captcha_sid'] = captcha_response['sid'] method_kwargs['captcha_key'] = captcha_response['key'] response = self.http_session.post(url=url, data=method_kwargs, timeout=vk_api.get_timeout()) return response def __repr__(self): # pragma: no cover return "%s(api_url='%s', access_token='%s')" % ( self.__class__.__name__, self.API_URL, self.auth_api._access_token)
class VKSession(object): API_URL = 'https://api.vk.com/method/' DEFAULT_AUTH_API_CLS = AuthAPI def __init__(self, app_id=None, user_login=None, user_password=None, phone_number=None, auth_api_cls=None, **api_kwargs): self.auth_api_cls = auth_api_cls or self.DEFAULT_AUTH_API_CLS self.auth_api = self.get_auth_api(app_id=app_id, login=user_login, password=user_password, phone_number=phone_number, **api_kwargs) self.censored_access_token = None # requests.Session subclass instance self.http_session = VerboseHTTPSession() self.http_session.headers['Accept'] = 'application/json' self.http_session.headers['Content-Type'] = \ 'application/x-www-form-urlencoded' def get_auth_api(self, app_id, login, password, phone_number, **api_kwargs): """Get auth api instance""" if not issubclass(self.auth_api_cls, BaseAuthAPI): raise TypeError( 'Wrong AUTH_API_CLS %s, must be subclass of %s' % (self.auth_api_cls, BaseAuthAPI.__name__, )) return self.auth_api_cls(app_id=app_id, user_login=login, user_password=password, phone_number=phone_number, **api_kwargs) @property def access_token(self): return self.auth_api.access_token @access_token.setter def access_token(self, value): self.auth_api._access_token = value if isinstance(value, six.string_types) 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) def make_request(self, request_obj, captcha_response=None): logger.debug('Prepare API Method request %r', request_obj) response = self.send_api_request(request=request_obj, captcha_response=captcha_response) 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 'error' in response_or_error: error_data = response_or_error['error'] vk_error = VkAPIError(error_data) if vk_error.is_captcha_needed(): captcha_key = self.auth_api.get_captcha_key( vk_error.captcha_img) if not captcha_key: raise vk_error captcha_response = { 'sid': vk_error.captcha_sid, 'key': captcha_key, } return self.make_request( request_obj, captcha_response=captcha_response) elif vk_error.is_access_token_incorrect(): logger.info( 'Authorization failed. Access token will be dropped') self.access_token = None return self.make_request(request_obj) else: raise vk_error elif 'execute_errors' in response_or_error: # can take place while running .execute vk method # See more: https://vk.com/dev/execute raise VkAPIError(response_or_error['execute_errors'][0]) elif 'response' in response_or_error: return response_or_error['response'] def send_api_request(self, request, captcha_response=None): url = self.API_URL + request.get_method_name() vk_api = request.get_api() # Prepare request arguments method_kwargs = {'v': self.auth_api.api_version} for values in (vk_api.get_default_kwargs(), request.get_method_args()): method_kwargs.update(stringify_values(values)) if self.auth_api.is_token_required(): # Auth api call if access_token weren't be got earlier method_kwargs['access_token'] = self.access_token if captcha_response: method_kwargs['captcha_sid'] = captcha_response['sid'] method_kwargs['captcha_key'] = captcha_response['key'] response = self.http_session.post( url=url, data=method_kwargs, timeout=vk_api.get_timeout()) return response def __repr__(self): return "%s(api_url='%s', access_token='%s')" % ( self.__class__.__name__, self.API_URL, self.auth_api._access_token)