Adding old-school presence so I can get presence support working in Empathy, wahooo
[theonering] / src / simple_presence.py
1 import logging
2
3 import telepathy
4
5 import gtk_toolbox
6 import handle
7 import gvoice.state_machine as state_machine
8
9
10 _moduleLogger = logging.getLogger("simple_presence")
11
12
13 class TheOneRingPresence(object):
14
15         # Note: these strings are also in the theonering.profile file
16         ONLINE = 'available'
17         AWAY = 'away'
18         HIDDEN = 'hidden'
19         OFFLINE = 'offline'
20
21         TO_PRESENCE_TYPE = {
22                 ONLINE: telepathy.constants.CONNECTION_PRESENCE_TYPE_AVAILABLE,
23                 AWAY: telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY,
24                 HIDDEN: telepathy.constants.CONNECTION_PRESENCE_TYPE_HIDDEN,
25                 OFFLINE: telepathy.constants.CONNECTION_PRESENCE_TYPE_OFFLINE,
26         }
27
28         @property
29         def session(self):
30                 """
31                 @abstract
32                 """
33                 raise NotImplementedError()
34
35         @property
36         def handle(self):
37                 """
38                 @abstract
39                 """
40                 raise NotImplementedError("Abstract property called")
41
42         def Disconnect(self):
43                 """
44                 @abstract
45                 """
46                 raise NotImplementedError("Abstract function called")
47
48         def get_presences(self, contactIds):
49                 """
50                 @return {ContactHandle: (Status, Presence Type, Message)}
51                 """
52                 presences = {}
53                 for handleId in contactIds:
54                         h = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
55                         if isinstance(h, handle.ConnectionHandle):
56                                 isDnd = self.session.backend.is_dnd()
57                                 if isDnd:
58                                         presence = TheOneRingPresence.HIDDEN
59                                 else:
60                                         state = self.session.stateMachine.get_state()
61                                         if state == state_machine.StateMachine.STATE_ACTIVE:
62                                                 presence = TheOneRingPresence.ONLINE
63                                         elif state == state_machine.StateMachine.STATE_IDLE:
64                                                 presence = TheOneRingPresence.AWAY
65                                         else:
66                                                 raise telepathy.errors.InvalidArgument("Unsupported state on the state machine: %s" % state)
67                                 presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence]
68                         else:
69                                 presence = TheOneRingPresence.ONLINE
70                                 presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence]
71
72                         presences[h] = (presenceType, presence)
73                 return presences
74
75         def set_presence(self, status):
76                 if status == self.ONLINE:
77                         self.session.backend.set_dnd(False)
78                         self.session.stateMachine.set_state(state_machine.StateMachine.STATE_ACTIVE)
79                 elif status == self.AWAY:
80                         self.session.stateMachine.set_state(state_machine.StateMachine.STATE_IDLE)
81                 elif status == self.HIDDEN:
82                         self.session.backend.set_dnd(True)
83                 elif status == self.OFFLINE:
84                         self.Disconnect()
85                 else:
86                         raise telepathy.errors.InvalidArgument("Unsupported status: %r" % status)
87                 _moduleLogger.info("Setting Presence to '%s'" % status)
88
89
90 class SimplePresenceMixin(telepathy.server.ConnectionInterfaceSimplePresence, TheOneRingPresence):
91
92         def __init__(self):
93                 telepathy.server.ConnectionInterfaceSimplePresence.__init__(self)
94                 TheOneRingPresence.__init__(self)
95
96                 self._implement_property_get(
97                         telepathy.server.CONNECTION_INTERFACE_SIMPLE_PRESENCE,
98                         {'Statuses' : self._get_statuses}
99                 )
100
101         @gtk_toolbox.log_exception(_moduleLogger)
102         def GetPresences(self, contacts):
103                 """
104                 @return {ContactHandle: (Status, Presence Type, Message)}
105                 """
106                 personalMessage = u""
107                 return dict(
108                         (h, (presenceType, presence, personalMessage))
109                         for (h, (presenceType, presence)) in self.get_presences(contacts).iteritems()
110                 )
111
112         @gtk_toolbox.log_exception(_moduleLogger)
113         def SetPresence(self, status, message):
114                 if message:
115                         raise telepathy.errors.InvalidArgument("Messages aren't supported")
116
117                 self.set_presence(status)
118
119         def _get_statuses(self):
120                 """
121                 Property mapping presence statuses available to the corresponding presence types
122
123                 @returns {Name: (Telepathy Type, May Set On Self, Can Have Message)}
124                 """
125                 return dict(
126                         (localType, (telepathyType, True, False))
127                         for (localType, telepathyType) in self.TO_PRESENCE_TYPE.iteritems()
128                 )