/*
Spacebar: A FOSS re-implementation and extension of the Discord.com backend.
Copyright (C) 2023 Spacebar and Spacebar Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
import {
RelationshipType,
ConnectedAccount,
Interaction,
ApplicationCommand,
VoiceState,
Message,
PartialEmoji,
Invite,
Role,
Emoji,
PublicMember,
Guild,
Channel,
PublicUser,
User,
Sticker,
Activity,
Status,
Presence,
UserSettings,
IReadyGuildDTO,
ReadState,
UserPrivate,
ReadyUserGuildSettingsEntries,
ReadyPrivateChannel,
} from "@spacebar/util";
export interface Event {
guild_id?: string;
user_id?: string;
channel_id?: string;
created_at?: Date;
event: EVENT;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data?: any;
}
// ! Custom Events that shouldn't get sent to the client but processed by the server
export interface InvalidatedEvent extends Event {
event: "INVALIDATED";
}
export interface PublicRelationship {
id: string;
user: PublicUser;
type: RelationshipType;
}
// ! END Custom Events that shouldn't get sent to the client but processed by the server
export interface ReadyEventData {
v: number;
user: UserPrivate;
private_channels: ReadyPrivateChannel[]; // this will be empty for bots
session_id: string; // resuming
guilds: IReadyGuildDTO[];
analytics_token?: string;
connected_accounts?: ConnectedAccount[];
consents?: {
personalization?: {
consented?: boolean;
};
};
country_code?: string; // e.g. DE
friend_suggestion_count?: number;
geo_ordered_rtc_regions?: string[]; // ["europe","russie","india","us-east","us-central"]
experiments?: [number, number, number, number, number][];
guild_experiments?: [
// ? what are guild_experiments?
// this is the structure of it:
number,
null,
number,
[[number, { e: number; s: number }[]]],
[number, [[number, [number, number]]]],
{ b: number; k: bigint[] }[],
][];
guild_join_requests?: unknown[]; // ? what is this? this is new
shard?: [number, number];
user_settings?: UserSettings;
relationships?: PublicRelationship[]; // TODO
read_state: {
entries: ReadState[]; // TODO
partial: boolean;
version: number;
};
user_guild_settings?: {
entries: ReadyUserGuildSettingsEntries[];
version: number;
partial: boolean;
};
application?: {
id: string;
flags: number;
};
merged_members?: PublicMember[][];
// probably all users who the user is in contact with
users?: PublicUser[];
sessions: unknown[];
api_code_version: number;
tutorial: number | null;
resume_gateway_url: string;
session_type: string;
auth_session_id_hash: string;
required_action?:
| "REQUIRE_VERIFIED_EMAIL"
| "REQUIRE_VERIFIED_PHONE"
| "REQUIRE_CAPTCHA" // TODO: allow these to be triggered
| "TOS_UPDATE_ACKNOWLEDGMENT"
| "AGREEMENTS";
}
export interface ReadyEvent extends Event {
event: "READY";
data: ReadyEventData;
}
export interface ChannelCreateEvent extends Event {
event: "CHANNEL_CREATE";
data: Channel;
}
export interface ChannelUpdateEvent extends Event {
event: "CHANNEL_UPDATE";
data: Channel;
}
export interface ChannelDeleteEvent extends Event {
event: "CHANNEL_DELETE";
data: Channel;
}
export interface ChannelPinsUpdateEvent extends Event {
event: "CHANNEL_PINS_UPDATE";
data: {
guild_id?: string;
channel_id: string;
last_pin_timestamp?: number;
};
}
export interface ChannelRecipientAddEvent extends Event {
event: "CHANNEL_RECIPIENT_ADD";
data: {
channel_id: string;
user: User;
};
}
export interface ChannelRecipientRemoveEvent extends Event {
event: "CHANNEL_RECIPIENT_REMOVE";
data: {
channel_id: string;
user: User;
};
}
export interface GuildCreateEvent extends Event {
event: "GUILD_CREATE";
data: IReadyGuildDTO & {
joined_at: Date;
// TODO: add them to guild
guild_scheduled_events: never[];
guild_hashes: unknown;
presences: never[];
stage_instances: never[];
threads: never[];
embedded_activities: never[];
};
}
export interface GuildUpdateEvent extends Event {
event: "GUILD_UPDATE";
data: Guild;
}
export interface GuildDeleteEvent extends Event {
event: "GUILD_DELETE";
data: {
id: string;
unavailable?: boolean;
};
}
export interface GuildBanAddEvent extends Event {
event: "GUILD_BAN_ADD";
data: {
guild_id: string;
user: User;
};
}
export interface GuildBanRemoveEvent extends Event {
event: "GUILD_BAN_REMOVE";
data: {
guild_id: string;
user: User;
};
}
export interface GuildEmojisUpdateEvent extends Event {
event: "GUILD_EMOJIS_UPDATE";
data: {
guild_id: string;
emojis: Emoji[];
};
}
export interface GuildStickersUpdateEvent extends Event {
event: "GUILD_STICKERS_UPDATE";
data: {
guild_id: string;
stickers: Sticker[];
};
}
export interface GuildIntegrationUpdateEvent extends Event {
event: "GUILD_INTEGRATIONS_UPDATE";
data: {
guild_id: string;
};
}
export interface GuildMemberAddEvent extends Event {
event: "GUILD_MEMBER_ADD";
data: PublicMember & {
guild_id: string;
};
}
export interface GuildMemberRemoveEvent extends Event {
event: "GUILD_MEMBER_REMOVE";
data: {
guild_id: string;
user: User;
};
}
export interface GuildMemberUpdateEvent extends Event {
event: "GUILD_MEMBER_UPDATE";
data: {
guild_id: string;
roles: string[];
user: User;
nick?: string;
joined_at?: Date;
premium_since?: number;
pending?: boolean;
};
}
export interface GuildMembersChunkEvent extends Event {
event: "GUILD_MEMBERS_CHUNK";
data: {
guild_id: string;
members: PublicMember[];
chunk_index: number;
chunk_count: number;
not_found: string[];
presences: Presence[];
nonce?: string;
};
}
export interface GuildRoleCreateEvent extends Event {
event: "GUILD_ROLE_CREATE";
data: {
guild_id: string;
role: Role;
};
}
export interface GuildRoleUpdateEvent extends Event {
event: "GUILD_ROLE_UPDATE";
data: {
guild_id: string;
role: Role;
};
}
export interface GuildRoleDeleteEvent extends Event {
event: "GUILD_ROLE_DELETE";
data: {
guild_id: string;
role_id: string;
};
}
export interface InviteCreateEvent extends Event {
event: "INVITE_CREATE";
data: Omit & {
channel_id: string;
guild_id?: string;
};
}
export interface InviteDeleteEvent extends Event {
event: "INVITE_DELETE";
data: {
channel_id: string;
guild_id?: string;
code: string;
};
}
export interface MessageCreateEvent extends Event {
event: "MESSAGE_CREATE";
data: Message;
}
export interface MessageUpdateEvent extends Event {
event: "MESSAGE_UPDATE";
data: Message;
}
export interface MessageDeleteEvent extends Event {
event: "MESSAGE_DELETE";
data: {
id: string;
channel_id: string;
guild_id?: string;
};
}
export interface MessageDeleteBulkEvent extends Event {
event: "MESSAGE_DELETE_BULK";
data: {
ids: string[];
channel_id: string;
guild_id?: string;
};
}
export interface MessageReactionAddEvent extends Event {
event: "MESSAGE_REACTION_ADD";
data: {
user_id: string;
channel_id: string;
message_id: string;
guild_id?: string;
member?: PublicMember;
emoji: PartialEmoji;
};
}
export interface MessageReactionRemoveEvent extends Event {
event: "MESSAGE_REACTION_REMOVE";
data: {
user_id: string;
channel_id: string;
message_id: string;
guild_id?: string;
emoji: PartialEmoji;
};
}
export interface MessageReactionRemoveAllEvent extends Event {
event: "MESSAGE_REACTION_REMOVE_ALL";
data: {
channel_id: string;
message_id: string;
guild_id?: string;
};
}
export interface MessageReactionRemoveEmojiEvent extends Event {
event: "MESSAGE_REACTION_REMOVE_EMOJI";
data: {
channel_id: string;
message_id: string;
guild_id?: string;
emoji: PartialEmoji;
};
}
export interface PresenceUpdateEvent extends Event {
event: "PRESENCE_UPDATE";
data: Presence;
}
export interface TypingStartEvent extends Event {
event: "TYPING_START";
data: {
channel_id: string;
user_id: string;
timestamp: number;
guild_id?: string;
member?: PublicMember;
};
}
export interface UserUpdateEvent extends Event {
event: "USER_UPDATE";
data: Omit;
}
export interface UserDeleteEvent extends Event {
event: "USER_DELETE";
data: {
user_id: string;
};
}
export interface VoiceStateUpdateEvent extends Event {
event: "VOICE_STATE_UPDATE";
data: VoiceState & {
member: PublicMember;
};
}
export interface VoiceServerUpdateEvent extends Event {
event: "VOICE_SERVER_UPDATE";
data: {
token: string;
guild_id: string;
endpoint: string;
};
}
export interface WebhooksUpdateEvent extends Event {
event: "WEBHOOKS_UPDATE";
data: {
guild_id: string;
channel_id: string;
};
}
export type ApplicationCommandPayload = ApplicationCommand & {
guild_id: string;
};
export interface ApplicationCommandCreateEvent extends Event {
event: "APPLICATION_COMMAND_CREATE";
data: ApplicationCommandPayload;
}
export interface ApplicationCommandUpdateEvent extends Event {
event: "APPLICATION_COMMAND_UPDATE";
data: ApplicationCommandPayload;
}
export interface ApplicationCommandDeleteEvent extends Event {
event: "APPLICATION_COMMAND_DELETE";
data: ApplicationCommandPayload;
}
export interface InteractionCreateEvent extends Event {
event: "INTERACTION_CREATE";
data: Interaction;
}
export interface MessageAckEvent extends Event {
event: "MESSAGE_ACK";
data: {
channel_id: string;
message_id: string;
version?: number;
manual?: boolean;
mention_count?: number;
};
}
export interface RelationshipAddEvent extends Event {
event: "RELATIONSHIP_ADD";
data: PublicRelationship & {
should_notify?: boolean;
user: PublicUser;
};
}
export interface RelationshipRemoveEvent extends Event {
event: "RELATIONSHIP_REMOVE";
data: Omit;
}
export interface SessionsReplace extends Event {
event: "SESSIONS_REPLACE";
data: {
activities: Activity[];
client_info: {
version: number;
os: string;
client: string;
};
status: Status;
}[];
}
export interface GuildMemberListUpdate extends Event {
event: "GUILD_MEMBER_LIST_UPDATE";
data: {
groups: { id: string; count: number }[];
guild_id: string;
id: string;
member_count: number;
online_count: number;
ops: {
index: number;
item: {
member?: PublicMember & { presence: Presence };
group?: { id: string; count: number }[];
};
}[];
};
}
export type EventData =
| InvalidatedEvent
| ReadyEvent
| ChannelCreateEvent
| ChannelUpdateEvent
| ChannelDeleteEvent
| ChannelPinsUpdateEvent
| ChannelRecipientAddEvent
| ChannelRecipientRemoveEvent
| GuildCreateEvent
| GuildUpdateEvent
| GuildDeleteEvent
| GuildBanAddEvent
| GuildBanRemoveEvent
| GuildEmojisUpdateEvent
| GuildIntegrationUpdateEvent
| GuildMemberAddEvent
| GuildMemberRemoveEvent
| GuildMemberUpdateEvent
| GuildMembersChunkEvent
| GuildMemberListUpdate
| GuildRoleCreateEvent
| GuildRoleUpdateEvent
| GuildRoleDeleteEvent
| InviteCreateEvent
| InviteDeleteEvent
| MessageCreateEvent
| MessageUpdateEvent
| MessageDeleteEvent
| MessageDeleteBulkEvent
| MessageReactionAddEvent
| MessageReactionRemoveEvent
| MessageReactionRemoveAllEvent
| MessageReactionRemoveEmojiEvent
| PresenceUpdateEvent
| TypingStartEvent
| UserUpdateEvent
| UserDeleteEvent
| VoiceStateUpdateEvent
| VoiceServerUpdateEvent
| WebhooksUpdateEvent
| ApplicationCommandCreateEvent
| ApplicationCommandUpdateEvent
| ApplicationCommandDeleteEvent
| InteractionCreateEvent
| MessageAckEvent
| RelationshipAddEvent
| RelationshipRemoveEvent;
// located in collection events
export enum EVENTEnum {
Ready = "READY",
ChannelCreate = "CHANNEL_CREATE",
ChannelUpdate = "CHANNEL_UPDATE",
ChannelDelete = "CHANNEL_DELETE",
ChannelPinsUpdate = "CHANNEL_PINS_UPDATE",
ChannelRecipientAdd = "CHANNEL_RECIPIENT_ADD",
ChannelRecipientRemove = "CHANNEL_RECIPIENT_REMOVE",
GuildCreate = "GUILD_CREATE",
GuildUpdate = "GUILD_UPDATE",
GuildDelete = "GUILD_DELETE",
GuildBanAdd = "GUILD_BAN_ADD",
GuildBanRemove = "GUILD_BAN_REMOVE",
GuildEmojUpdate = "GUILD_EMOJI_UPDATE",
GuildIntegrationsUpdate = "GUILD_INTEGRATIONS_UPDATE",
GuildMemberAdd = "GUILD_MEMBER_ADD",
GuildMemberRempve = "GUILD_MEMBER_REMOVE",
GuildMemberUpdate = "GUILD_MEMBER_UPDATE",
GuildMemberSpeaking = "GUILD_MEMBER_SPEAKING",
GuildMembersChunk = "GUILD_MEMBERS_CHUNK",
GuildMemberListUpdate = "GUILD_MEMBER_LIST_UPDATE",
GuildRoleCreate = "GUILD_ROLE_CREATE",
GuildRoleDelete = "GUILD_ROLE_DELETE",
GuildRoleUpdate = "GUILD_ROLE_UPDATE",
InviteCreate = "INVITE_CREATE",
InviteDelete = "INVITE_DELETE",
MessageCreate = "MESSAGE_CREATE",
MessageUpdate = "MESSAGE_UPDATE",
MessageDelete = "MESSAGE_DELETE",
MessageDeleteBulk = "MESSAGE_DELETE_BULK",
MessageReactionAdd = "MESSAGE_REACTION_ADD",
MessageReactionRemove = "MESSAGE_REACTION_REMOVE",
MessageReactionRemoveAll = "MESSAGE_REACTION_REMOVE_ALL",
MessageReactionRemoveEmoji = "MESSAGE_REACTION_REMOVE_EMOJI",
PresenceUpdate = "PRESENCE_UPDATE",
TypingStart = "TYPING_START",
UserUpdate = "USER_UPDATE",
UserDelete = "USER_DELETE",
WebhooksUpdate = "WEBHOOKS_UPDATE",
InteractionCreate = "INTERACTION_CREATE",
VoiceStateUpdate = "VOICE_STATE_UPDATE",
VoiceServerUpdate = "VOICE_SERVER_UPDATE",
ApplicationCommandCreate = "APPLICATION_COMMAND_CREATE",
ApplicationCommandUpdate = "APPLICATION_COMMAND_UPDATE",
ApplicationCommandDelete = "APPLICATION_COMMAND_DELETE",
SessionsReplace = "SESSIONS_REPLACE",
}
export type EVENT =
| "READY"
| "CHANNEL_CREATE"
| "CHANNEL_UPDATE"
| "CHANNEL_DELETE"
| "CHANNEL_PINS_UPDATE"
| "CHANNEL_RECIPIENT_ADD"
| "CHANNEL_RECIPIENT_REMOVE"
| "GUILD_CREATE"
| "GUILD_UPDATE"
| "GUILD_DELETE"
| "GUILD_BAN_ADD"
| "GUILD_BAN_REMOVE"
| "GUILD_EMOJIS_UPDATE"
| "GUILD_STICKERS_UPDATE"
| "GUILD_INTEGRATIONS_UPDATE"
| "GUILD_MEMBER_ADD"
| "GUILD_MEMBER_REMOVE"
| "GUILD_MEMBER_UPDATE"
| "GUILD_MEMBER_SPEAKING"
| "GUILD_MEMBERS_CHUNK"
| "GUILD_MEMBER_LIST_UPDATE"
| "GUILD_ROLE_CREATE"
| "GUILD_ROLE_DELETE"
| "GUILD_ROLE_UPDATE"
| "INVITE_CREATE"
| "INVITE_DELETE"
| "MESSAGE_CREATE"
| "MESSAGE_UPDATE"
| "MESSAGE_DELETE"
| "MESSAGE_DELETE_BULK"
| "MESSAGE_REACTION_ADD"
// TODO: add a new event: bulk add reaction:
// | "MESSAGE_REACTION_BULK_ADD"
| "MESSAGE_REACTION_REMOVE"
| "MESSAGE_REACTION_REMOVE_ALL"
| "MESSAGE_REACTION_REMOVE_EMOJI"
| "PRESENCE_UPDATE"
| "TYPING_START"
| "USER_UPDATE"
| "USER_DELETE"
| "USER_NOTE_UPDATE"
| "WEBHOOKS_UPDATE"
| "INTERACTION_CREATE"
| "VOICE_STATE_UPDATE"
| "VOICE_SERVER_UPDATE"
| "APPLICATION_COMMAND_CREATE"
| "APPLICATION_COMMAND_UPDATE"
| "APPLICATION_COMMAND_DELETE"
| "MESSAGE_ACK"
| "RELATIONSHIP_ADD"
| "RELATIONSHIP_REMOVE"
| "SESSIONS_REPLACE"
| CUSTOMEVENTS;
export type CUSTOMEVENTS = "INVALIDATED" | "RATELIMIT";