2014-11-12 20:41:29 -06:00
# -*- coding: utf-8 -*-
""" The main session object. Here are the twitter functions to interact with the " model " of TWBlue. """
2017-07-30 04:05:32 -05:00
import wx
2015-02-01 00:49:03 -06:00
import urllib2
2016-08-06 14:47:42 -05:00
import config
2014-11-12 20:41:29 -06:00
import twitter
2015-02-04 17:00:03 -06:00
from keys import keyring
2014-11-12 20:41:29 -06:00
import session_exceptions as Exceptions
import paths
import output
import time
import sound
2015-01-18 17:19:39 -06:00
import logging
2015-09-29 08:38:05 -05:00
from twitter import utils , compose
2014-11-12 20:41:29 -06:00
from twython import TwythonError , TwythonRateLimitError , TwythonAuthError
2015-03-30 10:55:56 -06:00
import config_utils
2015-05-01 00:48:42 -05:00
import shelve
2015-05-02 02:41:28 -05:00
import application
import os
2017-07-30 04:05:32 -05:00
from mysc . thread_utils import stream_threaded , call_threaded
2015-02-01 21:13:18 -06:00
from pubsub import pub
2015-01-18 17:19:39 -06:00
log = logging . getLogger ( " sessionmanager.session " )
2016-04-28 13:54:06 -05:00
from long_tweets import tweets , twishort
2017-07-30 04:05:32 -05:00
from wxUI import authorisationDialog
2014-11-12 20:41:29 -06:00
sessions = { }
class Session ( object ) :
""" A session object where we will save configuration, the twitter object and a local storage for saving the items retrieved through the Twitter API methods """
# Decorators.
def _require_login ( fn ) :
2015-04-12 18:43:19 -05:00
""" Decorator for checking if the user is logged in(a twitter object has credentials) on twitter.
Some functions may need this to avoid making unneeded twitter API calls . """
2014-11-12 20:41:29 -06:00
def f ( self , * args , * * kwargs ) :
if self . logged == True :
fn ( self , * args , * * kwargs )
else :
2015-04-12 18:43:19 -05:00
raise Exceptions . NotLoggedSessionError ( " You are not logged in yet. " )
2014-11-12 20:41:29 -06:00
return f
def _require_configuration ( fn ) :
""" Check if the user has a configured session. """
def f ( self , * args , * * kwargs ) :
if self . settings != None :
fn ( self , * args , * * kwargs )
else :
raise Exceptions . NotConfiguredSessionError ( " Not configured. " )
return f
2017-05-07 01:45:35 -05:00
def order_buffer ( self , name , data , ignore_older = True ) :
2014-11-12 20:41:29 -06:00
2015-04-12 18:43:19 -05:00
""" Put the new items in the local database.
2014-11-12 20:41:29 -06:00
name str : The name for the buffer stored in the dictionary .
data list : A list with tweets .
2015-04-12 18:43:19 -05:00
returns the number of items that have been added in this execution """
2014-11-12 20:41:29 -06:00
num = 0
2017-05-07 01:45:35 -05:00
last_id = None
2014-11-12 20:41:29 -06:00
if self . db . has_key ( name ) == False :
self . db [ name ] = [ ]
2018-07-17 09:27:13 -05:00
if self . db . has_key ( " users " ) == False :
self . db [ " users " ] = { }
2017-05-07 01:45:35 -05:00
if ignore_older and len ( self . db [ name ] ) > 0 :
if self . settings [ " general " ] [ " reverse_timelines " ] == False :
last_id = self . db [ name ] [ 0 ] [ " id " ]
else :
2017-05-07 19:12:06 -05:00
last_id = self . db [ name ] [ - 1 ] [ " id " ]
2014-11-12 20:41:29 -06:00
for i in data :
2017-05-07 01:45:35 -05:00
if ignore_older and last_id != None :
if i [ " id " ] < last_id :
2017-05-25 02:59:24 -05:00
log . error ( " Ignoring an older tweet... Last id: {0} , tweet id: {1} " . format ( last_id , i [ " id " ] ) )
2017-05-07 01:45:35 -05:00
continue
2017-11-13 17:45:01 -06:00
if utils . find_item ( i [ " id " ] , self . db [ name ] ) == None and utils . is_allowed ( i , self . settings , name ) == True :
2017-11-29 10:55:42 -06:00
i = self . check_quoted_status ( i )
2016-04-28 13:54:06 -05:00
i = self . check_long_tweet ( i )
2017-01-29 17:20:37 -06:00
if i == False : continue
2014-11-12 20:41:29 -06:00
if self . settings [ " general " ] [ " reverse_timelines " ] == False : self . db [ name ] . append ( i )
else : self . db [ name ] . insert ( 0 , i )
num = num + 1
2018-07-17 09:27:13 -05:00
if i . has_key ( " user " ) == True :
if self . db [ " users " ] . has_key ( i [ " user " ] [ " id " ] ) == False :
self . db [ " users " ] [ i [ " user " ] [ " id " ] ] = i [ " user " ]
2014-11-12 20:41:29 -06:00
return num
def order_cursored_buffer ( self , name , data ) :
""" Put the new items on the local database. Useful for cursored buffers (followers, friends, users of a list and searches)
name str : The name for the buffer stored in the dictionary .
data list : A list with items and some information about cursors .
2015-04-12 18:43:19 -05:00
returns the number of items that have been added in this execution """
2014-11-12 20:41:29 -06:00
num = 0
if self . db . has_key ( name ) == False :
self . db [ name ] = { }
self . db [ name ] [ " items " ] = [ ]
# if len(self.db[name]["items"]) > 0:
for i in data :
if utils . find_item ( i [ " id " ] , self . db [ name ] [ " items " ] ) == None :
if self . settings [ " general " ] [ " reverse_timelines " ] == False : self . db [ name ] [ " items " ] . append ( i )
else : self . db [ name ] [ " items " ] . insert ( 0 , i )
num = num + 1
return num
def __init__ ( self , session_id ) :
""" session_id (str): The name of the folder inside the config directory where the session is located. """
super ( Session , self ) . __init__ ( )
self . session_id = session_id
self . logged = False
self . settings = None
self . twitter = twitter . twitter . twitter ( )
2015-05-01 00:48:42 -05:00
self . db = { }
2015-01-13 12:31:37 -06:00
self . reconnection_function_active = False
2015-03-07 20:23:41 -06:00
self . counter = 0
2015-04-27 16:08:02 -05:00
self . lists = [ ]
pub . subscribe ( self . add_friends , " friends-receibed " )
2014-11-12 20:41:29 -06:00
2015-02-26 15:21:26 -06:00
@property
def is_logged ( self ) :
return self . logged
2014-11-12 20:41:29 -06:00
def get_configuration ( self ) :
2015-01-20 15:40:33 -06:00
""" Gets settings for a session. """
file_ = " %s /session.conf " % ( self . session_id , )
# try:
2015-01-18 17:19:39 -06:00
log . debug ( " Creating config file %s " % ( file_ , ) )
2015-03-30 10:55:56 -06:00
self . settings = config_utils . load_config ( paths . config_path ( file_ ) , paths . app_path ( " Conf.defaults " ) )
2015-01-20 15:40:33 -06:00
self . init_sound ( )
2015-05-09 22:12:17 -05:00
self . deshelve ( )
2015-01-20 15:40:33 -06:00
# except:
# log.exception("The session configuration has failed.")
# self.settings = None
def init_sound ( self ) :
2015-08-19 05:28:56 -05:00
try : self . sound = sound . soundSystem ( self . settings [ " sound " ] )
2017-07-19 08:25:09 -05:00
except : pass
2014-11-12 20:41:29 -06:00
@_require_configuration
2015-03-08 00:36:41 -06:00
def login ( self , verify_credentials = True ) :
2014-11-12 20:41:29 -06:00
2015-04-12 18:43:19 -05:00
""" Log into twitter using credentials from settings.
2014-11-12 20:41:29 -06:00
if the user account isn ' t authorised, it needs to call self.authorise() before login. " " "
if self . settings [ " twitter " ] [ " user_key " ] != None and self . settings [ " twitter " ] [ " user_secret " ] != None :
2017-02-13 06:35:32 -06:00
try :
log . debug ( " Logging in to twitter... " )
self . twitter . login ( self . settings [ " twitter " ] [ " user_key " ] , self . settings [ " twitter " ] [ " user_secret " ] , verify_credentials )
self . logged = True
log . debug ( " Logged. " )
self . counter = 0
except :
log . error ( " The login attempt failed. " )
self . logged = False
2014-11-12 20:41:29 -06:00
else :
self . logged = False
raise Exceptions . RequireCredentialsSessionError
@_require_configuration
def authorise ( self ) :
2015-04-12 18:43:19 -05:00
""" Authorises a Twitter account. This function needs to be called for each new session, after self.get_configuration() and before self.login() """
2014-11-12 20:41:29 -06:00
if self . logged == True :
raise Exceptions . AlreadyAuthorisedError ( " The authorisation process is not needed at this time. " )
else :
2018-06-06 09:11:37 -05:00
self . twitter . authorise ( )
2017-07-30 04:05:32 -05:00
self . authorisation_dialog = authorisationDialog ( )
self . authorisation_dialog . cancel . Bind ( wx . EVT_BUTTON , self . authorisation_cancelled )
2018-06-06 09:11:37 -05:00
self . authorisation_dialog . ok . Bind ( wx . EVT_BUTTON , self . authorisation_accepted )
2017-07-30 04:05:32 -05:00
self . authorisation_dialog . ShowModal ( )
def authorisation_cancelled ( self , * args , * * kwargs ) :
self . authorisation_dialog . Destroy ( )
del self . authorisation_dialog
2018-06-06 09:11:37 -05:00
def authorisation_accepted ( self , * args , * * kwargs ) :
pincode = self . authorisation_dialog . text . GetValue ( )
self . twitter . verify_authorisation ( self . settings , pincode )
2017-07-30 04:05:32 -05:00
self . authorisation_dialog . Destroy ( )
2014-11-12 20:41:29 -06:00
2018-07-19 12:27:01 -05:00
def get_more_items ( self , update_function , users = False , dm = False , name = None , * args , * * kwargs ) :
2015-02-03 09:59:18 -06:00
results = [ ]
data = getattr ( self . twitter . twitter , update_function ) ( * args , * * kwargs )
if users == True :
2017-07-10 17:46:20 -05:00
if type ( data ) == dict and data . has_key ( " next_cursor " ) :
2017-06-15 09:57:45 -05:00
self . db [ name ] [ " cursor " ] = data [ " next_cursor " ]
for i in data [ " users " ] : results . append ( i )
elif type ( data ) == list :
results . extend ( data [ 1 : ] )
2018-07-19 12:27:01 -05:00
elif dm == True :
self . db [ name ] [ " cursor " ] = data [ " next_cursor " ]
for i in data [ " events " ] : results . append ( i )
2015-02-03 09:59:18 -06:00
else :
results . extend ( data [ 1 : ] )
return results
2014-11-12 20:41:29 -06:00
def api_call ( self , call_name , action = " " , _sound = None , report_success = False , report_failure = True , preexec_message = " " , * args , * * kwargs ) :
2015-04-12 18:43:19 -05:00
""" Make a call to the Twitter API. If there is a connectionError or another exception not related to Twitter, It will call the method again at least 25 times, waiting a while between calls. Useful for post methods.
If twitter returns an error , it will not call the method anymore .
2014-11-12 20:41:29 -06:00
call_name str : The method to call
2015-04-12 18:43:19 -05:00
action str : What you are doing on twitter , it will be reported to the user if report_success is set to True .
2014-11-12 20:41:29 -06:00
for example " following @tw_blue2 " will be reported as " following @tw_blue2 succeeded " .
_sound str : a sound to play if the call is executed properly .
2015-04-12 18:43:19 -05:00
report_success and report_failure bool : These are self explanatory . True or False .
preexec_message str : A message to speak to the user while the method is running , example : " trying to follow x user " . """
2014-11-12 20:41:29 -06:00
finished = False
tries = 0
if preexec_message :
output . speak ( preexec_message , True )
while finished == False and tries < 25 :
try :
val = getattr ( self . twitter . twitter , call_name ) ( * args , * * kwargs )
finished = True
except TwythonError as e :
output . speak ( e . message )
2015-03-01 20:41:02 -06:00
if e . error_code != 403 and e . error_code != 404 :
tries = tries + 1
time . sleep ( 5 )
elif report_failure and hasattr ( e , ' message ' ) :
2014-11-12 20:41:29 -06:00
output . speak ( _ ( " %s failed. Reason: %s " ) % ( action , e . message ) )
finished = True
2016-12-19 11:43:32 -06:00
# except:
# tries = tries + 1
# time.sleep(5)
2014-11-12 20:41:29 -06:00
if report_success :
output . speak ( _ ( " %s succeeded. " ) % action )
2015-01-22 08:54:41 -06:00
if _sound != None : self . sound . play ( _sound )
2015-12-26 09:02:08 -06:00
return val
2014-11-12 20:41:29 -06:00
2015-03-24 17:07:14 -06:00
def search ( self , name , * args , * * kwargs ) :
tl = self . twitter . twitter . search ( * args , * * kwargs )
tl [ " statuses " ] . reverse ( )
return tl [ " statuses " ]
2014-11-12 20:41:29 -06:00
@_require_login
def get_favourites_timeline ( self , name , * args , * * kwargs ) :
2015-04-12 18:43:19 -05:00
""" Gets favourites for the authenticated user or a friend or follower.
name str : Name for storage in the database . """
2014-11-12 20:41:29 -06:00
tl = self . call_paged ( self . twitter . twitter . get_favorites , * args , * * kwargs )
return self . order_buffer ( name , tl )
def call_paged ( self , update_function , * args , * * kwargs ) :
""" Makes a call to the Twitter API methods several times. Useful for get methods.
this function is needed for retrieving more than 200 items .
update_function str : The function to call . This function must be child of self . twitter . twitter
2015-04-12 18:43:19 -05:00
returns a list with all items retrieved . """
2014-11-12 20:41:29 -06:00
2018-05-25 11:35:24 -05:00
if application . streaming_lives ( ) :
max = int ( self . settings [ " general " ] [ " max_api_calls " ] ) - 1
else :
max = 0
2014-11-12 20:41:29 -06:00
results = [ ]
data = getattr ( self . twitter . twitter , update_function ) ( count = self . settings [ " general " ] [ " max_tweets_per_call " ] , * args , * * kwargs )
results . extend ( data )
for i in range ( 0 , max ) :
if i == 0 : max_id = results [ - 1 ] [ " id " ]
else : max_id = results [ 0 ] [ " id " ]
2015-01-27 17:09:28 -06:00
data = getattr ( self . twitter . twitter , update_function ) ( max_id = max_id , count = self . settings [ " general " ] [ " max_tweets_per_call " ] , * args , * * kwargs )
2014-11-12 20:41:29 -06:00
results . extend ( data )
results . reverse ( )
return results
@_require_login
def get_user_info ( self ) :
""" Retrieves some information required by TWBlue for setup. """
f = self . twitter . twitter . get_account_settings ( )
sn = f [ " screen_name " ]
2015-03-03 13:48:57 -06:00
self . settings [ " twitter " ] [ " user_name " ] = sn
2014-11-12 20:41:29 -06:00
self . db [ " user_name " ] = sn
self . db [ " user_id " ] = self . twitter . twitter . show_user ( screen_name = sn ) [ " id_str " ]
try :
self . db [ " utc_offset " ] = f [ " time_zone " ] [ " utc_offset " ]
except KeyError :
self . db [ " utc_offset " ] = - time . timezone
2017-11-12 23:39:45 -06:00
# Get twitter's supported languages and save them in a global variable
#so we won't call to this method once per session.
if len ( application . supported_languages ) == 0 :
application . supported_languages = self . twitter . twitter . get_supported_languages ( )
2014-11-12 20:41:29 -06:00
self . get_lists ( )
self . get_muted_users ( )
self . settings . write ( )
@_require_login
def get_lists ( self ) :
2015-04-12 18:43:19 -05:00
""" Gets the lists that the user is subscribed to and stores them in the database. Returns None. """
2014-11-12 20:41:29 -06:00
self . db [ " lists " ] = self . twitter . twitter . show_lists ( reverse = True )
@_require_login
def get_muted_users ( self ) :
""" Gets muted users (oh really?). """
2015-05-26 20:23:02 -05:00
self . db [ " muted_users " ] = self . twitter . twitter . list_mute_ids ( ) [ " ids " ]
2014-11-12 20:41:29 -06:00
@_require_login
def get_stream ( self , name , function , * args , * * kwargs ) :
""" Retrieves the items for a regular stream.
2015-04-12 18:43:19 -05:00
name str : Name to save items to the database .
2014-11-12 20:41:29 -06:00
function str : A function to get the items . """
last_id = - 1
if self . db . has_key ( name ) :
try :
if self . db [ name ] [ 0 ] [ " id " ] > self . db [ name ] [ - 1 ] [ " id " ] :
last_id = self . db [ name ] [ 0 ] [ " id " ]
else :
last_id = self . db [ name ] [ - 1 ] [ " id " ]
except IndexError :
pass
tl = self . call_paged ( function , sinze_id = last_id , * args , * * kwargs )
self . order_buffer ( name , tl )
2015-12-26 23:28:46 -06:00
def get_cursored_stream ( self , name , function , items = " users " , get_previous = False , * args , * * kwargs ) :
2014-11-12 20:41:29 -06:00
2015-04-12 18:43:19 -05:00
""" Gets items for API calls that require using cursors to paginate the results.
2014-11-12 20:41:29 -06:00
name str : Name to save it in the database .
function str : Function that provides the items .
items : When the function returns the list with results , items will tell how the order function should be look .
2015-04-12 18:43:19 -05:00
for example get_followers_list returns a list and users are under list [ " users " ] , here the items should point to " users " . """
2014-11-12 20:41:29 -06:00
items_ = [ ]
try :
2015-12-26 23:28:46 -06:00
if self . db [ name ] . has_key ( " cursor " ) and get_previous :
2015-02-03 09:59:18 -06:00
cursor = self . db [ name ] [ " cursor " ]
2014-11-12 20:41:29 -06:00
else :
2015-02-03 09:59:18 -06:00
cursor = - 1
2014-11-12 20:41:29 -06:00
except KeyError :
2015-02-03 09:59:18 -06:00
cursor = - 1
2018-07-18 09:27:02 -05:00
if cursor != - 1 :
tl = getattr ( self . twitter . twitter , function ) ( cursor = cursor , count = self . settings [ " general " ] [ " max_tweets_per_call " ] , * args , * * kwargs )
else :
tl = getattr ( self . twitter . twitter , function ) ( count = self . settings [ " general " ] [ " max_tweets_per_call " ] , * args , * * kwargs )
2014-11-12 20:41:29 -06:00
tl [ items ] . reverse ( )
num = self . order_cursored_buffer ( name , tl [ items ] )
2018-07-18 09:27:02 -05:00
# Recently, Twitter's new endpoints have cursor if there are more results.
if tl . has_key ( " next_cursor " ) :
self . db [ name ] [ " cursor " ] = tl [ " next_cursor " ]
2014-11-12 20:41:29 -06:00
return num
def start_streaming ( self ) :
""" Start the streaming for sending tweets in realtime. """
2018-05-25 12:11:53 -05:00
if application . streaming_lives ( ) :
if not hasattr ( self , " main_stream " ) :
self . get_timelines ( )
if not hasattr ( self , " timelinesStream " ) :
self . get_main_stream ( )
2015-01-13 12:31:37 -06:00
def get_main_stream ( self ) :
2018-05-25 12:11:53 -05:00
if application . streaming_lives ( ) :
log . debug ( " Starting the main stream... " )
self . main_stream = twitter . buffers . stream . streamer ( keyring . get ( " api_key " ) , keyring . get ( " api_secret " ) , self . settings [ " twitter " ] [ " user_key " ] , self . settings [ " twitter " ] [ " user_secret " ] , self )
stream_threaded ( self . main_stream . user , self . session_id )
2015-01-13 12:31:37 -06:00
def get_timelines ( self ) :
2018-05-25 12:11:53 -05:00
if application . streaming_lives ( ) :
log . debug ( " Starting the timelines stream... " )
self . timelinesStream = twitter . buffers . indibidual . timelinesStreamer ( keyring . get ( " api_key " ) , keyring . get ( " api_secret " ) , self . settings [ " twitter " ] [ " user_key " ] , self . settings [ " twitter " ] [ " user_secret " ] , session = self )
ids = " "
for i in self . settings [ " other_buffers " ] [ " timelines " ] :
ids = ids + " %s , " % ( self . db [ i + " -timeline " ] [ 0 ] [ " user " ] [ " id_str " ] )
for i in self . lists :
for z in i . users :
ids + = str ( z ) + " , "
if ids != " " :
stream_threaded ( self . timelinesStream . statuses . filter , self . session_id , follow = ids )
2015-01-13 12:31:37 -06:00
2015-04-27 16:08:02 -05:00
def add_friends ( self ) :
2018-05-25 12:11:53 -05:00
if application . streaming_lives ( ) :
try :
self . timelinesStream . set_friends ( self . main_stream . friends )
except AttributeError :
pass
2015-04-27 16:08:02 -05:00
2015-01-13 12:31:37 -06:00
def listen_stream_error ( self ) :
2018-05-25 12:11:53 -05:00
if hasattr ( self , " main_stream " ) and application . streaming_lives ( ) :
2015-01-18 17:19:39 -06:00
log . debug ( " Disconnecting the main stream... " )
2015-01-13 12:31:37 -06:00
self . main_stream . disconnect ( )
del self . main_stream
2018-05-25 12:11:53 -05:00
if hasattr ( self , " timelinesStream " ) and application . streaming_lives ( ) :
2015-01-18 17:19:39 -06:00
log . debug ( " disconnecting the timelines stream... " )
2015-01-13 12:31:37 -06:00
self . timelinesStream . disconnect ( )
del self . timelinesStream
def check_connection ( self ) :
2018-06-17 19:38:29 -05:00
log . debug ( " Executing check connection... " )
2015-03-07 20:23:41 -06:00
instan = 0
self . counter + = 1
if self . counter > = 4 :
2018-06-17 19:38:29 -05:00
log . debug ( " Restarting connection after 5 minutes. " )
2015-03-07 20:23:41 -06:00
del self . twitter
self . logged = False
self . twitter = twitter . twitter . twitter ( )
2015-03-08 00:36:41 -06:00
self . login ( False )
2018-06-17 19:38:29 -05:00
self . counter = 0
2015-01-13 12:31:37 -06:00
if self . reconnection_function_active == True : return
self . reconnection_function_active = True
2018-06-17 19:26:47 -05:00
if not hasattr ( self , " main_stream " ) and application . streaming_lives ( ) :
2015-01-13 12:31:37 -06:00
self . get_main_stream ( )
2018-06-17 19:26:47 -05:00
if not hasattr ( self , " timelinesStream " ) and application . streaming_lives ( ) :
2015-01-13 12:31:37 -06:00
self . get_timelines ( )
self . reconnection_function_active = False
2015-05-02 17:22:28 -05:00
if hasattr ( self , " timelinesStream " ) and not hasattr ( self . timelinesStream , " friends " ) :
self . add_friends ( )
2015-11-23 10:30:23 -06:00
# try:
# urllib2.urlopen("http://74.125.228.231", timeout=5)
# except urllib2.URLError:
# pub.sendMessage("stream-error", session=self.session_id)
2015-02-12 10:29:51 -06:00
def remove_stream ( self , stream ) :
2018-05-25 12:11:53 -05:00
if application . streaming_lives ( ) :
if stream == " timelinesStream " :
if hasattr ( self , " timelinesStream " ) :
self . timelinesStream . disconnect ( )
del self . timelinesStream
else :
self . main_stream . disconnect ( )
del self . main_stream
2015-05-01 00:48:42 -05:00
def shelve ( self ) :
" Shelve the database to allow for persistance. "
2015-05-13 22:21:47 -05:00
shelfname = paths . config_path ( str ( self . session_id ) + " /cache.db " )
2015-05-09 22:12:17 -05:00
if self . settings [ " general " ] [ " persist_size " ] == 0 :
2015-05-09 22:13:17 -05:00
if os . path . exists ( shelfname ) :
2015-05-09 22:12:17 -05:00
os . remove ( shelfname )
return
2015-05-02 02:41:28 -05:00
try :
2015-05-02 03:04:29 -05:00
if not os . path . exists ( shelfname ) :
2015-05-02 03:00:29 -05:00
output . speak ( " Generating database, this might take a while. " , True )
2015-05-02 02:41:28 -05:00
shelf = shelve . open ( paths . config_path ( shelfname ) , ' c ' )
for key , value in self . db . items ( ) :
2015-05-02 02:53:20 -05:00
if type ( key ) != str and type ( key ) != unicode :
2015-05-02 03:00:29 -05:00
output . speak ( " Uh oh, while shelving the database, a key of type " + str ( type ( key ) ) + " has been found. It will be converted to type str, but this will cause all sorts of problems on deshelve. Please bring this to the attention of the " + application . name + " developers immediately. More information about the error will be written to the error log. " , True )
2015-05-02 02:53:20 -05:00
log . error ( " Uh oh, " + str ( key ) + " is of type " + str ( type ( key ) ) + " ! " )
2015-08-10 09:24:46 -05:00
# Convert unicode objects to UTF-8 strings before shelve these objects.
2015-05-09 22:19:21 -05:00
if type ( value ) == list and self . settings [ " general " ] [ " persist_size " ] != - 1 and len ( value ) > self . settings [ " general " ] [ " persist_size " ] :
2015-08-10 09:24:46 -05:00
shelf [ str ( key . encode ( " utf-8 " ) ) ] = value [ self . settings [ " general " ] [ " persist_size " ] : ]
2015-05-09 22:04:06 -05:00
else :
2015-08-10 09:24:46 -05:00
shelf [ str ( key . encode ( " utf-8 " ) ) ] = value
2015-05-02 02:41:28 -05:00
shelf . close ( )
except :
output . speak ( " An exception occurred while shelving the " + application . name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application . name + " developers. " , True )
log . exception ( " Exception while shelving " + shelfname )
os . remove ( shelfname )
2015-05-01 00:48:42 -05:00
def deshelve ( self ) :
" Import a shelved database. "
2015-05-13 22:21:47 -05:00
shelfname = paths . config_path ( str ( self . session_id ) + " /cache.db " )
2015-05-09 22:12:17 -05:00
if self . settings [ " general " ] [ " persist_size " ] == 0 :
2015-05-09 22:13:47 -05:00
if os . path . exists ( shelfname ) :
2015-05-09 22:12:17 -05:00
os . remove ( shelfname )
return
2015-05-02 02:41:28 -05:00
try :
shelf = shelve . open ( paths . config_path ( shelfname ) , ' c ' )
for key , value in shelf . items ( ) :
2015-08-10 09:24:46 -05:00
self . db [ key ] = value
2015-05-02 02:41:28 -05:00
shelf . close ( )
except :
output . speak ( " An exception occurred while deshelving the " + application . name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application . name + " developers. " , True )
log . exception ( " Exception while deshelving " + shelfname )
2015-06-11 16:35:56 -05:00
try :
os . remove ( shelfname )
except :
pass
2015-09-29 08:38:05 -05:00
def check_quoted_status ( self , tweet ) :
status = tweets . is_long ( tweet )
2016-08-06 14:47:42 -05:00
if status != False and config . app [ " app-settings " ] [ " handle_longtweets " ] :
2017-11-29 10:55:42 -06:00
quoted_tweet = self . get_quoted_tweet ( tweet )
return quoted_tweet
2015-09-29 08:38:05 -05:00
return tweet
def get_quoted_tweet ( self , tweet ) :
2016-04-28 13:54:06 -05:00
quoted_tweet = tweet
2016-10-03 22:54:54 -05:00
if tweet . has_key ( " full_text " ) :
value = " full_text "
else :
value = " text "
urls = utils . find_urls_in_text ( quoted_tweet [ value ] )
2015-09-29 08:38:05 -05:00
for url in range ( 0 , len ( urls ) ) :
2016-10-03 22:54:54 -05:00
try : quoted_tweet [ value ] = quoted_tweet [ value ] . replace ( urls [ url ] , quoted_tweet [ " entities " ] [ " urls " ] [ url ] [ " expanded_url " ] )
2015-09-29 08:38:05 -05:00
except IndexError : pass
2017-11-29 10:55:42 -06:00
if quoted_tweet . has_key ( " quoted_status " ) :
original_tweet = quoted_tweet [ " quoted_status " ]
elif quoted_tweet . has_key ( " retweeted_status " ) and quoted_tweet [ " retweeted_status " ] . has_key ( " quoted_status " ) :
original_tweet = quoted_tweet [ " retweeted_status " ] [ " quoted_status " ]
else :
return quoted_tweet
2016-07-27 11:56:38 -05:00
original_tweet = self . check_long_tweet ( original_tweet )
2017-12-05 08:43:26 -06:00
if original_tweet . has_key ( " full_text " ) :
value = " full_text "
2018-03-14 11:34:49 -06:00
elif original_tweet . has_key ( " message " ) :
value = " message "
2017-12-05 08:43:26 -06:00
else :
value = " text "
urls = utils . find_urls_in_text ( original_tweet [ value ] )
2015-09-29 08:38:05 -05:00
for url in range ( 0 , len ( urls ) ) :
2017-12-05 08:43:26 -06:00
try : original_tweet [ value ] = original_tweet [ value ] . replace ( urls [ url ] , original_tweet [ " entities " ] [ " urls " ] [ url ] [ " expanded_url " ] )
2015-09-29 08:38:05 -05:00
except IndexError : pass
return compose . compose_quoted_tweet ( quoted_tweet , original_tweet )
2016-04-28 13:54:06 -05:00
def check_long_tweet ( self , tweet ) :
long = twishort . is_long ( tweet )
2016-08-06 14:47:42 -05:00
if long != False and config . app [ " app-settings " ] [ " handle_longtweets " ] :
2018-03-14 11:34:49 -06:00
message = twishort . get_full_text ( long )
if tweet . has_key ( " quoted_status " ) :
tweet [ " quoted_status " ] [ " message " ] = message
if tweet [ " quoted_status " ] [ " message " ] == False : return False
tweet [ " quoted_status " ] [ " twishort " ] = True
for i in tweet [ " quoted_status " ] [ " entities " ] [ " user_mentions " ] :
if " @ %s " % ( i [ " screen_name " ] ) not in tweet [ " quoted_status " ] [ " message " ] and i [ " screen_name " ] != tweet [ " user " ] [ " screen_name " ] :
if tweet [ " quoted_status " ] . has_key ( " retweeted_status " ) and tweet [ " retweeted_status " ] [ " user " ] [ " screen_name " ] == i [ " screen_name " ] :
continue
tweet [ " quoted_status " ] [ " message " ] = u " @ %s %s " % ( i [ " screen_name " ] , tweet [ " message " ] )
else :
tweet [ " message " ] = message
if tweet [ " message " ] == False : return False
tweet [ " twishort " ] = True
for i in tweet [ " entities " ] [ " user_mentions " ] :
if " @ %s " % ( i [ " screen_name " ] ) not in tweet [ " message " ] and i [ " screen_name " ] != tweet [ " user " ] [ " screen_name " ] :
if tweet . has_key ( " retweeted_status " ) and tweet [ " retweeted_status " ] [ " user " ] [ " screen_name " ] == i [ " screen_name " ] :
continue
2018-07-17 10:58:09 -05:00
return tweet
def get_user ( self , id ) :
if self . db . has_key ( " users " ) == False or self . db [ " users " ] . has_key ( id ) == False :
user = self . twitter . twitter . show_user ( id = id )
2018-07-18 09:27:02 -05:00
self . db [ " users " ] [ user [ " id_str " ] ] = user
2018-07-17 10:58:09 -05:00
return user
else :
2018-07-25 11:22:57 -05:00
return self . db [ " users " ] [ id ]
def get_user_by_screen_name ( self , screen_name ) :
if self . db . has_key ( " users " ) == False :
user = utils . if_user_exists ( self . twitter . twitter , screen_name )
self . db [ " users " ] [ user [ " id_str " ] ] = user
return user [ " id_str " ]
else :
for i in self . db [ " users " ] . keys ( ) :
if self . db [ " users " ] [ i ] [ " screen_name " ] == screen_name :
return self . db [ " users " ] [ i ] [ " id_str " ]
user = utils . if_user_exists ( self . twitter . twitter , screen_name )
self . db [ " users " ] [ user [ " id_str " ] ] = user
return user [ " id_str " ]