Advertisement
stuppid_bot

VkClient Python 2/3

Jan 14th, 2015
387
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.79 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import re
  4. import time
  5. import requests
  6.  
  7. __author__ = "Sergey Sergeev <tz4678@gmail.com>"
  8. __license__ = "GNU General Public License v3"
  9.  
  10. try:
  11.     # Python 3
  12.     from urllib.parse import urlparse
  13.     is_string = lambda s: isinstance(s, str)
  14. except ImportError:
  15.     # Python 2
  16.     from urlparse import urlparse
  17.     is_string = lambda s: isinstance(s, basestring)
  18.  
  19. class VkClient(object):
  20.     """Класс для работы с API Вконтакте.
  21.    
  22.    Методы API Вконтакте можно вызывать в нативном виде:
  23.    
  24.        <object VkClient>.users.get(user_id=1)
  25.          
  26.    Параметры можно паредать в виде словаря:
  27.    
  28.        <object VkClient>.users.get({'user_id': 1})
  29.        
  30.    Оба варианта анологичны такой записи:
  31.    
  32.        <object VkClient>.api('users.get', {'user_id': 1})
  33.        
  34.    См. <http://vk.com/dev/methods>
  35.    """  
  36.     def __init__(self, access_token=None, api_version=None, api_delay=None):
  37.         """Конструктор.
  38.        :param access_token: Токен полученный при авторизации.
  39.        
  40.        :param api_version: Версия API Вконтакте. Об актуальной версии можно
  41.            узнать тут <http://vk.com/dev>.
  42.          
  43.        :param api_delay: Принудительная задержка возвращения результата
  44.            выполения метода API. Для приложений есть лимиты обращения к API
  45.            в секунду <http://vk.com/dev/api_requests>.
  46.        """
  47.         self.accessToken = access_token
  48.         self.apiVersion = api_version
  49.         self.apiDelay = api_delay
  50.         self.session = requests.Session()
  51.         self.session.headers['User-Agent'] = "Mozilla 5.0 (VkClient)"
  52.  
  53.     def api(self, method, params=None):
  54.         """Отправляет запрос к API.
  55.        
  56.        :param method: Имя метода.
  57.        :param params: - словарь, необязательный. Параметры запроса.
  58.        :return: Значение поля `response`.
  59.        """
  60.         params = dict(params) or {}
  61.  
  62.         if (not 'access_token' in params) and self.accessToken:
  63.             params['access_token'] = self.accessToken
  64.  
  65.         if (not 'v' in params) and self.apiVersion:
  66.             params['v'] = self.apiVersion
  67.  
  68.         if self.apiDelay:
  69.             time.sleep(self.apiDelay)
  70.  
  71.         u = 'https://api.vk.com/method/{}'.format(method)  
  72.         r = self.session.post(u, params).json()
  73.  
  74.         if 'error' in r:
  75.             r = r['error']
  76.             error = VkError(r['error_msg'], r['error_code'],
  77.                             method, params, r.get('captcha_img'),
  78.                             r.get('captcha_sid'), r.get('redirect_uri'))
  79.  
  80.             if error.code == 14:
  81.                 return self.captchaHandler(error)
  82.             elif error.code == 17:
  83.                 return self.validationHandler(error)
  84.  
  85.             raise error
  86.  
  87.         return r['response']
  88.    
  89.     def execute(self, code, **kw):
  90.         kw['code'] = code
  91.         return self.api('execute', kw)
  92.  
  93.     # комплексные методы вида <namespace>.<method>
  94.     def __getattr__(self, name):
  95.         if re.match('[a-z]+$', name):
  96.             return ComplexMethod(self, name)
  97.  
  98.     def captchaHandler(self, error):
  99.         raise error
  100.  
  101.     def validationHandler(self, error):
  102.         raise error
  103.  
  104.     def upload(self, url, files):
  105.         """Загружает файлы на сервер.
  106.        
  107.        :param url: Адрес сервера для загрузки файлов.
  108.        :param files: Словарь, где "имя поля" => "путь до файла" (может быть
  109.            ссылкой). Так же можно передавать кортеж или список вида
  110.            ("имя файла", "содержимое"). На сервере проверяется расширение
  111.            файла, mime тип не учитывается (поэтому клиентом он не передается).
  112.            Проверяются сигнатуры файлов
  113.            <http://en.wikipedia.org/wiki/List_of_file_signatures> при
  114.            загрузке изображений.
  115.        """
  116.         files = dict(files)
  117.  
  118.         for (k, v) in files.items():
  119.             if not is_string(v):
  120.                 continue
  121.  
  122.             filename = v  
  123.              
  124.             if re.match('(?i)https?://', filename):
  125.                 content = self.session.get(filename).content
  126.                 # http://example.com/path/to/file?query -> path/to/file
  127.                 filename = urlparse(filename).path
  128.             else:
  129.                 content = open(filename, 'rb').read()
  130.                
  131.             # path/to/file -> file
  132.             filename = os.path.basename(filename)
  133.             files[k] = (filename, content)
  134.  
  135.         r = self.session.post(url, files=files).json()
  136.  
  137.         if 'error' in r:
  138.             raise VkError(r['error'])
  139.  
  140.         return r
  141.    
  142.     def uploadWallPhoto(self, photo, group_id=None):
  143.         """Метод для тестирования загрузки фото на стену."""
  144.         args = {'group_id': group_id} if group_id else {}
  145.         u = self.photos.getWallUploadServer(args)['upload_url']
  146.         r = self.upload(u, {'photo': photo})
  147.         photos = self.photos.saveWallPhoto(r)
  148.         # return "photo{owner_id}_{id}".format(**photos[0])
  149.         return photos[0]
  150.    
  151. class ComplexMethod(object):
  152.     def __init__(self, client, prefix):
  153.         self._client = client
  154.         self._prefix = prefix
  155.        
  156.     def __getattr__(self, name):
  157.         def wrapper(*arg, **kw):
  158.             if len(arg) == 1 and isinstance(arg[0], dict):
  159.                 dict.update(arg[0], kw)
  160.                 kw = arg[0]
  161.  
  162.             return self._client.api(self._prefix + '.' + name, kw)
  163.        
  164.         # имена методов должны быть в camelCase
  165.         if re.match('[a-z]+([A-Z][a-z]+)*$', name):
  166.             return wrapper
  167.        
  168. class VkError(Exception):
  169.     def __init__(self, message=None, code=-1, method=None, params=None,
  170.                  captcha_img=None, captcha_sid=None, redirect_uri=None):      
  171.         Exception.__init__(self)
  172.         self.code = code
  173.         self.message = message
  174.         self.method = method
  175.         self.params = params
  176.         self.captchaSid = captcha_sid
  177.         self.captchaImg = captcha_img
  178.         self.redirectUri = redirect_uri
  179.        
  180.     def __str__(self):
  181.         return "[{}] {}".format(self.code, self.message)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement