diff --git a/packages/core/src/events/m.room.message.ts b/packages/core/src/events/m.room.message.ts index af4380163..524e63c4c 100644 --- a/packages/core/src/events/m.room.message.ts +++ b/packages/core/src/events/m.room.message.ts @@ -76,9 +76,14 @@ declare module './eventBase' { export type MessageRelation = { rel_type: RelationType; event_id: EventID; -} & (RelationTypeReplace | Record); +} & ( + | RelationTypeReplace + | RelationTypeAnnotation + | RelationTypeThread + | Record +); -export type RelationType = 'm.replace' | 'm.annotation'; +export type RelationType = 'm.replace' | 'm.annotation' | 'm.thread'; export type RelationTypeReplace = { rel_type: 'm.replace'; @@ -91,6 +96,24 @@ export type RelationTypeReplace = { }; }; +export type RelationTypeAnnotation = { + rel_type: 'm.annotation'; + event_id: EventID; + key: string; +}; + +export type RelationTypeThread = { + rel_type: 'm.thread'; + event_id: EventID; + 'm.in_reply_to'?: { + event_id: EventID; + room_id: string; + sender: string; + origin_server_ts: number; + }; + is_falling_back?: boolean; +}; + export type MessageAuthEvents = { 'm.room.create': EventID; 'm.room.power_levels': EventID; diff --git a/packages/federation-sdk/src/index.ts b/packages/federation-sdk/src/index.ts index 926822975..d65cac46a 100644 --- a/packages/federation-sdk/src/index.ts +++ b/packages/federation-sdk/src/index.ts @@ -1,4 +1,4 @@ -import type { Membership } from '@hs/core'; +import type { Membership, MessageType } from '@hs/core'; import type { EventID } from '@hs/room'; import { container } from 'tsyringe'; import { ConfigService } from './services/config.service'; @@ -115,23 +115,62 @@ export type HomeserverEventSignatures = { origin_server_ts: number; content: { body: string; - msgtype: string; - 'm.relates_to'?: { - rel_type: 'm.replace' | 'm.annotation' | 'm.thread'; - event_id: EventID; - 'm.in_reply_to'?: { - event_id: EventID; - room_id: string; - sender: string; - origin_server_ts: number; - }; - }; + msgtype: MessageType; + url?: string; + 'm.relates_to'?: + | { + rel_type: 'm.replace'; + event_id: EventID; + } + | { + rel_type: 'm.annotation'; + event_id: EventID; + key: string; + } + | { + rel_type: 'm.thread'; + event_id: EventID; + 'm.in_reply_to'?: { + event_id: EventID; + room_id: string; + sender: string; + origin_server_ts: number; + }; + is_falling_back?: boolean; + }; 'm.new_content'?: { body: string; - msgtype: string; + msgtype: MessageType; 'm.mentions'?: Record; }; formatted_body?: string; + info?: { + mimetype?: string; + w?: number; + h?: number; + size?: number; + thumbnail_file?: { + hashes: { + sha256: string; + }; + iv: string; + key: { + alg: string; + ext: boolean; + k: string; + key_ops: ['encrypt' | 'decrypt']; + kty: string; + }; + url: string; + v: 'v2'; + }; + thumbnail_info?: { + w?: number; + h?: number; + size?: number; + mimetype?: string; + }; + }; }; }; 'homeserver.matrix.accept-invite': { diff --git a/packages/federation-sdk/src/services/invite.service.ts b/packages/federation-sdk/src/services/invite.service.ts index 2092c6637..a6efa3279 100644 --- a/packages/federation-sdk/src/services/invite.service.ts +++ b/packages/federation-sdk/src/services/invite.service.ts @@ -1,5 +1,10 @@ import { EventBase, HttpException, HttpStatus } from '@hs/core'; -import { PersistentEventFactory, RoomVersion } from '@hs/room'; +import { + PduForType, + PersistentEventBase, + PersistentEventFactory, + RoomVersion, +} from '@hs/room'; import { singleton } from 'tsyringe'; import { createLogger } from '../utils/logger'; import { ConfigService } from './config.service'; @@ -121,13 +126,12 @@ export class InviteService { }; } - async processInvite< - T extends Omit & { - origin?: string | undefined; - room_id: string; - state_key: string; - }, - >(event: T, roomId: string, eventId: string, roomVersion: RoomVersion) { + async processInvite( + event: PduForType<'m.room.member'>, + roomId: string, + eventId: string, + roomVersion: RoomVersion, + ) { // SPEC: when a user invites another user on a different homeserver, a request to that homeserver to have the event signed and verified must be made const residentServer = roomId.split(':').pop(); @@ -135,12 +139,11 @@ export class InviteService { throw new Error(`Invalid roomId ${roomId}`); } - const inviteEvent = PersistentEventFactory.createFromRawEvent( - event as unknown as Parameters< - typeof PersistentEventFactory.createFromRawEvent - >[0], - roomVersion, - ); + const inviteEvent = + PersistentEventFactory.createFromRawEvent<'m.room.member'>( + event, + roomVersion, + ); if (inviteEvent.eventId !== eventId) { throw new Error(`Invalid eventId ${eventId}`); diff --git a/packages/federation-sdk/src/services/staging-area.service.ts b/packages/federation-sdk/src/services/staging-area.service.ts index 60a64efea..4b09dd56f 100644 --- a/packages/federation-sdk/src/services/staging-area.service.ts +++ b/packages/federation-sdk/src/services/staging-area.service.ts @@ -1,8 +1,8 @@ import type { EventBase, EventStagingStore, Membership } from '@hs/core'; import { singleton } from 'tsyringe'; -import { createLogger, isRedactedEvent } from '@hs/core'; -import { Pdu, PduPowerLevelsEventContent } from '@hs/room'; +import { MessageType, createLogger, isRedactedEvent } from '@hs/core'; +import { PduPowerLevelsEventContent } from '@hs/room'; import type { EventID } from '@hs/room'; import { EventAuthorizationService } from './event-authorization.service'; import { EventEmitterService } from './event-emitter.service'; @@ -148,14 +148,24 @@ export class StagingAreaService { content: { ...event.event.content, body: event.event.content?.body as string, - msgtype: event.event.content?.msgtype as string, - 'm.relates_to': event.event.content?.['m.relates_to'] as { - rel_type: 'm.replace' | 'm.annotation' | 'm.thread'; - event_id: EventID; - }, + msgtype: event.event.content?.msgtype as MessageType, + 'm.relates_to': event.event.content?.['m.relates_to'] as + | { + rel_type: 'm.replace'; + event_id: EventID; + } + | { + rel_type: 'm.annotation'; + event_id: EventID; + key: string; + } + | { + rel_type: 'm.thread'; + event_id: EventID; + }, 'm.new_content': event.event.content?.['m.new_content'] as { body: string; - msgtype: string; + msgtype: MessageType; }, formatted_body: (event.event.content?.formatted_body || '') as string,