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 ) :
""" Login using credentials from settings.
2016-02-17 08:11:47 -06:00
if the user account isn ' t authorised, it ' ll call self . authorise ( ) before login .
If the access_token has expired , it will call authorise ( ) too , for getting a new access token . """
2016-02-13 17:06:36 -06:00
if self . settings [ " vk " ] [ " token " ] != None :
2018-09-03 09:18:32 -05:00
# Handle special case where you get identical access tokens for two IP addresses.
# See https://github.com/manuelcortez/socializer/issues/11
2018-09-03 09:15:52 -05:00
try :
result = self . vk . login_access_token ( self . settings [ " vk " ] [ " token " ] )
self . logged = True
log . debug ( " Logged. " )
if result == False :
self . authorise ( )
2018-12-09 05:21:52 -06:00
except LoginRequired :
self . authorise ( )
2016-02-13 17:06:36 -06:00
else :
2016-02-14 18:46:23 -06:00
self . authorise ( )
2016-02-19 17:30:11 -06:00
self . get_my_data ( )
2016-02-13 17:06:36 -06:00
def authorise ( self ) :
2016-06-06 03:53:55 -05:00
try :
self . vk . login ( self . settings [ " vk " ] [ " user " ] , self . settings [ " vk " ] [ " password " ] )
self . settings [ " vk " ] [ " token " ] = self . vk . client . _session . access_token
self . settings . write ( )
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"])