Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0054.py @ 594:e629371a28d3
Fix pep8 support in src/plugins.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Fri, 18 Jan 2013 17:55:35 +0100 |
parents | beaf6bec2fcd |
children | 84a6e83157c2 |
comparison
equal
deleted
inserted
replaced
593:70bae685d05c | 594:e629371a28d3 |
---|---|
29 | 29 |
30 from zope.interface import implements | 30 from zope.interface import implements |
31 | 31 |
32 from wokkel import disco, iwokkel | 32 from wokkel import disco, iwokkel |
33 | 33 |
34 from base64 import b64decode,b64encode | 34 from base64 import b64decode, b64encode |
35 from hashlib import sha1 | 35 from hashlib import sha1 |
36 from sat.core import exceptions | 36 from sat.core import exceptions |
37 from sat.memory.persistent import PersistentDict | 37 from sat.memory.persistent import PersistentDict |
38 import Image | 38 import Image |
39 from cStringIO import StringIO | 39 from cStringIO import StringIO |
45 | 45 |
46 AVATAR_PATH = "avatars" | 46 AVATAR_PATH = "avatars" |
47 | 47 |
48 IQ_GET = '/iq[@type="get"]' | 48 IQ_GET = '/iq[@type="get"]' |
49 NS_VCARD = 'vcard-temp' | 49 NS_VCARD = 'vcard-temp' |
50 VCARD_REQUEST = IQ_GET + '/vCard[@xmlns="' + NS_VCARD + '"]' #TODO: manage requests | 50 VCARD_REQUEST = IQ_GET + '/vCard[@xmlns="' + NS_VCARD + '"]' # TODO: manage requests |
51 | 51 |
52 PRESENCE = '/presence' | 52 PRESENCE = '/presence' |
53 NS_VCARD_UPDATE = 'vcard-temp:x:update' | 53 NS_VCARD_UPDATE = 'vcard-temp:x:update' |
54 VCARD_UPDATE = PRESENCE + '/x[@xmlns="' + NS_VCARD_UPDATE + '"]' | 54 VCARD_UPDATE = PRESENCE + '/x[@xmlns="' + NS_VCARD_UPDATE + '"]' |
55 | 55 |
56 PLUGIN_INFO = { | 56 PLUGIN_INFO = { |
57 "name": "XEP 0054 Plugin", | 57 "name": "XEP 0054 Plugin", |
58 "import_name": "XEP-0054", | 58 "import_name": "XEP-0054", |
59 "type": "XEP", | 59 "type": "XEP", |
60 "protocols": ["XEP-0054", "XEP-0153"], | 60 "protocols": ["XEP-0054", "XEP-0153"], |
61 "dependencies": [], | 61 "dependencies": [], |
62 "main": "XEP_0054", | 62 "main": "XEP_0054", |
63 "handler": "yes", | 63 "handler": "yes", |
64 "description": _("""Implementation of vcard-temp""") | 64 "description": _("""Implementation of vcard-temp""") |
65 } | 65 } |
66 | |
66 | 67 |
67 class XEP_0054(object): | 68 class XEP_0054(object): |
68 #TODO: - check that nickname is ok | 69 #TODO: - check that nickname is ok |
69 # - refactor the code/better use of Wokkel | 70 # - refactor the code/better use of Wokkel |
70 # - get missing values | 71 # - get missing values |
74 self.host = host | 75 self.host = host |
75 self.avatar_path = os.path.join(self.host.memory.getConfig('', 'local_dir'), AVATAR_PATH) | 76 self.avatar_path = os.path.join(self.host.memory.getConfig('', 'local_dir'), AVATAR_PATH) |
76 if not os.path.exists(self.avatar_path): | 77 if not os.path.exists(self.avatar_path): |
77 os.makedirs(self.avatar_path) | 78 os.makedirs(self.avatar_path) |
78 self.avatars_cache = PersistentDict(NS_VCARD) | 79 self.avatars_cache = PersistentDict(NS_VCARD) |
79 self.avatars_cache.load() #FIXME: resulting deferred must be correctly managed | 80 self.avatars_cache.load() # FIXME: resulting deferred must be correctly managed |
80 host.bridge.addMethod("getCard", ".plugin", in_sign='ss', out_sign='s', method=self.getCard) | 81 host.bridge.addMethod("getCard", ".plugin", in_sign='ss', out_sign='s', method=self.getCard) |
81 host.bridge.addMethod("getAvatarFile", ".plugin", in_sign='s', out_sign='s', method=self.getAvatarFile) | 82 host.bridge.addMethod("getAvatarFile", ".plugin", in_sign='s', out_sign='s', method=self.getAvatarFile) |
82 host.bridge.addMethod("setAvatar", ".plugin", in_sign='ss', out_sign='', method=self.setAvatar, async = True) | 83 host.bridge.addMethod("setAvatar", ".plugin", in_sign='ss', out_sign='', method=self.setAvatar, async=True) |
83 host.trigger.add("presence_available", self.presenceTrigger) | 84 host.trigger.add("presence_available", self.presenceTrigger) |
84 | 85 |
85 def getHandler(self, profile): | 86 def getHandler(self, profile): |
86 return XEP_0054_handler(self) | 87 return XEP_0054_handler(self) |
87 | 88 |
142 info(_('Photo of type [%s] found') % str(elem)) | 143 info(_('Photo of type [%s] found') % str(elem)) |
143 if elem.name == 'BINVAL': | 144 if elem.name == 'BINVAL': |
144 debug(_('Decoding binary')) | 145 debug(_('Decoding binary')) |
145 decoded = b64decode(str(elem)) | 146 decoded = b64decode(str(elem)) |
146 image_hash = sha1(decoded).hexdigest() | 147 image_hash = sha1(decoded).hexdigest() |
147 filename = self.avatar_path+'/'+image_hash | 148 filename = self.avatar_path + '/' + image_hash |
148 if not os.path.exists(filename): | 149 if not os.path.exists(filename): |
149 with open(filename,'wb') as file: | 150 with open(filename, 'wb') as file: |
150 file.write(decoded) | 151 file.write(decoded) |
151 debug(_("file saved to %s") % image_hash) | 152 debug(_("file saved to %s") % image_hash) |
152 else: | 153 else: |
153 debug(_("file [%s] already in cache") % image_hash) | 154 debug(_("file [%s] already in cache") % image_hash) |
154 return image_hash | 155 return image_hash |
155 | 156 |
156 @inlineCallbacks | 157 @inlineCallbacks |
157 def vCard2Dict(self, vcard, target, profile): | 158 def vCard2Dict(self, vcard, target, profile): |
158 """Convert a VCard to a dict, and save binaries""" | 159 """Convert a VCard to a dict, and save binaries""" |
159 debug (_("parsing vcard")) | 160 debug(_("parsing vcard")) |
160 dictionary = {} | 161 dictionary = {} |
161 | 162 |
162 for elem in vcard.elements(): | 163 for elem in vcard.elements(): |
163 if elem.name == 'FN': | 164 if elem.name == 'FN': |
164 dictionary['fullname'] = unicode(elem) | 165 dictionary['fullname'] = unicode(elem) |
171 dictionary['email'] = unicode(elem) | 172 dictionary['email'] = unicode(elem) |
172 elif elem.name == 'BDAY': | 173 elif elem.name == 'BDAY': |
173 dictionary['birthday'] = unicode(elem) | 174 dictionary['birthday'] = unicode(elem) |
174 elif elem.name == 'PHOTO': | 175 elif elem.name == 'PHOTO': |
175 dictionary["avatar"] = yield threads.deferToThread(self.save_photo, elem) | 176 dictionary["avatar"] = yield threads.deferToThread(self.save_photo, elem) |
176 if not dictionary["avatar"]: #can happen in case of e.g. empty photo elem | 177 if not dictionary["avatar"]: # can happen in case of e.g. empty photo elem |
177 del dictionary['avatar'] | 178 del dictionary['avatar'] |
178 else: | 179 else: |
179 self.update_cache(target, 'avatar', dictionary['avatar'], profile) | 180 self.update_cache(target, 'avatar', dictionary['avatar'], profile) |
180 else: | 181 else: |
181 info (_('FIXME: [%s] VCard tag is not managed yet') % elem.name) | 182 info(_('FIXME: [%s] VCard tag is not managed yet') % elem.name) |
182 | 183 |
183 returnValue(dictionary) | 184 returnValue(dictionary) |
184 | 185 |
185 def vcard_ok(self, answer, profile): | 186 def vcard_ok(self, answer, profile): |
186 """Called after the first get IQ""" | 187 """Called after the first get IQ""" |
187 debug (_("VCard found")) | 188 debug(_("VCard found")) |
188 | 189 |
189 if answer.firstChildElement().name == "vCard": | 190 if answer.firstChildElement().name == "vCard": |
190 _jid, steam = self.host.getJidNStream(profile) | 191 _jid, steam = self.host.getJidNStream(profile) |
191 try: | 192 try: |
192 from_jid = jid.JID(answer["from"]) | 193 from_jid = jid.JID(answer["from"]) |
193 except KeyError: | 194 except KeyError: |
194 from_jid = _jid.userhostJID() | 195 from_jid = _jid.userhostJID() |
195 d = self.vCard2Dict(answer.firstChildElement(), from_jid, profile) | 196 d = self.vCard2Dict(answer.firstChildElement(), from_jid, profile) |
196 d.addCallback(lambda data: self.host.bridge.actionResult("RESULT", answer['id'], data, profile)) | 197 d.addCallback(lambda data: self.host.bridge.actionResult("RESULT", answer['id'], data, profile)) |
197 else: | 198 else: |
198 error (_("FIXME: vCard not found as first child element")) | 199 error(_("FIXME: vCard not found as first child element")) |
199 self.host.bridge.actionResult("SUPPRESS", answer['id'], {}, profile) #FIXME: maybe an error message would be better | 200 self.host.bridge.actionResult("SUPPRESS", answer['id'], {}, profile) # FIXME: maybe an error message would be better |
200 | 201 |
201 def vcard_err(self, failure, profile): | 202 def vcard_err(self, failure, profile): |
202 """Called when something is wrong with registration""" | 203 """Called when something is wrong with registration""" |
203 error (_("Can't find VCard of %s") % failure.value.stanza['from']) | 204 error(_("Can't find VCard of %s") % failure.value.stanza['from']) |
204 self.host.bridge.actionResult("SUPPRESS", failure.value.stanza['id'], {}, profile) #FIXME: maybe an error message would be better | 205 self.host.bridge.actionResult("SUPPRESS", failure.value.stanza['id'], {}, profile) # FIXME: maybe an error message would be better |
205 | 206 |
206 def getCard(self, target_s, profile_key='@DEFAULT@'): | 207 def getCard(self, target_s, profile_key='@DEFAULT@'): |
207 """Ask server for VCard | 208 """Ask server for VCard |
208 @param target_s: jid from which we want the VCard | 209 @param target_s: jid from which we want the VCard |
209 @result: id to retrieve the profile""" | 210 @result: id to retrieve the profile""" |
210 current_jid, xmlstream = self.host.getJidNStream(profile_key) | 211 current_jid, xmlstream = self.host.getJidNStream(profile_key) |
211 if not xmlstream: | 212 if not xmlstream: |
212 error (_('Asking vcard for a non-existant or not connected profile')) | 213 error(_('Asking vcard for a non-existant or not connected profile')) |
213 return "" | 214 return "" |
214 profile = self.host.memory.getProfileName(profile_key) | 215 profile = self.host.memory.getProfileName(profile_key) |
215 to_jid = jid.JID(target_s) | 216 to_jid = jid.JID(target_s) |
216 debug(_("Asking for %s's VCard") % to_jid.userhost()) | 217 debug(_("Asking for %s's VCard") % to_jid.userhost()) |
217 reg_request=IQ(xmlstream,'get') | 218 reg_request = IQ(xmlstream, 'get') |
218 reg_request["from"]=current_jid.full() | 219 reg_request["from"] = current_jid.full() |
219 reg_request["to"] = to_jid.userhost() | 220 reg_request["to"] = to_jid.userhost() |
220 reg_request.addElement('vCard', NS_VCARD) | 221 reg_request.addElement('vCard', NS_VCARD) |
221 reg_request.send(to_jid.userhost()).addCallbacks(self.vcard_ok, self.vcard_err, callbackArgs=[profile], errbackArgs=[profile]) | 222 reg_request.send(to_jid.userhost()).addCallbacks(self.vcard_ok, self.vcard_err, callbackArgs=[profile], errbackArgs=[profile]) |
222 return reg_request["id"] | 223 return reg_request["id"] |
223 | 224 |
224 def getAvatarFile(self, avatar_hash): | 225 def getAvatarFile(self, avatar_hash): |
225 """Give the full path of avatar from hash | 226 """Give the full path of avatar from hash |
226 @param hash: SHA1 hash | 227 @param hash: SHA1 hash |
227 @return full_path | 228 @return full_path |
228 """ | 229 """ |
229 filename = self.avatar_path+'/'+avatar_hash | 230 filename = self.avatar_path + '/' + avatar_hash |
230 if not os.path.exists(filename): | 231 if not os.path.exists(filename): |
231 error (_("Asking for an uncached avatar [%s]") % avatar_hash) | 232 error(_("Asking for an uncached avatar [%s]") % avatar_hash) |
232 return "" | 233 return "" |
233 return filename | 234 return filename |
234 | 235 |
235 def _buildSetAvatar(self, vcard_set, filepath): | 236 def _buildSetAvatar(self, vcard_set, filepath): |
236 try: | 237 try: |
257 # A proper full VCard management should be done (and more generaly a public/private profile) | 258 # A proper full VCard management should be done (and more generaly a public/private profile) |
258 client = self.host.getClient(profile_key) | 259 client = self.host.getClient(profile_key) |
259 if not client: | 260 if not client: |
260 raise exceptions.NotConnectedProfileError(_('Trying to set avatar for a non-existant or not connected profile')) | 261 raise exceptions.NotConnectedProfileError(_('Trying to set avatar for a non-existant or not connected profile')) |
261 | 262 |
262 vcard_set = IQ(client.xmlstream,'set') | 263 vcard_set = IQ(client.xmlstream, 'set') |
263 d = threads.deferToThread(self._buildSetAvatar, vcard_set, filepath) | 264 d = threads.deferToThread(self._buildSetAvatar, vcard_set, filepath) |
264 | 265 |
265 def elementBuilt(result): | 266 def elementBuilt(result): |
266 """Called once the image is at the right size/format, and the vcard set element is build""" | 267 """Called once the image is at the right size/format, and the vcard set element is build""" |
267 set_avatar_elt, img_hash = result | 268 set_avatar_elt, img_hash = result |
268 self.avatars_cache[client.jid.userhost()] = img_hash # we need to update the hash, so we can send a new presence | 269 self.avatars_cache[client.jid.userhost()] = img_hash # we need to update the hash, so we can send a new presence |
269 # element with the right hash | 270 # element with the right hash |
270 return set_avatar_elt.send().addCallback(lambda ignore: client.presence.available()) | 271 return set_avatar_elt.send().addCallback(lambda ignore: client.presence.available()) |
271 | 272 |
272 d.addCallback(elementBuilt) | 273 d.addCallback(elementBuilt) |
273 | 274 |
294 """Request for VCard's nickname | 295 """Request for VCard's nickname |
295 return the cached nickname if exists, else get VCard | 296 return the cached nickname if exists, else get VCard |
296 """ | 297 """ |
297 from_jid = jid.JID(presence['from']) | 298 from_jid = jid.JID(presence['from']) |
298 #FIXME: wokkel's data_form should be used here | 299 #FIXME: wokkel's data_form should be used here |
299 x_elem = filter (lambda x:x.name == "x", presence.elements())[0] #We only want the "x" element | 300 x_elem = filter(lambda x: x.name == "x", presence.elements())[0] # We only want the "x" element |
300 for elem in x_elem.elements(): | 301 for elem in x_elem.elements(): |
301 if elem.name == 'photo': | 302 if elem.name == 'photo': |
302 _hash = str(elem) | 303 _hash = str(elem) |
303 old_avatar = self.plugin_parent.get_cache(from_jid, 'avatar', self.parent.profile) | 304 old_avatar = self.plugin_parent.get_cache(from_jid, 'avatar', self.parent.profile) |
304 if not old_avatar or old_avatar != _hash: | 305 if not old_avatar or old_avatar != _hash: |