diff --git a/addon.xml b/addon.xml
index 08a355c..42aaab2 100644
--- a/addon.xml
+++ b/addon.xml
@@ -1,8 +1,8 @@
-
+
-
-
+
+
@@ -13,7 +13,7 @@
vk.com API Python wrapper
Based on code taken from https://pypi.python.org/pypi/vk/
GPLv3
- https://github.com/inpos/script.module.vk
-
+ https://git.ukamnya.ru/ukamnya/script.module.vk
+
-
\ No newline at end of file
+
diff --git a/lib/vk/__init__.py b/lib/vk/__init__.py
index 052fb16..42caa51 100644
--- a/lib/vk/__init__.py
+++ b/lib/vk/__init__.py
@@ -1,9 +1,5 @@
+from .session import API, UserAPI, CommunityAPI
-from vk.api import logger
-from vk.api import Session, AuthSession, InteractiveSession, InteractiveAuthSession
-from vk.api import VERSION
-from vk.api import API
+__version__ = '3.0-dev'
-__version__ = version = VERSION
-
-# API = OAuthAPI
+__all__ = (API, UserAPI, CommunityAPI)
diff --git a/lib/vk/__init__.pyc b/lib/vk/__init__.pyc
deleted file mode 100644
index e903b48..0000000
Binary files a/lib/vk/__init__.pyc and /dev/null differ
diff --git a/lib/vk/api.py b/lib/vk/api.py
index b51b9cb..13bf503 100644
--- a/lib/vk/api.py
+++ b/lib/vk/api.py
@@ -1,185 +1,38 @@
-# coding=utf8
-
import logging
-import logging.config
-from vk.logs import LOGGING_CONFIG
-from vk.utils import stringify_values, json_iter_parse, LoggingSession, str_type
-from vk.exceptions import VkAuthError, VkAPIError
-from vk.mixins import AuthMixin, InteractiveMixin
-from sys import version_info
+from vk.utils import stringify_values
-VERSION = '2.0.2'
-
-if version_info[0] >= 2 and version_info[1] >= 7: # http://xbmc.ru/forum/showpost.php?p=107619&postcount=20
- logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger('vk')
-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 = '{0}***{1}'.format(value[:4], value[-4:]) # http://xbmc.ru/forum/showpost.php?p=107619&postcount=20
- 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, 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 API(object):
- def __init__(self, session, timeout=10, **method_default_args):
- self._session = session
- self._timeout = timeout
- self._method_default_args = method_default_args
-
- def __getattr__(self, method_name):
- return Request(self, method_name)
-
- def __call__(self, method_name, **method_kwargs):
- return getattr(self, method_name)(**method_kwargs)
-
-
-class Request(object):
- __slots__ = ('_api', '_method_name', '_method_args')
-
- def __init__(self, api, method_name):
+class APINamespace:
+ def __init__(self, api, method_common_params):
self._api = api
- self._method_name = method_name
+ self._method_common_params = method_common_params
- def __getattr__(self, method_name):
- return Request(self._api, self._method_name + '.' + method_name)
+ def __call__(self, method):
+ return APIMethod(self._api, method, self._method_common_params)
- def __call__(self, **method_args):
- self._method_args = method_args
- return self._api._session.make_request(self)
+ __getattr__ = __call__
-class AuthSession(AuthMixin, Session):
- pass
+class APIMethod:
+ def __init__(self, api, method, method_common_params):
+ self._api = api
+ self._method = method
+ self._method_common_params = method_common_params
+
+ def __getattr__(self, method):
+ return self.__class__(self._api, self._method + '.' + method, self._method_common_params)
+
+ def __call__(self, **method_params):
+ request_method_params = self._method_common_params.copy()
+ request_method_params.update(stringify_values(method_params))
+
+ return self._api.send(APIRequest(self._method, request_method_params))
-class InteractiveSession(InteractiveMixin, Session):
- pass
-
-
-class InteractiveAuthSession(InteractiveMixin, AuthSession):
- pass
+class APIRequest:
+ def __init__(self, method, method_params):
+ self.method = method
+ self.method_params = method_params
diff --git a/lib/vk/api.pyc b/lib/vk/api.pyc
deleted file mode 100644
index d57dad0..0000000
Binary files a/lib/vk/api.pyc and /dev/null differ
diff --git a/lib/vk/exceptions.py b/lib/vk/exceptions.py
index 19987fa..c5763dc 100644
--- a/lib/vk/exceptions.py
+++ b/lib/vk/exceptions.py
@@ -4,8 +4,7 @@ AUTHORIZATION_FAILED = 5 # Invalid access token
PERMISSION_IS_DENIED = 7
CAPTCHA_IS_NEEDED = 14
ACCESS_DENIED = 15 # No access to call this method
- # User deactivated
-INVALID_USER_ID = 113
+INVALID_USER_ID = 113 # User deactivated
class VkException(Exception):
@@ -33,7 +32,7 @@ class VkAPIError(VkException):
@staticmethod
def get_pretty_request_params(error_data):
request_params = error_data.get('request_params', ())
- request_params = dict((param['key'], param['value']) for param in request_params) # http://xbmc.ru/forum/showpost.php?p=107615&postcount=16
+ request_params = {param['key']: param['value'] for param in request_params}
return request_params
def is_access_token_incorrect(self):
diff --git a/lib/vk/exceptions.pyc b/lib/vk/exceptions.pyc
deleted file mode 100644
index fe7e690..0000000
Binary files a/lib/vk/exceptions.pyc and /dev/null differ
diff --git a/lib/vk/logs.py b/lib/vk/logs.py
deleted file mode 100644
index 2a8cc35..0000000
--- a/lib/vk/logs.py
+++ /dev/null
@@ -1,27 +0,0 @@
-
-import sys
-
-
-LOGGING_CONFIG = {
- 'version': 1,
- 'disable_existing_loggers': False,
- 'loggers': {
- 'vk': {
- 'level': 'INFO',
- 'handlers': ['vk-stdout'],
- 'propagate': False,
- },
- },
- 'handlers': {
- 'vk-stdout': {
- 'class': 'logging.StreamHandler',
- 'stream': sys.stdout,
- 'formatter': 'vk-verbose',
- },
- },
- 'formatters': {
- 'vk-verbose': {
- 'format': '%(asctime)s %(name) -5s %(module)s:%(lineno)d %(levelname)s: %(message)s',
- },
- },
-}
diff --git a/lib/vk/logs.pyc b/lib/vk/logs.pyc
deleted file mode 100644
index 6aaeb57..0000000
Binary files a/lib/vk/logs.pyc and /dev/null differ
diff --git a/lib/vk/mixins.py b/lib/vk/mixins.py
deleted file mode 100644
index f8c40a4..0000000
--- a/lib/vk/mixins.py
+++ /dev/null
@@ -1,218 +0,0 @@
-# coding=utf8
-
-import logging
-
-from vk.exceptions import VkAuthError
-from vk.utils import raw_input, get_url_query, LoggingSession, get_form_action
-
-
-logger = logging.getLogger('vk')
-
-
-class AuthMixin(object):
- LOGIN_URL = 'https://m.vk.com'
- # REDIRECT_URI = 'https://oauth.vk.com/blank.html'
- AUTHORIZE_URL = 'https://oauth.vk.com/authorize'
- CAPTCHA_URI = 'https://m.vk.com/captcha.php'
-
- def __init__(self, app_id=None, user_login='', user_password='', scope='offline', **kwargs):
- logger.debug('AuthMixin.__init__(app_id=%(app_id)r, user_login=%(user_login)r, user_password=%(user_password)r, **kwargs=%(kwargs)s)',
- dict(app_id=app_id, user_login=user_login, user_password=user_password, kwargs=kwargs))
-
- super(AuthMixin, self).__init__(**kwargs)
-
- self.app_id = app_id
- self.user_login = user_login
- self.user_password = user_password
- self.scope = scope
-
- # Some API methods get args (e.g. user id) from access token.
- # If we define user login, we need get access token now.
- if self.user_login:
- self.access_token = self.get_access_token()
-
- @property
- def user_login(self):
- if not self._user_login:
- self._user_login = self.get_user_login()
- return self._user_login
-
- @user_login.setter
- def user_login(self, value):
- self._user_login = value
-
- def get_user_login(self):
- return self._user_login
-
- @property
- def user_password(self):
- if not self._user_password:
- self._user_password = self.get_user_password()
- return self._user_password
-
- @user_password.setter
- def user_password(self, value):
- self._user_password = value
-
- def get_user_password(self):
- return self._user_password
-
- def get_access_token(self):
- """
- Get access token using app id and user login and password.
- """
- logger.debug('AuthMixin.get_access_token()')
-
- auth_session = LoggingSession()
- with auth_session as self.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')
-
- def login(self):
- """
- Login
- """
-
- response = self.auth_session.get(self.LOGIN_URL)
- login_form_action = get_form_action(response.text)
- if not login_form_action:
- raise VkAuthError('VK changed login flow')
-
- login_form_data = {
- 'email': self.user_login,
- 'pass': self.user_password,
- }
- response = self.auth_session.post(login_form_action, login_form_data)
- logger.debug('Cookies: %s', self.auth_session.cookies)
-
- response_url_query = get_url_query(response.url)
-
- if 'remixsid' in self.auth_session.cookies or 'remixsid6' in self.auth_session.cookies:
- return
-
- if 'sid' in response_url_query:
- self.auth_captcha_is_needed(response, login_form_data)
- elif response_url_query.get('act') == 'authcheck':
- self.auth_check_is_needed(response.text)
- elif 'security_check' in response_url_query:
- self.phone_number_is_needed(response.text)
- else:
- message = 'Authorization error (incorrect password)'
- logger.error(message)
- raise VkAuthError(message)
-
- def oauth2_authorization(self):
- """
- OAuth2
- """
- auth_data = {
- 'client_id': self.app_id,
- 'display': 'mobile',
- 'response_type': 'token',
- 'scope': self.scope,
- 'v': '5.28',
- }
- response = self.auth_session.post(self.AUTHORIZE_URL, auth_data)
- response_url_query = get_url_query(response.url)
- if 'access_token' in response_url_query:
- return response_url_query
-
- # Permissions is needed
- logger.info('Getting permissions')
- # form_action = re.findall(r'