From be1ad9bd84d2cd96b157d347200aee5bd69495a7 Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Wed, 20 Oct 2021 00:08:37 +0000 Subject: [PATCH] guild handlers --- src/bot.ts | 288 ++++++++++++++++-- .../commands/APPLICATION_COMMAND_CREATE.ts | 7 - .../commands/APPLICATION_COMMAND_DELETE.ts | 7 - .../commands/APPLICATION_COMMAND_UPDATE.ts | 7 - src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts | 17 +- src/handlers/guilds/GUILD_BAN_ADD.ts | 18 +- src/handlers/guilds/GUILD_BAN_REMOVE.ts | 18 +- src/handlers/guilds/GUILD_CREATE.ts | 38 +-- src/handlers/guilds/GUILD_DELETE.ts | 33 +- .../guilds/GUILD_INTEGRATIONS_UPDATE.ts | 14 +- src/handlers/guilds/GUILD_LOADED_DD.ts | 17 ++ src/handlers/guilds/GUILD_UPDATE.ts | 50 +-- src/handlers/mod.ts | 82 +---- src/types/discordeno/event_handlers.ts | 11 - src/types/gateway/gateway_payload.ts | 94 +++--- src/ws/handle_discord_payload.ts | 16 - src/ws/handle_on_message.ts | 47 ++- src/ws/mod.ts | 1 - 18 files changed, 423 insertions(+), 342 deletions(-) delete mode 100644 src/handlers/commands/APPLICATION_COMMAND_CREATE.ts delete mode 100644 src/handlers/commands/APPLICATION_COMMAND_DELETE.ts delete mode 100644 src/handlers/commands/APPLICATION_COMMAND_UPDATE.ts create mode 100644 src/handlers/guilds/GUILD_LOADED_DD.ts delete mode 100644 src/ws/handle_discord_payload.ts diff --git a/src/bot.ts b/src/bot.ts index df02ca02e..9b5140c25 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -45,7 +45,6 @@ import { identify } from "./ws/identify.ts"; import { heartbeat } from "./ws/heartbeat.ts"; import { resharder } from "./ws/resharder.ts"; import { tellClusterToIdentify } from "./ws/tell_cluster_to_identify.ts"; -import { handleDiscordPayload } from "./ws/handle_discord_payload.ts"; import { log } from "./ws/events.ts"; import { handleOnMessage } from "./ws/handle_on_message.ts"; import { closeWS } from "./ws/close_ws.ts"; @@ -62,12 +61,64 @@ import { SLASH_COMMANDS_NAME_REGEX, USER_AGENT, } from "./util/constants.ts"; -import { GatewayPayload } from "./types/gateway/gateway_payload.ts"; +import { GatewayDispatchEventNames, GatewayEventNames, GatewayPayload } from "./types/gateway/gateway_payload.ts"; import { delay, validateSlashOptionChoices, validateSlashOptions } from "./util/utils.ts"; import { iconBigintToHash, iconHashToBigInt } from "./util/hash.ts"; import { validateLength } from "./util/validate_length.ts"; import { processGlobalQueue } from "./rest/process_global_queue.ts"; import { ChannelPinsUpdate } from "./types/channels/channel_pins_update.ts"; +import { ApplicationCommandTypes, Emoji } from "./types/mod.ts"; +import { ApplicationCommandOption } from "./types/mod.ts"; +import { handleGuildLoaded } from "./handlers/guilds/GUILD_LOADED_DD.ts"; +import { + handleReady, + handleChannelCreate, + handleChannelDelete, + handleChannelPinsUpdate, + handleChannelUpdate, + handleThreadCreate, + handleThreadUpdate, + handleThreadDelete, + handleThreadListSync, + handleThreadMemberUpdate, + handleThreadMembersUpdate, + handleStageInstanceCreate, + handleStageInstanceUpdate, + handleStageInstanceDelete, + handleGuildBanAdd, + handleGuildBanRemove, + handleGuildCreate, + handleGuildDelete, + handleGuildEmojisUpdate, + handleGuildIntegrationsUpdate, + handleGuildMemberAdd, + handleGuildMemberRemove, + handleGuildMemberUpdate, + handleGuildMembersChunk, + handleGuildRoleCreate, + handleGuildRoleDelete, + handleGuildRoleUpdate, + handleGuildUpdate, + handleInteractionCreate, + handleInviteCreate, + handleMessageCreate, + handleMessageDeleteBulk, + handleMessageDelete, + handleMessageReactionAdd, + handleMessageReactionRemoveAll, + handleMessageReactionRemoveEmoji, + handleMessageReactionRemove, + handleMessageUpdate, + handlePresenceUpdate, + handleTypingStart, + handleUserUpdate, + handleVoiceServerUpdate, + handleVoiceStateUpdate, + handleWebhooksUpdate, + handleIntegrationCreate, + handleIntegrationUpdate, + handleIntegrationDelete, +} from "./handlers/mod.ts"; export async function createBot(options: CreateBotOptions) { return { @@ -80,7 +131,12 @@ export async function createBot(options: CreateBotOptions) { isReady: false, activeGuildIds: new Set(), constants: createBotConstants(), + handlers: createBotGatewayHandlers({}), cache: { + forEach: function ( + type: "DELETE_MESSAGES_FROM_GUILD" | "DELETE_CHANNELS_FROM_GUILD" | "DELETE_GUILD_FROM_MEMBER", + options: Record + ) {}, guilds: { get: async function (id: bigint): Promise { return {} as any as DiscordenoGuild; @@ -91,6 +147,9 @@ export async function createBot(options: CreateBotOptions) { set: async function (id: bigint, guild: DiscordenoGuild): Promise { return; }, + delete: async function (id: bigint): Promise { + return; + }, }, channels: { get: async function (id: bigint): Promise { @@ -116,6 +175,9 @@ export async function createBot(options: CreateBotOptions) { set: async function (id: bigint, member: DiscordenoMember): Promise { return; }, + delete: async function (id: bigint): Promise { + return; + }, }, users: { get: async function (id: bigint): Promise { @@ -172,6 +234,15 @@ export function createEventHandlers(events: Partial): EventHandle channelDelete: events.channelDelete ?? ignore, channelPinsUpdate: events.channelPinsUpdate ?? ignore, channelUpdate: events.channelUpdate ?? ignore, + guildEmojisUpdate: events.guildEmojisUpdate ?? ignore, + guildBanAdd: events.guildBanAdd ?? ignore, + guildBanRemove: events.guildBanRemove ?? ignore, + guildLoaded: events.guildLoaded ?? ignore, + guildCreate: events.guildCreate ?? ignore, + guildDelete: events.guildDelete ?? ignore, + guildUpdate: events.guildUpdate ?? ignore, + integrationsUpdate: events.integrationsUpdate ?? ignore, + raw: events.raw ?? ignore, stageInstanceCreate: events.stageInstanceCreate ?? ignore, stageInstanceDelete: events.stageInstanceDelete ?? ignore, stageInstanceUpdate: events.stageInstanceUpdate ?? ignore, @@ -303,6 +374,10 @@ export interface HelperUtils { export function createGatewayManager(options: Partial): GatewayManager { return { + cache: { + guildIds: new Set(), + loadingGuildIds: new Set(), + }, secretKey: options.secretKey ?? "", url: options.url ?? "", reshard: options.reshard ?? true, @@ -337,7 +412,6 @@ export function createGatewayManager(options: Partial): GatewayM createShard, identify, heartbeat, - handleDiscordPayload, tellClusterToIdentify, log, resharder, @@ -346,6 +420,18 @@ export function createGatewayManager(options: Partial): GatewayM closeWS, sendShardMessage, resume, + handleDiscordPayload: + options.handleDiscordPayload || + async function (_, data: GatewayPayload, shardId: number) { + // TRIGGER RAW EVENT + bot.events.raw(bot as Bot, data, shardId); + + if (!data.t) return; + + // RUN DISPATCH CHECK + await bot.events.dispatchRequirements(bot as Bot, data, shardId); + bot.handlers[data.t as GatewayDispatchEventNames]?.(bot, data, shardId); + }, }; } @@ -466,6 +552,11 @@ export interface GatewayManager { >; utf8decoder: TextDecoder; + cache: { + guildIds: Set; + loadingGuildIds: Set; + }; + // METHODS /** The handler function that starts the gateway. */ @@ -479,7 +570,7 @@ export interface GatewayManager { /** Begins heartbeating of the shard to keep it alive. */ heartbeat: typeof heartbeat; /** Sends the discord payload to another server. */ - handleDiscordPayload: typeof handleDiscordPayload; + handleDiscordPayload: (gateway: GatewayManager, data: GatewayPayload, shardId: number) => any; /** Tell the cluster/worker to begin identifying this shard */ tellClusterToIdentify: typeof tellClusterToIdentify; /** Handle the different logs. Used for debugging. */ @@ -506,30 +597,54 @@ export interface EventHandlers { channelDelete: (bot: Bot, channel: DiscordenoChannel) => any; channelPinsUpdate: (bot: Bot, data: { guildId?: bigint; channelId: bigint; lastPinTimestamp?: number }) => any; channelUpdate: (bot: Bot, channel: DiscordenoChannel, oldChannel: DiscordenoChannel) => any; - stageInstanceCreate: (bot: Bot, data: { - id: bigint; - guildId: bigint; - channelId: bigint; - topic: string; - privacyLevel: number; - discoverableDisabled: boolean; - }) => any; - stageInstanceDelete: (bot: Bot, data: { - id: bigint; - guildId: bigint; - channelId: bigint; - topic: string; - privacyLevel: number; - discoverableDisabled: boolean; - }) => any; - stageInstanceUpdate: (bot: Bot, data: { - id: bigint; - guildId: bigint; - channelId: bigint; - topic: string; - privacyLevel: number; - discoverableDisabled: boolean; - }) => any; + stageInstanceCreate: ( + bot: Bot, + data: { + id: bigint; + guildId: bigint; + channelId: bigint; + topic: string; + privacyLevel: number; + discoverableDisabled: boolean; + } + ) => any; + stageInstanceDelete: ( + bot: Bot, + data: { + id: bigint; + guildId: bigint; + channelId: bigint; + topic: string; + privacyLevel: number; + discoverableDisabled: boolean; + } + ) => any; + stageInstanceUpdate: ( + bot: Bot, + data: { + id: bigint; + guildId: bigint; + channelId: bigint; + topic: string; + privacyLevel: number; + discoverableDisabled: boolean; + } + ) => any; + // TODO: THREADS + guildEmojisUpdate: ( + bot: Bot, + guild: DiscordenoGuild, + emojis: Collection, + cachedEmojis: Collection + ) => any; + guildBanAdd: (bot: Bot, user: DiscordenoUser, guildId: bigint) => any; + guildBanRemove: (bot: Bot, user: DiscordenoUser, guildId: bigint) => any; + guildLoaded: (bot: Bot, guild: DiscordenoGuild) => any; + guildCreate: (bot: Bot, guild: DiscordenoGuild) => any; + guildDelete: (bot: Bot, id: bigint, guild?: DiscordenoGuild) => any; + guildUpdate: (bot: Bot, guild: DiscordenoGuild, cachedGuild?: DiscordenoGuild) => any; + integrationsUpdate: (bot: Bot, data: { guildId: bigint }) => any; + raw: (bot: Bot, data: GatewayPayload, shardId: number) => any; } export function createBotConstants() { @@ -547,3 +662,120 @@ export function createBotConstants() { }, }; } + +export interface BotGatewayHandlerOptions { + READY: typeof handleReady; + CHANNEL_CREATE: typeof handleChannelCreate; + CHANNEL_DELETE: typeof handleChannelDelete; + CHANNEL_PINS_UPDATE: typeof handleChannelPinsUpdate; + CHANNEL_UPDATE: typeof handleChannelUpdate; + THREAD_CREATE: typeof handleThreadCreate; + THREAD_UPDATE: typeof handleThreadUpdate; + THREAD_DELETE: typeof handleThreadDelete; + THREAD_LIST_SYNC: typeof handleThreadListSync; + THREAD_MEMBER_UPDATE: typeof handleThreadMemberUpdate; + THREAD_MEMBERS_UPDATE: typeof handleThreadMembersUpdate; + STAGE_INSTANCE_CREATE: typeof handleStageInstanceCreate; + STAGE_INSTANCE_UPDATE: typeof handleStageInstanceUpdate; + STAGE_INSTANCE_DELETE: typeof handleStageInstanceDelete; + GUILD_BAN_ADD: typeof handleGuildBanAdd; + GUILD_BAN_REMOVE: typeof handleGuildBanRemove; + GUILD_CREATE: typeof handleGuildCreate; + GUILD_LOADED_DD: typeof handleGuildLoaded; + GUILD_DELETE: typeof handleGuildDelete; + GUILD_EMOJIS_UPDATE: typeof handleGuildEmojisUpdate; + GUILD_INTEGRATIONS_UPDATE: typeof handleGuildIntegrationsUpdate; + GUILD_MEMBER_ADD: typeof handleGuildMemberAdd; + GUILD_MEMBER_REMOVE: typeof handleGuildMemberRemove; + GUILD_MEMBER_UPDATE: typeof handleGuildMemberUpdate; + GUILD_MEMBERS_CHUNK: typeof handleGuildMembersChunk; + GUILD_ROLE_CREATE: typeof handleGuildRoleCreate; + GUILD_ROLE_DELETE: typeof handleGuildRoleDelete; + GUILD_ROLE_UPDATE: typeof handleGuildRoleUpdate; + GUILD_UPDATE: typeof handleGuildUpdate; + INTERACTION_CREATE: typeof handleInteractionCreate; + INVITE_CREATE: typeof handleInviteCreate; + INVITE_DELETE: typeof handleInviteCreate; + MESSAGE_CREATE: typeof handleMessageCreate; + MESSAGE_DELETE_BULK: typeof handleMessageDeleteBulk; + MESSAGE_DELETE: typeof handleMessageDelete; + MESSAGE_REACTION_ADD: typeof handleMessageReactionAdd; + MESSAGE_REACTION_REMOVE_ALL: typeof handleMessageReactionRemoveAll; + MESSAGE_REACTION_REMOVE_EMOJI: typeof handleMessageReactionRemoveEmoji; + MESSAGE_REACTION_REMOVE: typeof handleMessageReactionRemove; + MESSAGE_UPDATE: typeof handleMessageUpdate; + PRESENCE_UPDATE: typeof handlePresenceUpdate; + TYPING_START: typeof handleTypingStart; + USER_UPDATE: typeof handleUserUpdate; + VOICE_SERVER_UPDATE: typeof handleVoiceServerUpdate; + VOICE_STATE_UPDATE: typeof handleVoiceStateUpdate; + WEBHOOKS_UPDATE: typeof handleWebhooksUpdate; + INTEGRATION_CREATE: typeof handleIntegrationCreate; + INTEGRATION_UPDATE: typeof handleIntegrationUpdate; + INTEGRATION_DELETE: typeof handleIntegrationDelete; +} + +export function createBotGatewayHandlers(options: Partial) { + return { + // misc + READY: options.READY ?? handleReady, + // channels + CHANNEL_CREATE: options.CHANNEL_CREATE ?? handleChannelCreate, + CHANNEL_DELETE: options.CHANNEL_DELETE ?? handleChannelDelete, + CHANNEL_PINS_UPDATE: options.CHANNEL_PINS_UPDATE ?? handleChannelPinsUpdate, + CHANNEL_UPDATE: options.CHANNEL_UPDATE ?? handleChannelUpdate, + THREAD_CREATE: options.THREAD_CREATE ?? handleThreadCreate, + THREAD_UPDATE: options.THREAD_UPDATE ?? handleThreadUpdate, + THREAD_DELETE: options.THREAD_DELETE ?? handleThreadDelete, + THREAD_LIST_SYNC: options.THREAD_LIST_SYNC ?? handleThreadListSync, + THREAD_MEMBER_UPDATE: options.THREAD_MEMBER_UPDATE ?? handleThreadMemberUpdate, + THREAD_MEMBERS_UPDATE: options.THREAD_MEMBERS_UPDATE ?? handleThreadMembersUpdate, + STAGE_INSTANCE_CREATE: options.STAGE_INSTANCE_CREATE ?? handleStageInstanceCreate, + STAGE_INSTANCE_UPDATE: options.STAGE_INSTANCE_UPDATE ?? handleStageInstanceUpdate, + STAGE_INSTANCE_DELETE: options.STAGE_INSTANCE_DELETE ?? handleStageInstanceDelete, + + // guilds + GUILD_BAN_ADD: options.GUILD_BAN_ADD ?? handleGuildBanAdd, + GUILD_BAN_REMOVE: options.GUILD_BAN_REMOVE ?? handleGuildBanRemove, + GUILD_CREATE: options.GUILD_CREATE ?? handleGuildCreate, + GUILD_LOADED_DD: options.GUILD_LOADED_DD ?? handleGuildLoaded, + GUILD_DELETE: options.GUILD_DELETE ?? handleGuildDelete, + GUILD_EMOJIS_UPDATE: options.GUILD_EMOJIS_UPDATE ?? handleGuildEmojisUpdate, + GUILD_INTEGRATIONS_UPDATE: options.GUILD_INTEGRATIONS_UPDATE ?? handleGuildIntegrationsUpdate, + GUILD_MEMBER_ADD: options.GUILD_MEMBER_ADD ?? handleGuildMemberAdd, + GUILD_MEMBER_REMOVE: options.GUILD_MEMBER_REMOVE ?? handleGuildMemberRemove, + GUILD_MEMBER_UPDATE: options.GUILD_MEMBER_UPDATE ?? handleGuildMemberUpdate, + GUILD_MEMBERS_CHUNK: options.GUILD_MEMBERS_CHUNK ?? handleGuildMembersChunk, + GUILD_ROLE_CREATE: options.GUILD_ROLE_CREATE ?? handleGuildRoleCreate, + GUILD_ROLE_DELETE: options.GUILD_ROLE_DELETE ?? handleGuildRoleDelete, + GUILD_ROLE_UPDATE: options.GUILD_ROLE_UPDATE ?? handleGuildRoleUpdate, + GUILD_UPDATE: options.GUILD_UPDATE ?? handleGuildUpdate, + // interactions + INTERACTION_CREATE: options.INTERACTION_CREATE ?? handleInteractionCreate, + // invites + INVITE_CREATE: options.INVITE_CREATE ?? handleInviteCreate, + INVITE_DELETE: options.INVITE_DELETE ?? handleInviteCreate, + // messages + MESSAGE_CREATE: options.MESSAGE_CREATE ?? handleMessageCreate, + MESSAGE_DELETE_BULK: options.MESSAGE_DELETE_BULK ?? handleMessageDeleteBulk, + MESSAGE_DELETE: options.MESSAGE_DELETE ?? handleMessageDelete, + MESSAGE_REACTION_ADD: options.MESSAGE_REACTION_ADD ?? handleMessageReactionAdd, + MESSAGE_REACTION_REMOVE_ALL: options.MESSAGE_REACTION_REMOVE_ALL ?? handleMessageReactionRemoveAll, + MESSAGE_REACTION_REMOVE_EMOJI: options.MESSAGE_REACTION_REMOVE_EMOJI ?? handleMessageReactionRemoveEmoji, + MESSAGE_REACTION_REMOVE: options.MESSAGE_REACTION_REMOVE ?? handleMessageReactionRemove, + MESSAGE_UPDATE: options.MESSAGE_UPDATE ?? handleMessageUpdate, + // presence + PRESENCE_UPDATE: options.PRESENCE_UPDATE ?? handlePresenceUpdate, + TYPING_START: options.TYPING_START ?? handleTypingStart, + USER_UPDATE: options.USER_UPDATE ?? handleUserUpdate, + // voice + VOICE_SERVER_UPDATE: options.VOICE_SERVER_UPDATE ?? handleVoiceServerUpdate, + VOICE_STATE_UPDATE: options.VOICE_STATE_UPDATE ?? handleVoiceStateUpdate, + // webhooks + WEBHOOKS_UPDATE: options.WEBHOOKS_UPDATE ?? handleWebhooksUpdate, + // integrations + INTEGRATION_CREATE: options.INTEGRATION_CREATE ?? handleIntegrationCreate, + INTEGRATION_UPDATE: options.INTEGRATION_UPDATE ?? handleIntegrationUpdate, + INTEGRATION_DELETE: options.INTEGRATION_DELETE ?? handleIntegrationDelete, + }; +} diff --git a/src/handlers/commands/APPLICATION_COMMAND_CREATE.ts b/src/handlers/commands/APPLICATION_COMMAND_CREATE.ts deleted file mode 100644 index 06ff0d83d..000000000 --- a/src/handlers/commands/APPLICATION_COMMAND_CREATE.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { eventHandlers } from "../../bot.ts"; -import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import type { ApplicationCommandCreateUpdateDelete } from "../../types/interactions/commands/application_command_create_update_delete.ts"; - -export function handleApplicationCommandCreate(data: DiscordGatewayPayload) { - eventHandlers.applicationCommandCreate?.(data.d as ApplicationCommandCreateUpdateDelete); -} diff --git a/src/handlers/commands/APPLICATION_COMMAND_DELETE.ts b/src/handlers/commands/APPLICATION_COMMAND_DELETE.ts deleted file mode 100644 index b37ace927..000000000 --- a/src/handlers/commands/APPLICATION_COMMAND_DELETE.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { eventHandlers } from "../../bot.ts"; -import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import type { ApplicationCommandCreateUpdateDelete } from "../../types/interactions/commands/application_command_create_update_delete.ts"; - -export function handleApplicationCommandDelete(data: DiscordGatewayPayload) { - eventHandlers.applicationCommandDelete?.(data.d as ApplicationCommandCreateUpdateDelete); -} diff --git a/src/handlers/commands/APPLICATION_COMMAND_UPDATE.ts b/src/handlers/commands/APPLICATION_COMMAND_UPDATE.ts deleted file mode 100644 index 51fc2d063..000000000 --- a/src/handlers/commands/APPLICATION_COMMAND_UPDATE.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { eventHandlers } from "../../bot.ts"; -import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import type { ApplicationCommandCreateUpdateDelete } from "../../types/interactions/commands/application_command_create_update_delete.ts"; - -export function handleApplicationCommandUpdate(data: DiscordGatewayPayload) { - eventHandlers.applicationCommandUpdate?.(data.d as ApplicationCommandCreateUpdateDelete); -} diff --git a/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts b/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts index e5e27ed24..2ea8ef84e 100644 --- a/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts +++ b/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts @@ -1,19 +1,18 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot } from "../../bot.ts"; import type { GuildEmojisUpdate } from "../../types/emojis/guild_emojis_update.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; import { Collection } from "../../util/collection.ts"; -export async function handleGuildEmojisUpdate(data: DiscordGatewayPayload) { - const payload = data.d as GuildEmojisUpdate; - const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId)); +export async function handleGuildEmojisUpdate(bot: Bot, data: SnakeCasedPropertiesDeep) { + const payload = data.d as SnakeCasedPropertiesDeep; + const guild = await bot.cache.guilds.get(bot.transformers.snowflake(payload.guild_id)); if (!guild) return; const cachedEmojis = guild.emojis; - guild.emojis = new Collection(payload.emojis.map((emoji) => [snowflakeToBigint(emoji.id!), emoji])); + guild.emojis = new Collection(payload.emojis.map((emoji) => [bot.transformers.snowflake(emoji.id!), emoji])); - await cacheHandlers.set("guilds", guild.id, guild); + await bot.cache.guilds.set(guild.id, guild); - eventHandlers.guildEmojisUpdate?.(guild, guild.emojis, cachedEmojis); + bot.events.guildEmojisUpdate(bot, guild, guild.emojis, cachedEmojis); } diff --git a/src/handlers/guilds/GUILD_BAN_ADD.ts b/src/handlers/guilds/GUILD_BAN_ADD.ts index 68070fcb1..6a171f5e9 100644 --- a/src/handlers/guilds/GUILD_BAN_ADD.ts +++ b/src/handlers/guilds/GUILD_BAN_ADD.ts @@ -1,14 +1,12 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { GuildBanAddRemove } from "../../types/guilds/guild_ban_add_remove.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleGuildBanAdd(data: DiscordGatewayPayload) { - const payload = data.d as GuildBanAddRemove; - const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId)); - if (!guild) return; - - const member = await cacheHandlers.get("members", snowflakeToBigint(payload.user.id)); - eventHandlers.guildBanAdd?.(guild, payload.user, member); +export async function handleGuildBanAdd(bot: Bot, data: SnakeCasedPropertiesDeep) { + const payload = data.d as SnakeCasedPropertiesDeep; + // FIRST COMPLETE THE END USERS EVENT + await bot.events.guildBanAdd(bot, bot.transformers.user(bot, payload.user), bot.transformers.snowflake(payload.guild_id)); + // THEN DELETE THE MEMBER + await bot.cache.members.delete(bot.transformers.snowflake(payload.user.id)); } diff --git a/src/handlers/guilds/GUILD_BAN_REMOVE.ts b/src/handlers/guilds/GUILD_BAN_REMOVE.ts index 04a913b5c..cd2b41961 100644 --- a/src/handlers/guilds/GUILD_BAN_REMOVE.ts +++ b/src/handlers/guilds/GUILD_BAN_REMOVE.ts @@ -1,14 +1,14 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { GuildBanAddRemove } from "../../types/guilds/guild_ban_add_remove.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleGuildBanRemove(data: DiscordGatewayPayload) { - const payload = data.d as GuildBanAddRemove; - const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId)); - if (!guild) return; +export async function handleGuildBanRemove(bot: Bot, data: SnakeCasedPropertiesDeep) { + const payload = data.d as SnakeCasedPropertiesDeep; - const member = await cacheHandlers.get("members", snowflakeToBigint(payload.user.id)); - eventHandlers.guildBanRemove?.(guild, payload.user, member); + await bot.events.guildBanRemove( + bot, + bot.transformers.user(bot, payload.user), + bot.transformers.snowflake(payload.guild_id) + ); } diff --git a/src/handlers/guilds/GUILD_CREATE.ts b/src/handlers/guilds/GUILD_CREATE.ts index a4145e8a2..b7e7b7c0d 100644 --- a/src/handlers/guilds/GUILD_CREATE.ts +++ b/src/handlers/guilds/GUILD_CREATE.ts @@ -1,33 +1,17 @@ -import { eventHandlers } from "../../bot.ts"; -import { cache, cacheHandlers } from "../../cache.ts"; -import { structures } from "../../structures/mod.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { Guild } from "../../types/guilds/guild.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; -import { ws } from "../../ws/ws.ts"; -import { guildAvailable } from "../misc/READY.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleGuildCreate(data: DiscordGatewayPayload, shardId: number) { - const payload = data.d as Guild; - // When shards resume they emit GUILD_CREATE again. - if ( - (await cacheHandlers.has("guilds", snowflakeToBigint(payload.id))) || - cache.dispatchedGuildIds.has(snowflakeToBigint(payload.id)) - ) - return; +export async function handleGuildCreate( + bot: Bot, + data: SnakeCasedPropertiesDeep, + shardId: number +) { + const payload = data.d as SnakeCasedPropertiesDeep; - const guild = await structures.createDiscordenoGuild(payload, shardId); - await cacheHandlers.set("guilds", guild.id, guild); + const guild = bot.transformers.guild(bot, { guild: payload, shardId }); + await bot.cache.guilds.set(guild.id, guild); - const shard = ws.shards.get(shardId); - - if (shard?.unavailableGuildIds.has(guild.id)) { - await cacheHandlers.delete("unavailableGuilds", guild.id); - guildAvailable(shard, guild.id); - - return eventHandlers.guildAvailable?.(guild); - } - - if (!cache.isReady) return eventHandlers.guildLoaded?.(guild); - eventHandlers.guildCreate?.(guild); + await bot.events.guildCreate(bot, guild); } diff --git a/src/handlers/guilds/GUILD_DELETE.ts b/src/handlers/guilds/GUILD_DELETE.ts index b2d96db48..2ded20125 100644 --- a/src/handlers/guilds/GUILD_DELETE.ts +++ b/src/handlers/guilds/GUILD_DELETE.ts @@ -1,31 +1,22 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { UnavailableGuild } from "../../types/guilds/unavailable_guild.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; -import { ws } from "../../ws/ws.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleGuildDelete(data: DiscordGatewayPayload, shardId: number) { - const payload = data.d as UnavailableGuild; +export async function handleGuildDelete(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as SnakeCasedPropertiesDeep; - const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.id)); + const id = bot.transformers.snowflake(payload.id); + const guild = await bot.cache.guilds.get(id); + await bot.events.guildDelete(bot, id, guild); if (!guild) return; + + await bot.cache.guilds.delete(id); - await cacheHandlers.delete("guilds", guild.id); - - if (payload.unavailable) { - const shard = ws.shards.get(shardId); - if (shard) shard.unavailableGuildIds.add(guild.id); - await cacheHandlers.set("unavailableGuilds", guild.id, Date.now()); - - eventHandlers.guildUnavailable?.(guild); - } else { - eventHandlers.guildDelete?.(guild); - } await Promise.all([ - cacheHandlers.forEach("DELETE_MESSAGES_FROM_GUILD", { guildId: guild.id }), - cacheHandlers.forEach("DELETE_CHANNELS_FROM_GUILD", { guildId: guild.id }), - cacheHandlers.forEach("DELETE_GUILD_FROM_MEMBER", { guildId: guild.id }), + bot.cache.forEach("DELETE_MESSAGES_FROM_GUILD", { guildId: guild.id }), + bot.cache.forEach("DELETE_CHANNELS_FROM_GUILD", { guildId: guild.id }), + bot.cache.forEach("DELETE_GUILD_FROM_MEMBER", { guildId: guild.id }), ]); } diff --git a/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts b/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts index 57d6df937..827c629ed 100644 --- a/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts +++ b/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts @@ -1,14 +1,10 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { GuildIntegrationsUpdate } from "../../types/integrations/guild_integrations_update.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleGuildIntegrationsUpdate(data: DiscordGatewayPayload) { - const payload = data.d as GuildIntegrationsUpdate; +export async function handleGuildIntegrationsUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as SnakeCasedPropertiesDeep; - const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId)); - if (!guild) return; - - eventHandlers.guildIntegrationsUpdate?.(guild); + bot.events.integrationsUpdate(bot, { guildId: bot.transformers.snowflake(payload.guild_id) }); } diff --git a/src/handlers/guilds/GUILD_LOADED_DD.ts b/src/handlers/guilds/GUILD_LOADED_DD.ts new file mode 100644 index 000000000..d8a8c4562 --- /dev/null +++ b/src/handlers/guilds/GUILD_LOADED_DD.ts @@ -0,0 +1,17 @@ +import { Bot } from "../../bot.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { Guild } from "../../types/guilds/guild.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; + +export async function handleGuildLoaded( + bot: Bot, + data: SnakeCasedPropertiesDeep, + shardId: number +) { + const payload = data.d as SnakeCasedPropertiesDeep; + + const guild = bot.transformers.guild(bot, { guild: payload, shardId }); + await bot.cache.guilds.set(guild.id, guild); + + await bot.events.guildLoaded(bot, guild); +} diff --git a/src/handlers/guilds/GUILD_UPDATE.ts b/src/handlers/guilds/GUILD_UPDATE.ts index 41289d333..7d145ecab 100644 --- a/src/handlers/guilds/GUILD_UPDATE.ts +++ b/src/handlers/guilds/GUILD_UPDATE.ts @@ -1,44 +1,14 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; -import { structures } from "../../structures/mod.ts"; -import type { GuildUpdateChange } from "../../types/discordeno/guild_update_change.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { Guild } from "../../types/guilds/guild.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleGuildUpdate(data: DiscordGatewayPayload, shardId: number) { - const payload = data.d as Guild; - const oldGuild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.id)); - if (!oldGuild) return; - - const keysToSkip = ["id", "roles", "guildHashes", "guildId", "maxMembers", "emojis"]; - - const newGuild = await structures.createDiscordenoGuild(payload, shardId); - - const changes = Object.entries(newGuild) - .map(([key, value]) => { - if (keysToSkip.includes(key)) return; - - // @ts-ignore index signature - const cachedValue = oldGuild[key]; - - if (cachedValue === value) return; - // Guild create sends undefined and update sends false. - if (!cachedValue && !value) return; - - if (Array.isArray(cachedValue) && Array.isArray(value)) { - const different = - cachedValue.length !== value.length || - cachedValue.find((val) => !value.includes(val)) || - value.find((val) => !cachedValue.includes(val)); - if (!different) return; - } - - return { key, oldValue: cachedValue, value }; - }) - .filter((change) => change) as GuildUpdateChange[]; - - await cacheHandlers.set("guilds", newGuild.id, newGuild); - - eventHandlers.guildUpdate?.(newGuild, changes); +export async function handleGuildUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as SnakeCasedPropertiesDeep; + + const guild = bot.transformers.guild(bot, { guild: payload, shardId }); + const cached = await bot.cache.guilds.get(guild.id); + await bot.cache.guilds.set(guild.id, guild); + + bot.events.guildUpdate(bot, guild, cached); } diff --git a/src/handlers/mod.ts b/src/handlers/mod.ts index 9155ffdb6..6a108e792 100644 --- a/src/handlers/mod.ts +++ b/src/handlers/mod.ts @@ -11,9 +11,6 @@ import { handleThreadListSync } from "./channels/THREAD_LIST_SYNC.ts"; import { handleThreadMembersUpdate } from "./channels/THREAD_MEMBERS_UPDATE.ts"; import { handleThreadMemberUpdate } from "./channels/THREAD_MEMBER_UPDATE.ts"; import { handleThreadUpdate } from "./channels/THREAD_UPDATE.ts"; -import { handleApplicationCommandCreate } from "./commands/APPLICATION_COMMAND_CREATE.ts"; -import { handleApplicationCommandDelete } from "./commands/APPLICATION_COMMAND_DELETE.ts"; -import { handleApplicationCommandUpdate } from "./commands/APPLICATION_COMMAND_UPDATE.ts"; import { handleGuildEmojisUpdate } from "./emojis/GUILD_EMOJIS_UPDATE.ts"; import { handleGuildBanAdd } from "./guilds/GUILD_BAN_ADD.ts"; import { handleGuildBanRemove } from "./guilds/GUILD_BAN_REMOVE.ts"; @@ -48,11 +45,9 @@ import { handleGuildRoleUpdate } from "./roles/GUILD_ROLE_UPDATE.ts"; import { handleVoiceServerUpdate } from "./voice/VOICE_SERVER_UPDATE.ts"; import { handleVoiceStateUpdate } from "./voice/VOICE_STATE_UPDATE.ts"; import { handleWebhooksUpdate } from "./webhooks/WEBHOOKS_UPDATE.ts"; +import { handleGuildLoaded } from "./guilds/GUILD_LOADED_DD.ts"; export { - handleApplicationCommandCreate, - handleApplicationCommandDelete, - handleApplicationCommandUpdate, handleChannelCreate, handleChannelDelete, handleChannelPinsUpdate, @@ -102,77 +97,6 @@ export { handleWebhooksUpdate, }; -export let handlers = { - // misc - READY: handleReady, - // channels - CHANNEL_CREATE: handleChannelCreate, - CHANNEL_DELETE: handleChannelDelete, - CHANNEL_PINS_UPDATE: handleChannelPinsUpdate, - CHANNEL_UPDATE: handleChannelUpdate, - THREAD_CREATE: handleThreadCreate, - THREAD_UPDATE: handleThreadUpdate, - THREAD_DELETE: handleThreadDelete, - THREAD_LIST_SYNC: handleThreadListSync, - THREAD_MEMBER_UPDATE: handleThreadMemberUpdate, - THREAD_MEMBERS_UPDATE: handleThreadMembersUpdate, - STAGE_INSTANCE_CREATE: handleStageInstanceCreate, - STAGE_INSTANCE_UPDATE: handleStageInstanceUpdate, - STAGE_INSTANCE_DELETE: handleStageInstanceDelete, - - // commands - APPLICATION_COMMAND_CREATE: handleApplicationCommandCreate, - APPLICATION_COMMAND_DELETE: handleApplicationCommandDelete, - APPLICATION_COMMAND_UPDATE: handleApplicationCommandUpdate, - // guilds - GUILD_BAN_ADD: handleGuildBanAdd, - GUILD_BAN_REMOVE: handleGuildBanRemove, - GUILD_CREATE: handleGuildCreate, - GUILD_DELETE: handleGuildDelete, - GUILD_EMOJIS_UPDATE: handleGuildEmojisUpdate, - GUILD_INTEGRATIONS_UPDATE: handleGuildIntegrationsUpdate, - GUILD_MEMBER_ADD: handleGuildMemberAdd, - GUILD_MEMBER_REMOVE: handleGuildMemberRemove, - GUILD_MEMBER_UPDATE: handleGuildMemberUpdate, - GUILD_MEMBERS_CHUNK: handleGuildMembersChunk, - GUILD_ROLE_CREATE: handleGuildRoleCreate, - GUILD_ROLE_DELETE: handleGuildRoleDelete, - GUILD_ROLE_UPDATE: handleGuildRoleUpdate, - GUILD_UPDATE: handleGuildUpdate, - // interactions - INTERACTION_CREATE: handleInteractionCreate, - // invites - INVITE_CREATE: handleInviteCreate, - INVITE_DELETE: handleInviteCreate, - // messages - MESSAGE_CREATE: handleMessageCreate, - MESSAGE_DELETE_BULK: handleMessageDeleteBulk, - MESSAGE_DELETE: handleMessageDelete, - MESSAGE_REACTION_ADD: handleMessageReactionAdd, - MESSAGE_REACTION_REMOVE_ALL: handleMessageReactionRemoveAll, - MESSAGE_REACTION_REMOVE_EMOJI: handleMessageReactionRemoveEmoji, - MESSAGE_REACTION_REMOVE: handleMessageReactionRemove, - MESSAGE_UPDATE: handleMessageUpdate, - // presence - PRESENCE_UPDATE: handlePresenceUpdate, - TYPING_START: handleTypingStart, - USER_UPDATE: handleUserUpdate, - // voice - VOICE_SERVER_UPDATE: handleVoiceServerUpdate, - VOICE_STATE_UPDATE: handleVoiceStateUpdate, - // webhooks - WEBHOOKS_UPDATE: handleWebhooksUpdate, - // integrations - INTEGRATION_CREATE: handleIntegrationCreate, - INTEGRATION_UPDATE: handleIntegrationUpdate, - INTEGRATION_DELETE: handleIntegrationDelete, +export const handlers = { + }; - -export type Handlers = typeof handlers; - -export function updateHandlers(newHandlers: Handlers) { - handlers = { - ...handlers, - ...newHandlers, - }; -} diff --git a/src/types/discordeno/event_handlers.ts b/src/types/discordeno/event_handlers.ts index 7834cfc86..0b87a1669 100644 --- a/src/types/discordeno/event_handlers.ts +++ b/src/types/discordeno/event_handlers.ts @@ -1,8 +1,3 @@ -import type { DiscordenoChannel } from "../../structures/channel.ts"; -import type { DiscordenoGuild } from "../../structures/guild.ts"; -import type { DiscordenoMember } from "../../structures/member.ts"; -import type { DiscordenoMessage } from "../../structures/message.ts"; -import type { DiscordenoRole } from "../../structures/role.ts"; import { DiscordenoThread } from "../../util/transformers/channel_to_thread.ts"; import type { Collection } from "../../util/collection.ts"; import type { PresenceUpdate } from "../activity/presence_update.ts"; @@ -29,12 +24,6 @@ import type { DebugArg } from "./debug_arg.ts"; import type { GuildUpdateChange } from "./guild_update_change.ts"; export type EventHandlersDefinitions = { - /** Sent when a new Slash Command is created, relevant to the current user. */ - applicationCommandCreate: [data: ApplicationCommandCreateUpdateDelete]; - /** Sent when a Slash Command relevant to the current user is updated. */ - applicationCommandUpdate: [data: ApplicationCommandCreateUpdateDelete]; - /** Sent when a Slash Command relevant to the current user is deleted. */ - applicationCommandDelete: [data: ApplicationCommandCreateUpdateDelete]; /** Sent when properties about the user change. */ botUpdate: [user: User]; /** Sent when a new guild channel is created, relevant to the current user. */ diff --git a/src/types/gateway/gateway_payload.ts b/src/types/gateway/gateway_payload.ts index a47ea5459..72fef29e2 100644 --- a/src/types/gateway/gateway_payload.ts +++ b/src/types/gateway/gateway_payload.ts @@ -6,55 +6,53 @@ export interface GatewayPayload { /** Sequence number, used for resuming sessions and heartbeats */ s: number | null; /** The event name for this payload */ - t: - | "READY" - | "RESUMED" - | "CHANNEL_CREATE" - | "CHANNEL_DELETE" - | "CHANNEL_PINS_UPDATE" - | "CHANNEL_UPDATE" - | "APPLICATION_COMMAND_CREATE" - | "APPLICATION_COMMAND_DELETE" - | "APPLICATION_COMMAND_UPDATE" - | "GUILD_BAN_ADD" - | "GUILD_BAN_REMOVE" - | "GUILD_CREATE" - | "GUILD_DELETE" - | "GUILD_EMOJIS_UPDATE" - | "GUILD_INTEGRATIONS_UPDATE" - | "GUILD_MEMBER_ADD" - | "GUILD_MEMBER_REMOVE" - | "GUILD_MEMBER_UPDATE" - | "GUILD_MEMBERS_CHUNK" - | "GUILD_ROLE_CREATE" - | "GUILD_ROLE_DELETE" - | "GUILD_ROLE_UPDATE" - | "GUILD_UPDATE" - | "INTERACTION_CREATE" - | "INVITE_CREATE" - | "INVITE_DELETE" - | "MESSAGE_CREATE" - | "MESSAGE_DELETE_BULK" - | "MESSAGE_DELETE" - | "MESSAGE_REACTION_ADD" - | "MESSAGE_REACTION_REMOVE_ALL" - | "MESSAGE_REACTION_REMOVE_EMOJI" - | "MESSAGE_REACTION_REMOVE" - | "MESSAGE_UPDATE" - | "PRESENCE_UPDATE" - | "TYPING_START" - | "USER_UPDATE" - | "VOICE_SERVER_UPDATE" - | "VOICE_STATE_UPDATE" - | "WEBHOOKS_UPDATE" - | "INTEGRATION_CREATE" - | "INTEGRATION_UPDATE" - | "INTEGRATION_DELETE" - | "STAGE_INSTANCE_CREATE" - | "STAGE_INSTANCE_UPDATE" - | "STAGE_INSTANCE_DELETE" - | null; + t: GatewayEventNames | null; } /** https://discord.com/developers/docs/topics/gateway#payloads-gateway-payload-structure */ export type DiscordGatewayPayload = GatewayPayload; +export type GatewayDispatchEventNames = + | "READY" + | "CHANNEL_CREATE" + | "CHANNEL_DELETE" + | "CHANNEL_PINS_UPDATE" + | "CHANNEL_UPDATE" + | "GUILD_BAN_ADD" + | "GUILD_BAN_REMOVE" + | "GUILD_CREATE" + | "GUILD_DELETE" + | "GUILD_EMOJIS_UPDATE" + | "GUILD_INTEGRATIONS_UPDATE" + | "GUILD_MEMBER_ADD" + | "GUILD_MEMBER_REMOVE" + | "GUILD_MEMBER_UPDATE" + | "GUILD_MEMBERS_CHUNK" + | "GUILD_ROLE_CREATE" + | "GUILD_ROLE_DELETE" + | "GUILD_ROLE_UPDATE" + | "GUILD_UPDATE" + | "INTERACTION_CREATE" + | "INVITE_CREATE" + | "INVITE_DELETE" + | "MESSAGE_CREATE" + | "MESSAGE_DELETE_BULK" + | "MESSAGE_DELETE" + | "MESSAGE_REACTION_ADD" + | "MESSAGE_REACTION_REMOVE_ALL" + | "MESSAGE_REACTION_REMOVE_EMOJI" + | "MESSAGE_REACTION_REMOVE" + | "MESSAGE_UPDATE" + | "PRESENCE_UPDATE" + | "TYPING_START" + | "USER_UPDATE" + | "VOICE_SERVER_UPDATE" + | "VOICE_STATE_UPDATE" + | "WEBHOOKS_UPDATE" + | "INTEGRATION_CREATE" + | "INTEGRATION_UPDATE" + | "INTEGRATION_DELETE" + | "STAGE_INSTANCE_CREATE" + | "STAGE_INSTANCE_UPDATE" + | "STAGE_INSTANCE_DELETE"; + +export type GatewayEventNames = GatewayDispatchEventNames | "READY" | "RESUMED"; diff --git a/src/ws/handle_discord_payload.ts b/src/ws/handle_discord_payload.ts deleted file mode 100644 index 8bd709724..000000000 --- a/src/ws/handle_discord_payload.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts"; -import { GatewayManager } from "../bot.ts"; - -/** Handler for processing all dispatch payloads that should be sent/forwarded to another server/vps/process. */ -export async function handleDiscordPayload(gateway: GatewayManager, data: DiscordGatewayPayload, shardId: number) { - await fetch(gateway.url, { - headers: { - authorization: gateway.secretKey, - }, - method: "post", - body: JSON.stringify({ - shardId, - data, - }), - }).catch(console.error); -} diff --git a/src/ws/handle_on_message.ts b/src/ws/handle_on_message.ts index c860921e1..d0b8faa46 100644 --- a/src/ws/handle_on_message.ts +++ b/src/ws/handle_on_message.ts @@ -1,10 +1,13 @@ -import { eventHandlers, GatewayManager } from "../bot.ts"; -import { handlers } from "../handlers/mod.ts"; +import { GatewayManager } from "../bot.ts"; import { DiscordGatewayOpcodes } from "../types/codes/gateway_opcodes.ts"; import type { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts"; import type { DiscordHello } from "../types/gateway/hello.ts"; import type { DiscordReady } from "../types/gateway/ready.ts"; -import { camelize, delay } from "../util/utils.ts"; +import { Guild } from "../types/guilds/guild.ts"; +import { UnavailableGuild } from "../types/guilds/unavailable_guild.ts"; +import { SnakeCasedPropertiesDeep } from "../types/util.ts"; +import { snowflakeToBigint } from "../util/bigint.ts"; +import { delay } from "../util/utils.ts"; import { decompressWith } from "./deps.ts"; /** Handler for handling every message event from websocket. */ @@ -27,7 +30,7 @@ export async function handleOnMessage(gateway: GatewayManager, message: any, sha switch (messageData.op) { case DiscordGatewayOpcodes.Heartbeat: - if (shard?.gateway.readyState !== WebSocket.OPEN) return; + if (shard?.ws.readyState !== WebSocket.OPEN) return; shard.heartbeat.lastSentAt = Date.now(); // Discord randomly sends this requiring an immediate heartbeat back @@ -91,15 +94,18 @@ export async function handleOnMessage(gateway: GatewayManager, message: any, sha // Important for RESUME if (messageData.t === "READY") { const shard = gateway.shards.get(shardId); + const payload = messageData.d as DiscordReady; if (shard) { - shard.sessionId = (messageData.d as DiscordReady).session_id; + shard.sessionId = payload.session_id; } + payload.guilds.forEach((g) => gateway.cache.loadingGuildIds.add(snowflakeToBigint(g.id))); + gateway.loadingShards.get(shardId)?.resolve(true); gateway.loadingShards.delete(shardId); // Wait few seconds to spawn next shard setTimeout(() => { - const bucket = gateway.buckets.get(shardId % gateway.botGatewayData.sessionStartLimit.maxConcurrency); + const bucket = gateway.buckets.get(shardId % gateway.maxConcurrency); if (bucket) bucket.createNextShard.shift()?.(); }, gateway.spawnShardDelay); } @@ -112,18 +118,33 @@ export async function handleOnMessage(gateway: GatewayManager, message: any, sha } } - if (gateway.url) await gateway.handleDiscordPayload(gateway, messageData, shardId); - else { - eventHandlers.raw?.(messageData); - await eventHandlers.dispatchRequirements?.(messageData, shardId); + // MUST HANDLE GUILD_CREATE EVENTS AS THEY ARE EXPENSIVE WITHOUT GATEWAY CACHE + if (messageData.t === "GUILD_CREATE") { + const id = snowflakeToBigint((messageData.d as SnakeCasedPropertiesDeep).id); - if (messageData.op !== DiscordGatewayOpcodes.Dispatch) return; + // SHARD RESUMED MOST LIKELY, THEY EMIT GUILD CREATES. OR GUILD BECAME AVAILABLE AGAIN + if (gateway.cache.guildIds.has(id)) return; - if (!messageData.t) return; + // GUILD WAS MARKED LOADING IN READY EVENT, THIS WAS THE FIRST GUILD_CREATE TO ARRIVE + if (gateway.cache.loadingGuildIds.has(id)) { + // @ts-ignore override with a custom event + messageData.t = "GUILD_LOADED_DD"; + gateway.cache.loadingGuildIds.delete(id); + } - return handlers[messageData.t]?.(camelize(messageData), shardId); + gateway.cache.guildIds.add(id); } + // MUST HANDLE GUILD_DELETE EVENTS FOR UNAVAILABLE + if (messageData.t === "GUILD_DELETE") { + if ((messageData.d as UnavailableGuild).unavailable) return; + } + + // IF NO TYPE THEN THIS SHOULD NOT BE SENT FORWARD + if (!messageData.t) return; + + await gateway.handleDiscordPayload(gateway, messageData, shardId); + break; } } diff --git a/src/ws/mod.ts b/src/ws/mod.ts index 3dc203936..147278197 100644 --- a/src/ws/mod.ts +++ b/src/ws/mod.ts @@ -1,6 +1,5 @@ export * from "./create_shard.ts"; export * from "./events.ts"; -export * from "./handle_discord_payload.ts"; export * from "./handle_on_message.ts"; export * from "./heartbeat.ts"; export * from "./identify.ts";