Imitiating buttfly in being explicitly typed
[theonering] / src / avatars.py
1 from __future__ import with_statement
2
3 import os
4 import logging
5
6 import telepathy
7
8 import tp
9 import util.misc as misc_utils
10
11
12 _moduleLogger = logging.getLogger(__name__)
13
14
15 class AvatarsMixin(tp.server.ConnectionInterfaceAvatars):
16
17         __SELF_AVATAR = "tor_self"
18         __MOBILE_AVATAR = "tor_handset"
19         __LANDLINE_AVATAR = "tor_phone"
20         __OTHER_AVATAR = "tor_question"
21
22         __LOOKUP_PATHS = (
23                 "/usr/share/theonering",
24                 os.path.join(os.path.dirname(__file__), "../support/icons"),
25         )
26
27         def __init__(self):
28                 tp.server.ConnectionInterfaceAvatars.__init__(self)
29                 self._avatarCache = {}
30
31                 self._implement_property_get(
32                         telepathy.interfaces.CONNECTION_INTERFACE_AVATARS,
33                         {
34                                 'SupportedAvatarMimeTypes': lambda: ("image/png", ),
35                                 'MinimumAvatarHeight': lambda: 32,
36                                 'MinimumAvatarWidth': lambda: 32,
37                                 'RecommendedAvatarHeight': lambda: 32,
38                                 'RecommendedAvatarWidth': lambda: 32,
39                                 'MaximumAvatarHeight': lambda: 32,
40                                 'MaximumAvatarWidth': lambda: 32,
41                                 'MaximumAvatarBytes': lambda: 500 * 1024,
42                         },
43                 )
44
45         @property
46         def session(self):
47                 """
48                 @abstract
49                 """
50                 raise NotImplementedError("Abstract property called")
51
52         def get_handle_by_id(self, handleType, handleId):
53                 """
54                 @abstract
55                 """
56                 raise NotImplementedError("Abstract function called")
57
58         @misc_utils.log_exception(_moduleLogger)
59         def GetAvatarRequirements(self):
60                 mime_types = ("image/png", )
61                 return (mime_types, 32, 32, 64, 64, 500 * 1024)
62
63         @misc_utils.log_exception(_moduleLogger)
64         def GetAvatarTokens(self, contacts):
65                 result = {}
66                 for handleid in contacts:
67                         imageName = self._select_avatar(handleid)
68                         result[handleid] = imageName
69                 return result
70
71         @misc_utils.log_exception(_moduleLogger)
72         def GetKnownAvatarTokens(self, contacts):
73                 result = {}
74                 for handleid in contacts:
75                         imageName = self._select_avatar(handleid)
76                         result[handleid] = imageName
77                 return result
78
79         @misc_utils.log_exception(_moduleLogger)
80         def RequestAvatar(self, contact):
81                 imageName = self._select_avatar(contact)
82                 image = self._get_avatar(imageName)
83                 return image, "image/png"
84
85         @misc_utils.log_exception(_moduleLogger)
86         def RequestAvatars(self, contacts):
87                 for handleid in contacts:
88                         imageName = self._select_avatar(handleid)
89                         image = self._get_avatar(imageName)
90                         self.AvatarRetrieved(handleid, imageName, image, "image/png")
91
92         @misc_utils.log_exception(_moduleLogger)
93         def SetAvatar(self, avatar, mime_type):
94                 raise telepathy.errors.PermissionDenied
95
96         @misc_utils.log_exception(_moduleLogger)
97         def ClearAvatar(self):
98                 pass
99
100         def _select_avatar(self, handleId):
101                 handle = self.get_handle_by_id(telepathy.HANDLE_TYPE_CONTACT, handleId)
102
103                 if handle == self.GetSelfHandle():
104                         imageName = self.__SELF_AVATAR
105                 else:
106                         accountNumber = misc_utils.normalize_number(self.session.backend.get_account_number())
107                         phoneType = self.session.addressbook.get_phone_type(handle.phoneNumber)
108                         if handle.phoneNumber == accountNumber:
109                                 imageName = self.__SELF_AVATAR
110                         elif phoneType in ("mobile", ):
111                                 imageName = self.__MOBILE_AVATAR
112                         elif phoneType in ("home", "work"):
113                                 imageName = self.__LANDLINE_AVATAR
114                         else:
115                                 imageName = self.__OTHER_AVATAR
116
117                 return imageName
118
119         def _get_avatar(self, imageName):
120                 try:
121                         return self._avatarCache[imageName]
122                 except KeyError:
123                         image = self._load_avatar(imageName)
124                         self._avatarCache[imageName] = image
125                         return image
126
127         def _load_avatar(self, imageName):
128                 _moduleLogger.debug("Loading avatar %r from file" % (imageName, ))
129                 try:
130                         with open(os.sep.join([self.__LOOKUP_PATHS[0], imageName+".png"]), "rb") as f:
131                                 return f.read()
132                 except IOError:
133                         with open(os.sep.join([self.__LOOKUP_PATHS[1], "32-"+imageName+".png"]), "rb") as f:
134                                 return f.read()