(stanza)
| 123 | * @param {Element|Builder} stanza |
| 124 | */ |
| 125 | export async function handleMessageStanza(stanza) { |
| 126 | stanza = stanza instanceof Element ? stanza : stanza.tree(); |
| 127 | |
| 128 | if (isServerMessage(stanza)) { |
| 129 | // Prosody sends headline messages with type `chat`, so we need to filter them out here. |
| 130 | const from = stanza.getAttribute('from'); |
| 131 | return log.info(`handleMessageStanza: Ignoring incoming server message from JID: ${from}`); |
| 132 | } |
| 133 | if (await isMUCPrivateMessage(stanza)) { |
| 134 | return true; |
| 135 | } |
| 136 | |
| 137 | let attrs; |
| 138 | try { |
| 139 | attrs = await parseMessage(stanza); |
| 140 | } catch (e) { |
| 141 | return log.error(e); |
| 142 | } |
| 143 | if (u.isErrorObject(attrs)) { |
| 144 | const { stanza, message } = /** @type {StanzaParseError} */ (attrs); |
| 145 | if (stanza) log.error(stanza); |
| 146 | return log.error(message); |
| 147 | } |
| 148 | |
| 149 | const { body, plaintext, contact_jid, nick } = /** @type {MessageAttributes} */ (attrs); |
| 150 | |
| 151 | // XXX: Need to take XEP-428 <fallback> into consideration |
| 152 | const has_body = !!(body || plaintext); |
| 153 | const chatbox = await api.chats.get(contact_jid, { nickname: nick }, has_body); |
| 154 | await chatbox?.queueMessage(attrs); |
| 155 | /** |
| 156 | * @typedef {Object} MessageData |
| 157 | * An object containing the original message stanza, as well as the |
| 158 | * parsed attributes. |
| 159 | * @property {Element} stanza |
| 160 | * @property {MessageAttributes} stanza |
| 161 | * @property {ChatBox} chatbox |
| 162 | */ |
| 163 | const data = { stanza, attrs, chatbox }; |
| 164 | /** |
| 165 | * Triggered when a message stanza is been received and processed. |
| 166 | * @event _converse#message |
| 167 | * @type {MessageData} data |
| 168 | */ |
| 169 | api.trigger('message', data); |
| 170 | } |
| 171 | |
| 172 | /** |
| 173 | * Ask the XMPP server to enable Message Carbons |
no test coverage detected