Commit 8523cae8 authored by JC Brand's avatar JC Brand

Move message parsing code out of ChatBox into new stanza-utils plugin

parent caadb243
......@@ -6,7 +6,7 @@
], factory);
} (this, function (jasmine, mock, test_utils) {
"use strict";
const { Promise, Strophe, $msg, $pres, sizzle } = converse.env;
const { Promise, Strophe, $msg, $pres, sizzle, stanza_utils } = converse.env;
const u = converse.env.utils;
describe("A Groupchat Message", function () {
......@@ -621,9 +621,9 @@
<origin-id xmlns="urn:xmpp:sid:0" id="CE08D448-5ED8-4B6A-BB5B-07ED9DFE4FF0"/>
</message>`);
spyOn(_converse.api, "trigger").and.callThrough();
spyOn(view.model, "isReceipt").and.callThrough();
spyOn(stanza_utils, "isReceipt").and.callThrough();
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await u.waitUntil(() => view.model.isReceipt.calls.count() === 1);
await u.waitUntil(() => stanza_utils.isReceipt.calls.count() === 1);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
......@@ -657,9 +657,10 @@
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<received xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
spyOn(view.model, "isChatMarker").and.callThrough();
const stanza_utils = converse.env.stanza_utils;
spyOn(stanza_utils, "isChatMarker").and.callThrough();
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await u.waitUntil(() => view.model.isChatMarker.calls.count() === 1);
await u.waitUntil(() => stanza_utils.isChatMarker.calls.count() === 1);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
......@@ -669,7 +670,7 @@
<displayed xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await u.waitUntil(() => view.model.isChatMarker.calls.count() === 2);
await u.waitUntil(() => stanza_utils.isChatMarker.calls.count() === 2);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
......@@ -680,7 +681,7 @@
</message>`);
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await u.waitUntil(() => view.model.isChatMarker.calls.count() === 3);
await u.waitUntil(() => stanza_utils.isChatMarker.calls.count() === 3);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
......@@ -691,7 +692,7 @@
<markable xmlns="urn:xmpp:chat-markers:0"/>
</message>`);
_converse.connection._dataRecv(test_utils.createRequest(stanza));
await u.waitUntil(() => view.model.isChatMarker.calls.count() === 4);
await u.waitUntil(() => stanza_utils.isChatMarker.calls.count() === 4);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
done();
......
This diff is collapsed.
......@@ -18,6 +18,7 @@ import i18n from './i18n';
import log from '@converse/headless/log';
import pluggable from 'pluggable.js/src/pluggable';
import sizzle from 'sizzle';
import stanza_utils from "@converse/headless/utils/stanza";
import u from '@converse/headless/utils/core';
const Strophe = strophe.default.Strophe;
......@@ -91,7 +92,8 @@ const CORE_PLUGINS = [
'converse-rsm',
'converse-smacks',
'converse-status',
'converse-vcard'
'converse-vcard',
'stanza-utils'
];
......@@ -1800,20 +1802,7 @@ Object.assign(window.converse, {
* @property {function} converse.env.sizzle - [Sizzle](https://sizzlejs.com) CSS selector engine.
* @property {object} converse.env.utils - Module containing common utility methods used by Converse.
*/
'env': {
'$build': $build,
'$iq': $iq,
'$msg': $msg,
'$pres': $pres,
'Backbone': Backbone,
'Promise': Promise,
'Strophe': Strophe,
'_': _,
'log': log,
'dayjs': dayjs,
'sizzle': sizzle,
'utils': u
}
'env': { $build, $iq, $msg, $pres, Backbone, Promise, Strophe, _, dayjs, log, sizzle, stanza_utils, u, 'utils': u }
});
/**
......
......@@ -38,16 +38,6 @@ converse.plugins.add('converse-mam', {
return this.findDuplicateFromArchiveID(stanza);
}
return message;
},
getUpdatedMessageAttributes (message, stanza) {
const attrs = this.__super__.getUpdatedMessageAttributes.apply(this, arguments);
if (message && !message.get('is_archived')) {
return Object.assign(attrs, {
'is_archived': this.isArchived(stanza)
}, this.getStanzaIDs(stanza))
}
return attrs;
}
}
},
......
......@@ -15,6 +15,7 @@ import "./utils/muc";
import { clone, get, intersection, invoke, isElement, isObject, isString, uniq, zipObject } from "lodash";
import converse from "./converse-core";
import log from "./log";
import stanza_utils from "./utils/stanza";
import u from "./utils/form";
const MUC_ROLE_WEIGHTS = {
......@@ -1330,16 +1331,6 @@ converse.plugins.add('converse-muc', {
}
},
isReceipt (stanza) {
return sizzle(`received[xmlns="${Strophe.NS.RECEIPTS}"]`, stanza).length > 0;
},
isChatMarker (stanza) {
return sizzle(
`received[xmlns="${Strophe.NS.MARKERS}"],
displayed[xmlns="${Strophe.NS.MARKERS}"],
acknowledged[xmlns="${Strophe.NS.MARKERS}"]`, stanza).length > 0;
},
/**
* Handle a subject change and return `true` if so.
......@@ -1527,9 +1518,7 @@ converse.plugins.add('converse-muc', {
if (message) {
this.updateMessage(message, original_stanza);
}
if (message ||
this.isReceipt(stanza) ||
this.isChatMarker(stanza)) {
if (message || stanza_utils.isReceipt(stanza) || stanza_utils.isChatMarker(stanza)) {
return _converse.api.trigger('message', {'stanza': original_stanza});
}
const attrs = await this.getMessageAttributesFromStanza(stanza, original_stanza);
......
import * as strophe from 'strophe.js/src/core';
import { get, propertyOf } from "lodash";
import sizzle from 'sizzle';
import u from '@converse/headless/utils/core';
const Strophe = strophe.default.Strophe;
/**
* The stanza utils object. Contains utility functions related to stanza
* processing.
* @namespace stanza_utils
*/
const stanza_utils = {
isReceipt (stanza) {
return sizzle(`received[xmlns="${Strophe.NS.RECEIPTS}"]`, stanza).length > 0;
},
isChatMarker (stanza) {
return sizzle(
`received[xmlns="${Strophe.NS.MARKERS}"],
displayed[xmlns="${Strophe.NS.MARKERS}"],
acknowledged[xmlns="${Strophe.NS.MARKERS}"]`, stanza).length > 0;
},
/**
* Determines whether the passed in stanza represents a XEP-0313 MAM stanza
* @private
* @method stanza_utils#isArchived
* @param { XMLElement } stanza - The message stanza
* @returns { Boolean }
*/
isArchived (original_stanza) {
return !!sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop();
},
/**
* Extract the XEP-0359 stanza IDs from the passed in stanza
* and return a map containing them.
* @private
* @method _converse.stanza_utils#getStanzaIDs
* @param { XMLElement } stanza - The message stanza
* @returns { Object }
*/
getStanzaIDs (stanza) {
const attrs = {};
const stanza_ids = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza);
if (stanza_ids.length) {
stanza_ids.forEach(s => (attrs[`stanza_id ${s.getAttribute('by')}`] = s.getAttribute('id')));
}
const result = sizzle(`message > result[xmlns="${Strophe.NS.MAM}"]`, stanza).pop();
if (result) {
const by_jid = stanza.getAttribute('from');
attrs[`stanza_id ${by_jid}`] = result.getAttribute('id');
}
const origin_id = sizzle(`origin-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
if (origin_id) {
attrs['origin_id'] = origin_id.getAttribute('id');
}
// We prefer to use one of the XEP-0359 unique and stable stanza IDs
// as the Model id, to avoid duplicates.
attrs['id'] = attrs['origin_id'] || attrs[`stanza_id ${attrs.from}`] || u.getUniqueId();
return attrs;
},
/**
* Parses a passed in message stanza and returns an object of known attributes related to
* XEP-0422 Message Fastening.
* @private
* @method _converse.stanza_utils#getMessageFasteningAttributes
* @param { XMLElement } stanza - The message stanza
* @returns { Object }
*/
getMessageFasteningAttributes (stanza) {
const substanza = sizzle(`apply-to[xmlns="${Strophe.NS.FASTEN}"]`, stanza).pop();
if (substanza === null) {
return {};
}
const moderated = sizzle(`moderated[xmlns="${Strophe.NS.MODERATE}"]`, substanza).pop();
if (moderated) {
const retracted = !!sizzle(`retract[xmlns="${Strophe.NS.RETRACT}"]`, moderated).length;
return {
'moderated': retracted ? 'retracted' : 'unknown',
'moderated_by': moderated.get('by'),
'moderated_reason': get(moderated.querySelector('reason'), 'textContent')
}
}
},
getReferences (stanza) {
const text = propertyOf(stanza.querySelector('body'))('textContent');
return sizzle(`reference[xmlns="${Strophe.NS.REFERENCE}"]`, stanza).map(ref => {
const begin = ref.getAttribute('begin'),
end = ref.getAttribute('end');
return {
'begin': begin,
'end': end,
'type': ref.getAttribute('type'),
'value': text.slice(begin, end),
'uri': ref.getAttribute('uri')
};
});
},
getSenderAttributes (stanza, chatbox, _converse) {
const type = stanza.getAttribute('type');
if (type === 'groupchat') {
const from = stanza.getAttribute('from');
const nick = Strophe.unescapeNode(Strophe.getResourceFromJid(from));
return {
'from': from,
'nick': nick,
'sender': nick === chatbox.get('nick') ? 'me': 'them',
'received': (new Date()).toISOString(),
}
} else {
const from = Strophe.getBareJidFromJid(stanza.getAttribute('from'));
if (from === _converse.bare_jid) {
return {
from,
'sender': 'me',
'fullname': _converse.xmppstatus.get('fullname')
}
} else {
return {
from,
'sender': 'them',
'fullname': chatbox.get('fullname')
}
}
}
},
getSpoilerAttributes (stanza) {
const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, stanza).pop();
return {
'is_spoiler': !!spoiler,
'spoiler_hint': get(spoiler, 'textContent')
}
},
getOutOfBandAttributes (stanza) {
const xform = sizzle(`x[xmlns="${Strophe.NS.OUTOFBAND}"]`, stanza).pop();
if (xform) {
return {
'oob_url': get(xform.querySelector('url'), 'textContent'),
'oob_desc': get(xform.querySelector('desc'), 'textContent')
}
}
return {};
},
getCorrectionAttributes (stanza) {
const el = sizzle(`replace[xmlns="${Strophe.NS.MESSAGE_CORRECT}"]`, stanza).pop();
if (el) {
const replaced_id = el.getAttribute('id');
const msgid = replaced_id;
if (replaced_id) {
return {
msgid,
replaced_id,
'edited': new Date().toISOString()
}
}
}
return {};
}
}
export default stanza_utils;
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