Advertisement
stuppid_bot

Untitled

Dec 18th, 2013
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.93 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.encode('utf8'), 'password': password.encode('utf8')})
  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 escape_quote(self, s):
  106.         return s.replace('"', '\\"')
  107.  
  108.     def upload(self, upload_url, files):
  109.         boundary = '--VkClientBoundary_' + uuid.uuid4().hex
  110.         encoding = sys.getfilesystemencoding()
  111.         L = []
  112.         for fieldname, filename in files.items():
  113.             extension = os.path.splitext(filename)[1]
  114.             content_type = mimetypes.types_map[extension] if extension in mimetypes.types_map else 'application/octet-stream'
  115.             basename = os.path.basename(filename).encode(encoding)
  116.             L.extend([
  117.                 '--' + boundary,
  118.                 'Content-Disposition: form-data; name="%s"; filename="%s"' % (self.escape_quote(fieldname), basename),
  119.                 'Content-Type: ' + content_type,
  120.                 '',
  121.                 open(filename.encode(encoding), 'rb').read()
  122.             ])
  123.         L.extend([
  124.             '--' + boundary + '--',
  125.             ''
  126.         ])
  127.         headers = {
  128.             'Content-Type': 'multipart/form-data; boundary="%s"' % boundary,
  129.         }
  130.         data = '\r\n'.join(L)
  131.         result = self.fetch_json(upload_url, data, headers)
  132.         if 'error' in result:
  133.             raise VkUploadError(result['error'])
  134.         return result
  135.  
  136.     def filesdict(self, L):
  137.         out = {}
  138.         i = len(L)
  139.         while i:
  140.             out['file%s' % i] = L[i - 1]
  141.             i -= 1
  142.         return out
  143.  
  144.     def upload_photos(self, images, album_id, group_id = None):
  145.         params = {'album_id': album_id}
  146.         if group_id is not None:
  147.             params['group_id'] = group_id
  148.         server = self.api('photos.getUploadServer', params)
  149.         i = 0
  150.         total = len(images)
  151.         while i < total:
  152.             # только пять изображений можно загрузить за раз?
  153.             limit = i + 5
  154.             files = self.filesdict(images[i:limit])
  155.             r = self.upload(server['upload_url'], files)
  156.             # не все изменения в API документируются
  157.             if not 'album_id' in r:        
  158.                 r['album_id'] = r['aid']
  159.                 del r['aid']
  160.             self.api('photos.save', r)
  161.             i = limit
  162.  
  163.     # еще методы для загрузки
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement