comparison src/plugins/plugin_xep_0054.py @ 551:dcec4ba8e72c

plugin XEP-0054: naive approach to have a persistent cache of avatars
author Goffi <goffi@goffi.org>
date Thu, 22 Nov 2012 00:46:49 +0100
parents 2c4016921403
children 7ffae708b176
comparison
equal deleted inserted replaced
550:f25eef861b43 551:dcec4ba8e72c
31 from wokkel import disco, iwokkel 31 from wokkel import disco, iwokkel
32 32
33 from base64 import b64decode 33 from base64 import b64decode
34 from hashlib import sha1 34 from hashlib import sha1
35 from sat.core import exceptions 35 from sat.core import exceptions
36 from sat.memory.persistent import PersistentDict
36 37
37 try: 38 try:
38 from twisted.words.protocols.xmlstream import XMPPHandler 39 from twisted.words.protocols.xmlstream import XMPPHandler
39 except ImportError: 40 except ImportError:
40 from wokkel.subprotocols import XMPPHandler 41 from wokkel.subprotocols import XMPPHandler
69 info(_("Plugin XEP_0054 initialization")) 70 info(_("Plugin XEP_0054 initialization"))
70 self.host = host 71 self.host = host
71 self.avatar_path = os.path.join(self.host.memory.getConfig('', 'local_dir'), AVATAR_PATH) 72 self.avatar_path = os.path.join(self.host.memory.getConfig('', 'local_dir'), AVATAR_PATH)
72 if not os.path.exists(self.avatar_path): 73 if not os.path.exists(self.avatar_path):
73 os.makedirs(self.avatar_path) 74 os.makedirs(self.avatar_path)
75 self.avatars_cache = PersistentDict(NS_VCARD)
76 self.avatars_cache.load() #FIXME: resulting deferred must be correctly managed
74 host.bridge.addMethod("getCard", ".plugin", in_sign='ss', out_sign='s', method=self.getCard) 77 host.bridge.addMethod("getCard", ".plugin", in_sign='ss', out_sign='s', method=self.getCard)
75 host.bridge.addMethod("getAvatarFile", ".plugin", in_sign='s', out_sign='s', method=self.getAvatarFile) 78 host.bridge.addMethod("getAvatarFile", ".plugin", in_sign='s', out_sign='s', method=self.getAvatarFile)
76 79
77 def getHandler(self, profile): 80 def getHandler(self, profile):
78 return XEP_0054_handler(self) 81 return XEP_0054_handler(self)
79 82
83 def _fillCachedValues(self, result, client):
84 #FIXME: this is really suboptimal, need to be reworked
85 # the current naive approach keeps a map between all jids of all profiles
86 # in persistent cache, and check if cached jid are in roster, then put avatar
87 # hashs in memory.
88 for _jid in client.roster.getBareJids():
89 if _jid in self.avatars_cache:
90 self.host.memory.updateEntityData(jid.JID(_jid), "avatar", self.avatars_cache[_jid], client.profile)
91
92 def profileConnected(self, profile):
93 client = self.host.getClient(profile)
94 client.roster.got_roster.addCallback(self._fillCachedValues, client)
95
80 def update_cache(self, jid, name, value, profile): 96 def update_cache(self, jid, name, value, profile):
81 """update cache value 97 """update cache value
82 - save value in memory in case of change 98 - save value in memory in case of change
83 @param jid: jid of the owner of the vcard 99 @param jid: jid of the owner of the vcard
84 @param name: name of the item which changed 100 @param name: name of the item which changed
89 cached = self.host.memory.getEntityData(jid, [name], profile) 105 cached = self.host.memory.getEntityData(jid, [name], profile)
90 except exceptions.UnknownEntityError: 106 except exceptions.UnknownEntityError:
91 cached = {} 107 cached = {}
92 if not name in cached or cached[name] != value: 108 if not name in cached or cached[name] != value:
93 self.host.memory.updateEntityData(jid, name, value, profile) 109 self.host.memory.updateEntityData(jid, name, value, profile)
110 if name == "avatar":
111 self.avatars_cache[jid.userhost()] = value
94 112
95 def get_cache(self, jid, name, profile): 113 def get_cache(self, jid, name, profile):
96 """return cached value for jid 114 """return cached value for jid
97 @param jid: target contact 115 @param jid: target contact
98 @param name: name of the value ('nick' or 'avatar') 116 @param name: name of the value ('nick' or 'avatar')
220 from_jid = jid.JID(presence['from']) 238 from_jid = jid.JID(presence['from'])
221 #FIXME: wokkel's data_form should be used here 239 #FIXME: wokkel's data_form should be used here
222 x_elem = filter (lambda x:x.name == "x", presence.elements())[0] #We only want the "x" element 240 x_elem = filter (lambda x:x.name == "x", presence.elements())[0] #We only want the "x" element
223 for elem in x_elem.elements(): 241 for elem in x_elem.elements():
224 if elem.name == 'photo': 242 if elem.name == 'photo':
225 hash = str(elem) 243 _hash = str(elem)
226 old_avatar = self.plugin_parent.get_cache(from_jid, 'avatar', self.parent.profile) 244 old_avatar = self.plugin_parent.get_cache(from_jid, 'avatar', self.parent.profile)
227 if not old_avatar or old_avatar != hash: 245 if not old_avatar or old_avatar != _hash:
228 debug(_('New avatar found, requesting vcard')) 246 debug(_('New avatar found, requesting vcard'))
229 self.plugin_parent.getCard(from_jid.userhost(), self.parent.profile) 247 self.plugin_parent.getCard(from_jid.userhost(), self.parent.profile)