Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0050.py @ 4037:524856bd7b19
massive refactoring to switch from camelCase to snake_case:
historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a
pre-PEP8 code, to use the same coding style as in Twisted.
However, snake_case is more readable and it's better to follow PEP8 best practices, so it
has been decided to move on full snake_case. Because Libervia has a huge codebase, this
ended with a ugly mix of camelCase and snake_case.
To fix that, this patch does a big refactoring by renaming every function and method
(including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case.
This is a massive change, and may result in some bugs.
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 08 Apr 2023 13:54:42 +0200 |
parents | 6c93a18b6250 |
children |
comparison
equal
deleted
inserted
replaced
4036:c4464d7ae97b | 4037:524856bd7b19 |
---|---|
100 return self.parent | 100 return self.parent |
101 | 101 |
102 def getName(self, xml_lang=None): | 102 def getName(self, xml_lang=None): |
103 return self.label | 103 return self.label |
104 | 104 |
105 def isAuthorised(self, requestor): | 105 def is_authorised(self, requestor): |
106 if "@ALL@" in self.allowed_magics: | 106 if "@ALL@" in self.allowed_magics: |
107 return True | 107 return True |
108 forbidden = set(self.forbidden_jids) | 108 forbidden = set(self.forbidden_jids) |
109 for group in self.forbidden_groups: | 109 for group in self.forbidden_groups: |
110 forbidden.update(self.client.roster.getJidsFromGroup(group)) | 110 forbidden.update(self.client.roster.get_jids_from_group(group)) |
111 if requestor.userhostJID() in forbidden: | 111 if requestor.userhostJID() in forbidden: |
112 return False | 112 return False |
113 allowed = set(self.allowed_jids) | 113 allowed = set(self.allowed_jids) |
114 for group in self.allowed_groups: | 114 for group in self.allowed_groups: |
115 try: | 115 try: |
116 allowed.update(self.client.roster.getJidsFromGroup(group)) | 116 allowed.update(self.client.roster.get_jids_from_group(group)) |
117 except exceptions.UnknownGroupError: | 117 except exceptions.UnknownGroupError: |
118 log.warning(_("The groups [{group}] is unknown for profile [{profile}])") | 118 log.warning(_("The groups [{group}] is unknown for profile [{profile}])") |
119 .format(group=group, profile=self.client.profile)) | 119 .format(group=group, profile=self.client.profile)) |
120 if requestor.userhostJID() in allowed: | 120 if requestor.userhostJID() in allowed: |
121 return True | 121 return True |
192 error_elt = next(iq_elt.elements(None, "error")) | 192 error_elt = next(iq_elt.elements(None, "error")) |
193 error_elt.addElement(cmd_condition, NS_COMMANDS) | 193 error_elt.addElement(cmd_condition, NS_COMMANDS) |
194 self.client.send(iq_elt) | 194 self.client.send(iq_elt) |
195 del self.sessions[session_id] | 195 del self.sessions[session_id] |
196 | 196 |
197 def _requestEb(self, failure_, request, session_id): | 197 def _request_eb(self, failure_, request, session_id): |
198 if failure_.check(AdHocError): | 198 if failure_.check(AdHocError): |
199 error_constant = failure_.value.callback_error | 199 error_constant = failure_.value.callback_error |
200 else: | 200 else: |
201 log.error(f"unexpected error while handling request: {failure_}") | 201 log.error(f"unexpected error while handling request: {failure_}") |
202 error_constant = XEP_0050.ERROR.INTERNAL | 202 error_constant = XEP_0050.ERROR.INTERNAL |
203 | 203 |
204 self._sendError(error_constant, session_id, request) | 204 self._sendError(error_constant, session_id, request) |
205 | 205 |
206 def onRequest(self, command_elt, requestor, action, session_id): | 206 def on_request(self, command_elt, requestor, action, session_id): |
207 if not self.isAuthorised(requestor): | 207 if not self.is_authorised(requestor): |
208 return self._sendError( | 208 return self._sendError( |
209 XEP_0050.ERROR.FORBIDDEN, session_id, command_elt.parent | 209 XEP_0050.ERROR.FORBIDDEN, session_id, command_elt.parent |
210 ) | 210 ) |
211 if session_id: | 211 if session_id: |
212 try: | 212 try: |
218 if session_data["requestor"] != requestor: | 218 if session_data["requestor"] != requestor: |
219 return self._sendError( | 219 return self._sendError( |
220 XEP_0050.ERROR.FORBIDDEN, session_id, command_elt.parent | 220 XEP_0050.ERROR.FORBIDDEN, session_id, command_elt.parent |
221 ) | 221 ) |
222 else: | 222 else: |
223 session_id, session_data = self.sessions.newSession() | 223 session_id, session_data = self.sessions.new_session() |
224 session_data["requestor"] = requestor | 224 session_data["requestor"] = requestor |
225 if action == XEP_0050.ACTION.CANCEL: | 225 if action == XEP_0050.ACTION.CANCEL: |
226 d = defer.succeed((None, XEP_0050.STATUS.CANCELED, None, None)) | 226 d = defer.succeed((None, XEP_0050.STATUS.CANCELED, None, None)) |
227 else: | 227 else: |
228 d = utils.asDeferred( | 228 d = utils.as_deferred( |
229 self.callback, | 229 self.callback, |
230 self.client, | 230 self.client, |
231 command_elt, | 231 command_elt, |
232 session_data, | 232 session_data, |
233 action, | 233 action, |
234 self.node, | 234 self.node, |
235 ) | 235 ) |
236 d.addCallback(self._sendAnswer, session_id, command_elt.parent) | 236 d.addCallback(self._sendAnswer, session_id, command_elt.parent) |
237 d.addErrback(self._requestEb, command_elt.parent, session_id) | 237 d.addErrback(self._request_eb, command_elt.parent, session_id) |
238 | 238 |
239 | 239 |
240 class XEP_0050(object): | 240 class XEP_0050(object): |
241 STATUS = namedtuple("Status", ("EXECUTING", "COMPLETED", "CANCELED"))( | 241 STATUS = namedtuple("Status", ("EXECUTING", "COMPLETED", "CANCELED"))( |
242 "executing", "completed", "canceled" | 242 "executing", "completed", "canceled" |
274 | 274 |
275 def __init__(self, host): | 275 def __init__(self, host): |
276 log.info(_("plugin XEP-0050 initialization")) | 276 log.info(_("plugin XEP-0050 initialization")) |
277 self.host = host | 277 self.host = host |
278 self.requesting = Sessions() | 278 self.requesting = Sessions() |
279 host.bridge.addMethod( | 279 host.bridge.add_method( |
280 "adHocRun", | 280 "ad_hoc_run", |
281 ".plugin", | 281 ".plugin", |
282 in_sign="sss", | 282 in_sign="sss", |
283 out_sign="s", | 283 out_sign="s", |
284 method=self._run, | 284 method=self._run, |
285 async_=True, | 285 async_=True, |
286 ) | 286 ) |
287 host.bridge.addMethod( | 287 host.bridge.add_method( |
288 "adHocList", | 288 "ad_hoc_list", |
289 ".plugin", | 289 ".plugin", |
290 in_sign="ss", | 290 in_sign="ss", |
291 out_sign="s", | 291 out_sign="s", |
292 method=self._listUI, | 292 method=self._list_ui, |
293 async_=True, | 293 async_=True, |
294 ) | 294 ) |
295 host.bridge.addMethod( | 295 host.bridge.add_method( |
296 "adHocSequence", | 296 "ad_hoc_sequence", |
297 ".plugin", | 297 ".plugin", |
298 in_sign="ssss", | 298 in_sign="ssss", |
299 out_sign="s", | 299 out_sign="s", |
300 method=self._sequence, | 300 method=self._sequence, |
301 async_=True, | 301 async_=True, |
302 ) | 302 ) |
303 self.__requesting_id = host.registerCallback( | 303 self.__requesting_id = host.register_callback( |
304 self._requestingEntity, with_data=True | 304 self._requesting_entity, with_data=True |
305 ) | 305 ) |
306 host.importMenu( | 306 host.import_menu( |
307 (D_("Service"), D_("Commands")), | 307 (D_("Service"), D_("Commands")), |
308 self._commandsMenu, | 308 self._commands_menu, |
309 security_limit=2, | 309 security_limit=2, |
310 help_string=D_("Execute ad-hoc commands"), | 310 help_string=D_("Execute ad-hoc commands"), |
311 ) | 311 ) |
312 host.registerNamespace('commands', NS_COMMANDS) | 312 host.register_namespace('commands', NS_COMMANDS) |
313 | 313 |
314 def getHandler(self, client): | 314 def get_handler(self, client): |
315 return XEP_0050_handler(self) | 315 return XEP_0050_handler(self) |
316 | 316 |
317 def profileConnected(self, client): | 317 def profile_connected(self, client): |
318 # map from node to AdHocCommand instance | 318 # map from node to AdHocCommand instance |
319 client._XEP_0050_commands = {} | 319 client._XEP_0050_commands = {} |
320 if not client.is_component: | 320 if not client.is_component: |
321 self.addAdHocCommand(client, self._statusCallback, _("Status")) | 321 self.add_ad_hoc_command(client, self._status_callback, _("Status")) |
322 | 322 |
323 def do(self, client, entity, node, action=ACTION.EXECUTE, session_id=None, | 323 def do(self, client, entity, node, action=ACTION.EXECUTE, session_id=None, |
324 form_values=None, timeout=30): | 324 form_values=None, timeout=30): |
325 """Do an Ad-Hoc Command | 325 """Do an Ad-Hoc Command |
326 | 326 |
347 form.makeFields(form_values) | 347 form.makeFields(form_values) |
348 command_elt.addChild(form.toElement()) | 348 command_elt.addChild(form.toElement()) |
349 d = iq_elt.send() | 349 d = iq_elt.send() |
350 return d | 350 return d |
351 | 351 |
352 def getCommandElt(self, iq_elt): | 352 def get_command_elt(self, iq_elt): |
353 try: | 353 try: |
354 return next(iq_elt.elements(NS_COMMANDS, "command")) | 354 return next(iq_elt.elements(NS_COMMANDS, "command")) |
355 except StopIteration: | 355 except StopIteration: |
356 raise exceptions.NotFound(_("Missing command element")) | 356 raise exceptions.NotFound(_("Missing command element")) |
357 | 357 |
358 def adHocError(self, error_type): | 358 def ad_hoc_error(self, error_type): |
359 """Shortcut to raise an AdHocError | 359 """Shortcut to raise an AdHocError |
360 | 360 |
361 @param error_type(unicode): one of XEP_0050.ERROR | 361 @param error_type(unicode): one of XEP_0050.ERROR |
362 """ | 362 """ |
363 raise AdHocError(error_type) | 363 raise AdHocError(error_type) |
364 | 364 |
365 def _items2XMLUI(self, items, no_instructions): | 365 def _items_2_xmlui(self, items, no_instructions): |
366 """Convert discovery items to XMLUI dialog """ | 366 """Convert discovery items to XMLUI dialog """ |
367 # TODO: manage items on different jids | 367 # TODO: manage items on different jids |
368 form_ui = xml_tools.XMLUI("form", submit_id=self.__requesting_id) | 368 form_ui = xml_tools.XMLUI("form", submit_id=self.__requesting_id) |
369 | 369 |
370 if not no_instructions: | 370 if not no_instructions: |
372 | 372 |
373 options = [(item.nodeIdentifier, item.name) for item in items] | 373 options = [(item.nodeIdentifier, item.name) for item in items] |
374 form_ui.addList("node", options) | 374 form_ui.addList("node", options) |
375 return form_ui | 375 return form_ui |
376 | 376 |
377 def _getDataLvl(self, type_): | 377 def _get_data_lvl(self, type_): |
378 """Return the constant corresponding to <note/> type attribute value | 378 """Return the constant corresponding to <note/> type attribute value |
379 | 379 |
380 @param type_: note type (see XEP-0050 §4.3) | 380 @param type_: note type (see XEP-0050 §4.3) |
381 @return: a C.XMLUI_DATA_LVL_* constant | 381 @return: a C.XMLUI_DATA_LVL_* constant |
382 """ | 382 """ |
387 else: | 387 else: |
388 if type_ != "info": | 388 if type_ != "info": |
389 log.warning(_("Invalid note type [%s], using info") % type_) | 389 log.warning(_("Invalid note type [%s], using info") % type_) |
390 return C.XMLUI_DATA_LVL_INFO | 390 return C.XMLUI_DATA_LVL_INFO |
391 | 391 |
392 def _mergeNotes(self, notes): | 392 def _merge_notes(self, notes): |
393 """Merge notes with level prefix (e.g. "ERROR: the message") | 393 """Merge notes with level prefix (e.g. "ERROR: the message") |
394 | 394 |
395 @param notes (list): list of tuple (level, message) | 395 @param notes (list): list of tuple (level, message) |
396 @return: list of messages | 396 @return: list of messages |
397 """ | 397 """ |
400 C.XMLUI_DATA_LVL_WARNING: "%s: " % _("WARNING"), | 400 C.XMLUI_DATA_LVL_WARNING: "%s: " % _("WARNING"), |
401 C.XMLUI_DATA_LVL_ERROR: "%s: " % _("ERROR"), | 401 C.XMLUI_DATA_LVL_ERROR: "%s: " % _("ERROR"), |
402 } | 402 } |
403 return ["%s%s" % (lvl_map[lvl], msg) for lvl, msg in notes] | 403 return ["%s%s" % (lvl_map[lvl], msg) for lvl, msg in notes] |
404 | 404 |
405 def parseCommandAnswer(self, iq_elt): | 405 def parse_command_answer(self, iq_elt): |
406 command_elt = self.getCommandElt(iq_elt) | 406 command_elt = self.get_command_elt(iq_elt) |
407 data = {} | 407 data = {} |
408 data["status"] = command_elt.getAttribute("status", XEP_0050.STATUS.EXECUTING) | 408 data["status"] = command_elt.getAttribute("status", XEP_0050.STATUS.EXECUTING) |
409 data["session_id"] = command_elt.getAttribute("sessionid") | 409 data["session_id"] = command_elt.getAttribute("sessionid") |
410 data["notes"] = notes = [] | 410 data["notes"] = notes = [] |
411 for note_elt in command_elt.elements(NS_COMMANDS, "note"): | 411 for note_elt in command_elt.elements(NS_COMMANDS, "note"): |
412 notes.append( | 412 notes.append( |
413 ( | 413 ( |
414 self._getDataLvl(note_elt.getAttribute("type", "info")), | 414 self._get_data_lvl(note_elt.getAttribute("type", "info")), |
415 str(note_elt), | 415 str(note_elt), |
416 ) | 416 ) |
417 ) | 417 ) |
418 | 418 |
419 return command_elt, data | 419 return command_elt, data |
420 | 420 |
421 | 421 |
422 def _commandsAnswer2XMLUI(self, iq_elt, session_id, session_data): | 422 def _commands_answer_2_xmlui(self, iq_elt, session_id, session_data): |
423 """Convert command answer to an ui for frontend | 423 """Convert command answer to an ui for frontend |
424 | 424 |
425 @param iq_elt: command result | 425 @param iq_elt: command result |
426 @param session_id: id of the session used with the frontend | 426 @param session_id: id of the session used with the frontend |
427 @param profile_key: %(doc_profile_key)s | 427 @param profile_key: %(doc_profile_key)s |
428 """ | 428 """ |
429 command_elt, answer_data = self.parseCommandAnswer(iq_elt) | 429 command_elt, answer_data = self.parse_command_answer(iq_elt) |
430 status = answer_data["status"] | 430 status = answer_data["status"] |
431 if status in [XEP_0050.STATUS.COMPLETED, XEP_0050.STATUS.CANCELED]: | 431 if status in [XEP_0050.STATUS.COMPLETED, XEP_0050.STATUS.CANCELED]: |
432 # the command session is finished, we purge our session | 432 # the command session is finished, we purge our session |
433 del self.requesting[session_id] | 433 del self.requesting[session_id] |
434 if status == XEP_0050.STATUS.COMPLETED: | 434 if status == XEP_0050.STATUS.COMPLETED: |
466 dlg_level = notes[0][0] if len(notes) == 1 else C.XMLUI_DATA_LVL_INFO | 466 dlg_level = notes[0][0] if len(notes) == 1 else C.XMLUI_DATA_LVL_INFO |
467 return xml_tools.XMLUI( | 467 return xml_tools.XMLUI( |
468 C.XMLUI_DIALOG, | 468 C.XMLUI_DIALOG, |
469 dialog_opt={ | 469 dialog_opt={ |
470 C.XMLUI_DATA_TYPE: C.XMLUI_DIALOG_NOTE, | 470 C.XMLUI_DATA_TYPE: C.XMLUI_DIALOG_NOTE, |
471 C.XMLUI_DATA_MESS: "\n".join(self._mergeNotes(notes)), | 471 C.XMLUI_DATA_MESS: "\n".join(self._merge_notes(notes)), |
472 C.XMLUI_DATA_LVL: dlg_level, | 472 C.XMLUI_DATA_LVL: dlg_level, |
473 }, | 473 }, |
474 session_id=session_id, | 474 session_id=session_id, |
475 ) | 475 ) |
476 | 476 |
477 if session_id is None: | 477 if session_id is None: |
478 xmlui = xml_tools.dataFormEltResult2XMLUI(data_elt) | 478 xmlui = xml_tools.data_form_elt_result_2_xmlui(data_elt) |
479 if notes: | 479 if notes: |
480 for level, note in notes: | 480 for level, note in notes: |
481 if level != "info": | 481 if level != "info": |
482 note = f"[{level}] {note}" | 482 note = f"[{level}] {note}" |
483 xmlui.addWidget("text", note) | 483 xmlui.add_widget("text", note) |
484 return xmlui | 484 return xmlui |
485 | 485 |
486 form = data_form.Form.fromElement(data_elt) | 486 form = data_form.Form.fromElement(data_elt) |
487 # we add any present note to the instructions | 487 # we add any present note to the instructions |
488 form.instructions.extend(self._mergeNotes(notes)) | 488 form.instructions.extend(self._merge_notes(notes)) |
489 return xml_tools.dataForm2XMLUI(form, self.__requesting_id, session_id=session_id) | 489 return xml_tools.data_form_2_xmlui(form, self.__requesting_id, session_id=session_id) |
490 | 490 |
491 def _requestingEntity(self, data, profile): | 491 def _requesting_entity(self, data, profile): |
492 def serialise(ret_data): | 492 def serialise(ret_data): |
493 if "xmlui" in ret_data: | 493 if "xmlui" in ret_data: |
494 ret_data["xmlui"] = ret_data["xmlui"].toXml() | 494 ret_data["xmlui"] = ret_data["xmlui"].toXml() |
495 return ret_data | 495 return ret_data |
496 | 496 |
497 d = self.requestingEntity(data, profile) | 497 d = self.requesting_entity(data, profile) |
498 d.addCallback(serialise) | 498 d.addCallback(serialise) |
499 return d | 499 return d |
500 | 500 |
501 def requestingEntity(self, data, profile): | 501 def requesting_entity(self, data, profile): |
502 """Request and entity and create XMLUI accordingly. | 502 """Request and entity and create XMLUI accordingly. |
503 | 503 |
504 @param data: data returned by previous XMLUI (first one must come from | 504 @param data: data returned by previous XMLUI (first one must come from |
505 self._commandsMenu) | 505 self._commands_menu) |
506 @param profile: %(doc_profile)s | 506 @param profile: %(doc_profile)s |
507 @return: callback dict result (with "xmlui" corresponding to the answering | 507 @return: callback dict result (with "xmlui" corresponding to the answering |
508 dialog, or empty if it's finished without error) | 508 dialog, or empty if it's finished without error) |
509 """ | 509 """ |
510 if C.bool(data.get("cancelled", C.BOOL_FALSE)): | 510 if C.bool(data.get("cancelled", C.BOOL_FALSE)): |
511 return defer.succeed({}) | 511 return defer.succeed({}) |
512 data_form_values = xml_tools.XMLUIResult2DataFormResult(data) | 512 data_form_values = xml_tools.xmlui_result_2_data_form_result(data) |
513 client = self.host.getClient(profile) | 513 client = self.host.get_client(profile) |
514 # TODO: cancel, prev and next are not managed | 514 # TODO: cancel, prev and next are not managed |
515 # TODO: managed answerer errors | 515 # TODO: managed answerer errors |
516 # TODO: manage nodes with a non data form payload | 516 # TODO: manage nodes with a non data form payload |
517 if "session_id" not in data: | 517 if "session_id" not in data: |
518 # we just had the jid, we now request it for the available commands | 518 # we just had the jid, we now request it for the available commands |
519 session_id, session_data = self.requesting.newSession(profile=client.profile) | 519 session_id, session_data = self.requesting.new_session(profile=client.profile) |
520 entity = jid.JID(data[xml_tools.SAT_FORM_PREFIX + "jid"]) | 520 entity = jid.JID(data[xml_tools.SAT_FORM_PREFIX + "jid"]) |
521 session_data["jid"] = entity | 521 session_data["jid"] = entity |
522 d = self.listUI(client, entity) | 522 d = self.list_ui(client, entity) |
523 | 523 |
524 def sendItems(xmlui): | 524 def send_items(xmlui): |
525 xmlui.session_id = session_id # we need to keep track of the session | 525 xmlui.session_id = session_id # we need to keep track of the session |
526 return {"xmlui": xmlui} | 526 return {"xmlui": xmlui} |
527 | 527 |
528 d.addCallback(sendItems) | 528 d.addCallback(send_items) |
529 else: | 529 else: |
530 # we have started a several forms sessions | 530 # we have started a several forms sessions |
531 try: | 531 try: |
532 session_data = self.requesting.profileGet( | 532 session_data = self.requesting.profile_get( |
533 data["session_id"], client.profile | 533 data["session_id"], client.profile |
534 ) | 534 ) |
535 except KeyError: | 535 except KeyError: |
536 log.warning("session id doesn't exist, session has probably expired") | 536 log.warning("session id doesn't exist, session has probably expired") |
537 # TODO: send error dialog | 537 # TODO: send error dialog |
550 remote_id = session_data.get("remote_id") | 550 remote_id = session_data.get("remote_id") |
551 | 551 |
552 # we request execute node's command | 552 # we request execute node's command |
553 d = self.do(client, entity, session_data["node"], action=XEP_0050.ACTION.EXECUTE, | 553 d = self.do(client, entity, session_data["node"], action=XEP_0050.ACTION.EXECUTE, |
554 session_id=remote_id, form_values=data_form_values) | 554 session_id=remote_id, form_values=data_form_values) |
555 d.addCallback(self._commandsAnswer2XMLUI, session_id, session_data) | 555 d.addCallback(self._commands_answer_2_xmlui, session_id, session_data) |
556 d.addCallback(lambda xmlui: {"xmlui": xmlui} if xmlui is not None else {}) | 556 d.addCallback(lambda xmlui: {"xmlui": xmlui} if xmlui is not None else {}) |
557 | 557 |
558 return d | 558 return d |
559 | 559 |
560 def _commandsMenu(self, menu_data, profile): | 560 def _commands_menu(self, menu_data, profile): |
561 """First XMLUI activated by menu: ask for target jid | 561 """First XMLUI activated by menu: ask for target jid |
562 | 562 |
563 @param profile: %(doc_profile)s | 563 @param profile: %(doc_profile)s |
564 """ | 564 """ |
565 form_ui = xml_tools.XMLUI("form", submit_id=self.__requesting_id) | 565 form_ui = xml_tools.XMLUI("form", submit_id=self.__requesting_id) |
566 form_ui.addText(_("Please enter target jid"), "instructions") | 566 form_ui.addText(_("Please enter target jid"), "instructions") |
567 form_ui.changeContainer("pairs") | 567 form_ui.change_container("pairs") |
568 form_ui.addLabel("jid") | 568 form_ui.addLabel("jid") |
569 form_ui.addString("jid", value=self.host.getClient(profile).jid.host) | 569 form_ui.addString("jid", value=self.host.get_client(profile).jid.host) |
570 return {"xmlui": form_ui.toXml()} | 570 return {"xmlui": form_ui.toXml()} |
571 | 571 |
572 def _statusCallback(self, client, command_elt, session_data, action, node): | 572 def _status_callback(self, client, command_elt, session_data, action, node): |
573 """Ad-hoc command used to change the "show" part of status""" | 573 """Ad-hoc command used to change the "show" part of status""" |
574 actions = session_data.setdefault("actions", []) | 574 actions = session_data.setdefault("actions", []) |
575 actions.append(action) | 575 actions.append(action) |
576 | 576 |
577 if len(actions) == 1: | 577 if len(actions) == 1: |
594 try: | 594 try: |
595 x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x")) | 595 x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x")) |
596 answer_form = data_form.Form.fromElement(x_elt) | 596 answer_form = data_form.Form.fromElement(x_elt) |
597 show = answer_form["show"] | 597 show = answer_form["show"] |
598 except (KeyError, StopIteration): | 598 except (KeyError, StopIteration): |
599 self.adHocError(XEP_0050.ERROR.BAD_PAYLOAD) | 599 self.ad_hoc_error(XEP_0050.ERROR.BAD_PAYLOAD) |
600 if show not in SHOWS: | 600 if show not in SHOWS: |
601 self.adHocError(XEP_0050.ERROR.BAD_PAYLOAD) | 601 self.ad_hoc_error(XEP_0050.ERROR.BAD_PAYLOAD) |
602 if show == "disconnect": | 602 if show == "disconnect": |
603 self.host.disconnect(client.profile) | 603 self.host.disconnect(client.profile) |
604 else: | 604 else: |
605 self.host.setPresence(show=show, profile_key=client.profile) | 605 self.host.presence_set(show=show, profile_key=client.profile) |
606 | 606 |
607 # job done, we can end the session | 607 # job done, we can end the session |
608 status = XEP_0050.STATUS.COMPLETED | 608 status = XEP_0050.STATUS.COMPLETED |
609 payload = None | 609 payload = None |
610 note = (self.NOTE.INFO, _("Status updated")) | 610 note = (self.NOTE.INFO, _("Status updated")) |
611 else: | 611 else: |
612 self.adHocError(XEP_0050.ERROR.INTERNAL) | 612 self.ad_hoc_error(XEP_0050.ERROR.INTERNAL) |
613 | 613 |
614 return (payload, status, None, note) | 614 return (payload, status, None, note) |
615 | 615 |
616 def _run(self, service_jid_s="", node="", profile_key=C.PROF_KEY_NONE): | 616 def _run(self, service_jid_s="", node="", profile_key=C.PROF_KEY_NONE): |
617 client = self.host.getClient(profile_key) | 617 client = self.host.get_client(profile_key) |
618 service_jid = jid.JID(service_jid_s) if service_jid_s else None | 618 service_jid = jid.JID(service_jid_s) if service_jid_s else None |
619 d = defer.ensureDeferred(self.run(client, service_jid, node or None)) | 619 d = defer.ensureDeferred(self.run(client, service_jid, node or None)) |
620 d.addCallback(lambda xmlui: xmlui.toXml()) | 620 d.addCallback(lambda xmlui: xmlui.toXml()) |
621 return d | 621 return d |
622 | 622 |
629 None to get initial list | 629 None to get initial list |
630 @return(unicode): command page XMLUI | 630 @return(unicode): command page XMLUI |
631 """ | 631 """ |
632 if service_jid is None: | 632 if service_jid is None: |
633 service_jid = jid.JID(client.jid.host) | 633 service_jid = jid.JID(client.jid.host) |
634 session_id, session_data = self.requesting.newSession(profile=client.profile) | 634 session_id, session_data = self.requesting.new_session(profile=client.profile) |
635 session_data["jid"] = service_jid | 635 session_data["jid"] = service_jid |
636 if node is None: | 636 if node is None: |
637 xmlui = await self.listUI(client, service_jid) | 637 xmlui = await self.list_ui(client, service_jid) |
638 else: | 638 else: |
639 session_data["node"] = node | 639 session_data["node"] = node |
640 cb_data = await self.requestingEntity( | 640 cb_data = await self.requesting_entity( |
641 {"session_id": session_id}, client.profile | 641 {"session_id": session_id}, client.profile |
642 ) | 642 ) |
643 xmlui = cb_data["xmlui"] | 643 xmlui = cb_data["xmlui"] |
644 | 644 |
645 xmlui.session_id = session_id | 645 xmlui.session_id = session_id |
653 @return D(disco.DiscoItems): found commands | 653 @return D(disco.DiscoItems): found commands |
654 """ | 654 """ |
655 d = self.host.getDiscoItems(client, to_jid, NS_COMMANDS) | 655 d = self.host.getDiscoItems(client, to_jid, NS_COMMANDS) |
656 return d | 656 return d |
657 | 657 |
658 def _listUI(self, to_jid_s, profile_key): | 658 def _list_ui(self, to_jid_s, profile_key): |
659 client = self.host.getClient(profile_key) | 659 client = self.host.get_client(profile_key) |
660 to_jid = jid.JID(to_jid_s) if to_jid_s else None | 660 to_jid = jid.JID(to_jid_s) if to_jid_s else None |
661 d = self.listUI(client, to_jid, no_instructions=True) | 661 d = self.list_ui(client, to_jid, no_instructions=True) |
662 d.addCallback(lambda xmlui: xmlui.toXml()) | 662 d.addCallback(lambda xmlui: xmlui.toXml()) |
663 return d | 663 return d |
664 | 664 |
665 def listUI(self, client, to_jid, no_instructions=False): | 665 def list_ui(self, client, to_jid, no_instructions=False): |
666 """Request available commands and generate XMLUI | 666 """Request available commands and generate XMLUI |
667 | 667 |
668 @param to_jid(jid.JID, None): the entity answering the commands | 668 @param to_jid(jid.JID, None): the entity answering the commands |
669 None to use profile's server | 669 None to use profile's server |
670 @param no_instructions(bool): if True, don't add instructions widget | 670 @param no_instructions(bool): if True, don't add instructions widget |
671 @return D(xml_tools.XMLUI): UI with the commands | 671 @return D(xml_tools.XMLUI): UI with the commands |
672 """ | 672 """ |
673 d = self.list(client, to_jid) | 673 d = self.list(client, to_jid) |
674 d.addCallback(self._items2XMLUI, no_instructions) | 674 d.addCallback(self._items_2_xmlui, no_instructions) |
675 return d | 675 return d |
676 | 676 |
677 def _sequence(self, sequence, node, service_jid_s="", profile_key=C.PROF_KEY_NONE): | 677 def _sequence(self, sequence, node, service_jid_s="", profile_key=C.PROF_KEY_NONE): |
678 sequence = data_format.deserialise(sequence, type_check=list) | 678 sequence = data_format.deserialise(sequence, type_check=list) |
679 client = self.host.getClient(profile_key) | 679 client = self.host.get_client(profile_key) |
680 service_jid = jid.JID(service_jid_s) if service_jid_s else None | 680 service_jid = jid.JID(service_jid_s) if service_jid_s else None |
681 d = defer.ensureDeferred(self.sequence(client, sequence, node, service_jid)) | 681 d = defer.ensureDeferred(self.sequence(client, sequence, node, service_jid)) |
682 d.addCallback(lambda data: data_format.serialise(data)) | 682 d.addCallback(lambda data: data_format.serialise(data)) |
683 return d | 683 return d |
684 | 684 |
709 service_jid, | 709 service_jid, |
710 node, | 710 node, |
711 session_id=session_id, | 711 session_id=session_id, |
712 form_values=data_to_send, | 712 form_values=data_to_send, |
713 ) | 713 ) |
714 __, answer_data = self.parseCommandAnswer(iq_result_elt) | 714 __, answer_data = self.parse_command_answer(iq_result_elt) |
715 session_id = answer_data.pop("session_id") | 715 session_id = answer_data.pop("session_id") |
716 | 716 |
717 return answer_data | 717 return answer_data |
718 | 718 |
719 def addAdHocCommand(self, client, callback, label, node=None, features=None, | 719 def add_ad_hoc_command(self, client, callback, label, node=None, features=None, |
720 timeout=600, allowed_jids=None, allowed_groups=None, | 720 timeout=600, allowed_jids=None, allowed_groups=None, |
721 allowed_magics=None, forbidden_jids=None, forbidden_groups=None, | 721 allowed_magics=None, forbidden_jids=None, forbidden_groups=None, |
722 ): | 722 ): |
723 """Add an ad-hoc command for the current profile | 723 """Add an ad-hoc command for the current profile |
724 | 724 |
780 ) | 780 ) |
781 ad_hoc_command.setHandlerParent(client) | 781 ad_hoc_command.setHandlerParent(client) |
782 commands = client._XEP_0050_commands | 782 commands = client._XEP_0050_commands |
783 commands[node] = ad_hoc_command | 783 commands[node] = ad_hoc_command |
784 | 784 |
785 def onCmdRequest(self, request, client): | 785 def on_cmd_request(self, request, client): |
786 request.handled = True | 786 request.handled = True |
787 requestor = jid.JID(request["from"]) | 787 requestor = jid.JID(request["from"]) |
788 command_elt = next(request.elements(NS_COMMANDS, "command")) | 788 command_elt = next(request.elements(NS_COMMANDS, "command")) |
789 action = command_elt.getAttribute("action", self.ACTION.EXECUTE) | 789 action = command_elt.getAttribute("action", self.ACTION.EXECUTE) |
790 node = command_elt.getAttribute("node") | 790 node = command_elt.getAttribute("node") |
796 try: | 796 try: |
797 command = commands[node] | 797 command = commands[node] |
798 except KeyError: | 798 except KeyError: |
799 client.sendError(request, "item-not-found") | 799 client.sendError(request, "item-not-found") |
800 return | 800 return |
801 command.onRequest(command_elt, requestor, action, sessionid) | 801 command.on_request(command_elt, requestor, action, sessionid) |
802 | 802 |
803 | 803 |
804 @implementer(iwokkel.IDisco) | 804 @implementer(iwokkel.IDisco) |
805 class XEP_0050_handler(XMPPHandler): | 805 class XEP_0050_handler(XMPPHandler): |
806 | 806 |
811 def client(self): | 811 def client(self): |
812 return self.parent | 812 return self.parent |
813 | 813 |
814 def connectionInitialized(self): | 814 def connectionInitialized(self): |
815 self.xmlstream.addObserver( | 815 self.xmlstream.addObserver( |
816 CMD_REQUEST, self.plugin_parent.onCmdRequest, client=self.parent | 816 CMD_REQUEST, self.plugin_parent.on_cmd_request, client=self.parent |
817 ) | 817 ) |
818 | 818 |
819 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): | 819 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): |
820 identities = [] | 820 identities = [] |
821 if nodeIdentifier == NS_COMMANDS and self.client._XEP_0050_commands: | 821 if nodeIdentifier == NS_COMMANDS and self.client._XEP_0050_commands: |
826 def getDiscoItems(self, requestor, target, nodeIdentifier=""): | 826 def getDiscoItems(self, requestor, target, nodeIdentifier=""): |
827 ret = [] | 827 ret = [] |
828 if nodeIdentifier == NS_COMMANDS: | 828 if nodeIdentifier == NS_COMMANDS: |
829 commands = self.client._XEP_0050_commands | 829 commands = self.client._XEP_0050_commands |
830 for command in list(commands.values()): | 830 for command in list(commands.values()): |
831 if command.isAuthorised(requestor): | 831 if command.is_authorised(requestor): |
832 ret.append( | 832 ret.append( |
833 disco.DiscoItem(self.parent.jid, command.node, command.getName()) | 833 disco.DiscoItem(self.parent.jid, command.node, command.getName()) |
834 ) # TODO: manage name language | 834 ) # TODO: manage name language |
835 return ret | 835 return ret |