From 890db3427fad5d0816e52ff07b268875ce32fd25 Mon Sep 17 00:00:00 2001 From: Dele Olajide Date: Fri, 29 Nov 2019 11:21:38 +0000 Subject: [PATCH] Handle message notifications about affiliation change for users not in a room See https://git.happy-dev.fr/startinblox/components/sib-chat/issues/96 --- CHANGES.md | 3 +++ spec/muc.js | 43 ++++++++++++++++++++++++++++++++++++ src/headless/converse-muc.js | 39 ++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 0af307a76..511793327 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,8 +4,11 @@ - [enable_smacks](https://conversejs.org/docs/html/configuration.html#enable-smacks) is not set to `true` by default. - Refactor some presence and status handling code from `converse-core` into `@converse/headless/converse-status`. + +- Add support for [notifications about affiliation change for users not in a room](https://xmpp.org/extensions/xep-0045.html#example-196) - Add support for [XEP-0424 Message Retraction](http://localhost:3080/extensions/xep-0424.html) - Add support for [XEP-0425 Message Moderation](http://localhost:3080/extensions/xep-0425.html) + - New API [\_converse.api.headlines](https://conversejs.org/docs/html/api/-_converse.api.headlines.html#.get) - New config option [allow_message_retraction](https://conversejs.org/docs/html/configuration.html#allow-message-retraction) - New config option [muc-show-logs-before-join](https://conversejs.org/docs/html/configuration.html#muc-show-logs-before-join) diff --git a/spec/muc.js b/spec/muc.js index 844c3e906..2458e887c 100644 --- a/spec/muc.js +++ b/spec/muc.js @@ -2906,6 +2906,49 @@ expect(info_msgs.pop().textContent.trim()).toBe("annoyingGuy is no longer a member of this groupchat"); done(); })); + + it("notifies user of role and affiliation changes for members not in the groupchat", + mock.initConverse( + ['rosterGroupsFetched'], {}, + async function (done, _converse) { + + const muc_jid = 'lounge@montague.lit'; + await test_utils.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); + const view = _converse.api.chatviews.get(muc_jid); + + let message = $msg({ + from: 'lounge@montague.lit', + id: '2CF9013B-E8A8-42A1-9633-85AD7CA12F40', + to: 'romeo@montague.lit' + }) + .c('x', { 'xmlns': 'http://jabber.org/protocol/muc#user'}) + .c('item', { + 'jid': 'annoyingguy@montague.lit', + 'affiliation': 'member', + 'role': 'none' + }); + _converse.connection._dataRecv(test_utils.createRequest(message)); + await u.waitUntil(() => view.model.occupants.length > 1); + expect(view.model.occupants.length).toBe(2); + expect(view.model.occupants.findWhere({'jid': 'annoyingguy@montague.lit'}).get('affiliation')).toBe('member'); + + message = $msg({ + from: 'lounge@montague.lit', + id: '2CF9013B-E8A8-42A1-9633-85AD7CA12F41', + to: 'romeo@montague.lit' + }) + .c('x', { 'xmlns': 'http://jabber.org/protocol/muc#user'}) + .c('item', { + 'jid': 'annoyingguy@montague.lit', + 'affiliation': 'none', + 'role': 'none' + }); + _converse.connection._dataRecv(test_utils.createRequest(message)); + expect(view.model.occupants.length).toBe(2); + expect(view.model.occupants.findWhere({'jid': 'annoyingguy@montague.lit'}).get('affiliation')).toBe('none'); + + done(); + })); }); diff --git a/src/headless/converse-muc.js b/src/headless/converse-muc.js index 5b3aef94e..b21fdaeb3 100644 --- a/src/headless/converse-muc.js +++ b/src/headless/converse-muc.js @@ -504,6 +504,38 @@ converse.plugins.add('converse-muc', { }, null, 'message', 'groupchat', null, room_jid, {'matchBareFromJid': true} ); + this.muc_notifications_handler = _converse.connection.addHandler(stanza => { + const item = sizzle(`x[xmlns="${Strophe.NS.MUC_USER}"] item`, stanza).pop(); + + if (item) { + const from = stanza.getAttribute("from"); + const type = stanza.getAttribute("type"); + const affiliation = item.getAttribute('affiliation'); + const jid = item.getAttribute('jid'); + + const data = { + 'from': from, + 'nick': Strophe.getNodeFromJid(jid), + 'type': type, + 'states': [], + 'show': type == 'unavailable' ? 'offline' : 'online', + 'affiliation': affiliation, + 'role': item.getAttribute('role'), + 'jid': Strophe.getBareJidFromJid(jid), + 'resource': Strophe.getResourceFromJid(jid) + } + + const occupant = this.occupants.findOccupant({'jid': data.jid}); + + if (occupant) { + occupant.save(data); + } else { + this.occupants.create(data); + } + } + return true; + + }, Strophe.NS.MUC_USER, 'message', null, null, room_jid); }, removeHandlers () { @@ -521,6 +553,13 @@ converse.plugins.add('converse-muc', { } delete this.presence_handler; } + + if (this.muc_notifications_handler) { + if (_converse.connection) { + _converse.connection.deleteHandler(this.muc_notifications_handler); + } + delete this.muc_notifications_handler; + } return this; },