Converse converse.js

Source: headless/shared/api/send.js

  1. import _converse from '../../shared/_converse.js';
  2. import log from '../../log.js';
  3. import { Strophe } from 'strophe.js';
  4. import { TimeoutError } from '../errors.js';
  5. import { toStanza } from '../../utils/stanza.js';
  6. export default {
  7. /**
  8. * Allows you to send XML stanzas.
  9. * @method _converse.api.send
  10. * @param { Element | Stanza } stanza
  11. * @return { void }
  12. * @example
  13. * const msg = converse.env.$msg({
  14. * 'from': 'juliet@example.com/balcony',
  15. * 'to': 'romeo@example.net',
  16. * 'type':'chat'
  17. * });
  18. * _converse.api.send(msg);
  19. */
  20. send (stanza) {
  21. const { api } = _converse;
  22. if (!api.connection.connected()) {
  23. log.warn("Not sending stanza because we're not connected!");
  24. log.warn(Strophe.serialize(stanza));
  25. return;
  26. }
  27. if (typeof stanza === 'string') {
  28. stanza = toStanza(stanza);
  29. } else if (stanza?.tree) {
  30. stanza = stanza.tree();
  31. }
  32. if (stanza.tagName === 'iq') {
  33. return api.sendIQ(stanza);
  34. } else {
  35. _converse.connection.send(stanza);
  36. api.trigger('send', stanza);
  37. }
  38. },
  39. /**
  40. * Send an IQ stanza
  41. * @method _converse.api.sendIQ
  42. * @param { Element } stanza
  43. * @param { number } [timeout] - The default timeout value is taken from
  44. * the `stanza_timeout` configuration setting.
  45. * @param { Boolean } [reject=true] - Whether an error IQ should cause the promise
  46. * to be rejected. If `false`, the promise will resolve instead of being rejected.
  47. * @returns { Promise } A promise which resolves (or potentially rejected) once we
  48. * receive a `result` or `error` stanza or once a timeout is reached.
  49. * If the IQ stanza being sent is of type `result` or `error`, there's
  50. * nothing to wait for, so an already resolved promise is returned.
  51. */
  52. sendIQ (stanza, timeout, reject=true) {
  53. const { api, connection } = _converse;
  54. let promise;
  55. stanza = stanza.tree?.() ?? stanza;
  56. if (['get', 'set'].includes(stanza.getAttribute('type'))) {
  57. timeout = timeout || api.settings.get('stanza_timeout');
  58. if (reject) {
  59. promise = new Promise((resolve, reject) => connection.sendIQ(stanza, resolve, reject, timeout));
  60. promise.catch((e) => {
  61. if (e === null) {
  62. throw new TimeoutError(
  63. `Timeout error after ${timeout}ms for the following IQ stanza: ${Strophe.serialize(stanza)}`
  64. );
  65. }
  66. });
  67. } else {
  68. promise = new Promise((resolve) => connection.sendIQ(stanza, resolve, resolve, timeout));
  69. }
  70. } else {
  71. _converse.connection.sendIQ(stanza);
  72. promise = Promise.resolve();
  73. }
  74. api.trigger('send', stanza);
  75. return promise;
  76. }
  77. }