Reducing not-helpful traces
[theonering] / src / simple_presence.py
index 4f1c09b..bda9fed 100644 (file)
@@ -2,138 +2,127 @@ import logging
 
 import telepathy
 
+import util.misc as misc_utils
+import tp
+import handle
+import gvoice.state_machine as state_machine
 
-class ButterflyPresenceMapping(object):
+
+_moduleLogger = logging.getLogger(__name__)
+
+
+class TheOneRingPresence(object):
+
+       # Note: these strings are also in the theonering.profile file
        ONLINE = 'available'
        AWAY = 'away'
-       BUSY = 'dnd'
-       IDLE = 'xa'
-       BRB = 'brb'
-       PHONE = 'phone'
-       LUNCH = 'lunch'
-       INVISIBLE = 'hidden'
+       HIDDEN = 'hidden'
        OFFLINE = 'offline'
 
-       to_pymsn = {
-               ONLINE: pymsn.Presence.ONLINE,
-               AWAY: pymsn.Presence.AWAY,
-               BUSY: pymsn.Presence.BUSY,
-               IDLE: pymsn.Presence.IDLE,
-               BRB: pymsn.Presence.BE_RIGHT_BACK,
-               PHONE: pymsn.Presence.ON_THE_PHONE,
-               LUNCH: pymsn.Presence.OUT_TO_LUNCH,
-               INVISIBLE: pymsn.Presence.INVISIBLE,
-               OFFLINE: pymsn.Presence.OFFLINE
-       }
-
-       to_telepathy = {
-               pymsn.Presence.ONLINE: ONLINE,
-               pymsn.Presence.AWAY: AWAY,
-               pymsn.Presence.BUSY: BUSY,
-               pymsn.Presence.IDLE: IDLE,
-               pymsn.Presence.BE_RIGHT_BACK: BRB,
-               pymsn.Presence.ON_THE_PHONE: PHONE,
-               pymsn.Presence.OUT_TO_LUNCH: LUNCH,
-               pymsn.Presence.INVISIBLE: INVISIBLE,
-               pymsn.Presence.OFFLINE: OFFLINE
-       }
-
-       to_presence_type = {
+       TO_PRESENCE_TYPE = {
                ONLINE: telepathy.constants.CONNECTION_PRESENCE_TYPE_AVAILABLE,
                AWAY: telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY,
-               BUSY: telepathy.constants.CONNECTION_PRESENCE_TYPE_BUSY,
-               IDLE: telepathy.constants.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY,
-               BRB: telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY,
-               PHONE: telepathy.constants.CONNECTION_PRESENCE_TYPE_BUSY,
-               LUNCH: telepathy.constants.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY,
-               INVISIBLE: telepathy.constants.CONNECTION_PRESENCE_TYPE_HIDDEN,
-               OFFLINE: telepathy.constants.CONNECTION_PRESENCE_TYPE_OFFLINE
+               HIDDEN: telepathy.constants.CONNECTION_PRESENCE_TYPE_HIDDEN,
+               OFFLINE: telepathy.constants.CONNECTION_PRESENCE_TYPE_OFFLINE,
        }
 
+       @property
+       def session(self):
+               """
+               @abstract
+               """
+               raise NotImplementedError()
+
+       def Disconnect(self):
+               """
+               @abstract
+               """
+               raise NotImplementedError("Abstract function called")
+
+       def get_handle_by_id(self, handleType, handleId):
+               """
+               @abstract
+               """
+               raise NotImplementedError("Abstract function called")
+
+       def get_presences(self, contactIds):
+               """
+               @return {ContactHandle: (Status, Presence Type, Message)}
+               """
+               presences = {}
+               for handleId in contactIds:
+                       h = self.get_handle_by_id(telepathy.HANDLE_TYPE_CONTACT, handleId)
+                       if isinstance(h, handle.ConnectionHandle):
+                               isDnd = self.session.is_dnd()
+                               if isDnd:
+                                       presence = TheOneRingPresence.HIDDEN
+                               else:
+                                       state = self.session.stateMachine.state
+                                       if state == state_machine.StateMachine.STATE_ACTIVE:
+                                               presence = TheOneRingPresence.ONLINE
+                                       elif state == state_machine.StateMachine.STATE_IDLE:
+                                               presence = TheOneRingPresence.AWAY
+                                       else:
+                                               raise telepathy.errors.InvalidArgument("Unsupported state on the state machine: %s" % state)
+                               presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence]
+                       else:
+                               presence = TheOneRingPresence.AWAY
+                               presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence]
 
-class ButterflySimplePresence(telepathy.server.ConnectionInterfaceSimplePresence):
-
-       def __init__(self):
-               telepathy.server.ConnectionInterfaceSimplePresence.__init__(self)
-
-               dbus_interface = 'org.freedesktop.Telepathy.Connection.Interface.SimplePresence'
-
-               self._implement_property_get(dbus_interface, {'Statuses' : self.get_statuses})
-
-       def GetPresences(self, contacts):
-               return self.get_simple_presences(contacts)
+                       presences[h] = (presenceType, presence)
+               return presences
 
