Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions ee/packages/federation-matrix/src/FederationMatrix.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'reflect-metadata';

import type { PresenceState } from '@hs/core';
import type { FileMessageType, PresenceState } from '@hs/core';
import { ConfigService, createFederationContainer, getAllServices } from '@hs/federation-sdk';
import type { HomeserverEventSignatures, HomeserverServices, FederationContainerOptions } from '@hs/federation-sdk';
import type { EventID } from '@hs/room';
Expand Down Expand Up @@ -30,9 +30,7 @@ import { saveExternalUserIdForLocalUser } from './helpers/identifiers';
import { toExternalMessageFormat, toExternalQuoteMessageFormat } from './helpers/message.parsers';
import { MatrixMediaService } from './services/MatrixMediaService';

type MatrixFileTypes = 'm.image' | 'm.video' | 'm.audio' | 'm.file';

export const fileTypes: Record<string, MatrixFileTypes> = {
export const fileTypes: Record<string, FileMessageType> = {
image: 'm.image',
video: 'm.video',
audio: 'm.audio',
Expand Down Expand Up @@ -411,7 +409,7 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS
}
}

private getMatrixMessageType(mimeType?: string): MatrixFileTypes {
private getMatrixMessageType(mimeType?: string): FileMessageType {
const mainType = mimeType?.split('/')[0];
if (!mainType) {
return fileTypes.file;
Expand Down
43 changes: 23 additions & 20 deletions ee/packages/federation-matrix/src/events/message.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { FileMessageType, MessageType } from '@hs/core';
import type { HomeserverEventSignatures } from '@hs/federation-sdk';
import type { EventID } from '@hs/room';
import { FederationMatrix, Message, MeteorService } from '@rocket.chat/core-services';
import { UserStatus } from '@rocket.chat/core-typings';
import type { IUser, IRoom } from '@rocket.chat/core-typings';
Expand Down Expand Up @@ -108,7 +110,7 @@
return room;
}

async function getThreadMessageId(threadRootEventId: string): Promise<{ tmid: string; tshow: boolean } | undefined> {
async function getThreadMessageId(threadRootEventId: EventID): Promise<{ tmid: string; tshow: boolean } | undefined> {
const threadRootMessage = await Messages.findOneByFederationId(threadRootEventId);
if (!threadRootMessage) {
logger.warn('Thread root message not found for event:', threadRootEventId);
Expand All @@ -122,7 +124,7 @@
async function handleMediaMessage(
// TODO improve typing
content: any,
msgtype: string,
msgtype: MessageType,
messageBody: string,
user: IUser,
room: IRoom,
Expand Down Expand Up @@ -151,7 +153,7 @@
});

let fileExtension = '';
if (fileName && fileName.includes('.')) {

Check warning on line 156 in ee/packages/federation-matrix/src/events/message.ts

View workflow job for this annotation

GitHub Actions / 🔎 Code Check / Code Lint

Prefer using an optional chain expression instead, as it's more concise and easier to read
fileExtension = fileName.split('.').pop()?.toLowerCase() || '';
} else if (mimeType && mimeType.includes('/')) {
fileExtension = mimeType.split('/')[1] || '';
Expand Down Expand Up @@ -218,8 +220,7 @@
export function message(emitter: Emitter<HomeserverEventSignatures>, serverName: string) {
emitter.on('homeserver.matrix.message', async (data) => {
try {
// TODO remove type casting
const content = data.content as any;
const { content } = data;
const msgtype = content?.msgtype;
const messageBody = content?.body?.toString();

Expand All @@ -238,32 +239,34 @@
return;
}

const replyToRelation = content?.['m.relates_to'];
const threadRelation = content?.['m.relates_to'];
const isThreadMessage = threadRelation?.rel_type === 'm.thread';
const isQuoteMessage = replyToRelation?.['m.in_reply_to']?.event_id && !replyToRelation?.is_falling_back;
const threadRootEventId = isThreadMessage ? threadRelation.event_id : undefined;
const thread = await getThreadMessageId(threadRootEventId);
const relation = content['m.relates_to'];

const isMediaMessage = Object.values(fileTypes).includes(msgtype);
const isThreadMessage = relation && relation.rel_type === 'm.thread';
const threadRootEventId = isThreadMessage && relation.event_id;

const isEditedMessage = data.content['m.relates_to']?.rel_type === 'm.replace';
if (isEditedMessage && data.content['m.relates_to']?.event_id && data.content['m.new_content']) {
const quoteMessageEventId = relation && 'm.in_reply_to' in relation && relation['m.in_reply_to']?.event_id;

const thread = threadRootEventId ? await getThreadMessageId(threadRootEventId) : undefined;

const isMediaMessage = Object.values(fileTypes).includes(msgtype as FileMessageType);

const isEditedMessage = relation?.rel_type === 'm.replace';
if (isEditedMessage && relation?.event_id && data.content['m.new_content']) {
logger.debug('Received edited message from Matrix, updating existing message');
const originalMessage = await Messages.findOneByFederationId(data.content['m.relates_to'].event_id);
const originalMessage = await Messages.findOneByFederationId(relation.event_id);
if (!originalMessage) {
logger.error('Original message not found for edit:', data.content['m.relates_to'].event_id);
logger.error('Original message not found for edit:', relation.event_id);
return;
}
if (originalMessage.federation?.eventId !== data.content['m.relates_to'].event_id) {
if (originalMessage.federation?.eventId !== relation.event_id) {
return;
}
if (originalMessage.msg === data.content['m.new_content']?.body) {
logger.debug('No changes in message content, skipping update');
return;
}

if (isQuoteMessage && room.name) {
if (quoteMessageEventId && room.name) {
const messageToReplyToUrl = await MeteorService.getMessageURLToReplyTo(
room.t as string,
room._id,
Expand Down Expand Up @@ -305,10 +308,10 @@
return;
}

if (isQuoteMessage && room.name) {
const originalMessage = await Messages.findOneByFederationId(replyToRelation?.['m.in_reply_to']?.event_id);
if (quoteMessageEventId && room.name) {
const originalMessage = await Messages.findOneByFederationId(quoteMessageEventId);
if (!originalMessage) {
logger.error('Original message not found for quote:', replyToRelation?.['m.in_reply_to']?.event_id);
logger.error('Original message not found for quote:', quoteMessageEventId);
return;
}
const messageToReplyToUrl = await MeteorService.getMessageURLToReplyTo(room.t as string, room._id, room.name, originalMessage._id);
Expand Down
Loading