فهرست منبع

Don't show duplicate sent groupchat messages in Slack chat rooms

JC Brand 8 سال پیش
والد
کامیت
c012c2c1af
3فایلهای تغییر یافته به همراه51 افزوده شده و 17 حذف شده
  1. 2 2
      CHANGES.md
  2. 8 5
      src/converse-core.js
  3. 41 10
      src/converse-muc.js

+ 2 - 2
CHANGES.md

@@ -18,13 +18,13 @@
 - Removed jQuery from `converse-core`, `converse-vcard` and `converse-roomslist`. [jcbrand]
 - Remove `jquery.easing` from the full build. Was only being used by the
   [conversejs.org](https://conversejs.org) website, which has been updated to not rely on it. [jcbrand]
-- All promises are now native (or polyfilled) ES2015 Promises
-  instead of jQuery's Deferred. [jcbrand]
+- All promises are now native (or polyfilled) ES2015 Promises instead of jQuery's Deferred. [jcbrand]
 - #866 Add babel in order to support ES2015 syntax [jcbrand]
 
 #### Bugfixes:
 - Room name wasn't being updated after changing it in the configuration form. [jcbrand]
 - Server disco features were "forgotten" after logging out and then logging in again. [jcbrand]
+- Don't show duplicate sent groupchat messages in Slack chat rooms. [jcbrand]
 
 ## 3.1.1 (2017-07-12)
 

+ 8 - 5
src/converse-core.js

@@ -1444,13 +1444,17 @@
                 });
             },
 
-            getMessageAttributes (message, delay, original_stanza) {
-                delay = delay || message.querySelector('delay');
+            getMessageBody (message) {
                 const type = message.getAttribute('type');
-
-                const body = (type === 'error') ?
+                return (type === 'error') ?
                     _.propertyOf(message.querySelector('error text'))('textContent') :
                         _.propertyOf(message.querySelector('body'))('textContent');
+            },
+
+            getMessageAttributes (message, delay, original_stanza) {
+                delay = delay || message.querySelector('delay');
+                const type = message.getAttribute('type'),
+                      body = this.getMessageBody(message);
 
                 const delayed = !_.isNull(delay),
                     is_groupchat = type === 'groupchat',
@@ -1466,7 +1470,6 @@
                 } else {
                     from = Strophe.getBareJidFromJid(message.getAttribute('from'));
                 }
-
                 const time = delayed ? delay.getAttribute('stamp') : moment().format();
                 let sender, fullname;
                 if ((is_groupchat && from === this.get('nick')) || (!is_groupchat && from === _converse.bare_jid)) {

+ 41 - 10
src/converse-muc.js

@@ -1966,6 +1966,44 @@
                     this.scrollDown();
                 },
 
+                isDuplicateBasedOnTime (message) {
+                    /* Checks whether a received messages is actually a
+                     * duplicate based on whether it has a "ts" attribute
+                     * with a unix timestamp.
+                     *
+                     * This is used for better integration with Slack's XMPP
+                     * gateway, which doesn't use message IDs but instead the
+                     * aforementioned "ts" attributes.
+                     */
+                    const ts = message.getAttribute('ts');
+                    if (_.isNull(ts)) {
+                        return false;
+                    } else {
+                        return this.model.messages.where({
+                            'sender': this.model.get('nick'),
+                            'message': this.model.getMessageBody(message)
+                        }).filter(
+                            (msg) => Math.abs(moment(msg.get('time')).diff(moment.unix(ts))) < 2000
+                        ).length > 0;
+                    }
+                },
+
+                isDuplicate (message) {
+                    const msgid = message.getAttribute('id'),
+                          jid = message.getAttribute('from'),
+                          resource = Strophe.getResourceFromJid(jid),
+                          sender = resource && Strophe.unescapeNode(resource) || '';
+                    if (msgid) {
+                        return this.model.messages.filter(
+                            // Some bots (like HAL in the prosody chatroom)
+                            // respond to commands with the same ID as the
+                            // original message. So we also check the sender.
+                            (msg) => msg.get('msgid') === msgid && msg.get('fullname') === sender
+                        ).length > 0;
+                    }
+                    return this.isDuplicateBasedOnTime(message);
+                },
+
                 onChatRoomMessage (message) {
                     /* Given a <message> stanza, create a message
                      * Backbone.Model if appropriate.
@@ -1981,18 +2019,11 @@
                         delay = forwarded.querySelector('delay');
                     }
                     const jid = message.getAttribute('from'),
-                        msgid = message.getAttribute('id'),
                         resource = Strophe.getResourceFromJid(jid),
                         sender = resource && Strophe.unescapeNode(resource) || '',
-                        subject = _.propertyOf(message.querySelector('subject'))('textContent'),
-                        dupes = msgid && this.model.messages.filter(
-                            // Find duplicates.
-                            // Some bots (like HAL in the prosody chatroom)
-                            // respond to commands with the same ID as the
-                            // original message. So we also check the sender.
-                            (msg) => msg.get('msgid') === msgid && msg.get('fullname') === sender
-                        );
-                    if (dupes && dupes.length) {
+                        subject = _.propertyOf(message.querySelector('subject'))('textContent');
+
+                    if (this.isDuplicate(message)) {
                         return true;
                     }
                     if (subject) {