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