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