stuppid_bot

Untitled

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