Switching to multiple 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])
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._conversations = conversations.Conversations(self._backend)
38                 self._conversationsStateMachine = state_machine.UpdateStateMachine([self.conversations])
39                 self._conversationsStateMachine.set_state_strategy(
40                         state_machine.StateMachine.STATE_DND,
41                         state_machine.NopStateStrategy()
42                 )
43                 self._conversationsStateMachine.set_state_strategy(
44                         state_machine.StateMachine.STATE_IDLE,
45                         state_machine.ConstantStateStrategy(state_machine.to_milliseconds(minutes=30))
46                 )
47                 self._conversationsStateMachine.set_state_strategy(
48                         state_machine.StateMachine.STATE_ACTIVE,
49                         state_machine.GeometricStateStrategy(
50                                 state_machine.to_milliseconds(seconds=10),
51                                 state_machine.to_milliseconds(seconds=1),
52                                 state_machine.to_milliseconds(minutes=10),
53                         )
54                 )
55
56                 self._masterStateMachine = state_machine.MasterStateMachine()
57                 self._masterStateMachine.append_machine(self._addressbookStateMachine)
58                 self._masterStateMachine.append_machine(self._conversationsStateMachine)
59
60                 self._conversations.updateSignalHandler.register_sink(
61                         self._conversationsStateMachine.request_reset_timers
62                 )
63
64         def close(self):
65                 self._conversations.updateSignalHandler.unregister_sink(
66                         self._conversationsStateMachine.request_reset_timers
67                 )
68                 self._masterStateMachine.close()
69
70         def login(self, username, password):
71                 self._username = username
72                 self._password = password
73                 if not self._backend.is_authed():
74                         self._backend.login(self._username, self._password)
75
76                 self._masterStateMachine.start()
77
78         def logout(self):
79                 self._masterStateMachine.stop()
80                 self._backend.logout()
81
82                 self._username = None
83                 self._password = None
84
85         def is_logged_in(self):
86                 if self._username is None and self._password is None:
87                         _moduleLogger.info("Hasn't even attempted to login yet")
88                         return False
89                 elif self._backend.is_authed():
90                         return True
91                 else:
92                         try:
93                                 loggedIn = self._backend.login(self._username, self._password)
94                         except RuntimeError, e:
95                                 _moduleLogger.exception("Re-authenticating and erroring")
96                                 loggedIn = False
97                         if loggedIn:
98                                 return True
99                         else:
100                                 _moduleLogger.info("Login failed")
101                                 self.logout()
102                                 return False
103
104         @property
105         def backend(self):
106                 """
107                 Login enforcing backend
108                 """
109                 assert self.is_logged_in(), "User not logged in"
110                 return self._backend
111
112         @property
113         def addressbook(self):
114                 """
115                 Delay initialized addressbook
116                 """
117                 return self._addressbook
118
119         @property
120         def conversations(self):
121                 """
122                 Delay initialized addressbook
123                 """
124                 return self._conversations
125
126         @property
127         def stateMachine(self):
128                 return self._masterStateMachine
129
130         @property
131         def addressbookStateMachine(self):
132                 return self._addressbookStateMachine
133
134         @property
135         def conversationsStateMachine(self):
136                 return self._conversationsStateMachine