Cleaning up and improving the number formatter
[theonering] / src / aliasing.py
1 import logging
2
3 import telepathy
4
5 import gtk_toolbox
6 import util.misc as util_misc
7 import handle
8
9
10 _moduleLogger = logging.getLogger('aliasing')
11
12
13 def _make_pretty_with_areacodde(phonenumber):
14         prettynumber = "(%s)" % (phonenumber[0:3], )
15         if 3 < len(phonenumber):
16                 prettynumber += " %s" % (phonenumber[3:6], )
17                 if 6 < len(phonenumber):
18                         prettynumber += "-%s" % (phonenumber[6:], )
19         return prettynumber
20
21
22 def _make_pretty_local(phonenumber):
23         prettynumber = "%s" % (phonenumber[0:3], )
24         if 3 < len(phonenumber):
25                 prettynumber += "-%s" % (phonenumber[3:], )
26         return prettynumber
27
28
29 def _make_pretty_international(phonenumber):
30         if phonenumber.startswith("0"):
31                 prettynumber = "+%s " % (phonenumber[0:3], )
32                 if 3 < len(phonenumber):
33                         prettynumber += _make_pretty_with_areacodde(phonenumber[3:])
34         if phonenumber.startswith("1"):
35                 prettynumber = "1 "
36                 prettynumber += _make_pretty_with_areacodde(phonenumber[1:])
37         return prettynumber
38
39
40 def make_pretty(phonenumber):
41         """
42         Function to take a phone number and return the pretty version
43         pretty numbers:
44                 if phonenumber begins with 0:
45                         ...-(...)-...-....
46                 if phonenumber begins with 1: ( for gizmo callback numbers )
47                         1 (...)-...-....
48                 if phonenumber is 13 digits:
49                         (...)-...-....
50                 if phonenumber is 10 digits:
51                         ...-....
52         >>> make_pretty("12")
53         '12'
54         >>> make_pretty("1234567")
55         '123-4567'
56         >>> make_pretty("2345678901")
57         '(234) 567-8901'
58         >>> make_pretty("12345678901")
59         '1 (234) 567-8901'
60         >>> make_pretty("01234567890")
61         '+012 (345) 678-90'
62         >>> make_pretty("+01234567890")
63         '+012 (345) 678-90'
64         >>> make_pretty("+12")
65         '+1 (2)'
66         >>> make_pretty("+123")
67         '+1 (23)'
68         >>> make_pretty("+1234")
69         '+1 (234)'
70         """
71         if phonenumber is None or phonenumber is "":
72                 return ""
73
74         phonenumber = util_misc.strip_number(phonenumber)
75
76         if phonenumber[0] == "+":
77                 prettynumber = _make_pretty_international(phonenumber[1:])
78                 if not prettynumber.startswith("+"):
79                         prettynumber = "+"+prettynumber
80         elif 8 < len(phonenumber) and phonenumber[0] in ("0", "1"):
81                 prettynumber = _make_pretty_international(phonenumber)
82         elif 7 < len(phonenumber):
83                 prettynumber = _make_pretty_with_areacodde(phonenumber)
84         elif 3 < len(phonenumber):
85                 prettynumber = _make_pretty_local(phonenumber)
86         else:
87                 prettynumber = phonenumber
88         return prettynumber.strip()
89
90
91 class AliasingMixin(telepathy.server.ConnectionInterfaceAliasing):
92
93         USER_ALIAS_ACCOUNT = "account"
94         USER_ALIAS_CALLBACK = "callback"
95
96         def __init__(self):
97                 telepathy.server.ConnectionInterfaceAliasing.__init__(self)
98
99         @property
100         def session(self):
101                 """
102                 @abstract
103                 """
104                 raise NotImplementedError("Abstract property called")
105
106         @property
107         def userAliasType(self):
108                 """
109                 @abstract
110                 """
111                 raise NotImplementedError("Abstract property called")
112
113         def handle(self, handleType, handleId):
114                 """
115                 @abstract
116                 """
117                 raise NotImplementedError("Abstract function called")
118
119         @gtk_toolbox.log_exception(_moduleLogger)
120         def GetAliasFlags(self):
121                 return 0
122
123         @gtk_toolbox.log_exception(_moduleLogger)
124         def RequestAliases(self, contactHandleIds):
125                 _moduleLogger.debug("Called RequestAliases")
126                 return [self._get_alias(handleId) for handleId in contactHandleIds]
127
128         @gtk_toolbox.log_exception(_moduleLogger)
129         def GetAliases(self, contactHandleIds):
130                 _moduleLogger.debug("Called GetAliases")
131
132                 idToAlias = dict(
133                         (handleId, self._get_alias(handleId))
134                         for handleId in contactHandleIds
135                 )
136                 return idToAlias
137
138         @gtk_toolbox.log_exception(_moduleLogger)
139         def SetAliases(self, aliases):
140                 _moduleLogger.debug("Called SetAliases")
141                 if self.userAliasType == self.USER_ALIAS_ACCOUNT:
142                         raise telepathy.errors.PermissionDenied("No user customizable aliases")
143                 elif self.userAliasType != self.USER_ALIAS_CALLBACK:
144                         raise RuntimeError("Invalid alias type: %r" % self.userAliasType)
145
146                 # first validate that no other handle types are included
147                 userHandleAndAlias = None
148                 for handleId, alias in aliases.iteritems():
149                         h = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
150                         if not isinstance(h, handle.ConnectionHandle):
151                                 raise telepathy.errors.PermissionDenied("No user customizable aliases")
152                         userHandleAndAlias = h, alias
153                 if userHandleAndAlias is None:
154                         _moduleLogger.debug("No user handle")
155                         return
156
157                 # Update callback
158                 uglyNumber = util_misc.strip_number(userHandleAndAlias[1])
159                 self.session.backend.set_callback_number(uglyNumber)
160
161                 # Inform of change
162                 changedAliases = (userHandleAndAlias, )
163                 self.AliasesChanged(changedAliases)
164
165         def _get_alias(self, handleId):
166                 h = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
167                 if isinstance(h, handle.ConnectionHandle):
168                         if self.userAliasType == self.USER_ALIAS_CALLBACK:
169                                 aliasNumber = self.session.backend.get_callback_number()
170                         elif self.userAliasType == self.USER_ALIAS_ACCOUNT:
171                                 aliasNumber = self.session.backend.get_account_number()
172                         else:
173                                 raise RuntimeError("Invalid alias type: %r" % self.userAliasType)
174                         userAlias = make_pretty(aliasNumber)
175                         return userAlias
176                 else:
177                         contactId = h.contactID
178                         if contactId:
179                                 contactAlias = self.session.addressbook.get_contact_name(contactId)
180                         else:
181                                 contactAlias = make_pretty(h.phoneNumber)
182                         return contactAlias