Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # -*- coding: utf-8 -*-
- import os
- import re
- import time
- import requests
- __author__ = "Sergey Sergeev <tz4678@gmail.com>"
- __license__ = "GNU General Public License v3"
- try:
- # Python 3
- from urllib.parse import urlparse
- is_string = lambda s: isinstance(s, str)
- except ImportError:
- # Python 2
- from urlparse import urlparse
- is_string = lambda s: isinstance(s, basestring)
- class VkClient(object):
- """Класс для работы с API Вконтакте.
- Методы API Вконтакте можно вызывать в нативном виде:
- <object VkClient>.users.get(user_id=1)
- Параметры можно паредать в виде словаря:
- <object VkClient>.users.get({'user_id': 1})
- Оба варианта анологичны такой записи:
- <object VkClient>.api('users.get', {'user_id': 1})
- См. <http://vk.com/dev/methods>
- """
- def __init__(self, access_token=None, api_version=None, api_delay=None):
- """Конструктор.
- :param access_token: Токен полученный при авторизации.
- :param api_version: Версия API Вконтакте. Об актуальной версии можно
- узнать тут <http://vk.com/dev>.
- :param api_delay: Принудительная задержка возвращения результата
- выполения метода API. Для приложений есть лимиты обращения к API
- в секунду <http://vk.com/dev/api_requests>.
- """
- self.accessToken = access_token
- self.apiVersion = api_version
- self.apiDelay = api_delay
- self.session = requests.Session()
- self.session.headers['User-Agent'] = "Mozilla 5.0 (VkClient)"
- def api(self, method, params=None):
- """Отправляет запрос к API.
- :param method: Имя метода.
- :param params: - словарь, необязательный. Параметры запроса.
- :return: Значение поля `response`.
- """
- params = dict(params) or {}
- if (not 'access_token' in params) and self.accessToken:
- params['access_token'] = self.accessToken
- if (not 'v' in params) and self.apiVersion:
- params['v'] = self.apiVersion
- if self.apiDelay:
- time.sleep(self.apiDelay)
- u = 'https://api.vk.com/method/{}'.format(method)
- r = self.session.post(u, params).json()
- if 'error' in r:
- r = r['error']
- error = VkError(r['error_msg'], r['error_code'],
- method, params, r.get('captcha_img'),
- r.get('captcha_sid'), r.get('redirect_uri'))
- if error.code == 14:
- return self.captchaHandler(error)
- elif error.code == 17:
- return self.validationHandler(error)
- raise error
- return r['response']
- def execute(self, code, **kw):
- kw['code'] = code
- return self.api('execute', kw)
- # комплексные методы вида <namespace>.<method>
- def __getattr__(self, name):
- if re.match('[a-z]+$', name):
- return ComplexMethod(self, name)
- def captchaHandler(self, error):
- raise error
- def validationHandler(self, error):
- raise error
- def upload(self, url, files):
- """Загружает файлы на сервер.
- :param url: Адрес сервера для загрузки файлов.
- :param files: Словарь, где "имя поля" => "путь до файла" (может быть
- ссылкой). Так же можно передавать кортеж или список вида
- ("имя файла", "содержимое"). На сервере проверяется расширение
- файла, mime тип не учитывается (поэтому клиентом он не передается).
- Проверяются сигнатуры файлов
- <http://en.wikipedia.org/wiki/List_of_file_signatures> при
- загрузке изображений.
- """
- files = dict(files)
- for (k, v) in files.items():
- if not is_string(v):
- continue
- filename = v
- if re.match('(?i)https?://', filename):
- content = self.session.get(filename).content
- # http://example.com/path/to/file?query -> path/to/file
- filename = urlparse(filename).path
- else:
- content = open(filename, 'rb').read()
- # path/to/file -> file
- filename = os.path.basename(filename)
- files[k] = (filename, content)
- r = self.session.post(url, files=files).json()
- if 'error' in r:
- raise VkError(r['error'])
- return r
- def uploadWallPhoto(self, photo, group_id=None):
- """Метод для тестирования загрузки фото на стену."""
- args = {'group_id': group_id} if group_id else {}
- u = self.photos.getWallUploadServer(args)['upload_url']
- r = self.upload(u, {'photo': photo})
- photos = self.photos.saveWallPhoto(r)
- # return "photo{owner_id}_{id}".format(**photos[0])
- return photos[0]
- class ComplexMethod(object):
- def __init__(self, client, prefix):
- self._client = client
- self._prefix = prefix
- def __getattr__(self, name):
- def wrapper(*arg, **kw):
- if len(arg) == 1 and isinstance(arg[0], dict):
- dict.update(arg[0], kw)
- kw = arg[0]
- return self._client.api(self._prefix + '.' + name, kw)
- # имена методов должны быть в camelCase
- if re.match('[a-z]+([A-Z][a-z]+)*$', name):
- return wrapper
- class VkError(Exception):
- def __init__(self, message=None, code=-1, method=None, params=None,
- captcha_img=None, captcha_sid=None, redirect_uri=None):
- Exception.__init__(self)
- self.code = code
- self.message = message
- self.method = method
- self.params = params
- self.captchaSid = captcha_sid
- self.captchaImg = captcha_img
- self.redirectUri = redirect_uri
- def __str__(self):
- return "[{}] {}".format(self.code, self.message)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement