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