Adding dnd caching to reduce server hits on login for Maemo 5
[theonering] / src / gvoice / session.py
1 #!/usr/bin/env python
2
3 import os
4 import time
5 import logging
6
7 import backend
8 import addressbook
9 import conversations
10 import state_machine
11
12
13 _moduleLogger = logging.getLogger("gvoice.session")
14
15
16 class Session(object):
17
18         def __init__(self, cookiePath = None):
19                 self._username = None
20                 self._password = None
21
22                 self._backend = backend.GVoiceBackend(cookiePath)
23
24                 self._addressbook = addressbook.Addressbook(self._backend)
25                 self._addressbookStateMachine = state_machine.UpdateStateMachine([self.addressbook], "Addressbook")
26                 self._addressbookStateMachine.set_state_strategy(
27                         state_machine.StateMachine.STATE_DND,
28                         state_machine.NopStateStrategy()
29                 )
30                 self._addressbookStateMachine.set_state_strategy(
31                         state_machine.StateMachine.STATE_IDLE,
32                         state_machine.ConstantStateStrategy(state_machine.to_milliseconds(hours=6))
33                 )
34                 self._addressbookStateMachine.set_state_strategy(
35                         state_machine.StateMachine.STATE_ACTIVE,
36                         state_machine.ConstantStateStrategy(state_machine.to_milliseconds(hours=2))
37                 )
38
39                 self._voicemails = conversations.Conversations(self._backend.get_voicemails)
40                 self._voicemailsStateMachine = state_machine.UpdateStateMachine([self.voicemails], "Voicemail")
41                 self._voicemailsStateMachine.set_state_strategy(
42                         state_machine.StateMachine.STATE_DND,
43                         state_machine.NopStateStrategy()
44                 )
45                 self._voicemailsStateMachine.set_state_strategy(
46                         state_machine.StateMachine.STATE_IDLE,
47                         state_machine.ConstantStateStrategy(state_machine.to_milliseconds(minutes=60))
48                 )
49                 self._voicemailsStateMachine.set_state_strategy(
50                         state_machine.StateMachine.STATE_ACTIVE,
51                         state_machine.ConstantStateStrategy(state_machine.to_milliseconds(minutes=10))
52                 )
53                 self._voicemails.updateSignalHandler.register_sink(
54                         self._voicemailsStateMachine.request_reset_timers
55                 )
56
57                 self._texts = conversations.Conversations(self._backend.get_texts)
58                 self._textsStateMachine = state_machine.UpdateStateMachine([self.texts], "Texting")
59                 self._textsStateMachine.set_state_strategy(
60                         state_machine.StateMachine.STATE_DND,
61                         state_machine.NopStateStrategy()
62                 )
63                 self._textsStateMachine.set_state_strategy(
64                         state_machine.StateMachine.STATE_IDLE,
65                         state_machine.ConstantStateStrategy(state_machine.to_milliseconds(minutes=30))
66                 )
67                 self._textsStateMachine.set_state_strategy(
68                         state_machine.StateMachine.STATE_ACTIVE,
69                         state_machine.GeometricStateStrategy(
70                                 state_machine.to_milliseconds(seconds=20),
71                                 state_machine.to_milliseconds(milliseconds=500),
72                                 state_machine.to_milliseconds(minutes=10),
73                         )
74                 )
75                 self._texts.updateSignalHandler.register_sink(
76                         self._textsStateMachine.request_reset_timers
77                 )
78
79                 self._masterStateMachine = state_machine.MasterStateMachine()
80                 self._masterStateMachine.append_machine(self._addressbookStateMachine)
81                 self._masterStateMachine.append_machine(self._voicemailsStateMachine)
82                 self._masterStateMachine.append_machine(self._textsStateMachine)
83
84                 self._lastDndCheck = 0
85                 self._cachedIsDnd = False
86
87         def load(self, path):
88                 self._texts.load(os.sep.join((path, "texts.cache")))
89                 self._voicemails.load(os.sep.join((path, "voicemails.cache")))
90
91         def save(self, path):
92                 self._texts.save(os.sep.join((path, "texts.cache")))
93                 self._voicemails.save(os.sep.join((path, "voicemails.cache")))
94
95         def close(self):
96                 self._voicemails.updateSignalHandler.unregister_sink(
97                         self._voicemailsStateMachine.request_reset_timers
98                 )
99                 self._texts.updateSignalHandler.unregister_sink(
100                         self._textsStateMachine.request_reset_timers
101                 )
102                 self._masterStateMachine.close()
103
104         def login(self, username, password):
105                 self._username = username
106                 self._password = password
107                 self._backend.login(self._username, self._password)
108
109                 self._masterStateMachine.start()
110
111         def logout(self):
112                 self._masterStateMachine.stop()
113                 self._backend.logout()
114
115                 self._username = None
116                 self._password = None
117
118         def is_logged_in(self):
119                 if self._username is None and self._password is None:
120                         _moduleLogger.info("Hasn't even attempted to login yet")
121                         return False
122                 elif self._backend.is_authed():
123                         return True
124                 else:
125                         try:
126                                 loggedIn = self._backend.login(self._username, self._password)
127                         except RuntimeError, e:
128                                 _moduleLogger.exception("Re-authenticating and erroring")
129                                 loggedIn = False
130                         if loggedIn:
131                                 return True
132                         else:
133                                 _moduleLogger.info("Login failed")
134                                 self.logout()
135                                 return False
136
137         def set_dnd(self, doNotDisturb):
138                 self._backend.set_dnd(doNotDisturb)
139                 self._cachedIsDnd = doNotDisturb
140
141         def is_dnd(self):
142                 # To throttle checking with the server, use a 30s cache
143                 newTime = time.time()
144                 if self._lastDndCheck + 30 < newTime:
145                         self._lasDndCheck = newTime
146                         self._cachedIsDnd = self._backend.is_dnd()
147                 return self._cachedIsDnd
148
149         @property
150         def backend(self):
151                 """
152                 Login enforcing backend
153                 """
154                 assert self.is_logged_in(), "User not logged in"
155                 return self._backend
156
157         @property
158         def addressbook(self):
159                 return self._addressbook
160
161         @property
162         def texts(self):
163                 return self._texts
164
165         @property
166         def voicemails(self):
167                 return self._voicemails
168
169         @property
170         def stateMachine(self):
171                 return self._masterStateMachine
172
173         @property
174         def addressbookStateMachine(self):
175                 return self._addressbookStateMachine
176
177         @property
178         def voicemailsStateMachine(self):
179                 return self._voicemailsStateMachine
180
181         @property
182         def textsStateMachine(self):
183                 return self._textsStateMachine