浏览代码

XEP-0359: Better usage of `stanza-id` to check for dupes

JC Brand 6 年之前
父节点
当前提交
6eb05be4be
共有 5 个文件被更改,包括 93 次插入45 次删除
  1. 19 25
      dist/converse.js
  2. 56 1
      spec/messages.js
  3. 3 0
      src/headless/converse-chatboxes.js
  4. 0 5
      src/headless/converse-mam.js
  5. 15 14
      src/headless/converse-muc.js

+ 19 - 25
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(),
         const archive = sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop(),
               spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
               spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
               delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, 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;
               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 = {
         const attrs = {
@@ -61992,6 +61993,8 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
           'message': _converse.chatboxes.getMessageBody(stanza) || undefined,
           'message': _converse.chatboxes.getMessageBody(stanza) || undefined,
           'msgid': stanza.getAttribute('id'),
           'msgid': stanza.getAttribute('id'),
           'references': this.getReferencesFromStanza(stanza),
           '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'),
           'subject': _.propertyOf(stanza.querySelector('subject'))('textContent'),
           'thread': _.propertyOf(stanza.querySelector('thread'))('textContent'),
           'thread': _.propertyOf(stanza.querySelector('thread'))('textContent'),
           'time': delay ? delay.getAttribute('stamp') : moment().format(),
           'time': delay ? delay.getAttribute('stamp') : moment().format(),
@@ -65219,13 +65222,6 @@ function getMessageArchiveID(stanza) {
 
 
   if (!_.isUndefined(result)) {
   if (!_.isUndefined(result)) {
     return result.getAttribute('id');
     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;
         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
-          });
+      async isDuplicate(message, original_stanza) {
+        const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, message).pop();
 
 
-          if (msg && msg.get('sender') === 'me' && !msg.get('received')) {
-            msg.save({
-              'received': moment().format()
-            });
-          }
+        if (!stanza_id) {
+          return;
+        }
+
+        const by_jid = stanza_id.getAttribute('by');
+        const result = await _converse.api.disco.supports(Strophe.NS.SID, by_jid);
 
 
-          return msg;
+        if (!result.length) {
+          return false;
         }
         }
 
 
-        return false;
+        const msg = this.messages.findWhere({
+          'stanza_id': stanza_id.getAttribute('id'),
+          'stanza_id_by_jid': by_jid
+        });
+        return !_.isNil(msg);
       },
       },
 
 
       fetchFeaturesIfConfigurationChanged(stanza) {
       fetchFeaturesIfConfigurationChanged(stanza) {
@@ -67067,7 +67061,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
           stanza = forwarded.querySelector('message');
           stanza = forwarded.querySelector('message');
         }
         }
 
 
-        if (this.isDuplicate(stanza, original_stanza)) {
+        if (await this.isDuplicate(stanza, original_stanza)) {
           return;
           return;
         }
         }
 
 

+ 56 - 1
spec/messages.js

@@ -2172,7 +2172,6 @@
             done();
             done();
         }));
         }));
 
 
-
         it("can not be expected to have a unique id attribute",
         it("can not be expected to have a unique id attribute",
             mock.initConverse(
             mock.initConverse(
                 null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
                 null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
@@ -2204,6 +2203,62 @@
             done();
             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(`
+                <message xmlns="jabber:client"
+                         from="room@muc.example.com/some1"
+                         to="${_converse.connection.jid}"
+                         type="groupchat">
+                    <body>Typical body text</body>
+                    <stanza-id xmlns="urn:xmpp:sid:0"
+                               id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
+                               by="room@muc.example.com"/>
+                    <origin-id xmlns="urn:xmpp:sid:0" id="de305d54-75b4-431b-adb2-eb6b9e546013"/>
+                </message>`);
+            _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(`
+                <message xmlns="jabber:client"
+                         from="room@muc.example.com/some1"
+                         to="${_converse.connection.jid}"
+                         type="groupchat">
+                    <body>Typical body text</body>
+                    <stanza-id xmlns="urn:xmpp:sid:0"
+                               id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
+                               by="room@muc.example.com"/>
+                    <origin-id xmlns="urn:xmpp:sid:0" id="de305d54-75b4-431b-adb2-eb6b9e546013"/>
+                </message>`);
+            _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",
         it("keeps track whether you are the sender or not",
             mock.initConverse(
             mock.initConverse(
                 null, ['rosterGroupsFetched'], {},
                 null, ['rosterGroupsFetched'], {},

+ 3 - 0
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(),
                 const archive = sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop(),
                       spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
                       spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
                       delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, 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 ||
                       chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING ||
                             stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED ||
                             stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED ||
                             stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE ||
                             stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE ||
@@ -610,6 +611,8 @@ converse.plugins.add('converse-chatboxes', {
                     'message': _converse.chatboxes.getMessageBody(stanza) || undefined,
                     'message': _converse.chatboxes.getMessageBody(stanza) || undefined,
                     'msgid': stanza.getAttribute('id'),
                     'msgid': stanza.getAttribute('id'),
                     'references': this.getReferencesFromStanza(stanza),
                     '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'),
                     'subject': _.propertyOf(stanza.querySelector('subject'))('textContent'),
                     'thread': _.propertyOf(stanza.querySelector('thread'))('textContent'),
                     'thread': _.propertyOf(stanza.querySelector('thread'))('textContent'),
                     'time': delay ? delay.getAttribute('stamp') : moment().format(),
                     'time': delay ? delay.getAttribute('stamp') : moment().format(),

+ 0 - 5
src/headless/converse-mam.js

@@ -32,11 +32,6 @@ function getMessageArchiveID (stanza) {
     if (!_.isUndefined(result)) {
     if (!_.isUndefined(result)) {
         return result.getAttribute('id');
         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) {
 function queryForArchivedMessages (_converse, options, callback, errback) {

+ 15 - 14
src/headless/converse-muc.js

@@ -948,20 +948,21 @@ converse.plugins.add('converse-muc', {
                 return data;
                 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) {
             fetchFeaturesIfConfigurationChanged (stanza) {
@@ -1055,7 +1056,7 @@ converse.plugins.add('converse-muc', {
                 if (forwarded) {
                 if (forwarded) {
                     stanza = forwarded.querySelector('message');
                     stanza = forwarded.querySelector('message');
                 }
                 }
-                if (this.isDuplicate(stanza, original_stanza)) {
+                if (await this.isDuplicate(stanza, original_stanza)) {
                     return;
                     return;
                 }
                 }
                 const attrs = await this.getMessageAttributesFromStanza(stanza, original_stanza);
                 const attrs = await this.getMessageAttributesFromStanza(stanza, original_stanza);