|
@@ -7,6 +7,97 @@ import u from '@converse/headless/utils/core';
|
|
|
|
|
|
const Strophe = strophe.default.Strophe;
|
|
const Strophe = strophe.default.Strophe;
|
|
|
|
|
|
|
|
+
|
|
|
|
+function getSenderAttributes (stanza, chatbox, _converse) {
|
|
|
|
+ if (u.isChatRoom(chatbox)) {
|
|
|
|
+ const from = stanza.getAttribute('from');
|
|
|
|
+ const nick = Strophe.unescapeNode(Strophe.getResourceFromJid(from));
|
|
|
|
+ return {
|
|
|
|
+ 'from': from,
|
|
|
|
+ 'from_muc': Strophe.getBareJidFromJid(from),
|
|
|
|
+ 'nick': nick,
|
|
|
|
+ 'sender': nick === chatbox.get('nick') ? 'me': 'them',
|
|
|
|
+ 'received': (new Date()).toISOString(),
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ const from = Strophe.getBareJidFromJid(stanza.getAttribute('from'));
|
|
|
|
+ if (from === _converse.bare_jid) {
|
|
|
|
+ return {
|
|
|
|
+ from,
|
|
|
|
+ 'sender': 'me',
|
|
|
|
+ 'fullname': _converse.xmppstatus.get('fullname')
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ return {
|
|
|
|
+ from,
|
|
|
|
+ 'sender': 'them',
|
|
|
|
+ 'fullname': chatbox.get('fullname')
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getSpoilerAttributes (stanza) {
|
|
|
|
+ const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, stanza).pop();
|
|
|
|
+ return {
|
|
|
|
+ 'is_spoiler': !!spoiler,
|
|
|
|
+ 'spoiler_hint': spoiler?.textContent
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getOutOfBandAttributes (stanza) {
|
|
|
|
+ const xform = sizzle(`x[xmlns="${Strophe.NS.OUTOFBAND}"]`, stanza).pop();
|
|
|
|
+ if (xform) {
|
|
|
|
+ return {
|
|
|
|
+ 'oob_url': xform.querySelector('url')?.textContent,
|
|
|
|
+ 'oob_desc': xform.querySelector('desc')?.textContent
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return {};
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getCorrectionAttributes (stanza, original_stanza) {
|
|
|
|
+ const el = sizzle(`replace[xmlns="${Strophe.NS.MESSAGE_CORRECT}"]`, stanza).pop();
|
|
|
|
+ if (el) {
|
|
|
|
+ const replaced_id = el.getAttribute('id');
|
|
|
|
+ const msgid = replaced_id;
|
|
|
|
+ if (replaced_id) {
|
|
|
|
+ const delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop();
|
|
|
|
+ const time = delay ? dayjs(delay.getAttribute('stamp')).toISOString() : (new Date()).toISOString();
|
|
|
|
+ return {
|
|
|
|
+ msgid,
|
|
|
|
+ replaced_id,
|
|
|
|
+ 'edited': time
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return {};
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getEncryptionAttributes (stanza, original_stanza, attrs, chatbox, _converse) {
|
|
|
|
+ const encrypted = sizzle(`encrypted[xmlns="${Strophe.NS.OMEMO}"]`, original_stanza).pop();
|
|
|
|
+ if (!encrypted || !_converse.config.get('trusted')) {
|
|
|
|
+ return attrs;
|
|
|
|
+ }
|
|
|
|
+ const key = sizzle(`key[rid="${_converse.omemo_store.get('device_id')}"]`, encrypted).pop();
|
|
|
|
+ if (key) {
|
|
|
|
+ const header = encrypted.querySelector('header');
|
|
|
|
+ attrs['is_encrypted'] = true;
|
|
|
|
+ attrs['encrypted'] = {
|
|
|
|
+ 'device_id': header.getAttribute('sid'),
|
|
|
|
+ 'iv': header.querySelector('iv').textContent,
|
|
|
|
+ 'key': key.textContent,
|
|
|
|
+ 'payload': encrypted.querySelector('payload')?.textContent || null,
|
|
|
|
+ 'prekey': ['true', '1'].includes(key.getAttribute('prekey'))
|
|
|
|
+ }
|
|
|
|
+ // Returns a promise
|
|
|
|
+ return chatbox.decrypt(attrs);
|
|
|
|
+ } else {
|
|
|
|
+ return attrs;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* The stanza utils object. Contains utility functions related to stanza
|
|
* The stanza utils object. Contains utility functions related to stanza
|
|
* processing.
|
|
* processing.
|
|
@@ -168,73 +259,6 @@ const stanza_utils = {
|
|
});
|
|
});
|
|
},
|
|
},
|
|
|
|
|
|
-
|
|
|
|
- getSenderAttributes (stanza, chatbox, _converse) {
|
|
|
|
- if (u.isChatRoom(chatbox)) {
|
|
|
|
- const from = stanza.getAttribute('from');
|
|
|
|
- const nick = Strophe.unescapeNode(Strophe.getResourceFromJid(from));
|
|
|
|
- return {
|
|
|
|
- 'from': from,
|
|
|
|
- 'from_muc': Strophe.getBareJidFromJid(from),
|
|
|
|
- 'nick': nick,
|
|
|
|
- 'sender': nick === chatbox.get('nick') ? 'me': 'them',
|
|
|
|
- 'received': (new Date()).toISOString(),
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- const from = Strophe.getBareJidFromJid(stanza.getAttribute('from'));
|
|
|
|
- if (from === _converse.bare_jid) {
|
|
|
|
- return {
|
|
|
|
- from,
|
|
|
|
- 'sender': 'me',
|
|
|
|
- 'fullname': _converse.xmppstatus.get('fullname')
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- return {
|
|
|
|
- from,
|
|
|
|
- 'sender': 'them',
|
|
|
|
- 'fullname': chatbox.get('fullname')
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- getSpoilerAttributes (stanza) {
|
|
|
|
- const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, stanza).pop();
|
|
|
|
- return {
|
|
|
|
- 'is_spoiler': !!spoiler,
|
|
|
|
- 'spoiler_hint': spoiler?.textContent
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- getOutOfBandAttributes (stanza) {
|
|
|
|
- const xform = sizzle(`x[xmlns="${Strophe.NS.OUTOFBAND}"]`, stanza).pop();
|
|
|
|
- if (xform) {
|
|
|
|
- return {
|
|
|
|
- 'oob_url': xform.querySelector('url')?.textContent,
|
|
|
|
- 'oob_desc': xform.querySelector('desc')?.textContent
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return {};
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- getCorrectionAttributes (stanza, original_stanza) {
|
|
|
|
- const el = sizzle(`replace[xmlns="${Strophe.NS.MESSAGE_CORRECT}"]`, stanza).pop();
|
|
|
|
- if (el) {
|
|
|
|
- const replaced_id = el.getAttribute('id');
|
|
|
|
- const msgid = replaced_id;
|
|
|
|
- if (replaced_id) {
|
|
|
|
- const delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop();
|
|
|
|
- const time = delay ? dayjs(delay.getAttribute('stamp')).toISOString() : (new Date()).toISOString();
|
|
|
|
- return {
|
|
|
|
- msgid,
|
|
|
|
- replaced_id,
|
|
|
|
- 'edited': time
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return {};
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
getErrorMessage (stanza, is_muc, _converse) {
|
|
getErrorMessage (stanza, is_muc, _converse) {
|
|
const { __ } = _converse;
|
|
const { __ } = _converse;
|
|
if (is_muc) {
|
|
if (is_muc) {
|
|
@@ -292,7 +316,7 @@ const stanza_utils = {
|
|
* @param { _converse } _converse
|
|
* @param { _converse } _converse
|
|
* @returns { Object }
|
|
* @returns { Object }
|
|
*/
|
|
*/
|
|
- parseMessage (stanza, original_stanza, chatbox, _converse) {
|
|
|
|
|
|
+ async parseMessage (stanza, original_stanza, chatbox, _converse) {
|
|
const is_muc = u.isChatRoom(chatbox);
|
|
const is_muc = u.isChatRoom(chatbox);
|
|
let attrs = Object.assign(
|
|
let attrs = Object.assign(
|
|
stanza_utils.getStanzaIDs(stanza, original_stanza),
|
|
stanza_utils.getStanzaIDs(stanza, original_stanza),
|
|
@@ -316,11 +340,12 @@ const stanza_utils = {
|
|
'type': stanza.getAttribute('type')
|
|
'type': stanza.getAttribute('type')
|
|
},
|
|
},
|
|
attrs,
|
|
attrs,
|
|
- stanza_utils.getSenderAttributes(stanza, chatbox, _converse),
|
|
|
|
- stanza_utils.getOutOfBandAttributes(stanza),
|
|
|
|
- stanza_utils.getSpoilerAttributes(stanza),
|
|
|
|
- stanza_utils.getCorrectionAttributes(stanza, original_stanza)
|
|
|
|
|
|
+ getSenderAttributes(stanza, chatbox, _converse),
|
|
|
|
+ getOutOfBandAttributes(stanza),
|
|
|
|
+ getSpoilerAttributes(stanza),
|
|
|
|
+ getCorrectionAttributes(stanza, original_stanza),
|
|
)
|
|
)
|
|
|
|
+ attrs = await getEncryptionAttributes(stanza, original_stanza, attrs, chatbox, _converse)
|
|
// We prefer to use one of the XEP-0359 unique and stable stanza IDs
|
|
// We prefer to use one of the XEP-0359 unique and stable stanza IDs
|
|
// as the Model id, to avoid duplicates.
|
|
// as the Model id, to avoid duplicates.
|
|
attrs['id'] = attrs['origin_id'] || attrs[`stanza_id ${(attrs.from_muc || attrs.from)}`] || u.getUniqueId();
|
|
attrs['id'] = attrs['origin_id'] || attrs[`stanza_id ${(attrs.from_muc || attrs.from)}`] || u.getUniqueId();
|