diff --git a/dist/converse.js b/dist/converse.js
index d0b3e6594..582ad444a 100644
--- a/dist/converse.js
+++ b/dist/converse.js
@@ -61982,6 +61982,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
const archive = sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop(),
spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(),
+ stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop(),
chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE;
const attrs = {
@@ -61992,6 +61993,8 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
'message': _converse.chatboxes.getMessageBody(stanza) || undefined,
'msgid': stanza.getAttribute('id'),
'references': this.getReferencesFromStanza(stanza),
+ 'stanza_id': stanza_id ? stanza_id.getAttribute('id') : undefined,
+ 'stanza_id_by_jid': stanza_id ? stanza_id.getAttribute('by') : undefined,
'subject': _.propertyOf(stanza.querySelector('subject'))('textContent'),
'thread': _.propertyOf(stanza.querySelector('thread'))('textContent'),
'time': delay ? delay.getAttribute('stamp') : moment().format(),
@@ -65219,13 +65222,6 @@ function getMessageArchiveID(stanza) {
if (!_.isUndefined(result)) {
return result.getAttribute('id');
- } // See: https://xmpp.org/extensions/xep-0313.html#archives_id
-
-
- const stanza_id = sizzle__WEBPACK_IMPORTED_MODULE_3___default()(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
-
- if (!_.isUndefined(stanza_id)) {
- return stanza_id.getAttribute('id');
}
}
@@ -66942,27 +66938,25 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
return data;
},
- isDuplicate(message, original_stanza) {
- // XXX: original_stanza is not used here, but in converse-mam
- const msgid = message.getAttribute('id'),
- jid = message.getAttribute('from');
+ async isDuplicate(message, original_stanza) {
+ const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, message).pop();
- if (msgid) {
- const msg = this.messages.findWhere({
- 'msgid': msgid,
- 'from': jid
- });
-
- if (msg && msg.get('sender') === 'me' && !msg.get('received')) {
- msg.save({
- 'received': moment().format()
- });
- }
-
- return msg;
+ if (!stanza_id) {
+ return;
}
- return false;
+ const by_jid = stanza_id.getAttribute('by');
+ const result = await _converse.api.disco.supports(Strophe.NS.SID, by_jid);
+
+ if (!result.length) {
+ return false;
+ }
+
+ const msg = this.messages.findWhere({
+ 'stanza_id': stanza_id.getAttribute('id'),
+ 'stanza_id_by_jid': by_jid
+ });
+ return !_.isNil(msg);
},
fetchFeaturesIfConfigurationChanged(stanza) {
@@ -67067,7 +67061,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
stanza = forwarded.querySelector('message');
}
- if (this.isDuplicate(stanza, original_stanza)) {
+ if (await this.isDuplicate(stanza, original_stanza)) {
return;
}
diff --git a/spec/messages.js b/spec/messages.js
index 6211d5a66..2c50dcf13 100644
--- a/spec/messages.js
+++ b/spec/messages.js
@@ -2172,7 +2172,6 @@
done();
}));
-
it("can not be expected to have a unique id attribute",
mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
@@ -2204,6 +2203,62 @@
done();
}));
+ it("is ignored if it has the same stanza-id of an already received on",
+ mock.initConverse(
+ null, ['rosterGroupsFetched'], {},
+ async function (done, _converse) {
+
+ const features = [
+ 'http://jabber.org/protocol/muc',
+ 'jabber:iq:register',
+ 'muc_passwordprotected',
+ 'muc_hidden',
+ 'muc_temporary',
+ 'muc_membersonly',
+ 'muc_unmoderated',
+ 'muc_nonanonymous',
+ Strophe.NS.SID,
+ ];
+ await test_utils.openAndEnterChatRoom(_converse, 'room', 'muc.example.com', 'dummy', features);
+ const view = _converse.chatboxviews.get('room@muc.example.com');
+ spyOn(view.model, 'isDuplicate').and.callThrough();
+ let stanza = u.toStanza(`
+
+ Typical body text
+
+
+ `);
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
+ await test_utils.waitUntil(() => _converse.api.chats.get().length);
+ await test_utils.waitUntil(() => view.model.messages.length === 1);
+ await test_utils.waitUntil(() => view.model.isDuplicate.calls.count() === 1);
+ let result = await view.model.isDuplicate.calls.all()[0].returnValue;
+ expect(result).toBe(false);
+
+ stanza = u.toStanza(`
+
+ Typical body text
+
+
+ `);
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
+ await test_utils.waitUntil(() => view.model.isDuplicate.calls.count() === 2);
+ result = await view.model.isDuplicate.calls.all()[1].returnValue;
+ expect(result).toBe(true);
+ expect(view.model.messages.length).toBe(1);
+ done();
+ }));
+
it("keeps track whether you are the sender or not",
mock.initConverse(
null, ['rosterGroupsFetched'], {},
diff --git a/src/headless/converse-chatboxes.js b/src/headless/converse-chatboxes.js
index 89f94c9e1..454e4716b 100644
--- a/src/headless/converse-chatboxes.js
+++ b/src/headless/converse-chatboxes.js
@@ -596,6 +596,7 @@ converse.plugins.add('converse-chatboxes', {
const archive = sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop(),
spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(),
+ stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop(),
chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING ||
stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED ||
stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE ||
@@ -610,6 +611,8 @@ converse.plugins.add('converse-chatboxes', {
'message': _converse.chatboxes.getMessageBody(stanza) || undefined,
'msgid': stanza.getAttribute('id'),
'references': this.getReferencesFromStanza(stanza),
+ 'stanza_id': stanza_id ? stanza_id.getAttribute('id') : undefined,
+ 'stanza_id_by_jid': stanza_id ? stanza_id.getAttribute('by') : undefined,
'subject': _.propertyOf(stanza.querySelector('subject'))('textContent'),
'thread': _.propertyOf(stanza.querySelector('thread'))('textContent'),
'time': delay ? delay.getAttribute('stamp') : moment().format(),
diff --git a/src/headless/converse-mam.js b/src/headless/converse-mam.js
index e3b1b8671..1878144a1 100644
--- a/src/headless/converse-mam.js
+++ b/src/headless/converse-mam.js
@@ -32,11 +32,6 @@ function getMessageArchiveID (stanza) {
if (!_.isUndefined(result)) {
return result.getAttribute('id');
}
- // See: https://xmpp.org/extensions/xep-0313.html#archives_id
- const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
- if (!_.isUndefined(stanza_id)) {
- return stanza_id.getAttribute('id');
- }
}
function queryForArchivedMessages (_converse, options, callback, errback) {
diff --git a/src/headless/converse-muc.js b/src/headless/converse-muc.js
index a2c4d6f00..3db64b1f5 100644
--- a/src/headless/converse-muc.js
+++ b/src/headless/converse-muc.js
@@ -948,20 +948,21 @@ converse.plugins.add('converse-muc', {
return data;
},
- isDuplicate (message, original_stanza) {
- // XXX: original_stanza is not used here, but in converse-mam
- const msgid = message.getAttribute('id'),
- jid = message.getAttribute('from');
-
- if (msgid) {
- const msg = this.messages.findWhere({'msgid': msgid, 'from': jid});
- if (msg && msg.get('sender') === 'me' && !msg.get('received')) {
- msg.save({'received': moment().format()});
- }
- return msg;
+ async isDuplicate (message, original_stanza) {
+ const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, message).pop();
+ if (!stanza_id) {
+ return false;
}
- return false;
-
+ const by_jid = stanza_id.getAttribute('by');
+ const result = await _converse.api.disco.supports(Strophe.NS.SID, by_jid);
+ if (!result.length) {
+ return false;
+ }
+ const msg = this.messages.findWhere({
+ 'stanza_id': stanza_id.getAttribute('id'),
+ 'stanza_id_by_jid': by_jid
+ });
+ return !_.isNil(msg);
},
fetchFeaturesIfConfigurationChanged (stanza) {
@@ -1055,7 +1056,7 @@ converse.plugins.add('converse-muc', {
if (forwarded) {
stanza = forwarded.querySelector('message');
}
- if (this.isDuplicate(stanza, original_stanza)) {
+ if (await this.isDuplicate(stanza, original_stanza)) {
return;
}
const attrs = await this.getMessageAttributesFromStanza(stanza, original_stanza);