import type { Message, Reaction } from './message.models'; import type { MessageRevision } from './message-revision.models'; import type { UserRole, RoomMember } from './user.models'; import type { Room, RoomSettings, RoomPermissions, Channel } from './room.models'; import type { VoiceState } from './voice-state.models'; import type { GameActivity } from './game-activity.models'; import type { BanEntry } from './moderation.models'; import type { ChatAttachmentAnnouncement, ChatAttachmentMeta } from './attachment-contracts'; import type { CustomEmoji, CustomEmojiSummaryItem, CustomEmojiTransferManifest } from './custom-emoji.models'; import type { DirectMessageEventPayload, DirectMessageMutationEventPayload, DirectMessageSyncEventPayload, DirectMessageSyncRequestEventPayload, DirectMessageStatusEventPayload, DirectMessageTypingEventPayload } from './direct-message-contracts'; import type { DirectCallEventPayload } from './direct-call-contracts'; export interface ChatInventoryItem { id: string; ts: number; rc: number; ac?: number; revision?: number; headHash?: string; } // Every field that appears on any event is kept optional here so that // code which accesses `event.roomId` etc. without narrowing first // still compiles. Individual event interfaces below then make the // relevant fields **required**. export interface ChatEventBase { fromPeerId?: string; messageId?: string; message?: Message; reaction?: Reaction; data?: string | Partial; timestamp?: number; targetUserId?: string; roomId?: string; items?: ChatInventoryItem[]; ids?: string[]; messages?: Message[]; attachments?: Record; total?: number; index?: number; count?: number; lastUpdated?: number; file?: ChatAttachmentAnnouncement; fileId?: string; username?: string; hostId?: string; hostOderId?: string; previousHostId?: string; previousHostOderId?: string; kickedBy?: string; bannedBy?: string; content?: string; editedAt?: number; deletedAt?: number; deletedBy?: string; oderId?: string; displayName?: string; description?: string; profileUpdatedAt?: number; emoji?: string; reason?: string; settings?: Partial; permissions?: Partial; voiceState?: Partial; gameActivity?: GameActivity | null; isScreenSharing?: boolean; isCameraEnabled?: boolean; icon?: string; iconUpdatedAt?: number; avatarUrl?: string; avatarHash?: string; avatarMime?: string; avatarUpdatedAt?: number; role?: UserRole; room?: Partial; channels?: Channel[]; members?: RoomMember[]; ban?: BanEntry; bans?: BanEntry[]; banOderId?: string; expiresAt?: number; directMessage?: DirectMessageEventPayload; directMessageStatus?: DirectMessageStatusEventPayload; directMessageMutation?: DirectMessageMutationEventPayload; directMessageTyping?: DirectMessageTypingEventPayload; directMessageSyncRequest?: DirectMessageSyncRequestEventPayload; directMessageSync?: DirectMessageSyncEventPayload; directCall?: DirectCallEventPayload; pluginMessage?: unknown; customEmoji?: CustomEmoji; customEmojiTransfer?: CustomEmojiTransferManifest; customEmojiSummaries?: CustomEmojiSummaryItem[]; customEmojiId?: string; } export interface ChatMessageEvent extends ChatEventBase { type: 'message' | 'chat-message'; message: Message; } export interface MessageEditedEvent extends ChatEventBase { type: 'edit' | 'message-edited'; messageId: string; content: string; editedAt: number; } export interface MessageDeletedEvent extends ChatEventBase { type: 'delete' | 'message-deleted'; messageId: string; } export interface MessageRevisionEvent extends ChatEventBase { type: 'message-revision'; revision: MessageRevision; } export interface ReactionAddedEvent extends ChatEventBase { type: 'reaction' | 'reaction-added'; messageId: string; reaction: Reaction; } export interface ReactionRemovedEvent extends ChatEventBase { type: 'reaction-removed'; messageId: string; oderId: string; emoji: string; } export interface FileAnnounceChatEvent extends ChatEventBase { type: 'file-announce'; messageId: string; file: ChatAttachmentAnnouncement; } export interface FileChunkChatEvent extends ChatEventBase { type: 'file-chunk'; messageId: string; fileId: string; index: number; total: number; data: string; } export interface FileRequestChatEvent extends ChatEventBase { type: 'file-request'; messageId: string; fileId: string; } export interface FileCancelChatEvent extends ChatEventBase { type: 'file-cancel'; messageId: string; fileId: string; } export interface FileNotFoundChatEvent extends ChatEventBase { type: 'file-not-found'; messageId: string; fileId: string; } export interface ChatInventoryRequestEvent extends ChatEventBase { type: 'chat-inventory-request'; roomId: string; } export interface ChatInventoryEvent extends ChatEventBase { type: 'chat-inventory'; roomId: string; items: ChatInventoryItem[]; total: number; } export interface ChatSyncRequestIdsEvent extends ChatEventBase { type: 'chat-sync-request-ids'; roomId: string; ids: string[]; } export interface ChatSyncBatchEvent extends ChatEventBase { type: 'chat-sync-batch'; roomId: string; messages: Message[]; } export interface ChatSyncSummaryEvent extends ChatEventBase { type: 'chat-sync-summary'; } export interface ChatSyncRequestEvent extends ChatEventBase { type: 'chat-sync-request'; roomId: string; } export interface ChatSyncFullEvent extends ChatEventBase { type: 'chat-sync-full'; roomId: string; messages: Message[]; } export interface RoomDeletedEvent extends ChatEventBase { type: 'room-deleted'; roomId: string; } export interface RoomSettingsUpdateEvent extends ChatEventBase { type: 'room-settings-update'; roomId: string; settings: Partial; } export interface RoomPermissionsUpdateEvent extends ChatEventBase { type: 'room-permissions-update'; roomId: string; permissions?: Partial; } export interface HostChangeEvent extends ChatEventBase { type: 'host-change'; roomId: string; hostId: string; hostOderId: string; previousHostId: string; previousHostOderId: string; } export interface VoiceStateEvent extends ChatEventBase { type: 'voice-state'; voiceState: Partial; } export interface VoiceChannelMoveEvent extends ChatEventBase { type: 'voice-channel-move'; roomId: string; targetUserId: string; voiceState: Partial; } export interface ScreenStateEvent extends ChatEventBase { type: 'screen-state'; isScreenSharing: boolean; } export interface CameraStateEvent extends ChatEventBase { type: 'camera-state'; isCameraEnabled: boolean; } export interface GameActivityEvent extends ChatEventBase { type: 'game-activity'; gameActivity: GameActivity | null; } export interface VoiceStateRequestEvent extends ChatEventBase { type: 'voice-state-request'; } export interface StateRequestEvent extends ChatEventBase { type: 'state-request'; } export interface ScreenShareRequestEvent extends ChatEventBase { type: 'screen-share-request'; } export interface ScreenShareStopEvent extends ChatEventBase { type: 'screen-share-stop'; } export interface ServerIconSummaryEvent extends ChatEventBase { type: 'server-icon-summary'; roomId: string; iconUpdatedAt: number; } export interface ServerIconRequestEvent extends ChatEventBase { type: 'server-icon-request'; roomId: string; } export interface ServerIconFullEvent extends ChatEventBase { type: 'server-icon-full'; roomId: string; icon?: string; iconUpdatedAt: number; } export interface ServerIconUpdateEvent extends ChatEventBase { type: 'server-icon-update'; roomId: string; icon: string; iconUpdatedAt: number; } export interface UserAvatarSummaryEvent extends ChatEventBase { type: 'user-avatar-summary'; oderId: string; username?: string; displayName?: string; description?: string; profileUpdatedAt?: number; avatarHash?: string; avatarMime?: string; avatarUpdatedAt: number; } export interface UserAvatarRequestEvent extends ChatEventBase { type: 'user-avatar-request'; oderId: string; } export interface UserAvatarFullEvent extends ChatEventBase { type: 'user-avatar-full'; oderId: string; username?: string; displayName?: string; description?: string; profileUpdatedAt?: number; avatarHash?: string; avatarMime?: string; avatarUpdatedAt: number; total: number; } export interface UserAvatarChunkEvent extends ChatEventBase { type: 'user-avatar-chunk'; oderId: string; avatarHash?: string; avatarMime?: string; avatarUpdatedAt?: number; index: number; total: number; data: string; } export interface ServerStateRequestEvent extends ChatEventBase { type: 'server-state-request'; roomId: string; } export interface ServerStateFullEvent extends ChatEventBase { type: 'server-state-full'; roomId: string; room: Partial; } export interface MemberRosterRequestEvent extends ChatEventBase { type: 'member-roster-request'; roomId: string; } export interface MemberRosterEvent extends ChatEventBase { type: 'member-roster'; roomId: string; members: RoomMember[]; } export interface MemberLeaveEvent extends ChatEventBase { type: 'member-leave'; roomId: string; } export interface RoleChangeEvent extends ChatEventBase { type: 'role-change'; } export interface KickEvent extends ChatEventBase { type: 'kick'; } export interface BanEvent extends ChatEventBase { type: 'ban'; } export interface UnbanEvent extends ChatEventBase { type: 'unban'; } export interface ChannelsUpdateEvent extends ChatEventBase { type: 'channels-update'; roomId: string; channels: Channel[]; } export interface DirectMessagePeerEvent extends ChatEventBase { type: 'direct-message'; directMessage: DirectMessageEventPayload; } export interface DirectMessageStatusPeerEvent extends ChatEventBase { type: 'direct-message-status'; directMessageStatus: DirectMessageStatusEventPayload; } export interface DirectMessageMutationPeerEvent extends ChatEventBase { type: 'direct-message-mutation'; directMessageMutation: DirectMessageMutationEventPayload; } export interface DirectMessageTypingPeerEvent extends ChatEventBase { type: 'direct-message-typing'; directMessageTyping: DirectMessageTypingEventPayload; } export interface DirectMessageSyncRequestPeerEvent extends ChatEventBase { type: 'direct-message-sync-request'; directMessageSyncRequest: DirectMessageSyncRequestEventPayload; } export interface DirectMessageSyncPeerEvent extends ChatEventBase { type: 'direct-message-sync'; directMessageSync: DirectMessageSyncEventPayload; } export interface DirectCallPeerEvent extends ChatEventBase { type: 'direct-call'; directCall: DirectCallEventPayload; } export interface PluginMessageBusPeerEvent extends ChatEventBase { type: 'plugin-message-bus'; pluginMessage: unknown; } export interface CustomEmojiSummaryEvent extends ChatEventBase { type: 'custom-emoji-summary'; customEmojiSummaries: CustomEmojiSummaryItem[]; } export interface CustomEmojiRequestEvent extends ChatEventBase { type: 'custom-emoji-request'; ids: string[]; } export interface CustomEmojiFullEvent extends ChatEventBase { type: 'custom-emoji-full'; customEmoji?: CustomEmoji; customEmojiTransfer?: CustomEmojiTransferManifest; total?: number; } export interface CustomEmojiChunkEvent extends ChatEventBase { type: 'custom-emoji-chunk'; customEmojiId: string; index: number; total: number; data: string; } /** Discriminated union of all P2P chat events. Narrow via `event.type`. */ export type ChatEvent = | ChatMessageEvent | MessageEditedEvent | MessageDeletedEvent | MessageRevisionEvent | ReactionAddedEvent | ReactionRemovedEvent | FileAnnounceChatEvent | FileChunkChatEvent | FileRequestChatEvent | FileCancelChatEvent | FileNotFoundChatEvent | ChatInventoryRequestEvent | ChatInventoryEvent | ChatSyncRequestIdsEvent | ChatSyncBatchEvent | ChatSyncSummaryEvent | ChatSyncRequestEvent | ChatSyncFullEvent | RoomDeletedEvent | RoomSettingsUpdateEvent | RoomPermissionsUpdateEvent | HostChangeEvent | VoiceStateEvent | VoiceChannelMoveEvent | ScreenStateEvent | CameraStateEvent | GameActivityEvent | VoiceStateRequestEvent | StateRequestEvent | ScreenShareRequestEvent | ScreenShareStopEvent | UserAvatarSummaryEvent | UserAvatarRequestEvent | UserAvatarFullEvent | UserAvatarChunkEvent | ServerIconSummaryEvent | ServerIconRequestEvent | ServerIconFullEvent | ServerIconUpdateEvent | ServerStateRequestEvent | ServerStateFullEvent | MemberRosterRequestEvent | MemberRosterEvent | MemberLeaveEvent | RoleChangeEvent | KickEvent | BanEvent | UnbanEvent | ChannelsUpdateEvent | DirectMessagePeerEvent | DirectMessageStatusPeerEvent | DirectMessageMutationPeerEvent | DirectMessageTypingPeerEvent | DirectMessageSyncRequestPeerEvent | DirectMessageSyncPeerEvent | DirectCallPeerEvent | PluginMessageBusPeerEvent | CustomEmojiSummaryEvent | CustomEmojiRequestEvent | CustomEmojiFullEvent | CustomEmojiChunkEvent; /** All possible `type` values, derived from the union. */ export type ChatEventType = ChatEvent['type'];