Also create MEP messages received from a MAM archive
This commit is contained in:
parent
f40a8f69ae
commit
8f34065fc0
|
@ -28,7 +28,9 @@ async function handleErrorMessage (stanza) {
|
|||
return;
|
||||
}
|
||||
const chatbox = await api.chatboxes.get(from_jid);
|
||||
chatbox?.handleErrorMessageStanza(stanza);
|
||||
if (chatbox.get('type') === _converse.PRIVATE_CHAT_TYPE) {
|
||||
chatbox?.handleErrorMessageStanza(stanza);
|
||||
}
|
||||
}
|
||||
|
||||
export function autoJoinChats () {
|
||||
|
|
|
@ -434,6 +434,7 @@ const ChatRoomMixin = {
|
|||
if (!(await this.shouldShowErrorMessage(attrs))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message = this.getMessageReferencedByError(attrs);
|
||||
if (message) {
|
||||
const new_attrs = {
|
||||
|
@ -535,19 +536,22 @@ const ChatRoomMixin = {
|
|||
* @param { XMLElement } stanza
|
||||
*/
|
||||
async handleMessageStanza (stanza) {
|
||||
if (stanza.getAttribute('type') !== 'groupchat') {
|
||||
this.handleForwardedMentions(stanza);
|
||||
return;
|
||||
} else if (isArchived(stanza)) {
|
||||
// MAM messages are handled in converse-mam.
|
||||
// We shouldn't get MAM messages here because
|
||||
// they shouldn't have a `type` attribute.
|
||||
return log.warn(`Received a MAM message with type "groupchat"`);
|
||||
const type = stanza.getAttribute('type');
|
||||
if (type === 'error') {
|
||||
return this.handleErrorMessageStanza(stanza);
|
||||
}
|
||||
if (type === 'groupchat') {
|
||||
if (isArchived(stanza)) {
|
||||
// MAM messages are handled in converse-mam.
|
||||
// We shouldn't get MAM messages here because
|
||||
// they shouldn't have a `type` attribute.
|
||||
return log.warn(`Received a MAM message with type "groupchat"`);
|
||||
}
|
||||
this.createInfoMessages(stanza);
|
||||
this.fetchFeaturesIfConfigurationChanged(stanza);
|
||||
} else if (!type) {
|
||||
return this.handleForwardedMentions(stanza);
|
||||
}
|
||||
|
||||
this.createInfoMessages(stanza);
|
||||
this.fetchFeaturesIfConfigurationChanged(stanza);
|
||||
|
||||
/**
|
||||
* @typedef { Object } MUCMessageData
|
||||
* An object containing the original groupchat message stanza,
|
||||
|
@ -2098,11 +2102,43 @@ const ChatRoomMixin = {
|
|||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Given { @link MessageAttributes } look for XEP-0316 Room Notifications and create info
|
||||
* messages for them.
|
||||
* @param { XMLElement } stanza
|
||||
*/
|
||||
handleMEPNotification (attrs) {
|
||||
if (attrs.from !== this.get('jid') || !attrs.activities) {
|
||||
return false;
|
||||
}
|
||||
attrs.activities?.forEach(activity_attrs => {
|
||||
const mdata = Object.assign({ 'msgid': attrs.msgid }, activity_attrs);
|
||||
this.createMessage(mdata)
|
||||
});
|
||||
return !!attrs.activities.length
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an already cached message (if it exists) based on the
|
||||
* passed in attributes map.
|
||||
* @method _converse.ChatRoom#getDuplicateMessage
|
||||
* @param { object } attrs - Attributes representing a received
|
||||
* message, as returned by { @link parseMUCMessage }
|
||||
* @returns {Promise<_converse.Message>}
|
||||
*/
|
||||
getDuplicateMessage (attrs) {
|
||||
if (attrs.activities?.length) {
|
||||
return this.messages.findWhere({'type': 'info', 'msgid': attrs.msgid});
|
||||
} else {
|
||||
return _converse.ChatBox.prototype.getDuplicateMessage.call(this, attrs);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Handler for all MUC messages sent to this groupchat. This method
|
||||
* shouldn't be called directly, instead {@link _converse.ChatRoom#queueMessage}
|
||||
* should be called.
|
||||
* @private
|
||||
* @method _converse.ChatRoom#onMessage
|
||||
* @param { MessageAttributes } attrs - A promise which resolves to the message attributes.
|
||||
*/
|
||||
|
@ -2114,13 +2150,15 @@ const ChatRoomMixin = {
|
|||
}
|
||||
const message = this.getDuplicateMessage(attrs);
|
||||
if (message) {
|
||||
return this.updateMessage(message, attrs);
|
||||
(message.get('type') === 'groupchat') && this.updateMessage(message, attrs);
|
||||
return;
|
||||
} else if (attrs.is_valid_receipt_request || attrs.is_marker || this.ignorableCSN(attrs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.handleMetadataFastening(attrs) ||
|
||||
this.handleMEPNotification(attrs) ||
|
||||
(await this.handleRetraction(attrs)) ||
|
||||
(await this.handleModeration(attrs)) ||
|
||||
(await this.handleSubjectChange(attrs))
|
||||
|
@ -2128,6 +2166,7 @@ const ChatRoomMixin = {
|
|||
attrs.nick && this.removeNotification(attrs.nick, ['composing', 'paused']);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setEditable(attrs, attrs.time);
|
||||
|
||||
if (attrs['chat_state']) {
|
||||
|
|
|
@ -33,7 +33,7 @@ const { NS } = Strophe;
|
|||
export function getMEPActivities (stanza) {
|
||||
const items_el = sizzle(`items[node="${Strophe.NS.CONFINFO}"]`, stanza).pop();
|
||||
if (!items_el) {
|
||||
return [];
|
||||
return null;
|
||||
}
|
||||
const from = stanza.getAttribute('from');
|
||||
const msgid = stanza.getAttribute('id');
|
||||
|
@ -127,6 +127,7 @@ export async function parseMUCMessage (stanza, chatbox, _converse) {
|
|||
* @typedef { Object } MUCMessageAttributes
|
||||
* The object which {@link parseMUCMessage} returns
|
||||
* @property { ('me'|'them') } sender - Whether the message was sent by the current user or someone else
|
||||
* @property { Array<Object> } activities - A list of objects representing XEP-0316 MEP notification data
|
||||
* @property { Array<Object> } references - A list of objects representing XEP-0372 references
|
||||
* @property { Boolean } editable - Is this message editable via XEP-0308?
|
||||
* @property { Boolean } is_archived - Is this message from a XEP-0313 MAM archive?
|
||||
|
@ -181,6 +182,7 @@ export async function parseMUCMessage (stanza, chatbox, _converse) {
|
|||
{
|
||||
from,
|
||||
nick,
|
||||
'activities': getMEPActivities(stanza),
|
||||
'body': stanza.querySelector('body')?.textContent?.trim(),
|
||||
'chat_state': getChatState(stanza),
|
||||
'from_muc': Strophe.getBareJidFromJid(from),
|
||||
|
|
|
@ -2,7 +2,6 @@ import isObject from 'lodash-es/isObject';
|
|||
import log from "@converse/headless/log.js";
|
||||
import { ROLES } from '@converse/headless/plugins/muc/index.js';
|
||||
import { _converse, api, converse } from '@converse/headless/core.js';
|
||||
import { getMEPActivities } from '@converse/headless/plugins/muc/parsers.js';
|
||||
import { safeSave } from '@converse/headless/utils/core.js';
|
||||
|
||||
const { Strophe, sizzle, u } = converse.env;
|
||||
|
@ -180,57 +179,6 @@ export async function autoJoinRooms () {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a stanza, look for XEP-0316 Room Notifications and create info
|
||||
* messages for them.
|
||||
* @param { XMLElement } stanza
|
||||
*/
|
||||
async function handleMEPNotification (stanza) {
|
||||
const from = stanza.getAttribute('from');
|
||||
if (u.isSameBareJID(from, _converse.bare_jid)) {
|
||||
return;
|
||||
}
|
||||
const room = await api.rooms.get(from);
|
||||
if (!room) {
|
||||
log.warn(`Received a MEP message for a non-existent room: ${from}`);
|
||||
return;
|
||||
}
|
||||
const msgid = stanza.getAttribute('id');
|
||||
if (room.messages.findWhere({ msgid })) {
|
||||
// We already handled this stanza before
|
||||
return;
|
||||
}
|
||||
getMEPActivities(stanza, room).forEach(attrs => {
|
||||
room.createMessage(attrs);
|
||||
api.trigger('message', { stanza, attrs, 'chatbox': room });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function checkIfMEP (message) {
|
||||
try {
|
||||
if (sizzle(`event[xmlns="${Strophe.NS.PUBSUB}#event"]`, message).length) {
|
||||
handleMEPNotification(message);
|
||||
}
|
||||
} catch (e) {
|
||||
log.error(e.message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
export function registerPEPPushHandler () {
|
||||
// Add a handler for devices pushed from other connected clients
|
||||
_converse.connection.addHandler(checkIfMEP, null, 'message', 'headline');
|
||||
|
||||
// XXX: This is a hack. Prosody's MUC MAM doesn't allow for quering
|
||||
// non-groupchat messages. So even though they might be archived, they
|
||||
// don't get returned on query. To bypass this, some MEP messages are sent
|
||||
// with type="groupchat".
|
||||
// https://hg.prosody.im/prosody-modules/rev/da9469e68dee
|
||||
_converse.connection.addHandler(checkIfMEP, null, 'message', 'groupchat');
|
||||
}
|
||||
|
||||
export function onAddClientFeatures () {
|
||||
if (api.settings.get('allow_muc')) {
|
||||
api.disco.own.features.add(Strophe.NS.MUC);
|
||||
|
|
|
@ -576,7 +576,6 @@ describe("Message Retractions", function () {
|
|||
occupant.save('role', 'member');
|
||||
const retraction_stanza = await sendAndThenRetractMessage(_converse, view);
|
||||
await u.waitUntil(() => view.querySelectorAll('.chat-msg--retracted').length === 1, 1000);
|
||||
console.log('XXX: First message retracted by author');
|
||||
|
||||
const msg_obj = view.model.messages.last();
|
||||
expect(msg_obj.get('retracted')).toBeTruthy();
|
||||
|
@ -598,19 +597,15 @@ describe("Message Retractions", function () {
|
|||
const reflection = u.toStanza(`
|
||||
<message type="groupchat" id="${retraction_stanza.getAttribute('id')}" from="${muc_jid}" to="${muc_jid}/romeo">
|
||||
<apply-to id="${stanza_id}" xmlns="urn:xmpp:fasten:0">
|
||||
<moderated by='${_converse.bare_jid}' xmlns='urn:xmpp:message-moderate:0'>
|
||||
<retract xmlns='urn:xmpp:message-retract:0' />
|
||||
</moderated>
|
||||
<retract xmlns='urn:xmpp:message-retract:0' />
|
||||
</apply-to>
|
||||
</message>`);
|
||||
|
||||
spyOn(view.model, 'handleRetraction').and.callThrough();
|
||||
_converse.connection._dataRecv(mock.createRequest(reflection));
|
||||
await u.waitUntil(() => view.model.handleRetraction.calls.count() === 1, 1000);
|
||||
console.log('XXX: Handle retraction was called on reflection');
|
||||
|
||||
await u.waitUntil(() => view.model.messages.length === 1, 1000);
|
||||
console.log('XXX: We have one message');
|
||||
await u.waitUntil(() => view.model.messages.length === 2, 1000);
|
||||
expect(view.model.messages.last().get('retracted')).toBeTruthy();
|
||||
expect(view.model.messages.last().get('is_ephemeral')).toBe(false);
|
||||
expect(view.model.messages.last().get('editable')).toBe(false);
|
||||
|
@ -648,9 +643,7 @@ describe("Message Retractions", function () {
|
|||
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
||||
</error>
|
||||
<apply-to id="${stanza_id}" xmlns="urn:xmpp:fasten:0">
|
||||
<moderated by='${_converse.bare_jid}' xmlns='urn:xmpp:message-moderate:0'>
|
||||
<retract xmlns='urn:xmpp:message-retract:0' />
|
||||
</moderated>
|
||||
</apply-to>
|
||||
</message>`);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user