Commit 8d002946 authored by JC Brand's avatar JC Brand

Use `origin-id` to check for reflected messages.

Also, store the returned `stanza-id` on the message.
parent 6eb05be4
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
- Accessibility: Tag the chat-content as an ARIA live region, for screen readers - Accessibility: Tag the chat-content as an ARIA live region, for screen readers
- Set releases URL to new Github repo - Set releases URL to new Github repo
- Rudimentary support for XEP-0333 chat markers - Rudimentary support for XEP-0333 chat markers
- Better support for XEP-0359 `stanza-id` and `origin-id` elements.
- #1369 Don't wrongly interpret message with `subject` as a topic change. - #1369 Don't wrongly interpret message with `subject` as a topic change.
- #1405 Status of contacts list are not displayed properly - #1405 Status of contacts list are not displayed properly
- #1408 New config option `roomconfig_whitelist` - #1408 New config option `roomconfig_whitelist`
......
...@@ -66942,7 +66942,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc ...@@ -66942,7 +66942,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, message).pop(); const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, message).pop();
if (!stanza_id) { if (!stanza_id) {
return; return false;
} }
const by_jid = stanza_id.getAttribute('by'); const by_jid = stanza_id.getAttribute('by');
...@@ -66992,22 +66992,32 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc ...@@ -66992,22 +66992,32 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
const own_message = Strophe.getResourceFromJid(from) == this.get('nick'); const own_message = Strophe.getResourceFromJid(from) == this.get('nick');
if (own_message) { if (own_message) {
const msgid = stanza.getAttribute('id'), const origin_id = sizzle(`origin-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
jid = stanza.getAttribute('from'); // TODO: use stanza-id?
if (!origin_id) {
return false;
}
if (msgid) {
const msg = this.messages.findWhere({ const msg = this.messages.findWhere({
'msgid': msgid, 'origin_id': origin_id.getAttribute('id'),
'from': jid 'sender': 'me'
}); });
if (msg && msg.get('sender') === 'me' && !msg.get('received')) { if (msg) {
msg.save({ const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
'received': moment().format() const attrs = {
}); 'stanza_id': stanza_id ? stanza_id.getAttribute('id') : undefined,
return true; 'stanza_id_by_jid': stanza_id ? stanza_id.getAttribute('by') : undefined
};
if (!msg.get('received')) {
attrs.received = moment().format();
} }
msg.save(attrs);
} }
return msg ? true : false;
} }
}, },
...@@ -2208,18 +2208,7 @@ ...@@ -2208,18 +2208,7 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
async function (done, _converse) { async function (done, _converse) {
const features = [ await test_utils.openAndEnterChatRoom(_converse, 'room', 'muc.example.com', 'dummy');
'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'); const view = _converse.chatboxviews.get('room@muc.example.com');
spyOn(view.model, 'isDuplicate').and.callThrough(); spyOn(view.model, 'isDuplicate').and.callThrough();
let stanza = u.toStanza(` let stanza = u.toStanza(`
...@@ -2464,20 +2453,68 @@ ...@@ -2464,20 +2453,68 @@
}); });
await new Promise((resolve, reject) => view.once('messageInserted', resolve)); await new Promise((resolve, reject) => view.once('messageInserted', resolve));
const msg_obj = view.model.messages.at(0); const msg_obj = view.model.messages.at(0);
const msg_id = msg_obj.get('msgid'); const stanza = u.toStanza(`
const from = msg_obj.get('from'); <message xmlns="jabber:client"
const body = msg_obj.get('message'); from="${msg_obj.get('from')}"
const msg = $msg({ to="${_converse.connection.jid}"
'from': from, type="groupchat">
'id': msg_id, <body>${msg_obj.get('message')}</body>
'to': 'dummy@localhost', <stanza-id xmlns="urn:xmpp:sid:0"
'type': 'groupchat', id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
}).c('body').t(body).up().tree(); by="lounge@localhost"/>
await view.model.onMessage(msg); <origin-id xmlns="urn:xmpp:sid:0" id="${msg_obj.get('origin_id')}"/>
</message>`);
await view.model.onMessage(stanza);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(1);
done(); done();
})); }));
it("gets updated with its stanza-id upon MUC reflection",
mock.initConverse(
null, ['rosterGroupsFetched'], {},
async function (done, _converse) {
await test_utils.openAndEnterChatRoom(_converse, 'room', 'muc.example.com', 'dummy');
const view = _converse.chatboxviews.get('room@muc.example.com');
const attrs = {
'id': _converse.connection.getUniqueId(),
'origin_id': _converse.connection.getUniqueId(),
'fullname': 'dummy',
'references': [],
'from': _converse.connection.jid,
'sender': 'me',
'time': moment().format(),
'message': 'Hello world',
'is_spoiler': false,
'type': 'groupchat'
}
view.model.sendMessage(attrs);
await test_utils.waitUntil(() => _converse.api.chats.get().length);
await test_utils.waitUntil(() => view.model.messages.length === 1);
expect(view.model.messages.at(0).get('stanza_id')).toBeUndefined();
expect(view.model.messages.at(0).get('origin_id')).toBe(attrs.origin_id);
const stanza = u.toStanza(`
<message xmlns="jabber:client"
from="room@muc.example.com/dummy"
to="${_converse.connection.jid}"
type="groupchat">
<body>Hello world</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="${attrs.origin_id}"/>
</message>`);
spyOn(view.model, 'reflectionHandled').and.callThrough();
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await test_utils.waitUntil(() => view.model.reflectionHandled.calls.count() === 1);
expect(view.model.messages.length).toBe(1);
expect(view.model.messages.at(0).get('stanza_id')).toBe("5f3dbc5e-e1d3-4077-a492-693f3769c7ad");
expect(view.model.messages.at(0).get('origin_id')).toBe(attrs.origin_id);
done();
}));
it("can cause a delivery receipt to be returned", it("can cause a delivery receipt to be returned",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
......
...@@ -1869,13 +1869,18 @@ ...@@ -1869,13 +1869,18 @@
// Let's check that if we receive the same message again, it's // Let's check that if we receive the same message again, it's
// not shown. // not shown.
const message = $msg({ const stanza = u.toStanza(`
from: 'lounge@localhost/dummy', <message xmlns="jabber:client"
to: 'dummy@localhost.com', from="lounge@localhost/dummy"
type: 'groupchat', to="${_converse.connection.jid}"
id: view.model.messages.at(0).get('msgid') type="groupchat">
}).c('body').t(text); <body>${text}</body>
await view.model.onMessage(message.nodeTree); <stanza-id xmlns="urn:xmpp:sid:0"
id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
by="lounge@localhost"/>
<origin-id xmlns="urn:xmpp:sid:0" id="${view.model.messages.at(0).get('origin_id')}"/>
</message>`);
await view.model.onMessage(stanza);
expect(chat_content.querySelectorAll('.chat-msg').length).toBe(1); expect(chat_content.querySelectorAll('.chat-msg').length).toBe(1);
expect(sizzle('.chat-msg__text:last').pop().textContent).toBe(text); expect(sizzle('.chat-msg__text:last').pop().textContent).toBe(text);
expect(view.model.messages.length).toBe(1); expect(view.model.messages.length).toBe(1);
......
...@@ -999,17 +999,26 @@ converse.plugins.add('converse-muc', { ...@@ -999,17 +999,26 @@ converse.plugins.add('converse-muc', {
const from = stanza.getAttribute('from'); const from = stanza.getAttribute('from');
const own_message = Strophe.getResourceFromJid(from) == this.get('nick'); const own_message = Strophe.getResourceFromJid(from) == this.get('nick');
if (own_message) { if (own_message) {
const msgid = stanza.getAttribute('id'), const origin_id = sizzle(`origin-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
jid = stanza.getAttribute('from'); if (!origin_id) {
return false;
// TODO: use stanza-id? }
if (msgid) { const msg = this.messages.findWhere({
const msg = this.messages.findWhere({'msgid': msgid, 'from': jid}); 'origin_id': origin_id.getAttribute('id'),
if (msg && msg.get('sender') === 'me' && !msg.get('received')) { 'sender': 'me'
msg.save({'received': moment().format()}); });
return true; if (msg) {
const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
const attrs = {
'stanza_id': stanza_id ? stanza_id.getAttribute('id') : undefined,
'stanza_id_by_jid': stanza_id ? stanza_id.getAttribute('by') : undefined
}
if (!msg.get('received')) {
attrs.received = moment().format();
} }
msg.save(attrs);
} }
return msg ? true : false;
} }
}, },
......
...@@ -142,6 +142,7 @@ ...@@ -142,6 +142,7 @@
features = features.length ? features : [ features = features.length ? features : [
'http://jabber.org/protocol/muc', 'http://jabber.org/protocol/muc',
'jabber:iq:register', 'jabber:iq:register',
Strophe.NS.SID,
'muc_passwordprotected', 'muc_passwordprotected',
'muc_hidden', 'muc_hidden',
'muc_temporary', 'muc_temporary',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment