Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0054.py @ 1341:6dbeb2ef966c frontends_multi_profiles
plugin XEP-0054: "nick" is now keeped in cache:
- cache now manage different kind of data (instead of only avatar)
- PeristentBinaryDict is used to keep cache (because we now store a dict, not just strings)
- CACHED_DATA is a set of data kept in cache (only nick and avatar so far)
- a signal update flag is put on "nick"
- data in cache are reset if they are not present in cache (this avoid to keep the old value)
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 24 Feb 2015 17:01:33 +0100 |
parents | bd69d341d969 |
children | 069ad98b360d |
comparison
equal
deleted
inserted
replaced
1340:91e72da1d093 | 1341:6dbeb2ef966c |
---|---|
34 from wokkel import disco, iwokkel | 34 from wokkel import disco, iwokkel |
35 | 35 |
36 from base64 import b64decode, b64encode | 36 from base64 import b64decode, b64encode |
37 from hashlib import sha1 | 37 from hashlib import sha1 |
38 from sat.core import exceptions | 38 from sat.core import exceptions |
39 from sat.memory.persistent import PersistentDict | 39 from sat.memory import persistent |
40 from PIL import Image | 40 from PIL import Image |
41 from cStringIO import StringIO | 41 from cStringIO import StringIO |
42 | 42 |
43 try: | 43 try: |
44 from twisted.words.protocols.xmlstream import XMPPHandler | 44 from twisted.words.protocols.xmlstream import XMPPHandler |
53 VCARD_REQUEST = IQ_GET + '/vCard[@xmlns="' + NS_VCARD + '"]' # TODO: manage requests | 53 VCARD_REQUEST = IQ_GET + '/vCard[@xmlns="' + NS_VCARD + '"]' # TODO: manage requests |
54 | 54 |
55 PRESENCE = '/presence' | 55 PRESENCE = '/presence' |
56 NS_VCARD_UPDATE = 'vcard-temp:x:update' | 56 NS_VCARD_UPDATE = 'vcard-temp:x:update' |
57 VCARD_UPDATE = PRESENCE + '/x[@xmlns="' + NS_VCARD_UPDATE + '"]' | 57 VCARD_UPDATE = PRESENCE + '/x[@xmlns="' + NS_VCARD_UPDATE + '"]' |
58 | |
59 CACHED_DATA = {'avatar', 'nick'} | |
58 | 60 |
59 PLUGIN_INFO = { | 61 PLUGIN_INFO = { |
60 "name": "XEP 0054 Plugin", | 62 "name": "XEP 0054 Plugin", |
61 "import_name": "XEP-0054", | 63 "import_name": "XEP-0054", |
62 "type": "XEP", | 64 "type": "XEP", |
77 log.info(_("Plugin XEP_0054 initialization")) | 79 log.info(_("Plugin XEP_0054 initialization")) |
78 self.host = host | 80 self.host = host |
79 self.avatar_path = os.path.join(self.host.memory.getConfig('', 'local_dir'), AVATAR_PATH) | 81 self.avatar_path = os.path.join(self.host.memory.getConfig('', 'local_dir'), AVATAR_PATH) |
80 if not os.path.exists(self.avatar_path): | 82 if not os.path.exists(self.avatar_path): |
81 os.makedirs(self.avatar_path) | 83 os.makedirs(self.avatar_path) |
82 self.avatars_cache = {} | 84 self.cache = {} |
83 host.bridge.addMethod("getCard", ".plugin", in_sign='ss', out_sign='s', method=self._getCard) | 85 host.bridge.addMethod("getCard", ".plugin", in_sign='ss', out_sign='s', method=self._getCard) |
84 host.bridge.addMethod("getAvatarFile", ".plugin", in_sign='s', out_sign='s', method=self.getAvatarFile) | 86 host.bridge.addMethod("getAvatarFile", ".plugin", in_sign='s', out_sign='s', method=self.getAvatarFile) |
85 host.bridge.addMethod("setAvatar", ".plugin", in_sign='ss', out_sign='', method=self.setAvatar, async=True) | 87 host.bridge.addMethod("setAvatar", ".plugin", in_sign='ss', out_sign='', method=self.setAvatar, async=True) |
86 host.trigger.add("presence_available", self.presenceTrigger) | 88 host.trigger.add("presence_available", self.presenceTrigger) |
87 host.memory.setSignalOnUpdate("avatar") | 89 host.memory.setSignalOnUpdate("avatar") |
90 host.memory.setSignalOnUpdate("nick") | |
88 | 91 |
89 def getHandler(self, profile): | 92 def getHandler(self, profile): |
90 return XEP_0054_handler(self) | 93 return XEP_0054_handler(self) |
91 | 94 |
92 def presenceTrigger(self, presence_elt, client): | 95 def presenceTrigger(self, presence_elt, client): |
93 if client.jid.userhost() in self.avatars_cache[client.profile]: | 96 if client.jid.userhost() in self.cache[client.profile]: |
94 x_elt = domish.Element((NS_VCARD_UPDATE, 'x')) | 97 x_elt = domish.Element((NS_VCARD_UPDATE, 'x')) |
95 x_elt.addElement('photo', content=self.avatars_cache[client.profile][client.jid.userhost()]) | 98 x_elt.addElement('photo', content=self.cache[client.profile][client.jid.userhost()]['avatar']) |
96 presence_elt.addChild(x_elt) | 99 presence_elt.addChild(x_elt) |
97 | 100 |
98 return True | 101 return True |
99 | 102 |
100 def _fillCachedValues(self, profile): | 103 def _fillCachedValues(self, profile): |
101 #FIXME: this is really suboptimal, need to be reworked | 104 #FIXME: this is really suboptimal, need to be reworked |
102 # the current naive approach keeps a map between all jids of all profiles | 105 # the current naive approach keeps a map between all jids of all profiles |
103 # in persistent cache, then put avatar | 106 # in persistent cache, then put avatar |
104 # hashs in memory. Hashed should be shared between profiles | 107 # hashs in memory. Hashed should be shared between profiles |
105 for jid_s, avatar_hash in self.avatars_cache[profile].iteritems(): | 108 for jid_s, data in self.cache[profile].iteritems(): |
106 jid_ = jid.JID(jid_s) | 109 jid_ = jid.JID(jid_s) |
107 self.host.memory.updateEntityData(jid_, "avatar", avatar_hash, silent=True, profile_key=profile) | 110 for name in CACHED_DATA: |
111 try: | |
112 self.host.memory.updateEntityData(jid_, name, data[name], silent=True, profile_key=profile) | |
113 except KeyError: | |
114 pass | |
108 | 115 |
109 @defer.inlineCallbacks | 116 @defer.inlineCallbacks |
110 def profileConnecting(self, profile): | 117 def profileConnecting(self, profile): |
111 self.avatars_cache[profile] = PersistentDict(NS_VCARD, profile) | 118 self.cache[profile] = persistent.PersistentBinaryDict(NS_VCARD, profile) |
112 yield self.avatars_cache[profile].load() | 119 yield self.cache[profile].load() |
113 self._fillCachedValues(profile) | 120 self._fillCachedValues(profile) |
114 | 121 |
115 def profileDisconnected(self, profile): | 122 def profileDisconnected(self, profile): |
116 log.debug(u"Deleting profile cache for avatars") | 123 log.debug(u"Deleting profile cache for avatars") |
117 del self.avatars_cache[profile] | 124 del self.cache[profile] |
118 | 125 |
119 def updateCache(self, jid_, name, value, profile): | 126 def updateCache(self, jid_, name, value, profile): |
120 """update cache value | 127 """update cache value |
121 | 128 |
122 save value in memory in case of change | 129 save value in memory in case of change |
125 @param value(unicode): new value of the item | 132 @param value(unicode): new value of the item |
126 @param profile(unicode): profile which received the update | 133 @param profile(unicode): profile which received the update |
127 """ | 134 """ |
128 assert not jid_.resource # VCard are retrieved with bare jid | 135 assert not jid_.resource # VCard are retrieved with bare jid |
129 self.host.memory.updateEntityData(jid_, name, value, profile_key=profile) | 136 self.host.memory.updateEntityData(jid_, name, value, profile_key=profile) |
130 if name == "avatar": | 137 if name in CACHED_DATA: |
131 self.avatars_cache[profile][jid_.userhost()] = value | 138 jid_s = jid_.userhost() |
139 self.cache[profile].setdefault(jid_s, {})[name] = value | |
140 self.cache[profile].force(jid_s) | |
132 | 141 |
133 def getCache(self, entity_jid, name, profile): | 142 def getCache(self, entity_jid, name, profile): |
134 """return cached value for jid | 143 """return cached value for jid |
135 | 144 |
136 @param entity_jid: target contact | 145 @param entity_jid: target contact |
202 del dictionary['avatar'] | 211 del dictionary['avatar'] |
203 else: | 212 else: |
204 self.updateCache(target, 'avatar', dictionary['avatar'], profile) | 213 self.updateCache(target, 'avatar', dictionary['avatar'], profile) |
205 else: | 214 else: |
206 log.info(_('FIXME: [%s] VCard tag is not managed yet') % elem.name) | 215 log.info(_('FIXME: [%s] VCard tag is not managed yet') % elem.name) |
216 | |
217 # if a data in cache doesn't exist anymore, we need to reset it | |
218 # so we check CACHED_DATA no gotten (i.e. not in dictionary keys) | |
219 # and we reset them | |
220 for datum in CACHED_DATA.difference(dictionary.keys()): | |
221 log.debug(u"reseting vcard datum [{datum}] for {entity}".format(datum=datum, entity=target.full())) | |
222 self.updateCache(target, datum, '', profile) | |
207 | 223 |
208 defer.returnValue(dictionary) | 224 defer.returnValue(dictionary) |
209 | 225 |
210 def _VCardCb(self, answer, profile): | 226 def _VCardCb(self, answer, profile): |
211 """Called after the first get IQ""" | 227 """Called after the first get IQ""" |