2016-02-13 17:06:36 -06:00
# -*- coding: utf-8 -*-
2018-12-06 15:37:16 -06:00
import logging
2016-02-13 17:06:36 -06:00
import languageHandler
import paths
import vkSessionHandler
2016-05-24 17:48:22 -05:00
import sound
2016-02-13 17:06:36 -06:00
from config_utils import Configuration , ConfigurationResetException
2016-06-06 03:53:55 -05:00
from pubsub import pub
2018-12-09 05:21:52 -06:00
from vk_api.exceptions import LoginRequired , VkApiError
2016-06-06 03:53:55 -05:00
2016-05-10 20:23:48 -05:00
log = logging . getLogger ( "session" )
2016-02-13 17:06:36 -06:00
sessions = {}
2016-02-17 08:11:47 -06:00
# Saves possible set of identifier keys for VK'S data types
# see https://vk.com/dev/datatypes for more information.
2016-05-10 20:23:48 -05:00
# I've added the Date identifier (this is a field in unix time format), for special objects (like friendship indicators) because these objects doesn't have an own identifier.
identifiers = [ "aid" , "gid" , "uid" , "pid" , "id" , "post_id" , "nid" , "date" ]
2016-02-17 08:11:47 -06:00
def find_item ( list , item ):
""" Finds an item in a list by taking an identifier"""
# determines the kind of identifier that we are using
global identifiers
2016-05-10 20:23:48 -05:00
identifier = None
for i in identifiers :
if item . has_key ( i ):
identifier = i
break
2016-02-17 08:11:47 -06:00
if identifier == None :
2016-02-17 09:18:36 -06:00
# if there are objects that can't be processed by lack of identifier, let's print keys for finding one.
2016-05-10 20:23:48 -05:00
log . exception ( "Can't find an identifier for the following object: %r " % ( item . keys (),))
2016-02-17 08:11:47 -06:00
for i in list :
if i . has_key ( identifier ) and i [ identifier ] == item [ identifier ]:
return True
return False
2016-02-13 17:06:36 -06:00
class vkSession ( object ):
2016-02-23 17:49:55 -06:00
def order_buffer ( self , name , data , show_nextpage ):
2016-02-13 17:06:36 -06:00
2016-02-17 08:11:47 -06:00
""" Put new items on the local database. Useful for cursored buffers
2016-02-13 17:06:36 -06:00
name str: The name for the buffer stored in the dictionary.
data list: A list with items and some information about cursors.
returns the number of items that has been added in this execution"""
2016-02-17 08:11:47 -06:00
first_addition = False
2016-02-13 17:06:36 -06:00
num = 0
if self . db . has_key ( name ) == False :
self . db [ name ] = {}
self . db [ name ][ "items" ] = []
2016-02-17 08:11:47 -06:00
first_addition = True
2016-02-13 17:06:36 -06:00
for i in data :
2016-05-17 12:46:57 -05:00
if i . has_key ( "type" ) and ( i [ "type" ] == "wall_photo" or i [ "type" ] == "photo_tag" or i [ "type" ] == "photo" ):
2016-05-10 20:23:48 -05:00
log . debug ( "Skipping unsupported item... %r " % ( i ,))
continue
2016-02-17 08:11:47 -06:00
if find_item ( self . db [ name ][ "items" ], i ) == False :
# if i not in self.db[name]["items"]:
2016-02-25 04:52:02 -06:00
if first_addition == True or show_nextpage == True :
2016-02-17 08:11:47 -06:00
if self . settings [ "general" ][ "reverse_timelines" ] == False : self . db [ name ][ "items" ] . append ( i )
else : self . db [ name ][ "items" ] . insert ( 0 , i )
else :
if self . settings [ "general" ][ "reverse_timelines" ] == False : self . db [ name ][ "items" ] . insert ( 0 , i )
else : self . db [ name ][ "items" ] . append ( i )
2016-02-13 17:06:36 -06:00
num = num + 1
2016-05-10 20:23:48 -05:00
log . debug ( "There are %d items in the %s buffer" % ( len ( self . db [ name ][ "items" ]), name ))
2016-02-13 17:06:36 -06:00
return num
def __init__ ( self , session_id ):
self . session_id = session_id
self . logged = False
self . settings = None
self . vk = vkSessionHandler . vkObject ()
self . db = {}
self . db [ "users" ] = {}
self . db [ "groups" ] = {}
@property
def is_logged ( self ):
return self . logged
def get_configuration ( self ):
""" Gets settings for a session."""
file_ = " %s /session.conf" % ( self . session_id ,)
# try:
log . debug ( "Creating config file %s " % ( file_ ,))
self . settings = Configuration ( paths . config_path ( file_ ), paths . app_path ( "session.defaults" ))
2016-05-24 17:48:22 -05:00
self . soundplayer = sound . soundSystem ( self . settings [ "sound" ])
2016-02-13 17:06:36 -06:00
# except:
# log.exception("The session configuration has failed.")
def login ( self ):
2016-06-06 03:53:55 -05:00
try :
2018-12-09 21:41:09 -06:00
self . vk . login ( self . settings [ "vk" ][ "user" ], self . settings [ "vk" ][ "password" ], filename = paths . config_path ( self . session_id + "/vkconfig.json" ))
2016-06-06 03:53:55 -05:00
self . settings [ "vk" ][ "token" ] = self . vk . client . _session . access_token
self . settings . write ()
2018-12-09 07:25:30 -06:00
self . logged = True
2018-12-09 05:21:52 -06:00
except ValueError :
2016-06-06 03:53:55 -05:00
self . settings [ "vk" ][ "user" ] = ""
self . settings [ "vk" ][ "password" ] = ""
self . settings . write ()
pub . sendMessage ( "authorisation-failed" )
2016-02-13 17:06:36 -06:00
def post_wall_status ( self , message , * args , ** kwargs ):
2016-02-17 08:11:47 -06:00
""" Sends a post to an user, group or community wall."""
2016-05-10 20:23:48 -05:00
log . debug ( "Making a post to the user's wall with the following params: %r " % ( kwargs ,))
2016-02-13 17:06:36 -06:00
response = self . vk . client . wall . post ( message = message , * args , ** kwargs )
2016-02-23 17:49:55 -06:00
def get_newsfeed ( self , name = "newsfeed" , show_nextpage = False , endpoint = "" , * args , ** kwargs ):
2016-05-10 20:23:48 -05:00
log . debug ( "Updating news feed..." )
2016-03-28 05:19:08 -06:00
if show_nextpage == True and self . db [ name ] . has_key ( "cursor" ):
2016-05-10 20:23:48 -05:00
log . debug ( "user has requested previous items" )
2016-02-23 17:49:55 -06:00
kwargs [ "start_from" ] = self . db [ name ][ "cursor" ]
2016-05-10 20:23:48 -05:00
log . debug ( "Params for sending to vk: %r " % ( kwargs ,))
2016-02-13 17:06:36 -06:00
data = getattr ( self . vk . client . newsfeed , "get" )( * args , ** kwargs )
if data != None :
2016-02-23 17:49:55 -06:00
if show_nextpage == False :
self . process_usernames ( data )
2016-02-25 04:52:02 -06:00
# else:
# print data.keys(), len(data["items"]), data["next_from"]
num = self . order_buffer ( name , data [ "items" ], show_nextpage )
2016-05-10 20:23:48 -05:00
log . debug ( "Keys of the returned data for debug purposes: %r " % ( data . keys (),))
2016-03-28 05:19:08 -06:00
if data . has_key ( "next_from" ):
self . db [ name ][ "cursor" ] = data [ "next_from" ]
2016-02-13 17:06:36 -06:00
return num
2016-02-23 17:49:55 -06:00
def get_page ( self , name = "" , show_nextpage = False , endpoint = "" , * args , ** kwargs ):
2016-02-13 17:06:36 -06:00
data = None
2018-12-09 05:21:52 -06:00
if "audio" in endpoint :
c = self . vk . client_audio
else :
c = self . vk . client
2016-02-13 17:06:36 -06:00
if kwargs . has_key ( "parent_endpoint" ):
p = kwargs [ "parent_endpoint" ]
2018-12-09 05:21:52 -06:00
if "audio" in p :
c = self . vk . client_audio
2016-02-13 17:06:36 -06:00
kwargs . pop ( "parent_endpoint" )
2018-12-09 05:21:52 -06:00
try :
p = getattr ( c , p )
except AttributeError :
p = c
2016-05-10 20:23:48 -05:00
log . debug ( "Calling endpoint %s with params %r " % ( p , kwargs ,))
2016-02-13 17:06:36 -06:00
data = getattr ( p , endpoint )( * args , ** kwargs )
if data != None :
2016-03-22 02:59:31 -06:00
if type ( data ) == dict :
num = self . order_buffer ( name , data [ "items" ], show_nextpage )
2016-06-19 12:25:06 -05:00
if len ( data [ "items" ]) > 0 and data [ "items" ][ 0 ] . has_key ( "first_name" ):
2016-07-07 10:20:03 -05:00
data2 = { "profiles" : [], "groups" : []}
2016-05-25 11:33:57 -05:00
for i in data [ "items" ]:
2016-07-07 10:20:03 -05:00
data2 [ "profiles" ] . append ( i )
2016-07-07 13:23:49 -05:00
self . process_usernames ( data2 )
2016-03-30 16:27:37 -06:00
if data . has_key ( "profiles" ) and data . has_key ( "groups" ):
self . process_usernames ( data )
2016-03-22 02:59:31 -06:00
else :
num = self . order_buffer ( name , data , show_nextpage )
2016-02-13 17:06:36 -06:00
return num
2016-05-17 12:46:57 -05:00
def get_messages ( self , name = "" , * args , ** kwargs ):
data = self . vk . client . messages . getHistory ( * args , ** kwargs )
2018-11-04 01:39:06 -06:00
data [ "items" ] . reverse ()
2016-05-17 12:46:57 -05:00
if data != None :
num = self . order_buffer ( name , data [ "items" ], False )
return num
2016-07-07 10:20:03 -05:00
def get_user_name ( self , user_id , case_name = "gen" ):
2016-02-13 17:06:36 -06:00
if user_id > 0 :
if self . db [ "users" ] . has_key ( user_id ):
2016-07-07 10:20:03 -05:00
if self . db [ "users" ][ user_id ] . has_key ( case_name ):
return self . db [ "users" ][ user_id ][ case_name ]
else :
return self . db [ "users" ][ user_id ][ "nom" ]
2016-02-13 17:06:36 -06:00
else :
return "no specified user"
else :
if self . db [ "groups" ] . has_key ( abs ( user_id )):
2016-07-07 10:20:03 -05:00
return self . db [ "groups" ][ abs ( user_id )][ "nom" ]
2016-02-13 17:06:36 -06:00
else :
return "no specified community"
def get_users ( self , user_ids = None , group_ids = None ):
2016-05-10 20:23:48 -05:00
log . debug ( "Getting user information from the VK servers" )
2016-02-13 17:06:36 -06:00
if user_ids != None :
u = self . vk . client . users . get ( user_ids = user_ids , fields = "uid, first_name, last_name" )
for i in u :
2016-02-23 17:49:55 -06:00
self . db [ "users" ][ i [ "id" ]] = u " {0} {1} " . format ( i [ "first_name" ], i [ "last_name" ])
2016-02-13 17:06:36 -06:00
if group_ids != None :
g = self . vk . client . groups . getById ( group_ids = group_ids , fields = "name" )
for i in g :
2016-02-23 17:49:55 -06:00
self . db [ "groups" ][ i [ "id" ]] = i [ "name" ]
2016-02-17 09:18:36 -06:00
def process_usernames ( self , data ):
2016-07-07 10:20:03 -05:00
""" processes user IDS and saves them in a local storage system.
Every function wich needs to convert from an ID to user or community name will have to call the get_user_name function in this session object.
Every function that needs to save a set ot user ids for a future use needs to pass a data dictionary with a profiles key being a list of user objects.
For russian, it gets the genitive case of every name for future use."""
2016-05-10 20:23:48 -05:00
log . debug ( "Adding usernames to the local database..." )
2016-07-07 10:20:03 -05:00
ids = ""
2016-02-17 09:18:36 -06:00
for i in data [ "profiles" ]:
2016-07-07 10:20:03 -05:00
if self . db [ "users" ] . has_key ( i [ "id" ]) == False :
self . db [ "users" ][ i [ "id" ]] = dict ( nom = u " {0} {1} " . format ( i [ "first_name" ], i [ "last_name" ]))
ids = ids + " {0} ," . format ( i [ "id" ],)
gids = ""
2016-02-17 09:18:36 -06:00
for i in data [ "groups" ]:
2016-07-07 10:20:03 -05:00
self . db [ "groups" ][ i [ "id" ]] = dict ( nom = i [ "name" ])
gids = " {0} ," . format ( i [ "id" ],)
if not "ru" in languageHandler . getLanguage ():
return
2016-07-10 22:51:06 -05:00
if ids != "" :
users_genitive = self . vk . client . users . get ( user_ids = ids , fields = "first_name, last_name" , name_case = "gen" )
users_instrumental = self . vk . client . users . get ( user_ids = ids , fields = "first_name, last_name" , name_case = "ins" )
for i in users_genitive :
if self . db [ "users" ] . has_key ( i [ "id" ]):
self . db [ "users" ][ i [ "id" ]][ "gen" ] = u " {0} {1} " . format ( i [ "first_name" ], i [ "last_name" ])
for i in users_instrumental :
if self . db [ "users" ] . has_key ( i [ "id" ]):
self . db [ "users" ][ i [ "id" ]][ "ins" ] = u " {0} {1} " . format ( i [ "first_name" ], i [ "last_name" ])
2016-02-19 17:30:11 -06:00
def get_my_data ( self ):
2016-05-10 20:23:48 -05:00
log . debug ( "Getting user identifier..." )
2016-03-14 16:07:44 -06:00
user = self . vk . client . users . get ( fields = "uid, first_name, last_name" )
self . user_id = user [ 0 ][ "id" ]
2016-07-07 10:20:03 -05:00
# self.db["users"][self.user_id] = u"{0} {1}".format(user[0]["first_name"], user[0]["last_name"])