Skip to content

Commit 8d451e3

Browse files
rodrigokggazzo
andauthored
feat: add support to encrypted messages (#270)
Co-authored-by: Guilherme Gazzo <guilhermegazzo@gmail.com>
1 parent a7b591b commit 8d451e3

File tree

4 files changed

+126
-47
lines changed

4 files changed

+126
-47
lines changed

packages/federation-sdk/src/index.ts

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,39 @@ export interface HomeserverServices {
114114
emitter: EventEmitterService;
115115
}
116116

117+
type RelatesTo =
118+
| {
119+
rel_type: 'm.replace';
120+
event_id: EventID;
121+
}
122+
| {
123+
rel_type: 'm.annotation';
124+
event_id: EventID;
125+
key: string;
126+
}
127+
| {
128+
rel_type: 'm.thread';
129+
event_id: EventID;
130+
'm.in_reply_to'?: {
131+
event_id: EventID;
132+
room_id: string;
133+
sender: string;
134+
origin_server_ts: number;
135+
};
136+
is_falling_back?: boolean;
137+
}
138+
| {
139+
// SPEC: Though rich replies form a relationship to another event, they do not use rel_type to create this relationship.
140+
// Instead, a subkey named m.in_reply_to is used to describe the reply’s relationship,
141+
142+
// rich {"body":"quote","m.mentions":{},"m.relates_to":{"is_falling_back":false,"m.in_reply_to":{"event_id":"$0vkvf2Ha_FdWe3zVaoDw3X15VCyZIZRYrHQXuoZDURQ"}},"msgtype":"m.text"}
143+
144+
'm.in_reply_to': {
145+
event_id: EventID;
146+
};
147+
is_falling_back?: boolean;
148+
};
149+
117150
export type HomeserverEventSignatures = {
118151
'homeserver.ping': {
119152
message: string;
@@ -130,6 +163,22 @@ export type HomeserverEventSignatures = {
130163
last_active_ago?: number;
131164
origin?: string;
132165
};
166+
'homeserver.matrix.encrypted': {
167+
event_id: EventID;
168+
event: PduForType<'m.room.encrypted'>;
169+
170+
room_id: string;
171+
sender: string;
172+
origin_server_ts: number;
173+
content: {
174+
algorithm: 'm.megolm.v1.aes-sha2';
175+
ciphertext: string;
176+
'm.relates_to'?: RelatesTo;
177+
device_id?: string;
178+
sender_key?: string;
179+
session_id?: string;
180+
};
181+
};
133182
'homeserver.matrix.message': {
134183
event_id: EventID;
135184
event: PduForType<'m.room.message'>;
@@ -141,38 +190,7 @@ export type HomeserverEventSignatures = {
141190
body: string;
142191
msgtype: MessageType;
143192
url?: string;
144-
'm.relates_to'?:
145-
| {
146-
rel_type: 'm.replace';
147-
event_id: EventID;
148-
}
149-
| {
150-
rel_type: 'm.annotation';
151-
event_id: EventID;
152-
key: string;
153-
}
154-
| {
155-
rel_type: 'm.thread';
156-
event_id: EventID;
157-
'm.in_reply_to'?: {
158-
event_id: EventID;
159-
room_id: string;
160-
sender: string;
161-
origin_server_ts: number;
162-
};
163-
is_falling_back?: boolean;
164-
}
165-
| {
166-
// SPEC: Though rich replies form a relationship to another event, they do not use rel_type to create this relationship.
167-
// Instead, a subkey named m.in_reply_to is used to describe the reply’s relationship,
168-
169-
// rich {"body":"quote","m.mentions":{},"m.relates_to":{"is_falling_back":false,"m.in_reply_to":{"event_id":"$0vkvf2Ha_FdWe3zVaoDw3X15VCyZIZRYrHQXuoZDURQ"}},"msgtype":"m.text"}
170-
171-
'm.in_reply_to': {
172-
event_id: EventID;
173-
};
174-
is_falling_back?: boolean;
175-
};
193+
'm.relates_to'?: RelatesTo;
176194
'm.new_content'?: {
177195
body: string;
178196
msgtype: MessageType;

packages/federation-sdk/src/repositories/event.repository.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export class EventRepository {
7676
case 'm.reaction':
7777
case 'm.room.name':
7878
case 'm.room.message':
79+
case 'm.room.encrypted':
7980
case 'm.room.member':
8081
case 'm.room.power_levels':
8182
case 'm.room.topic':

packages/federation-sdk/src/services/staging-area.service.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,32 @@ export class StagingAreaService {
240240
},
241241
});
242242
break;
243+
case event.event.type === 'm.room.encrypted':
244+
this.eventEmitterService.emit('homeserver.matrix.encrypted', {
245+
event_id: eventId,
246+
event: event.event,
247+
room_id: roomId,
248+
sender: event.event.sender,
249+
origin_server_ts: event.event.origin_server_ts,
250+
content: {
251+
...event.event.content,
252+
'm.relates_to': event.event.content?.['m.relates_to'] as
253+
| {
254+
rel_type: 'm.replace';
255+
event_id: EventID;
256+
}
257+
| {
258+
rel_type: 'm.annotation';
259+
event_id: EventID;
260+
key: string;
261+
}
262+
| {
263+
rel_type: 'm.thread';
264+
event_id: EventID;
265+
},
266+
},
267+
});
268+
break;
243269
case event.event.type === 'm.reaction': {
244270
this.eventEmitterService.emit('homeserver.matrix.reaction', {
245271
event_id: eventId,

packages/room/src/types/v3-11.ts

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -366,21 +366,8 @@ export type PduRoomNameEventContent = z.infer<
366366
typeof PduRoomNameEventContentSchema
367367
>;
368368

369-
// Base message content schema
370-
const BaseMessageContentSchema = z.object({
371-
body: z.string().describe('The body of the message.'),
372-
msgtype: z
373-
.enum([
374-
'm.text',
375-
'm.image',
376-
'm.file',
377-
'm.audio',
378-
'm.video',
379-
'm.emote',
380-
'm.notice',
381-
'm.location',
382-
])
383-
.describe('The type of the message.'),
369+
// Base timeline content schema
370+
const BaseTimelineContentSchema = z.object({
384371
// Optional fields for message edits and relations aka threads
385372
'm.relates_to': z
386373
.object({
@@ -406,6 +393,24 @@ const BaseMessageContentSchema = z.object({
406393
})
407394
.optional()
408395
.describe('Relation information for edits, replies, reactions, etc.'),
396+
});
397+
398+
// Base message content schema
399+
const BaseMessageContentSchema = BaseTimelineContentSchema.extend({
400+
body: z.string().describe('The body of the message.'),
401+
msgtype: z
402+
.enum([
403+
'm.text',
404+
'm.image',
405+
'm.file',
406+
'm.audio',
407+
'm.video',
408+
'm.emote',
409+
'm.notice',
410+
'm.location',
411+
])
412+
.describe('The type of the message.'),
413+
// Optional fields for message edits and relations aka threads
409414
format: z
410415
.enum(['org.matrix.custom.html'])
411416
.describe('The format of the message content.')
@@ -512,6 +517,26 @@ export const PduMessageEventContentSchema = z.union([
512517
}),
513518
]);
514519

520+
const EncryptedContentSchema = BaseTimelineContentSchema.extend({
521+
algorithm: z
522+
.enum(['m.megolm.v1.aes-sha2'])
523+
.describe('The algorithm used to encrypt the content.'),
524+
ciphertext: z.string().describe('The encrypted content.'),
525+
// Optional fields for message edits and relations aka threads
526+
device_id: z
527+
.string()
528+
.describe('The formatted body of the message.')
529+
.optional(),
530+
sender_key: z
531+
.string()
532+
.describe('The formatted body of the message.')
533+
.optional(),
534+
session_id: z
535+
.string()
536+
.describe('The formatted body of the message.')
537+
.optional(),
538+
});
539+
515540
export type PduMessageEventContent = z.infer<
516541
typeof PduMessageEventContentSchema
517542
>;
@@ -675,6 +700,12 @@ const EventPduTypeRoomTombstone = z.object({
675700
content: PduRoomTombstoneEventContentSchema,
676701
});
677702

703+
const EventPduTypeRoomEncrypted = z.object({
704+
...PduNoContentTimelineEventSchema,
705+
type: z.literal('m.room.encrypted'),
706+
content: EncryptedContentSchema,
707+
});
708+
678709
const EventPduTypeRoomMessage = z.object({
679710
...PduNoContentTimelineEventSchema,
680711
type: z.literal('m.room.message'),
@@ -723,6 +754,8 @@ export const PduStateEventSchema = z.discriminatedUnion('type', [
723754
export const PduTimelineSchema = z.discriminatedUnion('type', [
724755
EventPduTypeRoomMessage,
725756

757+
EventPduTypeRoomEncrypted,
758+
726759
EventPduTypeRoomReaction,
727760

728761
EventPduTypeRoomRedaction,
@@ -740,6 +773,7 @@ export type PduContent<T extends PduType = PduType> = PduForType<T>['content'];
740773
export function isTimelineEventType(type: PduType) {
741774
return (
742775
type === 'm.room.message' ||
776+
type === 'm.room.encrypted' ||
743777
type === 'm.reaction' ||
744778
type === 'm.room.redaction'
745779
);

0 commit comments

Comments
 (0)