Attempting to fix a bug in code I stole from python-telepathy in which they deviated...
[theonering] / src / handle.py
1 import logging
2 import weakref
3
4 import telepathy
5
6 import util.misc as util_misc
7
8
9 _moduleLogger = logging.getLogger("handle")
10
11
12 class TheOneRingHandle(telepathy.server.Handle):
13         """
14         Instances are memoized
15         """
16
17         def __init__(self, connection, id, handleType, name):
18                 telepathy.server.Handle.__init__(self, id, handleType, name)
19                 self._conn = weakref.proxy(connection)
20
21         def __repr__(self):
22                 return "<%s id=%u name='%s'>" % (
23                         type(self).__name__, self.id, self.name
24                 )
25
26         def is_same(self, handleType, handleName):
27                 return self.get_name() == handleName and self.get_type() == handleType
28
29         id = property(telepathy.server.Handle.get_id)
30         type = property(telepathy.server.Handle.get_type)
31         name = property(telepathy.server.Handle.get_name)
32
33
34 class ConnectionHandle(TheOneRingHandle):
35
36         def __init__(self, connection, id):
37                 handleType = telepathy.HANDLE_TYPE_CONTACT
38                 handleName = connection.username
39                 TheOneRingHandle.__init__(self, connection, id, handleType, handleName)
40
41                 self.profile = connection.username
42
43
44 class ContactHandle(TheOneRingHandle):
45
46         def __init__(self, connection, id, contactId, phoneNumber):
47                 handleType = telepathy.HANDLE_TYPE_CONTACT
48                 handleName = self.to_handle_name(contactId, phoneNumber)
49                 TheOneRingHandle.__init__(self, connection, id, handleType, handleName)
50
51                 self._contactId = contactId
52                 self._phoneNumber = util_misc.strip_number(phoneNumber)
53
54         @staticmethod
55         def from_handle_name(handleName):
56                 parts = handleName.split("#", 1)
57                 if len(parts) == 2:
58                         contactId, contactNumber = parts[0:2]
59                 elif len(parts) == 1:
60                         contactId, contactNumber = "", handleName
61                 else:
62                         raise RuntimeError("Invalid handle: %s" % handleName)
63
64                 contactNumber = util_misc.strip_number(contactNumber)
65                 return contactId, contactNumber
66
67         @staticmethod
68         def to_handle_name(contactId, contactNumber):
69                 handleName = "#".join((contactId, util_misc.strip_number(contactNumber)))
70                 return handleName
71
72         @classmethod
73         def normalize_handle_name(cls, name):
74                 if "#" in name:
75                         # Already a properly formatted name, run through the ringer just in case
76                         return cls.to_handle_name(*cls.from_handle_name(name))
77                         return name
78                 else:
79                         return cls.to_handle_name("", name)
80
81         def is_same(self, handleType, handleName):
82                 handleName = self.normalize_handle_name(handleName)
83                 _moduleLogger.info("%r == %r %r?" % (self, handleType, handleName))
84                 return self.get_name() == handleName and self.get_type() == handleType
85
86         @property
87         def contactID(self):
88                 return self._contactId
89
90         @property
91         def phoneNumber(self):
92                 return self._phoneNumber
93
94         @property
95         def contactDetails(self):
96                 return self._conn.addressbook.get_contact_details(self._id)
97
98
99 class ListHandle(TheOneRingHandle):
100
101         def __init__(self, connection, id, listName):
102                 handleType = telepathy.HANDLE_TYPE_LIST
103                 handleName = listName
104                 TheOneRingHandle.__init__(self, connection, id, handleType, handleName)
105
106
107 _HANDLE_TYPE_MAPPING = {
108         'connection': ConnectionHandle,
109         'contact': ContactHandle,
110         'list': ListHandle,
111 }
112
113
114 def create_handle_factory():
115
116         cache = weakref.WeakValueDictionary()
117
118         def create_handle(connection, type, *args):
119                 Handle = _HANDLE_TYPE_MAPPING[type]
120                 key = Handle, connection.username, args
121                 try:
122                         handle = cache[key]
123                         isNewHandle = False
124                 except KeyError:
125                         # The misnamed get_handle_id requests a new handle id
126                         handle = Handle(connection, connection.get_handle_id(), *args)
127                         cache[key] = handle
128                         isNewHandle = True
129                 connection._handles[handle.get_type(), handle.get_id()] = handle
130                 if False:
131                         handleStatus = "Is New!" if isNewHandle else "From Cache"
132                         _moduleLogger.info("Created Handle: %r (%s)" % (handle, handleStatus))
133                 return handle
134
135         return create_handle
136
137
138 create_handle = create_handle_factory()