Source

VkApi / api.py

Full commit
#!/usr/bin/python
# -*- coding:utf-8 -*-

import json
import urllib2

# class VkAudioFile(object):
#     """Represents VK audio file
#     """
    
#     def __init__(self, p):
#         """
#         """

# class VkMainObject(object):
#     """Provides _sid"""
#     def __init__(self, sid):
#         self._sid = sid

class dummy:   # Just for convenience
    pass     

def json_vk_load(data):
    """A little helper to load data from userapi"""
    return json.load(urllib2.urlopen(r"http://userapi.com/data", data=data))

def vk_request(sid, *args, **kwargs):
    s = ''
    for arg in kwargs:
        if kwargs[arg].__class__ != dummy:    # That's a trick
            s = s + '%s=%s&' %(arg.lower(), kwargs[arg])  # lower is for allowing "reserved" keywords as keys
            
    s = s + 'sid=%s' %sid
    return json_vk_load(s)
    

maxcount = 10000 # For getting messages. Userapi is weird.


class VkPhoto(object):
    """VK photo
    """

    def __init__(self, image, sid):
        self._image = image
        self._sid = sid

    def owner(self):
        return VkUser(self._image[0].split('_')[0], self._sid)

    def id(self):
        return self._image[0].split('_')[1]

    def url(self):
        return self._image[2]

    def url_preview(self):
        return self._image[1]


class VkMessage(object):
    """Vkontakte basic message
    """
    
    def __init__(self, message, sid):
        """

        Arguments:
        - `message`: message from json-encoded server responce
        """
        self._mess = message
        self._sid = sid

    def id(self):
        return self._mess[0]

    def sender(self):
        return VkUser(self._mess[3][0], self._sid)
     
    def time(self):
        return int(self._mess[1])

    def type(self):
        try:
            t_id = self._mess[2][1]
        except IndexError:
            return u'text'

        if t_id == 0:
            return 'text'
        elif t_id == 1:
            return 'photo'
        elif t_id == 2:
            return 'graffiti'
        elif t_id == 3:
            return 'video'
        elif t_id == 4:
            return 'audio'

    def content(self):
        try:
            return self._mess[2][0] # FIXME later
        except IndexError:
            return u''

    def is_read(self):
        """Only for private messages"""
        return self._mess[5]

    def __unicode__(self):
        return self.content().encode('utf8')

    def __repr__(self):
        return "'%s'" %self.content().encode('utf8')   # Dirty, but it's needed
      
        
class VkWall(object):
    """Profile's wall
    """
    def __init__(self, vkid, sid):
        """

        Arguments:
        - `vkid`: VKontakte id
        - `sid`:  userapi sid
        """
        self._vkid = vkid
        self._sid = sid

    def messages_count(self):
        """Gets count of messages
        """
        raw_messages = vk_request(self._sid, Act='wall', Id=self._vkid)
        return raw_messages['n']

    def messages(self, first=0, last=maxcount):
        """Gets messages
        
        Arguments:
        - `first`:
        - `last`:
        """
        raw_messages = vk_request(self._sid, Act='wall', From=first, To=last, Id=self._vkid)

        messages = [VkMessage(i, self._sid) for i in raw_messages['d']]

        return messages


class VkUser(object):
    """Represents VK user
    """
    
    def __init__(self, vkid, sid):
        """
        
        Arguments:
        - `vkid`: VK id
        - `sid`: userapi sid
        """
        self._vkid = vkid
        self._sid = sid

    def wall(self):
        """
        
        """
        return VkWall(self._vkid, self._sid)

    def private_messages(self, first=0, last=maxcount, act="inbox", user=dummy()):
        """By default return all inbox messages.

        If parameter "act" is set then returns what is set (i.e. outbox or message session with some user)
        TODO: Document and unittest "act" and "user"
        BUG: If outbox, may return not all text of message
        """
        if act == "message" and user == dummy():
            pass # TODO
        
        raw_messages = vk_request(self._sid, Act=act, From=first, To=last, Id=user)

        messages = [VkMessage(i, self._sid) for i in raw_messages['d']]

        return messages        

    def friends(self, first=0, last=dummy()):
        raw_friends_list = vk_request(self._sid, Act='friends', From=first, To=last, Id=self._vkid)

        friends = [VkUser(x[0], self._sid) for x in raw_friends_list]
        return friends

    def friends_online(self, first=0, last=dummy()):
        raw_friends_list = vk_request(self._sid, Act='friends_online', From=first, To=last, Id=self._vkid)

        friends = [VkUser(x[0], self._sid) for x in raw_friends_list]
        return friends

    def photos(self, first=0, last=maxcount):
        raw_photos_list = vk_request(self._sid, Act='photos', From=first, To=last, Id=self._vkid)

        photos = [VkPhoto(x, self._sid) for x in raw_photos_list]
        return photos

    def photos_with(self, first=0, last=maxcount):
        raw_photos_list = vk_request(self._sid, Act='photos_with', From=first, To=last, Id=self._vkid)

        photos = [VkPhoto(x, self._sid) for x in raw_photos_list['d']]
        return photos

    
class VkClient(object):
    """Client for vkontakte.ru
    """
    
    def __init__(self, username):
        """
        
        Arguments:
        - `username`:
        """
        self._username = username

    def auth(self, password):
        """Performs authentification with given password
        """
        url = urllib2.urlopen(r"http://login.userapi.com/auth", data="login=force&site=2​&email=%s&pass=%s" %(self._username, password))
        
        if url.geturl().count('sid') > 0:
            self._sid = url.geturl().split('sid=')[1]
        else:
            raise Exception

    def user(self, vkid):
        """
        """
        return VkUser(vkid, self._sid)