~roignac/gwibber/vkontakte-ru-plugin-cleanup

« back to all changes in this revision

Viewing changes to gwibber/microblog/plugins/vkontakte/vk_api_wrapper.py

  • Committer: Vadim Rutkovsky
  • Date: 2011-12-20 10:41:31 UTC
  • Revision ID: roignac@gmail.com-20111220104131-6q6z3ps845b1skv0
Cleaning up vkontakte-plugin branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
'''
 
3
Created on 07.12.2010
 
4
 
 
5
@author: Sergey Prokhorov <root@seriyps.ru>
 
6
'''
 
7
from gwibber.microblog import network
 
8
from gwibber.microblog.util import log
 
9
import urllib
 
10
import time
 
11
 
 
12
class vkException(Exception):
 
13
 
 
14
  def __init__(self, code, msg, url, response):
 
15
    self.code=code
 
16
    self.msg=msg
 
17
    self.response=response
 
18
    self.url=url
 
19
    Exception.__init__(self, code, msg, url, response)
 
20
 
 
21
 
 
22
class vk_api:
 
23
  """Vkontakte.ru (vk.com) API wrapper for Gwibber
 
24
  == Usage ==
 
25
  Initialization:
 
26
    api=vk_api(access_token)
 
27
    "access_token" can be retrieved from call to http://api.vkontakte.ru/oauth/authorize
 
28
    (see http://vkontakte.ru/developers.php?o=-1&p=%C0%E2%F2%EE%F0%E8%E7%E0%F6%E8%FF%20%EA%EB%E8%E5%ED%F2%F1%EA%E8%F5%20%EF%F0%E8%EB%EE%E6%E5%ED%E8%E9)
 
29
  Make calls to simple methods (has no dots in name, like "getProfiles", "isAppUser"):
 
30
    res=api.method(arg_name1=arg1, arg_name2=arg2)
 
31
    eg res=api.getProfiles(uids="535397,1", fields="uid,first_name,last_name")
 
32
  Make calls to namespaced methods (has dots in name, like "wall.post", "newsfeed.get"):
 
33
    res=api.namespace.method(arg_name1=arg1, arg_name2=arg2)
 
34
    eg res=api.wall.post(message="New wall post from API")
 
35
  Alternative call syntax (better performance):
 
36
    res=api._load('namespace.method', arg_name1=arg1, arg_name2=arg2)
 
37
    eg res=api._get('wall.post', message="New wall post from API")
 
38
  """
 
39
 
 
40
  api_url='https://api.vkontakte.ru/method/%s'
 
41
 
 
42
  def __init__(self, access_token):
 
43
    self._access_token=access_token
 
44
    self._prefix=[]
 
45
 
 
46
  def _load(self, method, **params):
 
47
    """Make call by method name and arguments"""
 
48
    params["access_token"]=self._access_token
 
49
    url=self.api_url%method
 
50
    for _i in xrange(3):#this cycle used for API error #6 "Too many requests"
 
51
      log.logger.debug("Perform API request to method %s. URL: %s?%s", method, url, urllib.urlencode(params))
 
52
      res=network.Download(url, params, False).get_json()
 
53
      if not res.has_key("error"):
 
54
        #log.logger.debug("%s"%res)
 
55
        return res
 
56
 
 
57
      if res["error"]["error_code"]!=6:
 
58
        break
 
59
      log.logging.warning('Error #6 "%s". Wait 0.5s and retry...', res["error"]["error_msg"])
 
60
      '''if we get error #6 "Too many requests per second" (vk allow
 
61
      max 3rps http://vkontakte.ru/developers.php?o=-1&p=%D0%92%D0%B7%D0%B0%D0%B8%D0%BC%D0%BE%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D0%B5+%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F+%D1%81+API )
 
62
      try to sleep with small delay and retry request not more then 3x times'''
 
63
      time.sleep(0.5)#TODO: play with sleep value
 
64
    raise vkException(res["error"]["error_code"],
 
65
                          res["error"]["error_msg"],
 
66
                          "%s?%s"%(url, urllib.urlencode(params)),
 
67
                          res)
 
68
 
 
69
 
 
70
  """Support for api.namespace.method(**kwargs) calls below"""
 
71
  def __getattr__(self, name):
 
72
    self._prefix.append(name)
 
73
    return self
 
74
 
 
75
  def __call__(self, **kwargs):
 
76
    if self._prefix:
 
77
      method=".".join(self._prefix)
 
78
      self._prefix=[]
 
79
    else:
 
80
      method=kwargs.pop("method")
 
81
    return self._load(method, **kwargs)