mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-02 08:50:07 +00:00
Merge remote-tracking branch 'upstream/fp-attempt-9001' into fp-attempt-9001
# Conflicts: # src/bot.ts
This commit is contained in:
188
src/bot.ts
188
src/bot.ts
@@ -50,8 +50,8 @@ import {
|
||||
baseEndpoints,
|
||||
CHANNEL_MENTION_REGEX,
|
||||
CONTEXT_MENU_COMMANDS_NAME_REGEX,
|
||||
DISCORD_SNOWFLAKE_REGEX,
|
||||
DISCORDENO_VERSION,
|
||||
DISCORD_SNOWFLAKE_REGEX,
|
||||
endpoints,
|
||||
SLASH_COMMANDS_NAME_REGEX,
|
||||
USER_AGENT,
|
||||
@@ -90,7 +90,12 @@ export async function createBot(options: CreateBotOptions) {
|
||||
isReady: false,
|
||||
activeGuildIds: new Set<bigint>(),
|
||||
constants: createBotConstants(),
|
||||
handlers: createBotGatewayHandlers({}),
|
||||
cache: {
|
||||
forEach: function (
|
||||
type: "DELETE_MESSAGES_FROM_GUILD" | "DELETE_CHANNELS_FROM_GUILD" | "DELETE_GUILD_FROM_MEMBER",
|
||||
options: Record<string, any>
|
||||
) {},
|
||||
guilds: {
|
||||
get: async function (id: bigint): Promise<DiscordenoGuild | undefined> {
|
||||
return {} as any as DiscordenoGuild;
|
||||
@@ -101,6 +106,9 @@ export async function createBot(options: CreateBotOptions) {
|
||||
set: async function (id: bigint, guild: DiscordenoGuild): Promise<void> {
|
||||
return;
|
||||
},
|
||||
delete: async function (id: bigint): Promise<void> {
|
||||
return;
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
get: async function (id: bigint): Promise<DiscordenoChannel | undefined> {
|
||||
@@ -126,6 +134,9 @@ export async function createBot(options: CreateBotOptions) {
|
||||
set: async function (id: bigint, member: DiscordenoMember): Promise<void> {
|
||||
return;
|
||||
},
|
||||
delete: async function (id: bigint): Promise<void> {
|
||||
return;
|
||||
},
|
||||
},
|
||||
users: {
|
||||
get: async function (id: bigint): Promise<DiscordenoUser | undefined> {
|
||||
@@ -182,6 +193,15 @@ export function createEventHandlers(events: Partial<EventHandlers>): 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,
|
||||
@@ -319,6 +339,10 @@ export interface HelperUtils {
|
||||
|
||||
export function createGatewayManager(options: Partial<GatewayManager>): GatewayManager {
|
||||
return {
|
||||
cache: {
|
||||
guildIds: new Set(),
|
||||
loadingGuildIds: new Set(),
|
||||
},
|
||||
secretKey: options.secretKey ?? "",
|
||||
url: options.url ?? "",
|
||||
reshard: options.reshard ?? true,
|
||||
@@ -347,12 +371,12 @@ export function createGatewayManager(options: Partial<GatewayManager>): GatewayM
|
||||
loadingShards: options.loadingShards ?? new Collection(),
|
||||
buckets: new Collection(),
|
||||
utf8decoder: new TextDecoder(),
|
||||
|
||||
startGateway,
|
||||
spawnShards,
|
||||
createShard,
|
||||
identify,
|
||||
heartbeat,
|
||||
handleDiscordPayload,
|
||||
tellClusterToIdentify,
|
||||
log,
|
||||
resharder,
|
||||
@@ -361,6 +385,18 @@ export function createGatewayManager(options: Partial<GatewayManager>): 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);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -394,8 +430,8 @@ export interface Transformers {
|
||||
snowflake: typeof snowflakeToBigint;
|
||||
channel: typeof transformChannel;
|
||||
guild: typeof transformGuild;
|
||||
member: typeof transformMember;
|
||||
user: typeof transformUser;
|
||||
member: typeof transformMember;
|
||||
message: typeof transformMessage;
|
||||
role: typeof transformRole;
|
||||
voiceState: typeof transformVoiceState;
|
||||
@@ -404,6 +440,13 @@ export interface Transformers {
|
||||
export function createTransformers(options: Partial<Transformers>) {
|
||||
return {
|
||||
snowflake: options.snowflake || snowflakeToBigint,
|
||||
channel: options.channel || transformChannel,
|
||||
guild: options.guild || transformGuild,
|
||||
user: options.user || transformUser,
|
||||
member: options.member || transformMember,
|
||||
message: options.message || transformMessage,
|
||||
role: options.role || transformRole,
|
||||
voiceState: options.voiceState || transformVoiceState,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -474,6 +517,11 @@ export interface GatewayManager {
|
||||
>;
|
||||
utf8decoder: TextDecoder;
|
||||
|
||||
cache: {
|
||||
guildIds: Set<bigint>;
|
||||
loadingGuildIds: Set<bigint>;
|
||||
};
|
||||
|
||||
// METHODS
|
||||
|
||||
/** The handler function that starts the gateway. */
|
||||
@@ -487,7 +535,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. */
|
||||
@@ -547,6 +595,21 @@ export interface EventHandlers {
|
||||
discoverableDisabled: boolean;
|
||||
}
|
||||
) => any;
|
||||
// TODO: THREADS
|
||||
guildEmojisUpdate: (
|
||||
bot: Bot,
|
||||
guild: DiscordenoGuild,
|
||||
emojis: Collection<bigint, Emoji>,
|
||||
cachedEmojis: Collection<bigint, Emoji>
|
||||
) => 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() {
|
||||
@@ -565,3 +628,120 @@ export function createBotConstants() {
|
||||
Errors,
|
||||
};
|
||||
}
|
||||
|
||||
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<BotGatewayHandlerOptions>) {
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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<DiscordGatewayPayload>) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<GuildEmojisUpdate>;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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<DiscordGatewayPayload>) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<GuildBanAddRemove>;
|
||||
// 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));
|
||||
}
|
||||
|
||||
@@ -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<DiscordGatewayPayload>) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<GuildBanAddRemove>;
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<DiscordGatewayPayload>,
|
||||
shardId: number
|
||||
) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<Guild>;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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<UnavailableGuild>;
|
||||
|
||||
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 }),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -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<GuildIntegrationsUpdate>;
|
||||
|
||||
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) });
|
||||
}
|
||||
|
||||
17
src/handlers/guilds/GUILD_LOADED_DD.ts
Normal file
17
src/handlers/guilds/GUILD_LOADED_DD.ts
Normal file
@@ -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<DiscordGatewayPayload>,
|
||||
shardId: number
|
||||
) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<Guild>;
|
||||
|
||||
const guild = bot.transformers.guild(bot, { guild: payload, shardId });
|
||||
await bot.cache.guilds.set(guild.id, guild);
|
||||
|
||||
await bot.events.guildLoaded(bot, guild);
|
||||
}
|
||||
@@ -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<Guild>;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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<Guild>).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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
export * from "./close_ws.ts";
|
||||
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";
|
||||
|
||||
Reference in New Issue
Block a user