Advertisement
stuppid_bot

VkPy

Nov 21st, 2013
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.60 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. # @author: noname <tz4678@gmail.com>
  3. # @description: модуль для работы с API Вконтакте
  4. # Полный список методов API можно увидеть здесь https://vk.com/dev/methods
  5. import sys
  6. import json
  7. import urllib2
  8. import urllib
  9. import uuid
  10. import os
  11. import mimetypes
  12.  
  13. class VkNeedCaptcha(Exception):
  14.     pass
  15.  
  16. class VkAuthError(Exception):
  17.     pass
  18.  
  19. class VkAuthFailed(Exception):
  20.     pass
  21.  
  22. class VkApiError(Exception):
  23.     pass
  24.  
  25. class VkUploadError(Exception):
  26.     pass
  27.  
  28. class VkClient(object):
  29.     def __init__(self, client_id, client_secret, permissions, api_version):
  30.         self.client_id = client_id
  31.         self.client_secret = client_secret
  32.         self.permissions = permissions
  33.         self.api_version = api_version
  34.         self.user_agent = 'VkClient (Python %s.%s.%s)' % sys.version_info[:3]
  35.         self.user_id = None
  36.         self.access_token = None
  37.  
  38.     def fetch_json(self, url, data = None, headers = {}):
  39.         url = str(url)
  40.         headers.setdefault('User-Agent', self.user_agent)
  41.         request = urllib2.Request(url, data, headers)
  42.         response = urllib2.urlopen(request);
  43.         content = response.read().decode('utf-8')
  44.         # print content
  45.         return json.loads(content)
  46.  
  47.     # переопределяем метод при необходимости
  48.     def captcha_handler(self, url):
  49.         raise VkNeedCaptcha('Captcha is needed')
  50.  
  51.     def captcha_params(self, params, response):
  52.         params.update({
  53.             'captcha_key': self.captcha_handler(response['captcha_img']),
  54.             'captcha_sid': response['captcha_sid']
  55.         })
  56.  
  57.     def _auth(self, params):
  58.         defaults = {
  59.             'client_id': self.client_id,
  60.             'client_secret': self.client_secret,
  61.             'scope': self.permissions,
  62.             'v': self.api_version,
  63.             'grant_type': 'password'
  64.         }
  65.         defaults.update(params)
  66.         params = defaults
  67.         result = self.fetch_json('https://oauth.vk.com/token?' + urllib.urlencode(params))
  68.         if 'error' in result:
  69.             if result['error'] == 'need_captcha':
  70.                 self.captcha_params(params, result)
  71.                 return self._auth(params)
  72.             raise VkAuthError('%s. Error Description: %s' % (result['error'], result.get('error_description', '')))
  73.         self.user_id = result['user_id']
  74.         self.access_token = result['access_token']
  75.  
  76.     def auth(self, login, password):
  77.         self._auth({'username': login, 'password': password})
  78.  
  79.     def raw_api(self, method, params = {}):
  80.         # print params
  81.         headers = {}
  82.         if len(params):
  83.             for k, v in params.items():
  84.                 if type(v) == unicode:
  85.                     params[k] = v.encode('utf-8')
  86.             headers['Content-Type'] = 'application/x-www-form-urlencoded'
  87.         data = urllib.urlencode(params) if len(params) else None
  88.         # print data
  89.         result = self.fetch_json('https://api.vk.com/method/' + method, data, headers)
  90.         if 'error' in result:
  91.             result = result['error']
  92.             if result['error_code'] == 14:
  93.                 self.captcha_params(params, result)
  94.                 return self.raw_api(method, params)
  95.             elif result['error_code'] == 5:
  96.                 raise VkAuthFailed(result['error_msg'])
  97.             raise VkApiError(result['error_msg'])
  98.         return result['response']
  99.  
  100.     def api(self, method, params = {}):
  101.         params.setdefault('access_token', self.access_token)
  102.         params.setdefault('v', self.api_version)
  103.         return self.raw_api(method, params)
  104.  
  105.     def search(self, method_type, q, count, offset = 0, extra = {}, **kwrags):
  106.         params = {
  107.             'q': q,
  108.             'count': count,
  109.             'offset': offset
  110.         }
  111.         extra.update(params)
  112.         params = extra
  113.         return self.api('%s.search' % method_type, params)
  114.  
  115.     def searchiter(self, method_type, q, count, offset = 0, extra = {}, **kwrags):
  116.         while True:
  117.             result = self.search(method_type, q, count, offset, extra)
  118.             offset += count
  119.             # некоторые методы не отдают больше 1000 результатов
  120.             if len(items) == 0 or offset >= result['count']:
  121.                 break
  122.             yield result
  123.  
  124.     def escape_quote(self, s):
  125.         return s.replace('"', '\\"')
  126.  
  127.     def upload(self, upload_url, files):
  128.         boundary = '--VkClientBoundary_' + uuid.uuid4().hex
  129.         encoding = sys.getfilesystemencoding()
  130.         L = []
  131.         for fieldname, filename in files.items():
  132.             extension = os.path.splitext(filename)[1]
  133.             content_type = mimetypes.types_map[extension] if extension in mimetypes.types_map else 'application/octet-stream'
  134.             basename = os.path.basename(filename).encode(encoding)
  135.             L.extend([
  136.                 '--' + boundary,
  137.                 'Content-Disposition: form-data; name="%s"; filename="%s"' % (self.escape_quote(fieldname), basename),
  138.                 'Content-Type: ' + content_type,
  139.                 '',
  140.                 open(filename.encode(encoding), 'rb').read()
  141.             ])
  142.         L.extend([
  143.             '--' + boundary + '--',
  144.             ''
  145.         ])
  146.         headers = {
  147.             'Content-Type': 'multipart/form-data; boundary="%s"' % boundary,
  148.         }
  149.         data = '\r\n'.join(L)
  150.         result = self.fetch_json(upload_url, data, headers)
  151.         if 'error' in result:
  152.             raise VkUploadError(result['error'])
  153.         return result
  154.  
  155.     def filesdict(self, L):
  156.         out = {}
  157.         i = len(L)
  158.         while i:
  159.             out['file%s' % i] = L[i - 1]
  160.             i -= 1
  161.         return out
  162.  
  163.     # TODO: доделать
  164.     def upload_photos(self, images, album_id, group_id = None):
  165.         params = {'album_id': album_id}
  166.         server = self.api('photos.getUploadServer', params)
  167.         i = 0
  168.         total = len(images)
  169.         while i < total:
  170.             # только пять изображений можно загрузить за раз?
  171.             limit = i + 5
  172.             files = self.filesdict(images[i:limit])
  173.             r = self.upload(server['upload_url'], files)
  174.             # вместо aid нужно отправлять album_id, только в документации к API об этом написать забыли!!!
  175.             r['album_id'] = r['aid']
  176.             del r['aid']
  177.             self.api('photos.save', r)
  178.             i = limit
  179.  
  180.     # еще методы для загрузки
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement