Imitiating buttfly in being explicitly typed
[theonering] / src / avatars.py
index c623e1a..5583d49 100644 (file)
+from __future__ import with_statement
+
+import os
 import logging
 
 import telepathy
 
+import tp
+import util.misc as misc_utils
+
+
+_moduleLogger = logging.getLogger(__name__)
+
+
+class AvatarsMixin(tp.server.ConnectionInterfaceAvatars):
+
+       __SELF_AVATAR = "tor_self"
+       __MOBILE_AVATAR = "tor_handset"
+       __LANDLINE_AVATAR = "tor_phone"
+       __OTHER_AVATAR = "tor_question"
 
-class ButterflyAvatars(telepathy.server.ConnectionInterfaceAvatars):
+       __LOOKUP_PATHS = (
+               "/usr/share/theonering",
+               os.path.join(os.path.dirname(__file__), "../support/icons"),
+       )
 
        def __init__(self):
-               self._avatar_known = False
-               telepathy.server.ConnectionInterfaceAvatars.__init__(self)
+               tp.server.ConnectionInterfaceAvatars.__init__(self)
+               self._avatarCache = {}
 
+               self._implement_property_get(
+                       telepathy.interfaces.CONNECTION_INTERFACE_AVATARS,
+                       {
+                               'SupportedAvatarMimeTypes': lambda: ("image/png", ),
+                               'MinimumAvatarHeight': lambda: 32,
+                               'MinimumAvatarWidth': lambda: 32,
+                               'RecommendedAvatarHeight': lambda: 32,
+                               'RecommendedAvatarWidth': lambda: 32,
+                               'MaximumAvatarHeight': lambda: 32,
+                               'MaximumAvatarWidth': lambda: 32,
+                               'MaximumAvatarBytes': lambda: 500 * 1024,
+                       },
+               )
+
+       @property
+       def session(self):
+               """
+               @abstract
+               """
+               raise NotImplementedError("Abstract property called")
+
+       def get_handle_by_id(self, handleType, handleId):
+               """
+               @abstract
+               """
+               raise NotImplementedError("Abstract function called")
+
+       @misc_utils.log_exception(_moduleLogger)
        def GetAvatarRequirements(self):
-               mime_types = ("image/png","image/jpeg","image/gif")
-               return (mime_types, 96, 96, 192, 192, 500 * 1024)
+               mime_types = ("image/png", )
+               return (mime_types, 32, 32, 64, 64, 500 * 1024)
 
-       def GetKnownAvatarTokens(self, contacts):
+       @misc_utils.log_exception(_moduleLogger)
+       def GetAvatarTokens(self, contacts):
                result = {}
-               for handle_id in contacts:
-                       handle = self.handle(telepathy.HANDLE_TYPE_CONTACT, handle_id)
-                       if handle == self.GetSelfHandle():
-                               contact = handle.profile
-                       else:
-                               contact = handle.contact
-
-                       if contact is not None:
-                               msn_object = contact.msn_object
-                       else:
-                               msn_object = None
+               for handleid in contacts:
+                       imageName = self._select_avatar(handleid)
+                       result[handleid] = imageName
+               return result
 
-                       if msn_object is not None:
-                               result[handle] = msn_object._data_sha.encode("hex")
-                       elif self._avatar_known:
-                               result[handle] = ""
+       @misc_utils.log_exception(_moduleLogger)
+       def GetKnownAvatarTokens(self, contacts):
+               result = {}
+               for handleid in contacts:
+                       imageName = self._select_avatar(handleid)
+                       result[handleid] = imageName
                return result
 
+       @misc_utils.log_exception(_moduleLogger)
+       def RequestAvatar(self, contact):
+               imageName = self._select_avatar(contact)
+               image = self._get_avatar(imageName)
+               return image, "image/png"
+
+       @misc_utils.log_exception(_moduleLogger)
        def RequestAvatars(self, contacts):
-               for handle_id in contacts:
-                       handle = self.handle(telepathy.HANDLE_TYPE_CONTACT, handle_id)
-                       if handle == self.GetSelfHandle():
-                               msn_object = self.msn_client.profile.msn_object
-                               self._msn_object_retrieved(msn_object, handle)
-                       else:
-                               contact = handle.contact
-                               if contact is not None:
-                                       msn_object = contact.msn_object
-                               else:
-                                       msn_object = None
-                               if msn_object is not None:
-                                       self.msn_client.msn_object_store.request(msn_object,\
-                                                       (self._msn_object_retrieved, handle))
+               for handleid in contacts:
+                       imageName = self._select_avatar(handleid)
+                       image = self._get_avatar(imageName)
+                       self.AvatarRetrieved(handleid, imageName, image, "image/png")
 
+       @misc_utils.log_exception(_moduleLogger)
        def SetAvatar(self, avatar, mime_type):
-               self._avatar_known = True
-               if not isinstance(avatar, str):
-                       avatar = "".join([chr(b) for b in avatar])
-               avatarToken = 0
-               logging.info("Setting self avatar to %s" % avatarToken)
-               return avatarToken
+               raise telepathy.errors.PermissionDenied
 
+       @misc_utils.log_exception(_moduleLogger)
        def ClearAvatar(self):
-               self.msn_client.profile.msn_object = None
-               self._avatar_known = True
+               pass
+
+       def _select_avatar(self, handleId):
+               handle = self.get_handle_by_id(telepathy.HANDLE_TYPE_CONTACT, handleId)
+
+               if handle == self.GetSelfHandle():
+                       imageName = self.__SELF_AVATAR
+               else:
+                       accountNumber = misc_utils.normalize_number(self.session.backend.get_account_number())
+                       phoneType = self.session.addressbook.get_phone_type(handle.phoneNumber)
+                       if handle.phoneNumber == accountNumber:
+                               imageName = self.__SELF_AVATAR
+                       elif phoneType in ("mobile", ):
+                               imageName = self.__MOBILE_AVATAR
+                       elif phoneType in ("home", "work"):
+                               imageName = self.__LANDLINE_AVATAR
+                       else:
+                               imageName = self.__OTHER_AVATAR
+
+               return imageName
+
+       def _get_avatar(self, imageName):
+               try:
+                       return self._avatarCache[imageName]
+               except KeyError:
+                       image = self._load_avatar(imageName)
+                       self._avatarCache[imageName] = image
+                       return image
+
+       def _load_avatar(self, imageName):
+               _moduleLogger.debug("Loading avatar %r from file" % (imageName, ))
+               try:
+                       with open(os.sep.join([self.__LOOKUP_PATHS[0], imageName+".png"]), "rb") as f:
+                               return f.read()
+               except IOError:
+                       with open(os.sep.join([self.__LOOKUP_PATHS[1], "32-"+imageName+".png"]), "rb") as f:
+                               return f.read()