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