13 _moduleLogger = logging.getLogger("gvoice.session")
16 class Session(object):
19 "contacts": (12, "hours"),
20 "voicemail": (120, "minutes"),
21 "texts": (10, "minutes"),
24 _MINIMUM_MESSAGE_PERIOD = state_machine.to_seconds(minutes=30)
26 def __init__(self, cookiePath = None, defaults = None):
28 defaults = self._DEFAULTS
30 for key, (quant, unit) in defaults.iteritems():
32 defaults[key] = (self._DEFAULTS[key], unit)
34 defaults[key] = (state_machine.UpdateStateMachine.INFINITE_PERIOD, unit)
38 self._backend = backend.GVoiceBackend(cookiePath)
40 if defaults["contacts"][0] == state_machine.UpdateStateMachine.INFINITE_PERIOD:
41 contactsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
43 contactsPeriodInSeconds = state_machine.to_seconds(
44 **{defaults["contacts"][1]: defaults["contacts"][0],}
46 self._addressbook = addressbook.Addressbook(self._backend)
47 self._addressbookStateMachine = state_machine.UpdateStateMachine([self.addressbook], "Addressbook")
48 self._addressbookStateMachine.set_state_strategy(
49 state_machine.StateMachine.STATE_DND,
50 state_machine.NopStateStrategy()
52 self._addressbookStateMachine.set_state_strategy(
53 state_machine.StateMachine.STATE_IDLE,
54 state_machine.NopStateStrategy()
56 self._addressbookStateMachine.set_state_strategy(
57 state_machine.StateMachine.STATE_ACTIVE,
58 state_machine.ConstantStateStrategy(contactsPeriodInSeconds)
61 if defaults["voicemail"][0] == state_machine.UpdateStateMachine.INFINITE_PERIOD:
62 voicemailPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
63 idleVoicemailPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
65 voicemailPeriodInSeconds = state_machine.to_seconds(
66 **{defaults["voicemail"][1]: defaults["voicemail"][0],}
68 idleVoicemailPeriodInSeconds = max(voicemailPeriodInSeconds * 4, self._MINIMUM_MESSAGE_PERIOD)
69 self._voicemails = conversations.Conversations(self._backend.get_voicemails)
70 self._voicemailsStateMachine = state_machine.UpdateStateMachine([self.voicemails], "Voicemail")
71 self._voicemailsStateMachine.set_state_strategy(
72 state_machine.StateMachine.STATE_DND,
73 state_machine.NopStateStrategy()
75 self._voicemailsStateMachine.set_state_strategy(
76 state_machine.StateMachine.STATE_IDLE,
77 state_machine.ConstantStateStrategy(idleVoicemailPeriodInSeconds)
79 self._voicemailsStateMachine.set_state_strategy(
80 state_machine.StateMachine.STATE_ACTIVE,
81 state_machine.NTimesStateStrategy(
82 3 * [state_machine.to_seconds(minutes=1)], voicemailPeriodInSeconds
85 self._voicemails.updateSignalHandler.register_sink(
86 self._voicemailsStateMachine.request_reset_timers
89 if defaults["texts"][0] == state_machine.UpdateStateMachine.INFINITE_PERIOD:
90 initTextsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
91 minTextsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
92 textsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
93 idleTextsPeriodInSeconds = state_machine.UpdateStateMachine.INFINITE_PERIOD
95 initTextsPeriodInSeconds = state_machine.to_seconds(seconds=20)
96 minTextsPeriodInSeconds = state_machine.to_seconds(seconds=1)
97 textsPeriodInSeconds = state_machine.to_seconds(
98 **{defaults["texts"][1]: defaults["texts"][0],}
100 idleTextsPeriodInSeconds = max(textsPeriodInSeconds * 4, self._MINIMUM_MESSAGE_PERIOD)
101 self._texts = conversations.Conversations(self._backend.get_texts)
102 self._textsStateMachine = state_machine.UpdateStateMachine([self.texts], "Texting")
103 self._textsStateMachine.set_state_strategy(
104 state_machine.StateMachine.STATE_DND,
105 state_machine.NopStateStrategy()
107 self._textsStateMachine.set_state_strategy(
108 state_machine.StateMachine.STATE_IDLE,
109 state_machine.ConstantStateStrategy(idleTextsPeriodInSeconds)
111 self._textsStateMachine.set_state_strategy(
112 state_machine.StateMachine.STATE_ACTIVE,
113 state_machine.GeometricStateStrategy(
114 initTextsPeriodInSeconds,
115 minTextsPeriodInSeconds,
116 textsPeriodInSeconds,
119 self._texts.updateSignalHandler.register_sink(
120 self._textsStateMachine.request_reset_timers
123 self._masterStateMachine = state_machine.MasterStateMachine()
124 self._masterStateMachine.append_machine(self._addressbookStateMachine)
125 self._masterStateMachine.append_machine(self._voicemailsStateMachine)
126 self._masterStateMachine.append_machine(self._textsStateMachine)
128 self._lastDndCheck = 0
129 self._cachedIsDnd = False
131 def load(self, path):
132 self._texts.load(os.sep.join((path, "texts.cache")))
133 self._voicemails.load(os.sep.join((path, "voicemails.cache")))
135 def save(self, path):
136 self._texts.save(os.sep.join((path, "texts.cache")))
137 self._voicemails.save(os.sep.join((path, "voicemails.cache")))
140 self._voicemails.updateSignalHandler.unregister_sink(
141 self._voicemailsStateMachine.request_reset_timers
143 self._texts.updateSignalHandler.unregister_sink(
144 self._textsStateMachine.request_reset_timers
146 self._masterStateMachine.close()
148 def login(self, username, password):
149 self._username = username
150 self._password = password
151 self._backend.login(self._username, self._password)
153 self._masterStateMachine.start()
156 self._masterStateMachine.stop()
157 self._backend.logout()
159 self._username = None
160 self._password = None
162 def is_logged_in(self):
163 if self._username is None and self._password is None:
164 _moduleLogger.info("Hasn't even attempted to login yet")
166 elif self._backend.is_authed():
170 loggedIn = self._backend.login(self._username, self._password)
171 except RuntimeError, e:
172 _moduleLogger.exception("Re-authenticating and erroring")
177 _moduleLogger.info("Login failed")
181 def set_dnd(self, doNotDisturb):
182 self._backend.set_dnd(doNotDisturb)
183 self._cachedIsDnd = doNotDisturb
186 # To throttle checking with the server, use a 30s cache
187 newTime = time.time()
188 if self._lastDndCheck + 30 < newTime:
189 self._lastDndCheck = newTime
190 self._cachedIsDnd = self._backend.is_dnd()
191 return self._cachedIsDnd
196 Login enforcing backend
198 assert self.is_logged_in(), "User not logged in"
202 def addressbook(self):
203 return self._addressbook
210 def voicemails(self):
211 return self._voicemails
214 def stateMachine(self):
215 return self._masterStateMachine
218 def addressbookStateMachine(self):
219 return self._addressbookStateMachine
222 def voicemailsStateMachine(self):
223 return self._voicemailsStateMachine
226 def textsStateMachine(self):
227 return self._textsStateMachine