Advertisement
stuppid_bot

Untitled

Mar 13th, 2014
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.95 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. # Модуль для работы с API Вконтакте. Список методов API можно увидеть здесь https://vk.com/dev/methods.
  3. #
  4. # @author tz4678@gmail.com
  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.         # print response.info().getheader('Content-Type')
  44.         content = response.read().decode('utf-8')
  45.         # print content
  46.         return json.loads(content)
  47.  
  48.     # переопределяем метод при необходимости
  49.     def captcha_handler(self, url):
  50.         raise VkNeedCaptcha('Captcha is needed')
  51.  
  52.     def captcha_params(self, params, response):
  53.         params.update({
  54.             'captcha_key': self.captcha_handler(response['captcha_img']),
  55.             'captcha_sid': response['captcha_sid']
  56.         })
  57.  
  58.     def _auth(self, params):
  59.         defaults = {
  60.             'client_id': self.client_id,
  61.             'client_secret': self.client_secret,
  62.             'scope': self.permissions,
  63.             'v': self.api_version,
  64.             'grant_type': 'password'
  65.         }
  66.         defaults.update(params)
  67.         params = defaults
  68.         result = self.fetch_json('https://oauth.vk.com/token?' + urllib.urlencode(params))
  69.         if 'error' in result:
  70.             if result['error'] == 'need_captcha':
  71.                 self.captcha_params(params, result)
  72.                 return self._auth(params)
  73.             raise VkAuthError('%s. Error Description: %s' % (result['error'], result.get('error_description', '')))
  74.         self.user_id = result['user_id']
  75.         self.access_token = result['access_token']
  76.  
  77.     def auth(self, login, password):
  78.         self._auth({'username': login.encode('utf8'), 'password': password.encode('utf8')})
  79.  
  80.     def raw_api(self, method, params = {}):
  81.         # print params
  82.         headers = {}
  83.         if len(params):
  84.             for k, v in params.items():
  85.                 if type(v) == unicode:
  86.                     params[k] = v.encode('utf-8')
  87.             headers['Content-Type'] = 'application/x-www-form-urlencoded'
  88.         data = urllib.urlencode(params) if len(params) else None
  89.         # print data
  90.         result = self.fetch_json('https://api.vk.com/method/' + method, data, headers)
  91.         if 'error' in result:
  92.             result = result['error']
  93.             if result['error_code'] == 14:
  94.                 self.captcha_params(params, result)
  95.                 return self.raw_api(method, params)
  96.             elif result['error_code'] == 5:
  97.                 raise VkAuthFailed(result['error_msg'])
  98.             raise VkApiError(result['error_msg'])
  99.         return result['response']
  100.  
  101.     def api(self, method, params = {}):
  102.         params.setdefault('access_token', self.access_token)
  103.         params.setdefault('v', self.api_version)
  104.         return self.raw_api(method, params)
  105.  
  106.     def escape_quote(self, s):
  107.         return s.replace('"', '\\"')
  108.  
  109.     def upload(self, upload_url, files):
  110.         boundary = '--VkClientBoundary_' + uuid.uuid4().hex
  111.         encoding = sys.getfilesystemencoding()
  112.         L = []
  113.         for fieldname, filename in files.items():
  114.             extension = os.path.splitext(filename)[1]
  115.             content_type = mimetypes.types_map[extension] if extension in mimetypes.types_map else 'application/octet-stream'
  116.             basename = os.path.basename(filename).encode(encoding)
  117.             L.extend([
  118.                 '--' + boundary,
  119.                 'Content-Disposition: form-data; name="%s"; filename="%s"' % (self.escape_quote(fieldname), basename),
  120.                 'Content-Type: ' + content_type,
  121.                 '',
  122.                 open(filename.encode(encoding), 'rb').read()
  123.             ])
  124.         L.extend([
  125.             '--' + boundary + '--',
  126.             ''
  127.         ])
  128.         headers = {
  129.             'Content-Type': 'multipart/form-data; boundary="%s"' % boundary,
  130.         }
  131.         data = '\r\n'.join(L)
  132.         result = self.fetch_json(upload_url, data, headers)
  133.         if 'error' in result:
  134.             raise VkUploadError(result['error'])
  135.         return result
  136.  
  137.     def filesdict(self, L):
  138.         out = {}
  139.         i = len(L)
  140.         while i:
  141.             out['file%s' % i] = L[i - 1]
  142.             i -= 1
  143.         return out
  144.  
  145.     def upload_photos(self, images, album_id, group_id = None):
  146.         params = {'album_id': album_id}
  147.         if group_id is not None:
  148.             params['group_id'] = group_id
  149.         server = self.api('photos.getUploadServer', params)
  150.         i = 0
  151.         total = len(images)
  152.         while i < total:
  153.             # только пять изображений можно загрузить за раз?
  154.             limit = i + 5
  155.             files = self.filesdict(images[i:limit])
  156.             r = self.upload(server['upload_url'], files)
  157.             # не все изменения в API документируются
  158.             if not 'album_id' in r:        
  159.                 r['album_id'] = r['aid']
  160.                 del r['aid']
  161.             self.api('photos.save', r)
  162.             i = limit
  163.  
  164.     # еще методы для загрузки
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement