Advertisement
stuppid_bot

Untitled

Nov 30th, 2014
295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.90 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import re
  4. import sys
  5. import json
  6. import time
  7. import uuid
  8. import urllib
  9. import urllib2
  10. import mimetypes
  11. from CaptchaDialog import CaptchaDialog
  12.  
  13. class VKError(Exception):
  14.     pass
  15.  
  16. class VKValidationError(VKError):
  17.     pass
  18.  
  19. class VKCaptchaError(VKError):
  20.     pass
  21.  
  22. class VKAuthError(VKError):
  23.     def __init__(self, t, d):
  24.         super(VKAuthError, self).__init__("%s: %s" % (t, d))
  25.         self.type=t
  26.  
  27. class VKApiError(VKError):
  28.     def __init__(self, c, d):
  29.         super(VKApiError, self).__init__("[%s] %s" % (c, d))
  30.         self.code=c
  31.  
  32. DEFAULT_USER_AGENT='VKClient +https://github.com/...'
  33.  
  34. class VKClient(object):
  35.     def __init__(self, access_token=None, user_id=None,
  36.         expires=None, api_version=5.25, lang=None, default_delay=0,
  37.         user_agent=DEFAULT_USER_AGENT):
  38.         self.access_token=access_token
  39.         self.user_id=user_id
  40.         self.expires=expires
  41.         self.api_version=api_version
  42.         self.lang=lang
  43.         self.default_delay=default_delay
  44.         self.user_agent=user_agent
  45.  
  46.     def login(self, username, password, client_id=3140623,
  47.         client_secret='VeWdmVclDCtn6ihuP1nt', scope=None):
  48.         u"Прямая авторизация."
  49.         params={
  50.             'username': username,
  51.             'password': password,
  52.             'client_id': client_id,
  53.             'client_secret': client_secret,
  54.             'scope': scope,
  55.             'grant_type': 'password',
  56.             # 'test_redirect_uri': 1,
  57.         }
  58.         self.auth('token', params)
  59.  
  60.     def api(self, method, params={}, delay=None):
  61.         u"""Вызывает метод API Вконтакте."""
  62.         params=dict(params)
  63.         if not 'access_token' in params and self.access_token:
  64.             params['access_token']=self.access_token
  65.         if not 'lang' in params and self.lang:
  66.             params['lang']=self.lang
  67.         if not 'v' in params:
  68.             params['v']=self.api_version
  69.         return self.raw_api(method, params, delay)
  70.  
  71.     def auth(self, action, params):
  72.         url='https://oauth.vk.com/' + action
  73.         r=self.post(url, params)
  74.         if 'error' in r:
  75.             if 'need_validation' == r['error']:
  76.                 self.validate(r['redirect_uri'])
  77.             elif 'need_captcha' == r['error']:
  78.                 self.captcha_params(params, r['captcha_img'], r['captcha_sid'])
  79.             else:
  80.                 raise VKAuthError(r['error'], r['error_description'])
  81.             return self.auth(action, params)
  82.         self.access_token = r['access_token']
  83.         self.user_id = r.get('user_id')
  84.         if r['expires_in']:
  85.             self.expires = r['expires_in'] + time.time()
  86.  
  87.     def raw_api(self, method, params={}, delay=None):
  88.         if delay != None and self.default_delay > 0:
  89.             time.sleep(delay)
  90.         url='https://api.vk.com/method/' + method
  91.         r=self.post(url, params)
  92.         if 'response' in r:
  93.             return r['response']
  94.         error=r['error']
  95.         if error['error_code'] == 14:
  96.             self.captcha_params(params, error['captcha_img'], error['captcha_sid'])
  97.         elif error['error_code'] == 17:
  98.             self.validate(error['redirect_uri'])
  99.         else:
  100.             raise VKApiError(error['error_code'], error['error_msg'])
  101.         self.raw_api(method, params)
  102.  
  103.     def post(self, url, params):
  104.         params=self.build_params(params)
  105.         headers={'Content-Type': 'application/x-www-form-urlencoded'}
  106.         return self.get_json(url, params, headers)
  107.  
  108.     def upload(self, url, files):
  109.         u"""Загружает файлы."""
  110.         lines=[]
  111.         boundary=uuid.uuid4().hex
  112.         content_type='application/octet-stream'
  113.         for k, v in files.items():
  114.             if re.match('(?i)https?://', v, re.I):
  115.                 r=self.fetch(v)
  116.                 content_type=r.headers.get('content-type', content_type)
  117.                 data=r.read()
  118.             else:
  119.                 f=open(v, 'rb')
  120.                 data=f.read()
  121.                 f.close()
  122.                 ending=os.path.splitext(v)[1]
  123.                 content_type=mimetypes.types_map.get(ending, content_type)
  124.                 v=v.encode(sys.getfilesystemencoding())
  125.             lines.extend([
  126.                 '--' + boundary,
  127.                 'Content-Disposition: form-data; name="' + k +\
  128.                 '"; filename="' + os.path.basename(v) + '"',
  129.                 'Content-Type: ' + content_type,
  130.                 '',
  131.                 data
  132.             ])
  133.         lines.extend([
  134.             '--' + boundary + '--',
  135.             ''
  136.         ])
  137.         data='\r\n'.join(lines)
  138.         headers={'Content-Type': 'multipart/form-data; boundary=' + boundary}
  139.         return self.exec_url(url, data, headers)
  140.  
  141.     def upload_photo(self, url, filename):
  142.         u"""Загружает фото."""
  143.         return self.upload(url, {'photo': filename})
  144.  
  145.     def upload_file(self, url, filename):
  146.         return self.upload(url, {'file': filename})
  147.  
  148.     def upload_files(self, url, file_list):
  149.         u"""Загружает список файлов."""
  150.         files_dict={}
  151.         for i in range(len(file_list)):
  152.             files_dict['file%i' % (i + 1)] = file_list[i]
  153.         return self.upload(url, files_dict)
  154.  
  155.     def upload_photos(self, photo_list, album_id, group_id=None, delay=None):
  156.         u"""Грузим фотографии в альбом."""
  157.         u=self.api('photos.getUploadServer', dict(
  158.             album_id=album_id,
  159.             group_id=group_id
  160.         ), delay)['upload_url']
  161.         ret=[]
  162.         for i in range(0, len(photo_list), 5):
  163.             L=photo_list[i:i + 5]
  164.             r=self.upload_files(u, L)
  165.             # недоработка у разработчиков API
  166.             r['album_id']=r.pop('aid')
  167.             ret += self.api('photos.save', r, delay)
  168.         return ret
  169.  
  170.     # 0 - себе на стену
  171.     def upload_wall_photo(self, filename, owner_id=0, delay=None):
  172.         u"""Грузим фото на стену."""
  173.         gid=abs(owner_id) if owner_id < 1 else None
  174.         u=self.api('photos.getWallUploadServer', {
  175.             'group_id': gid
  176.         }, delay)['upload_url']
  177.         r=self.upload_photo(u, filename)
  178.         if gid:
  179.             r['group_id']=gid
  180.         elif owner_id:
  181.             r['user_id']=owner_id
  182.         return self.api('photos.saveWallPhoto', r, delay)
  183.  
  184.     def upload_owner_photo(self, filename, group_id=0, delay=None):
  185.         u"""Грузим фото на аву."""
  186.         owner_id=None
  187.         if group_id:
  188.             owner_id=-group_id
  189.         u=self.api('photos.getOwnerPhotoUploadServer', {
  190.             'owner_id': owner_id
  191.         }, delay)['upload_url']
  192.         r=self.upload_photo(u, filename)
  193.         return self.api('photos.saveOwnerPhoto', r)
  194.  
  195.     def upload_message_photo(self, filename, delay=None):
  196.         u"""Грузим фото в личное сообщение."""
  197.         u=self.api('photos.getMessagesUploadServer', {}, delay)\
  198.           ['upload_url']
  199.         r=self.upload_photo(u, filename)
  200.         return self.api('photos.saveMessagesPhoto', r, delay)
  201.  
  202.     def upload_audio(self, filename, title=None, artist=None,\
  203.         delay=None):
  204.         u"""Грузим аудиозапись."""
  205.         u=self.api('audio.getUploadServer', {}, delay)['upload_url']
  206.         r=self.upload_file(u, filename)
  207.         r['title']=title
  208.         r['artist']=artist
  209.         return self.api('audio.save', r, delay)
  210.  
  211.     def upload_doc(self, filename, group_id=None, delay=None):
  212.         u"""Грузим документ в "Документы"."""
  213.         u=self.api('docs.getUploadServer', {'group_id': group_id}, delay)\
  214.           ['upload_url']
  215.         r=self.upload_file(u, filename)
  216.         return self.api('docs.save', r, delay)
  217.  
  218.     def upload_wall_doc(self, filename, group_id=None,\
  219.         delay=None):
  220.         u"""Грузим документ на стену."""
  221.         u=self.api('docs.getWallUploadServer', {
  222.             'group_id': group_id
  223.         }, delay)['upload_url']
  224.         r=self.upload_file(u, filename)
  225.         return self.api('docs.save', r, delay)
  226.  
  227.     def upload_video(self, filename, name=None, description=None,
  228.         is_private=None, wallpost=None, group_id=None, album_id=None,
  229.         repeat=None, delay=None):
  230.         u"""Загружает и сохраняет видеофайл."""
  231.         ret={}
  232.         res=self.api('video.save', dict(
  233.             name=name,
  234.             description=description,
  235.             is_private=is_private,
  236.             wallpost=wallpost,
  237.             group_id=group_id,
  238.             album_id=album_id,
  239.             repeat=repeat
  240.         ), delay)
  241.         ret['video_id']=res['video_id']
  242.         ret['owner_id']=res['owner_id']
  243.         # содержит единственное поле 'size'
  244.         ret['size']=self.upload(res['upload_url'], {
  245.             'video_file': filename
  246.         })['size']
  247.         return ret
  248.  
  249.     def import_video(self, url, name=None, description=None, is_private=None,
  250.         wallpost=None, group_id=None, album_id=None, repeat=None, delay=None):
  251.         u"""Импортуриует видео с популярных видеохостингов типа YouTube."""
  252.         u=self.api('video.save', dict(
  253.             name=name,
  254.             description=description,
  255.             is_private=is_private,
  256.             wallpost=wallpost,
  257.             link=url,
  258.             group_id=group_id,
  259.             album_id=album_id,
  260.             repeat=repeat
  261.         ), delay)['upload_url']
  262.         return self.exec_url(u)
  263.  
  264.     def fetch(self, url, data=None, headers={}):
  265.         url=str(url) # bugfix
  266.         _headers={'User-Agent': self.user_agent}
  267.         _headers.update(headers)
  268.         r=urllib2.Request(url, data, _headers)
  269.         try:
  270.             r=urllib2.urlopen(r)
  271.         except urllib2.HTTPError as r:
  272.             pass
  273.         return r
  274.  
  275.     def get_content(self, url, headers={}):
  276.         return self.fetch(url, None, headers).read()
  277.  
  278.     def get_json(self, url, data=None, headers={}):
  279.         j=self.fetch(url, data, headers).read()
  280.         try:
  281.             j=json.loads(j)
  282.         except:
  283.             # некоторые методы отдают данные в windows-1251 вместо utf-8
  284.             j=json.loads(j, 'windows-1251')
  285.         return j
  286.  
  287.     # !Неудачное имя метода.
  288.     def exec_url(self, url, data=None, headers={}):
  289.         u"""
  290.        Возвращает response, либо бросает исключение, если в ответе есть
  291.        поле error.
  292.        """
  293.         r = self.get_json(url, data, headers)
  294.         if 'error' in r:
  295.             raise VKError(r['error'])
  296.         return r
  297.  
  298.     def build_params(self, params):
  299.         q={}
  300.         for k, v in params.items():
  301.             if v is None:
  302.                 continue
  303.             q[k]=v.encode('utf-8') if type(v) == unicode else v
  304.         return urllib.urlencode(q)
  305.  
  306.     def get_captcha_key(self, url):
  307.         u"Возвращает значение капчи."
  308.         app=CaptchaDialog(url)
  309.         app.run()
  310.         return app.captcha_code
  311.  
  312.     def captcha_params(self, params, url, sid):
  313.         u"Добавляет парамерты капчи."
  314.         params['captcha_sid']=sid
  315.         params['captcha_key']=self.get_captcha_key(url)
  316.  
  317.     def validate(self, url):
  318.         u"""
  319.        Осуществляет автоматическую валидацию пользователя при заходе из
  320.        подозрительного места.
  321.        """
  322.         s=self.get_content(url)
  323.         m=re.search(r'/security_check\?[^"]+', s)
  324.         if m:
  325.             u='https://oauth.vk.com' + m.group(0)
  326.             r=self.fetch(u)
  327.             if r.geturl() == 'https://oauth.vk.com/blank.html?success=1':
  328.                 return
  329.         raise VKValidationError('Validation failed.')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement