Skip to content

Commit c8d6c60

Browse files
authored
refactor: standardize event handling in federation-matrix (RocketChat#37535)
1 parent ed544f8 commit c8d6c60

4 files changed

Lines changed: 86 additions & 82 deletions

File tree

ee/packages/federation-matrix/src/events/member.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,51 @@ import { createOrUpdateFederatedUser, getUsernameServername } from '../Federatio
88

99
const logger = new Logger('federation-matrix:member');
1010

11-
async function membershipLeaveAction(data: HomeserverEventSignatures['homeserver.matrix.membership']) {
12-
const room = await Rooms.findOne({ 'federation.mrid': data.room_id }, { projection: { _id: 1 } });
11+
async function membershipLeaveAction(event: HomeserverEventSignatures['homeserver.matrix.membership']['event']) {
12+
const room = await Rooms.findOne({ 'federation.mrid': event.room_id }, { projection: { _id: 1 } });
1313
if (!room) {
14-
logger.warn(`No bridged room found for Matrix room_id: ${data.room_id}`);
14+
logger.warn(`No bridged room found for Matrix room_id: ${event.room_id}`);
1515
return;
1616
}
1717

1818
const serverName = federationSDK.getConfig('serverName');
1919

20-
const [affectedUsername] = getUsernameServername(data.state_key, serverName);
20+
const [affectedUsername] = getUsernameServername(event.state_key, serverName);
2121
// state_key is the user affected by the membership change
2222
const affectedUser = await Users.findOneByUsername(affectedUsername);
2323
if (!affectedUser) {
24-
logger.error(`No Rocket.Chat user found for bridged user: ${data.state_key}`);
24+
logger.error(`No Rocket.Chat user found for bridged user: ${event.state_key}`);
2525
return;
2626
}
2727

2828
// Check if this is a kick (sender != state_key) or voluntary leave (sender == state_key)
29-
if (data.sender === data.state_key) {
29+
if (event.sender === event.state_key) {
3030
// Voluntary leave
3131
await Room.removeUserFromRoom(room._id, affectedUser);
3232
logger.info(`User ${affectedUser.username} left room ${room._id} via Matrix federation`);
3333
} else {
3434
// Kick - find who kicked
3535

36-
const [kickerUsername] = getUsernameServername(data.sender, serverName);
36+
const [kickerUsername] = getUsernameServername(event.sender, serverName);
3737
const kickerUser = await Users.findOneByUsername(kickerUsername);
3838

3939
await Room.removeUserFromRoom(room._id, affectedUser, {
4040
byUser: kickerUser || { _id: 'matrix.federation', username: 'Matrix User' },
4141
});
4242

43-
const reasonText = data.content.reason ? ` Reason: ${data.content.reason}` : '';
44-
logger.info(`User ${affectedUser.username} was kicked from room ${room._id} by ${data.sender} via Matrix federation.${reasonText}`);
43+
const reasonText = event.content.reason ? ` Reason: ${event.content.reason}` : '';
44+
logger.info(`User ${affectedUser.username} was kicked from room ${room._id} by ${event.sender} via Matrix federation.${reasonText}`);
4545
}
4646
}
4747

48-
async function membershipJoinAction(data: HomeserverEventSignatures['homeserver.matrix.membership']) {
49-
const room = await Rooms.findOne({ 'federation.mrid': data.room_id });
48+
async function membershipJoinAction(event: HomeserverEventSignatures['homeserver.matrix.membership']['event']) {
49+
const room = await Rooms.findOne({ 'federation.mrid': event.room_id });
5050
if (!room) {
51-
logger.warn(`No bridged room found for room_id: ${data.room_id}`);
51+
logger.warn(`No bridged room found for room_id: ${event.room_id}`);
5252
return;
5353
}
5454

55-
const [username, serverName, isLocal] = getUsernameServername(data.sender, federationSDK.getConfig('serverName'));
55+
const [username, serverName, isLocal] = getUsernameServername(event.sender, federationSDK.getConfig('serverName'));
5656

5757
// for local users we must to remove the @ and the server domain
5858
const localUser = isLocal && (await Users.findOneByUsername(username));
@@ -71,9 +71,9 @@ async function membershipJoinAction(data: HomeserverEventSignatures['homeserver.
7171
}
7272

7373
const insertedId = await createOrUpdateFederatedUser({
74-
username: data.event.state_key,
74+
username: event.state_key,
7575
origin: serverName,
76-
name: data.content.displayname || (data.state_key as `@${string}:${string}`),
76+
name: event.content.displayname || event.state_key,
7777
});
7878

7979
const user = await Users.findOneById(insertedId);
@@ -86,17 +86,17 @@ async function membershipJoinAction(data: HomeserverEventSignatures['homeserver.
8686
}
8787

8888
export function member(emitter: Emitter<HomeserverEventSignatures>) {
89-
emitter.on('homeserver.matrix.membership', async (data) => {
89+
emitter.on('homeserver.matrix.membership', async ({ event }) => {
9090
try {
91-
if (data.content.membership === 'leave') {
92-
return membershipLeaveAction(data);
91+
if (event.content.membership === 'leave') {
92+
return membershipLeaveAction(event);
9393
}
9494

95-
if (data.content.membership === 'join') {
96-
return membershipJoinAction(data);
95+
if (event.content.membership === 'join') {
96+
return membershipJoinAction(event);
9797
}
9898

99-
logger.debug(`Ignoring membership event with membership: ${data.content.membership}`);
99+
logger.debug(`Ignoring membership event with membership: ${event.content.membership}`);
100100
} catch (error) {
101101
logger.error('Failed to process Matrix membership event:', error);
102102
}

ee/packages/federation-matrix/src/events/message.ts

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -119,31 +119,30 @@ async function handleMediaMessage(
119119
}
120120

121121
export function message(emitter: Emitter<HomeserverEventSignatures>) {
122-
emitter.on('homeserver.matrix.message', async (data) => {
122+
emitter.on('homeserver.matrix.message', async ({ event, event_id: eventId }) => {
123123
try {
124-
const { content } = data;
125-
const { msgtype } = content;
126-
const messageBody = content.body.toString();
124+
const { msgtype, body } = event.content;
125+
const messageBody = body.toString();
127126

128127
if (!messageBody && !msgtype) {
129128
logger.debug('No message content found in event');
130129
return;
131130
}
132131

133132
// at this point we know for sure the user already exists
134-
const user = await Users.findOneByUsername(data.sender);
133+
const user = await Users.findOneByUsername(event.sender);
135134
if (!user) {
136-
throw new Error(`User not found for sender: ${data.sender}`);
135+
throw new Error(`User not found for sender: ${event.sender}`);
137136
}
138137

139-
const room = await Rooms.findOne({ 'federation.mrid': data.room_id });
138+
const room = await Rooms.findOne({ 'federation.mrid': event.room_id });
140139
if (!room) {
141-
throw new Error(`No mapped room found for room_id: ${data.room_id}`);
140+
throw new Error(`No mapped room found for room_id: ${event.room_id}`);
142141
}
143142

144143
const serverName = federationSDK.getConfig('serverName');
145144

146-
const relation = content['m.relates_to'];
145+
const relation = event.content['m.relates_to'];
147146

148147
// SPEC: For example, an m.thread relationship type denotes that the event is part of a “thread” of messages and should be rendered as such.
149148
const hasRelation = relation && 'rel_type' in relation;
@@ -161,7 +160,7 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
161160
const thread = threadRootEventId ? await getThreadMessageId(threadRootEventId) : undefined;
162161

163162
const isEditedMessage = hasRelation && relation.rel_type === 'm.replace';
164-
if (isEditedMessage && relation.event_id && data.content['m.new_content']) {
163+
if (isEditedMessage && relation.event_id && event.content['m.new_content']) {
165164
logger.debug('Received edited message from Matrix, updating existing message');
166165
const originalMessage = await Messages.findOneByFederationId(relation.event_id);
167166
if (!originalMessage) {
@@ -171,7 +170,7 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
171170
if (originalMessage.federation?.eventId !== relation.event_id) {
172171
return;
173172
}
174-
if (originalMessage.msg === data.content['m.new_content']?.body) {
173+
if (originalMessage.msg === event.content['m.new_content']?.body) {
175174
logger.debug('No changes in message content, skipping update');
176175
return;
177176
}
@@ -180,10 +179,10 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
180179
const messageToReplyToUrl = await MeteorService.getMessageURLToReplyTo(room.t as string, room._id, originalMessage._id);
181180
const formatted = await toInternalQuoteMessageFormat({
182181
messageToReplyToUrl,
183-
formattedMessage: data.content.formatted_body || '',
182+
formattedMessage: event.content.formatted_body || '',
184183
rawMessage: messageBody,
185184
homeServerDomain: serverName,
186-
senderExternalId: data.sender,
185+
senderExternalId: event.sender,
187186
});
188187
await Message.updateMessage(
189188
{
@@ -197,11 +196,12 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
197196
}
198197

199198
const formatted = toInternalMessageFormat({
200-
rawMessage: data.content['m.new_content'].body,
201-
formattedMessage: data.content.formatted_body || '',
199+
rawMessage: event.content['m.new_content'].body,
200+
formattedMessage: event.content.formatted_body || '',
202201
homeServerDomain: serverName,
203-
senderExternalId: data.sender,
202+
senderExternalId: event.sender,
204203
});
204+
205205
await Message.updateMessage(
206206
{
207207
...originalMessage,
@@ -222,47 +222,47 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
222222
const messageToReplyToUrl = await MeteorService.getMessageURLToReplyTo(room.t as string, room._id, originalMessage._id);
223223
const formatted = await toInternalQuoteMessageFormat({
224224
messageToReplyToUrl,
225-
formattedMessage: data.content.formatted_body || '',
225+
formattedMessage: event.content.formatted_body || '',
226226
rawMessage: messageBody,
227227
homeServerDomain: serverName,
228-
senderExternalId: data.sender,
228+
senderExternalId: event.sender,
229229
});
230230
await Message.saveMessageFromFederation({
231231
fromId: user._id,
232232
rid: room._id,
233233
msg: formatted,
234-
federation_event_id: data.event_id,
234+
federation_event_id: eventId,
235235
thread,
236236
});
237237
return;
238238
}
239239

240240
const isMediaMessage = Object.values(fileTypes).includes(msgtype as FileMessageType);
241-
if (isMediaMessage && content.url) {
241+
if (isMediaMessage && 'url' in event.content) {
242242
const result = await handleMediaMessage(
243-
content.url,
244-
content.info,
243+
event.content.url,
244+
event.content.info,
245245
msgtype,
246246
messageBody,
247247
user,
248248
room,
249-
data.room_id,
250-
data.event_id,
249+
event.room_id,
250+
eventId,
251251
thread,
252252
);
253253
await Message.saveMessageFromFederation(result);
254254
} else {
255255
const formatted = toInternalMessageFormat({
256256
rawMessage: messageBody,
257-
formattedMessage: data.content.formatted_body || '',
257+
formattedMessage: event.content.formatted_body || '',
258258
homeServerDomain: serverName,
259-
senderExternalId: data.sender,
259+
senderExternalId: event.sender,
260260
});
261261
await Message.saveMessageFromFederation({
262262
fromId: user._id,
263263
rid: room._id,
264264
msg: formatted,
265-
federation_event_id: data.event_id,
265+
federation_event_id: eventId,
266266
thread,
267267
});
268268
}
@@ -271,25 +271,25 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
271271
}
272272
});
273273

274-
emitter.on('homeserver.matrix.encrypted', async (data) => {
274+
emitter.on('homeserver.matrix.encrypted', async ({ event, event_id: eventId }) => {
275275
try {
276-
if (!data.content.ciphertext) {
276+
if (!event.content.ciphertext) {
277277
logger.debug('No message content found in event');
278278
return;
279279
}
280280

281281
// at this point we know for sure the user already exists
282-
const user = await Users.findOneByUsername(data.sender);
282+
const user = await Users.findOneByUsername(event.sender);
283283
if (!user) {
284-
throw new Error(`User not found for sender: ${data.sender}`);
284+
throw new Error(`User not found for sender: ${event.sender}`);
285285
}
286286

287-
const room = await Rooms.findOne({ 'federation.mrid': data.room_id });
287+
const room = await Rooms.findOne({ 'federation.mrid': event.room_id });
288288
if (!room) {
289-
throw new Error(`No mapped room found for room_id: ${data.room_id}`);
289+
throw new Error(`No mapped room found for room_id: ${event.room_id}`);
290290
}
291291

292-
const relation = data.content['m.relates_to'];
292+
const relation = event.content['m.relates_to'];
293293

294294
// SPEC: For example, an m.thread relationship type denotes that the event is part of a “thread” of messages and should be rendered as such.
295295
const hasRelation = relation && 'rel_type' in relation;
@@ -317,7 +317,7 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
317317
if (originalMessage.federation?.eventId !== relation.event_id) {
318318
return;
319319
}
320-
if (originalMessage.content?.ciphertext === data.content.ciphertext) {
320+
if (originalMessage.content?.ciphertext === event.content.ciphertext) {
321321
logger.debug('No changes in message content, skipping update');
322322
return;
323323
}
@@ -327,8 +327,8 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
327327
{
328328
...originalMessage,
329329
content: {
330-
algorithm: data.content.algorithm,
331-
ciphertext: data.content.ciphertext,
330+
algorithm: event.content.algorithm,
331+
ciphertext: event.content.ciphertext,
332332
},
333333
},
334334
user,
@@ -341,8 +341,8 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
341341
{
342342
...originalMessage,
343343
content: {
344-
algorithm: data.content.algorithm,
345-
ciphertext: data.content.ciphertext,
344+
algorithm: event.content.algorithm,
345+
ciphertext: event.content.ciphertext,
346346
},
347347
},
348348
user,
@@ -361,10 +361,10 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
361361
fromId: user._id,
362362
rid: room._id,
363363
e2e_content: {
364-
algorithm: data.content.algorithm,
365-
ciphertext: data.content.ciphertext,
364+
algorithm: event.content.algorithm,
365+
ciphertext: event.content.ciphertext,
366366
},
367-
federation_event_id: data.event_id,
367+
federation_event_id: eventId,
368368
thread,
369369
});
370370
return;
@@ -374,20 +374,20 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
374374
fromId: user._id,
375375
rid: room._id,
376376
e2e_content: {
377-
algorithm: data.content.algorithm,
378-
ciphertext: data.content.ciphertext,
377+
algorithm: event.content.algorithm,
378+
ciphertext: event.content.ciphertext,
379379
},
380-
federation_event_id: data.event_id,
380+
federation_event_id: eventId,
381381
thread,
382382
});
383383
} catch (error) {
384384
logger.error(error, 'Error processing Matrix message:');
385385
}
386386
});
387387

388-
emitter.on('homeserver.matrix.redaction', async (data) => {
388+
emitter.on('homeserver.matrix.redaction', async ({ event }) => {
389389
try {
390-
const redactedEventId = data.redacts;
390+
const redactedEventId = event.redacts;
391391
if (!redactedEventId) {
392392
logger.debug('No redacts field in redaction event');
393393
return;
@@ -399,12 +399,12 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
399399
return;
400400
}
401401

402-
const rcMessage = await Messages.findOneByFederationId(data.redacts);
402+
const rcMessage = await Messages.findOneByFederationId(event.redacts);
403403
if (!rcMessage) {
404-
logger.debug(`No RC message found for event ${data.redacts}`);
404+
logger.debug(`No RC message found for event ${event.redacts}`);
405405
return;
406406
}
407-
const internalUsername = data.sender;
407+
const internalUsername = event.sender;
408408
const user = await Users.findOneByUsername(internalUsername);
409409
if (!user) {
410410
logger.debug(`User not found: ${internalUsername}`);

0 commit comments

Comments
 (0)