Example #1
0
    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')
Example #2
0
    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
Example #3
0
    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'
Example #4
0
    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'
Example #5
0
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)
Example #6
0
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)