Upating telepathy python to a7418e92965713edae61d9e762b8c895a68a7251
[theonering] / src / simple_presence.py
index cd36856..c71a5c2 100644 (file)
 import logging
 
+import dbus
 import telepathy
 
+import util.misc as misc_utils
+import tp
+import handle
+import gvoice.state_machine as state_machine
+
+
+_moduleLogger = logging.getLogger(__name__)
+
 
 class TheOneRingPresence(object):
+
+       # Note: these strings are also in the theonering.profile file
        ONLINE = 'available'
-       BUSY = 'dnd'
+       AWAY = 'away'
+       HIDDEN = 'hidden'
+       OFFLINE = 'offline'
 
        TO_PRESENCE_TYPE = {
-               ONLINE: telepathy.constants.CONNECTION_PRESENCE_TYPE_AVAILABLE,
-               BUSY: telepathy.constants.CONNECTION_PRESENCE_TYPE_BUSY,
+               ONLINE: dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_AVAILABLE),
+               AWAY: dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY),
+               HIDDEN: dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_HIDDEN),
+               OFFLINE: dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_OFFLINE),
        }
 
+       @property
+       def session(self):
+               """
+               @abstract
+               """
+               raise NotImplementedError()
 
-class TheOneRingSimplePresence(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 Disconnect(self):
+               """
+               @abstract
+               """
+               raise NotImplementedError("Abstract function called")
 
-       def GetPresences(self, contacts):
+       def get_handle_by_id(self, handleType, handleId):
                """
-               @todo Figure out how to know when its self and get whether busy or not
+               @abstract
+               """
+               raise NotImplementedError("Abstract function called")
 
+       def get_presences(self, contactIds):
+               """
                @return {ContactHandle: (Status, Presence Type, Message)}
                """
                presences = {}
-               for handleId in contacts:
-                       handle = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
+               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]
+
+                       presences[h] = (presenceType, presence)
+               return presences
 
-                       presence = TheOneRingPresence.BUSY
-                       personalMessage = u""
-                       presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence]
+       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)
 
-                       presences[handle] = (presenceType, presence, personalMessage)
-               return presences
 
+class SimplePresenceMixin(tp.ConnectionInterfaceSimplePresence, TheOneRingPresence):
+
+       def __init__(self):
+               tp.ConnectionInterfaceSimplePresence.__init__(self)
+               TheOneRingPresence.__init__(self)
+
+               self._implement_property_get(
+                       tp.CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+                       {'Statuses' : self._get_statuses}
+               )
+
+       @misc_utils.log_exception(_moduleLogger)
+       def GetPresences(self, contacts):
+               """
+               @return {ContactHandle: (Status, Presence Type, Message)}
+               """
+               personalMessage = u""
+               return dbus.Dictionary(
+                       (
+                               (h, dbus.Struct((presenceType, presence, personalMessage), signature="uss"))
+                               for (h, (presenceType, presence)) in self.get_presences(contacts).iteritems()
+                       ),
+                       signature="u(uss)"
+               )
+
+       @misc_utils.log_exception(_moduleLogger)
        def SetPresence(self, status, message):
                if message:
-                       raise telepathy.errors.InvalidArgument
-
-               if status == TheOneRingPresence.ONLINE:
-                       self._conn.mark_dnd(True)
-               elif status == TheOneRingPresence.BUSY:
-                       self._conn.mark_dnd(False)
-               else:
-                       raise telepathy.errors.InvalidArgument
-               logging.info("Setting Presence to '%s'" % status)
+                       raise telepathy.errors.InvalidArgument("Messages aren't supported")
 
+               self.set_presence(status)
 
        def _get_statuses(self):
                """
@@ -58,14 +126,7 @@ class TheOneRingSimplePresence(telepathy.server.ConnectionInterfaceSimplePresenc
 
                @returns {Name: (Telepathy Type, May Set On Self, Can Have Message)}
                """
-               return {
-                       TheOneRingPresence.ONLINE: (
-                               telepathy.CONNECTION_PRESENCE_TYPE_AVAILABLE,
-                               True, False
-                       ),
-                       TheOneRingPresence.BUSY: (
-                               telepathy.CONNECTION_PRESENCE_TYPE_AWAY,
-                               True, False
-                       ),
-               }
-
+               return dict(
+                       (localType, (telepathyType, True, False))
+                       for (localType, telepathyType) in self.TO_PRESENCE_TYPE.iteritems()
+               )