Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0050.py @ 1110:36c1bbb8ca24
plugin XEP-0050: notes are now managed:
- a note without payload in a completed command appear in a dialog. If there is a unique note, it's level is used, else info dialog is used with merged notes
- if there is a data form payload, notes are added to form's instructions
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 20 Aug 2014 21:22:06 +0200 |
parents | c0ef97002ef4 |
children | 069ad98b360d |
comparison
equal
deleted
inserted
replaced
1109:0a448c947038 | 1110:36c1bbb8ca24 |
---|---|
240 | 240 |
241 options = [(item.nodeIdentifier, item.name) for item in items] | 241 options = [(item.nodeIdentifier, item.name) for item in items] |
242 form_ui.addList("node", options) | 242 form_ui.addList("node", options) |
243 return form_ui | 243 return form_ui |
244 | 244 |
245 def _getDataLvl(self, type_): | |
246 """Return the constant corresponding to <note/> type attribute value | |
247 | |
248 @param type_: note type (see XEP-0050 ยง4.3) | |
249 @return: a C.XMLUI_DATA_LVL_* constant | |
250 """ | |
251 if type_ == 'error': | |
252 return C.XMLUI_DATA_LVL_ERROR | |
253 elif type_ == 'warn': | |
254 return C.XMLUI_DATA_LVL_WARNING | |
255 else: | |
256 if type_ != 'info': | |
257 log.warning(_("Invalid note type [%s], using info") % type_) | |
258 return C.XMLUI_DATA_LVL_INFO | |
259 | |
260 def _mergeNotes(self, notes): | |
261 """Merge notes with level prefix (e.g. "ERROR: the message") | |
262 | |
263 @param notes (list): list of tuple (level, message) | |
264 @return: list of messages | |
265 """ | |
266 lvl_map = {C.XMLUI_DATA_LVL_INFO: '', | |
267 C.XMLUI_DATA_LVL_WARNING: "%s: " % _("WARNING"), | |
268 C.XMLUI_DATA_LVL_ERROR: "%s: " % _("ERROR") | |
269 } | |
270 return [u"%s%s" % (lvl_map[lvl], msg) for lvl, msg in notes] | |
271 | |
245 def _commandsAnswer2XMLUI(self, iq_elt, session_id, session_data): | 272 def _commandsAnswer2XMLUI(self, iq_elt, session_id, session_data): |
246 """ | 273 """ |
247 Convert command answer to an ui for frontend | 274 Convert command answer to an ui for frontend |
248 @param iq_elt: command result | 275 @param iq_elt: command result |
249 @param session_id: id of the session used with the frontend | 276 @param session_id: id of the session used with the frontend |
260 else: | 287 else: |
261 return None | 288 return None |
262 remote_session_id = command_elt.getAttribute('sessionid') | 289 remote_session_id = command_elt.getAttribute('sessionid') |
263 if remote_session_id: | 290 if remote_session_id: |
264 session_data['remote_id'] = remote_session_id | 291 session_data['remote_id'] = remote_session_id |
265 data_elt = command_elt.elements(data_form.NS_X_DATA, 'x').next() | 292 notes = [] |
293 for note_elt in command_elt.elements(NS_COMMANDS, 'note'): | |
294 notes.append((self._getDataLvl(note_elt.getAttribute('type', 'info')), | |
295 unicode(note_elt))) | |
296 try: | |
297 data_elt = command_elt.elements(data_form.NS_X_DATA, 'x').next() | |
298 except StopIteration: | |
299 if status != XEP_0050.STATUS.COMPLETED: | |
300 log.warning(_("No known payload found in ad-hoc command result, aborting")) | |
301 del self.requesting[session_id] | |
302 return xml_tools.XMLUI(C.XMLUI_DIALOG, | |
303 dialog_opt = {C.XMLUI_DATA_TYPE: C.XMLUI_DIALOG_NOTE, | |
304 C.XMLUI_DATA_MESS: _("No payload found"), | |
305 C.XMLUI_DATA_LVL: C.XMLUI_DATA_LVL_ERROR, | |
306 } | |
307 ) | |
308 if not notes: | |
309 # the status is completed, and we have no note to show | |
310 return None | |
311 | |
312 # if we have only one note, we show a dialog with the level of the note | |
313 # if we have more, we show a dialog with "info" level, and all notes merged | |
314 dlg_level = notes[0][0] if len(notes) == 1 else C.XMLUI_DATA_LVL_INFO | |
315 return xml_tools.XMLUI( | |
316 C.XMLUI_DIALOG, | |
317 dialog_opt = {C.XMLUI_DATA_TYPE: C.XMLUI_DIALOG_NOTE, | |
318 C.XMLUI_DATA_MESS: u'\n'.join(self._mergeNotes(notes)), | |
319 C.XMLUI_DATA_LVL: dlg_level, | |
320 }, | |
321 session_id = session_id | |
322 ) | |
323 | |
266 if session_id is None: | 324 if session_id is None: |
267 return xml_tools.dataFormResult2XMLUI(data_elt) | 325 return xml_tools.dataFormResult2XMLUI(data_elt) |
268 form = data_form.Form.fromElement(data_elt) | 326 form = data_form.Form.fromElement(data_elt) |
269 return xml_tools.dataForm2XMLUI(form, self.__requesting_id, session_id=session_id) | 327 # we add any present note to the instructions |
328 form.instructions.extend(self._mergeNotes(notes)) | |
329 return xml_tools.dataForm2XMLUI(form, self.__requesting_id, session_id=session_id) | |
270 | 330 |
271 def _requestingEntity(self, data, profile): | 331 def _requestingEntity(self, data, profile): |
272 """ | 332 """ |
273 request and entity and create XMLUI accordingly | 333 request and entity and create XMLUI accordingly |
274 @param data: data returned by previous XMLUI (first one must come from self._commandsMenu) | 334 @param data: data returned by previous XMLUI (first one must come from self._commandsMenu) |
300 # TODO: send error dialog | 360 # TODO: send error dialog |
301 return defer.succeed({}) | 361 return defer.succeed({}) |
302 session_id = data["session_id"] | 362 session_id = data["session_id"] |
303 entity = session_data['jid'] | 363 entity = session_data['jid'] |
304 try: | 364 try: |
305 node = session_data['node'] | 365 session_data['node'] |
306 # node has already been received | 366 # node has already been received |
307 except KeyError: | 367 except KeyError: |
308 # it's the first time we know the node, we save it in session data | 368 # it's the first time we know the node, we save it in session data |
309 node = session_data['node'] = data[xml_tools.SAT_FORM_PREFIX+'node'] | 369 session_data['node'] = data[xml_tools.SAT_FORM_PREFIX+'node'] |
310 | 370 |
311 client = self.host.getClient(profile) | 371 client = self.host.getClient(profile) |
312 | 372 |
313 # we request execute node's command | 373 # we request execute node's command |
314 iq_elt = compat.IQ(client.xmlstream, 'set') | 374 iq_elt = compat.IQ(client.xmlstream, 'set') |
400 d.addCallback(self._items2XMLUI) | 460 d.addCallback(self._items2XMLUI) |
401 return d | 461 return d |
402 | 462 |
403 def addAdHocCommand(self, callback, label, node="", features = None, timeout = 600, allowed_jids = None, allowed_groups = None, | 463 def addAdHocCommand(self, callback, label, node="", features = None, timeout = 600, allowed_jids = None, allowed_groups = None, |
404 allowed_magics = None, forbidden_jids = None, forbidden_groups = None, profile_key=C.PROF_KEY_NONE): | 464 allowed_magics = None, forbidden_jids = None, forbidden_groups = None, profile_key=C.PROF_KEY_NONE): |
405 """ | 465 """Add an ad-hoc command for the current profile |
406 | |
407 Add an ad-hoc command for the current profile | |
408 | 466 |
409 @param callback: method associated with this ad-hoc command which return the payload data (see AdHocCommand._sendAnswer), can return a deferred | 467 @param callback: method associated with this ad-hoc command which return the payload data (see AdHocCommand._sendAnswer), can return a deferred |
410 @param label: label associated with this command on the main menu | 468 @param label: label associated with this command on the main menu |
411 @param node: disco item node associated with this command. None or "" to use autogenerated node | 469 @param node: disco item node associated with this command. None or "" to use autogenerated node |
412 @param features: features associated with the payload (list of strings), usualy data form | 470 @param features: features associated with the payload (list of strings), usualy data form |