-       def SetPresence(self, status, message):
-               if status == ButterflyPresenceMapping.OFFLINE:
+       def set_presence(self, status):
+               if status == self.ONLINE:
+                       self.session.set_dnd(False)
+                       self.session.stateMachine.set_state(state_machine.StateMachine.STATE_ACTIVE)
+               elif status == self.AWAY:
+                       self.session.stateMachine.set_state(state_machine.StateMachine.STATE_IDLE)
+               elif status == self.HIDDEN:
+                       self.session.set_dnd(True)
+               elif status == self.OFFLINE:
                        self.Disconnect()
+               else:
+                       raise telepathy.errors.InvalidArgument("Unsupported status: %r" % status)
+               _moduleLogger.info("Setting Presence to '%s'" % status)
 
-               try:
-                       presence = ButterflyPresenceMapping.to_pymsn[status]
-               except KeyError:
-                       raise telepathy.errors.InvalidArgument
-               message = message.encode("utf-8")
 
-               logging.info("Setting Presence to '%s'" % presence)
-               logging.info("Setting Personal message to '%s'" % message)
+class SimplePresenceMixin(tp.ConnectionInterfaceSimplePresence, TheOneRingPresence):
 
-               if self._status != telepathy.CONNECTION_STATUS_CONNECTED:
-                       self._initial_presence = presence
-                       self._initial_personal_message = message
-               else:
-                       self.msn_client.profile.personal_message = message
-                       self.msn_client.profile.presence = presence
+       def __init__(self):
+               tp.ConnectionInterfaceSimplePresence.__init__(self)
+               TheOneRingPresence.__init__(self)
 
-       def get_simple_presences(self, contacts):
-               presences = {}
-               for handle_id in contacts:
-                       handle = self.handle(telepathy.HANDLE_TYPE_CONTACT, handle_id)
-                       try:
-                               contact = handle.contact
-                       except AttributeError:
-                               contact = handle.profile
-
-                       if contact is not None:
-                               presence = ButterflyPresenceMapping.to_telepathy[contact.presence]
-                               personal_message = unicode(contact.personal_message, "utf-8")
-                       else:
-                               presence = ButterflyPresenceMapping.OFFLINE
-                               personal_message = u""
+               self._implement_property_get(
+                       tp.CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+                       {'Statuses' : self._get_statuses}
+               )
 
-                       presence_type = ButterflyPresenceMapping.to_presence_type[presence]
+       @misc_utils.log_exception(_moduleLogger)
+       def GetPresences(self, contacts):
+               """
+               @return {ContactHandle: (Status, Presence Type, Message)}
+               """
+               personalMessage = u""
+               return dict(
+                       (h, (presenceType, presence, personalMessage))
+                       for (h, (presenceType, presence)) in self.get_presences(contacts).iteritems()
+               )
+
+       @misc_utils.log_exception(_moduleLogger)
+       def SetPresence(self, status, message):
+               if message:
+                       raise telepathy.errors.InvalidArgument("Messages aren't supported")
 
-                       presences[handle] = (presence_type, presence, personal_message)
-               return presences
+               self.set_presence(status)
 
-       def get_statuses(self):
-               # you get one of these for each status
-               # {name:(Type, May_Set_On_Self, Can_Have_Message}
-               return {
-                       ButterflyPresenceMapping.ONLINE:(
-                               telepathy.CONNECTION_PRESENCE_TYPE_AVAILABLE,
-                               True, True),
-                       ButterflyPresenceMapping.AWAY:(
-                               telepathy.CONNECTION_PRESENCE_TYPE_AWAY,
-                               True, True),
-                       ButterflyPresenceMapping.BUSY:(
-                               telepathy.CONNECTION_PRESENCE_TYPE_AWAY,
-                               True, True),
-                       ButterflyPresenceMapping.IDLE:(
-                               telepathy.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY,
-                               True, True),
-                       ButterflyPresenceMapping.BRB:(
-                               telepathy.CONNECTION_PRESENCE_TYPE_AWAY,
-                               True, True),
-                       ButterflyPresenceMapping.PHONE:(
-                               telepathy.CONNECTION_PRESENCE_TYPE_AWAY,
-                               True, True),
-                       ButterflyPresenceMapping.LUNCH:(
-                               telepathy.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY,
-                               True, True),
-                       ButterflyPresenceMapping.INVISIBLE:(
-                               telepathy.CONNECTION_PRESENCE_TYPE_HIDDEN,
-                               True, False),
-                       ButterflyPresenceMapping.OFFLINE:(
-                               telepathy.CONNECTION_PRESENCE_TYPE_OFFLINE,
-                               True, False)
-               }
+       def _get_statuses(self):
+               """
+               Property mapping presence statuses available to the corresponding presence types
 
+               @returns {Name: (Telepathy Type, May Set On Self, Can Have Message)}
+               """
+               return dict(
+                       (localType, (telepathyType, True, False))
+                       for (localType, telepathyType) in self.TO_PRESENCE_TYPE.iteritems()
+               )