12 import util.go_utils as gobject_utils
15 _moduleLogger = logging.getLogger(__name__)
18 class Session(object):
21 "contacts": (12, "hours"),
22 "voicemail": (120, "minutes"),
23 "texts": (10, "minutes"),
26 _MINIMUM_MESSAGE_PERIOD = state_machine.to_seconds(minutes=30)
28 def __init__(self, cookiePath = None, defaults = None):
30 defaults = self._DEFAULTS
32 for key, (quant, unit) in defaults.iteritems():
34 defaults[key] = (self._DEFAULTS[key], unit)
36 defaults[key] = (state_machine.UpdateStateMachine.INFINITE_PERIOD, unit)
40 self._asyncPool = gobject_utils.AsyncPool()
41 self._backend = backend.GVoiceBackend(cookiePath)
43 if defaults["contacts"][0] == state_machine.UpdateStateMachine.INFINITE_PERIOD:
44 contactsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
46 contactsPeriodInSeconds = state_machine.to_seconds(
47 **{defaults["contacts"][1]: defaults["contacts"][0],}
49 self._addressbook = addressbook.Addressbook(self._backend, self._asyncPool)
50 self._addressbookStateMachine = state_machine.UpdateStateMachine([self.addressbook], "Addressbook")
51 self._addressbookStateMachine.set_state_strategy(
52 state_machine.StateMachine.STATE_DND,
53 state_machine.NopStateStrategy()
55 self._addressbookStateMachine.set_state_strategy(
56 state_machine.StateMachine.STATE_IDLE,
57 state_machine.NopStateStrategy()
59 self._addressbookStateMachine.set_state_strategy(
60 state_machine.StateMachine.STATE_ACTIVE,
61 state_machine.ConstantStateStrategy(contactsPeriodInSeconds)
64 if defaults["voicemail"][0] == state_machine.UpdateStateMachine.INFINITE_PERIOD:
65 voicemailPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
66 idleVoicemailPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
68 voicemailPeriodInSeconds = state_machine.to_seconds(
69 **{defaults["voicemail"][1]: defaults["voicemail"][0],}
71 idleVoicemailPeriodInSeconds = max(voicemailPeriodInSeconds * 4, self._MINIMUM_MESSAGE_PERIOD)
72 self._voicemails = conversations.Conversations(self._backend.get_voicemails, self._asyncPool)
73 self._voicemailsStateMachine = state_machine.UpdateStateMachine([self.voicemails], "Voicemail")
74 self._voicemailsStateMachine.set_state_strategy(
75 state_machine.StateMachine.STATE_DND,
76 state_machine.NopStateStrategy()
78 self._voicemailsStateMachine.set_state_strategy(
79 state_machine.StateMachine.STATE_IDLE,
80 state_machine.ConstantStateStrategy(idleVoicemailPeriodInSeconds)
82 self._voicemailsStateMachine.set_state_strategy(
83 state_machine.StateMachine.STATE_ACTIVE,
84 state_machine.NTimesStateStrategy(
85 3 * [state_machine.to_seconds(minutes=1)], voicemailPeriodInSeconds
88 self._voicemails.updateSignalHandler.register_sink(
89 self._voicemailsStateMachine.request_reset_timers
92 if defaults["texts"][0] == state_machine.UpdateStateMachine.INFINITE_PERIOD:
93 initTextsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
94 minTextsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
95 textsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
96 idleTextsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
98 initTextsPeriodInSeconds = state_machine.to_seconds(seconds=20)
99 minTextsPeriodInSeconds = state_machine.to_seconds(seconds=1)
100 textsPeriodInSeconds = state_machine.to_seconds(
101 **{defaults["texts"][1]: defaults["texts"][0],}
103 idleTextsPeriodInSeconds = max(textsPeriodInSeconds * 4, self._MINIMUM_MESSAGE_PERIOD)
104 self._texts = conversations.Conversations(self._backend.get_texts, self._asyncPool)
105 self._textsStateMachine = state_machine.UpdateStateMachine([self.texts], "Texting")
106 self._textsStateMachine.set_state_strategy(
107 state_machine.StateMachine.STATE_DND,
108 state_machine.NopStateStrategy()
110 self._textsStateMachine.set_state_strategy(
111 state_machine.StateMachine.STATE_IDLE,
112 state_machine.ConstantStateStrategy(idleTextsPeriodInSeconds)
114 self._textsStateMachine.set_state_strategy(
115 state_machine.StateMachine.STATE_ACTIVE,
116 state_machine.GeometricStateStrategy(
117 initTextsPeriodInSeconds,
118 minTextsPeriodInSeconds,
119 textsPeriodInSeconds,
122 self._texts.updateSignalHandler.register_sink(
123 self._textsStateMachine.request_reset_timers
126 self._masterStateMachine = state_machine.MasterStateMachine()
127 self._masterStateMachine.append_machine(self._addressbookStateMachine)
128 self._masterStateMachine.append_machine(self._voicemailsStateMachine)
129 self._masterStateMachine.append_machine(self._textsStateMachine)
131 self._lastDndCheck = 0
132 self._cachedIsDnd = False
134 def load(self, path):
135 self._texts.load(os.sep.join((path, "texts.cache")))
136 self._voicemails.load(os.sep.join((path, "voicemails.cache")))
138 def save(self, path):
139 self._texts.save(os.sep.join((path, "texts.cache")))
140 self._voicemails.save(os.sep.join((path, "voicemails.cache")))
143 self._voicemails.updateSignalHandler.unregister_sink(
144 self._voicemailsStateMachine.request_reset_timers
146 self._texts.updateSignalHandler.unregister_sink(
147 self._textsStateMachine.request_reset_timers
149 self._masterStateMachine.close()
151 def login(self, username, password, on_success, on_error):
152 self._username = username
153 self._password = password
154 self._asyncPool.start()
155 self._asyncPool.add_task(
157 (self._username, self._password),
159 self.__on_login_success(on_success),
163 def __on_login_success(self, user_success):
165 def _actual_success(self, *args, **kwds):
166 self._masterStateMachine.start()
167 user_success(*args, **kwds)
169 return _actual_success
172 self._asyncPool.stop()
173 self._masterStateMachine.stop()
174 self._backend.logout()
176 self._username = None
177 self._password = None
179 def is_logged_in(self):
180 if self._username is None and self._password is None:
181 _moduleLogger.info("Hasn't even attempted to login yet")
183 elif self._backend.is_authed():
187 loggedIn = self._backend.login(self._username, self._password)
188 except RuntimeError, e:
189 _moduleLogger.exception("Re-authenticating and erroring")
194 _moduleLogger.info("Login failed")
198 def set_dnd(self, doNotDisturb):
199 self._backend.set_dnd(doNotDisturb)
200 self._cachedIsDnd = doNotDisturb
203 # To throttle checking with the server, use a 30s cache
204 newTime = time.time()
205 if self._lastDndCheck + 30 < newTime:
206 self._lastDndCheck = newTime
207 self._cachedIsDnd = self._backend.is_dnd()
208 return self._cachedIsDnd
216 return self._asyncPool
219 def addressbook(self):
220 return self._addressbook
227 def voicemails(self):
228 return self._voicemails
231 def stateMachine(self):
232 return self._masterStateMachine
235 def addressbookStateMachine(self):
236 return self._addressbookStateMachine
239 def voicemailsStateMachine(self):
240 return self._voicemailsStateMachine
243 def textsStateMachine(self):
244 return self._textsStateMachine