From: Ed Page Date: Fri, 8 Jan 2010 03:27:10 +0000 (-0600) Subject: Separating voicemail / texts into their own state machines X-Git-Url: http://git.maemo.org/git/?p=theonering;a=commitdiff_plain;h=65374a31d2215fb2883146dbab644336514fb31d Separating voicemail / texts into their own state machines --- diff --git a/src/channel/text.py b/src/channel/text.py index 4eb601d..2b39833 100644 --- a/src/channel/text.py +++ b/src/channel/text.py @@ -37,14 +37,23 @@ class TextChannel(telepathy.server.ChannelTypeText): self._on_conversations_updated ) ) - self._conn.session.conversations.updateSignalHandler.register_sink( + self._conn.session.voicemails.updateSignalHandler.register_sink( + self._callback + ) + self._conn.session.texts.updateSignalHandler.register_sink( self._callback ) # The only reason there should be anything in the conversation is if # its new, so report it all try: - mergedConversations = self._conn.session.conversations.get_conversation(self._contactKey) + mergedConversations = self._conn.session.voicemails.get_conversation(self._contactKey) + except KeyError: + _moduleLogger.info("Nothing in the conversation yet for %r" % (self._contactKey, )) + else: + self._report_conversation(mergedConversations) + try: + mergedConversations = self._conn.session.texts.get_conversation(self._contactKey) except KeyError: _moduleLogger.info("Nothing in the conversation yet for %r" % (self._contactKey, )) else: @@ -56,7 +65,7 @@ class TextChannel(telepathy.server.ChannelTypeText): raise telepathy.errors.NotImplemented("Unhandled message type: %r" % messageType) self._conn.session.backend.send_sms(self._otherHandle.phoneNumber, text) - self._conn.session.conversationsStateMachine.reset_timers() + self._conn.session.textsStateMachine.reset_timers() self.Sent(int(time.time()), messageType, text) @@ -65,7 +74,10 @@ class TextChannel(telepathy.server.ChannelTypeText): self.close() def close(self): - self._conn.session.conversations.updateSignalHandler.unregister_sink( + self._conn.session.voicemails.updateSignalHandler.unregister_sink( + self._callback + ) + self._conn.session.texts.updateSignalHandler.unregister_sink( self._callback ) self._callback = None @@ -87,7 +99,7 @@ class TextChannel(telepathy.server.ChannelTypeText): if self._contactKey not in conversationIds: return _moduleLogger.info("Incoming messages from %r for existing conversation" % (self._contactKey, )) - mergedConversations = self._conn.session.conversations.get_conversation(self._contactKey) + mergedConversations = conv.get_conversation(self._contactKey) self._report_conversation(mergedConversations) def _report_conversation(self, mergedConversations): diff --git a/src/connection.py b/src/connection.py index 18bdd4e..8885232 100644 --- a/src/connection.py +++ b/src/connection.py @@ -1,12 +1,9 @@ """ -@todo Add params for disable/enable state machines -@todo Separate voicemail/sms into separate conversation instances -@todo Setup addressbook, voicemail, sms state machines +@todo Add params for different state machines update times @todo Add option to use screen name as callback @todo Get a callback for missed calls to force an update of the voicemail state machine @todo Get a callback on an incoming call and if its from GV, auto-pickup -@todo Use state-strategies to keep mega-state-machine generic @todo Observe when connected/disconnected to disconnect CM """ @@ -137,7 +134,10 @@ class TheOneRingConnection( self._on_conversations_updated ) ) - self.session.conversations.updateSignalHandler.register_sink( + self.session.voicemails.updateSignalHandler.register_sink( + self._callback + ) + self.session.texts.updateSignalHandler.register_sink( self._callback ) self.session.login(*self._credentials) @@ -169,7 +169,10 @@ class TheOneRingConnection( """ _moduleLogger.info("Disconnecting") try: - self.session.conversations.updateSignalHandler.unregister_sink( + self.session.voicemails.updateSignalHandler.unregister_sink( + self._callback + ) + self.session.texts.updateSignalHandler.unregister_sink( self._callback ) self._callback = None @@ -256,8 +259,6 @@ class TheOneRingConnection( @gobject_utils.async @gtk_toolbox.log_exception(_moduleLogger) def _on_conversations_updated(self, conv, conversationIds): - # @todo get conversations update running - # @todo test conversatiuons _moduleLogger.info("Incoming messages from: %r" % (conversationIds, )) for contactId, phoneNumber in conversationIds: h = handle.create_handle(self, 'contact', contactId, phoneNumber) diff --git a/src/gvoice/backend.py b/src/gvoice/backend.py index bf9aed1..3b1d568 100755 --- a/src/gvoice/backend.py +++ b/src/gvoice/backend.py @@ -477,21 +477,21 @@ class GVoiceBackend(object): if contactId != "0": yield contactId, contactDetails - def get_conversations(self): + def get_voicemails(self): voicemailPage = self._get_page(self._XML_VOICEMAIL_URL) voicemailHtml = self._grab_html(voicemailPage) voicemailJson = self._grab_json(voicemailPage) parsedVoicemail = self._parse_voicemail(voicemailHtml) voicemails = self._merge_conversation_sources(parsedVoicemail, voicemailJson) + return voicemails + def get_texts(self): smsPage = self._get_page(self._XML_SMS_URL) smsHtml = self._grab_html(smsPage) smsJson = self._grab_json(smsPage) parsedSms = self._parse_sms(smsHtml) smss = self._merge_conversation_sources(parsedSms, smsJson) - - allConversations = itertools.chain(voicemails, smss) - return allConversations + return smss def mark_message(self, messageId, asRead): postData = { diff --git a/src/gvoice/conversations.py b/src/gvoice/conversations.py index 36aca67..d5e060f 100644 --- a/src/gvoice/conversations.py +++ b/src/gvoice/conversations.py @@ -12,8 +12,8 @@ _moduleLogger = logging.getLogger("gvoice.conversations") class Conversations(object): - def __init__(self, backend): - self._backend = backend + def __init__(self, getter): + self._get_raw_conversations = getter self._conversations = {} self.updateSignalHandler = coroutines.CoTee() @@ -25,7 +25,7 @@ class Conversations(object): oldConversationIds = set(self._conversations.iterkeys()) updateConversationIds = set() - conversations = list(self._backend.get_conversations()) + conversations = list(self._get_raw_conversations()) conversations.sort() for conversation in conversations: key = conversation.contactId, util_misc.strip_number(conversation.number) diff --git a/src/gvoice/session.py b/src/gvoice/session.py index adb551e..0235daa 100644 --- a/src/gvoice/session.py +++ b/src/gvoice/session.py @@ -20,7 +20,7 @@ class Session(object): self._backend = backend.GVoiceBackend(cookiePath) self._addressbook = addressbook.Addressbook(self._backend) - self._addressbookStateMachine = state_machine.UpdateStateMachine([self.addressbook]) + self._addressbookStateMachine = state_machine.UpdateStateMachine([self.addressbook], "Addressbook") self._addressbookStateMachine.set_state_strategy( state_machine.StateMachine.STATE_DND, state_machine.NopStateStrategy() @@ -34,17 +34,35 @@ class Session(object): state_machine.ConstantStateStrategy(state_machine.to_milliseconds(hours=1)) ) - self._conversations = conversations.Conversations(self._backend) - self._conversationsStateMachine = state_machine.UpdateStateMachine([self.conversations]) - self._conversationsStateMachine.set_state_strategy( + self._voicemails = conversations.Conversations(self._backend.get_voicemails) + self._voicemailsStateMachine = state_machine.UpdateStateMachine([self.voicemails], "Voicemail") + self._voicemailsStateMachine.set_state_strategy( state_machine.StateMachine.STATE_DND, state_machine.NopStateStrategy() ) - self._conversationsStateMachine.set_state_strategy( + self._voicemailsStateMachine.set_state_strategy( state_machine.StateMachine.STATE_IDLE, state_machine.ConstantStateStrategy(state_machine.to_milliseconds(minutes=30)) ) - self._conversationsStateMachine.set_state_strategy( + self._voicemailsStateMachine.set_state_strategy( + state_machine.StateMachine.STATE_ACTIVE, + state_machine.ConstantStateStrategy(state_machine.to_milliseconds(minutes=5)) + ) + self._voicemails.updateSignalHandler.register_sink( + self._voicemailsStateMachine.request_reset_timers + ) + + self._texts = conversations.Conversations(self._backend.get_texts) + self._textsStateMachine = state_machine.UpdateStateMachine([self.texts], "Texting") + self._textsStateMachine.set_state_strategy( + state_machine.StateMachine.STATE_DND, + state_machine.NopStateStrategy() + ) + self._textsStateMachine.set_state_strategy( + state_machine.StateMachine.STATE_IDLE, + state_machine.ConstantStateStrategy(state_machine.to_milliseconds(minutes=30)) + ) + self._textsStateMachine.set_state_strategy( state_machine.StateMachine.STATE_ACTIVE, state_machine.GeometricStateStrategy( state_machine.to_milliseconds(seconds=10), @@ -52,18 +70,21 @@ class Session(object): state_machine.to_milliseconds(minutes=10), ) ) + self._texts.updateSignalHandler.register_sink( + self._textsStateMachine.request_reset_timers + ) self._masterStateMachine = state_machine.MasterStateMachine() self._masterStateMachine.append_machine(self._addressbookStateMachine) - self._masterStateMachine.append_machine(self._conversationsStateMachine) - - self._conversations.updateSignalHandler.register_sink( - self._conversationsStateMachine.request_reset_timers - ) + self._masterStateMachine.append_machine(self._voicemailsStateMachine) + self._masterStateMachine.append_machine(self._textsStateMachine) def close(self): - self._conversations.updateSignalHandler.unregister_sink( - self._conversationsStateMachine.request_reset_timers + self._voicemails.updateSignalHandler.unregister_sink( + self._voicemailsStateMachine.request_reset_timers + ) + self._texts.updateSignalHandler.unregister_sink( + self._textsStateMachine.request_reset_timers ) self._masterStateMachine.close() @@ -111,17 +132,15 @@ class Session(object): @property def addressbook(self): - """ - Delay initialized addressbook - """ return self._addressbook @property - def conversations(self): - """ - Delay initialized addressbook - """ - return self._conversations + def texts(self): + return self._texts + + @property + def voicemails(self): + return self._voicemails @property def stateMachine(self): @@ -132,5 +151,9 @@ class Session(object): return self._addressbookStateMachine @property - def conversationsStateMachine(self): - return self._conversationsStateMachine + def voicemailsStateMachine(self): + return self._voicemailsStateMachine + + @property + def textsStateMachine(self): + return self._textsStateMachine diff --git a/src/gvoice/state_machine.py b/src/gvoice/state_machine.py index d26a57c..3f9fcc2 100644 --- a/src/gvoice/state_machine.py +++ b/src/gvoice/state_machine.py @@ -151,7 +151,8 @@ class UpdateStateMachine(StateMachine): _IS_DAEMON = True - def __init__(self, updateItems): + def __init__(self, updateItems, name=""): + self._name = name self._updateItems = updateItems self._state = self.STATE_ACTIVE @@ -204,10 +205,6 @@ class UpdateStateMachine(StateMachine): def _strategy(self): return self._strategies[self._state] - @property - def _name(self): - return "/".join(type(s).__name__ for s in self._updateItems) - @gobject_utils.async @gtk_toolbox.log_exception(_moduleLogger) def _request_reset_timers(self, *args):