mirror of
https://github.com/discordeno/discordeno.git
synced 2026-09-17 08:47:22 +00:00
remaining collectors
This commit is contained in:
@@ -0,0 +1,107 @@
|
|||||||
|
import { eventHandlers } from "../module/client.ts";
|
||||||
|
import { structures } from "../structures/mod.ts";
|
||||||
|
import { DiscordPayload } from "../types/discord.ts";
|
||||||
|
import {
|
||||||
|
MessageCreateOptions,
|
||||||
|
MessageDeletePayload,
|
||||||
|
MessageDeleteBulkPayload,
|
||||||
|
} from "../types/message.ts";
|
||||||
|
import { cache } from "../utils/cache.ts";
|
||||||
|
|
||||||
|
export function handleInternalMessageCreate(data: DiscordPayload) {
|
||||||
|
if (data.t !== "MESSAGE_CREATE") return;
|
||||||
|
|
||||||
|
const payload = data.d as MessageCreateOptions;
|
||||||
|
const channel = cache.channels.get(payload.channel_id);
|
||||||
|
if (channel) channel.lastMessageID = payload.id;
|
||||||
|
|
||||||
|
const message = structures.createMessage(payload);
|
||||||
|
// Cache the message
|
||||||
|
cache.messages.set(payload.id, message);
|
||||||
|
const guild = payload.guild_id
|
||||||
|
? cache.guilds.get(payload.guild_id)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (payload.member) {
|
||||||
|
// If in a guild cache the author as a member
|
||||||
|
guild?.members.set(
|
||||||
|
payload.author.id,
|
||||||
|
structures.createMember(
|
||||||
|
{ ...payload.member, user: payload.author },
|
||||||
|
guild,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.mentions.forEach((mention) => {
|
||||||
|
// Cache the member if its a valid member
|
||||||
|
if (mention.member) {
|
||||||
|
guild?.members.set(
|
||||||
|
mention.id,
|
||||||
|
structures.createMember(
|
||||||
|
{ ...mention.member, user: mention },
|
||||||
|
guild,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
eventHandlers.messageCreate?.(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalMessageDelete(data: DiscordPayload) {
|
||||||
|
if (data.t !== "MESSAGE_DELETE") return;
|
||||||
|
|
||||||
|
const payload = data.d as MessageDeletePayload;
|
||||||
|
const channel = cache.channels.get(payload.channel_id);
|
||||||
|
if (!channel) return;
|
||||||
|
|
||||||
|
eventHandlers.messageDelete?.(
|
||||||
|
cache.messages.get(payload.id) || { id: payload.id, channel },
|
||||||
|
);
|
||||||
|
|
||||||
|
cache.messages.delete(payload.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalMessageDeleteBulk(data: DiscordPayload) {
|
||||||
|
if (data.t !== "MESSAGE_DELETE_BULK") return;
|
||||||
|
|
||||||
|
const payload = data.d as MessageDeleteBulkPayload;
|
||||||
|
const channel = cache.channels.get(payload.channel_id);
|
||||||
|
if (!channel) return;
|
||||||
|
|
||||||
|
payload.ids.forEach((id) => {
|
||||||
|
eventHandlers.messageDelete?.(cache.messages.get(id) || { id, channel });
|
||||||
|
cache.messages.delete(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalMessageUpdate(data: DiscordPayload) {
|
||||||
|
if (data.t !== "MESSAGE_UPDATE") return;
|
||||||
|
|
||||||
|
const payload = data.d as MessageCreateOptions;
|
||||||
|
const channel = cache.channels.get(payload.channel_id);
|
||||||
|
if (!channel) return;
|
||||||
|
|
||||||
|
const cachedMessage = cache.messages.get(payload.id);
|
||||||
|
if (!cachedMessage) return;
|
||||||
|
|
||||||
|
const oldMessage = {
|
||||||
|
attachments: cachedMessage.attachments,
|
||||||
|
content: cachedMessage.content,
|
||||||
|
embeds: cachedMessage.embeds,
|
||||||
|
editedTimestamp: cachedMessage.editedTimestamp,
|
||||||
|
tts: cachedMessage.tts,
|
||||||
|
pinned: cachedMessage.pinned,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Messages with embeds can trigger update but they wont have edited_timestamp
|
||||||
|
if (
|
||||||
|
!payload.edited_timestamp ||
|
||||||
|
(cachedMessage.content !== payload.content)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventHandlers.messageUpdate?.(cachedMessage, oldMessage);
|
||||||
|
}
|
||||||
+112
-6
@@ -1,16 +1,28 @@
|
|||||||
import { delay } from "https://deno.land/std@0.67.0/async/delay.ts";
|
import { delay } from "https://deno.land/std@0.67.0/async/delay.ts";
|
||||||
import { eventHandlers, setBotID } from "../module/client.ts";
|
import { eventHandlers, setBotID } from "../module/client.ts";
|
||||||
import { allowNextShard } from "../module/shardingManager.ts";
|
import { allowNextShard } from "../module/shardingManager.ts";
|
||||||
import { DiscordPayload, ReadyPayload } from "../types/discord.ts";
|
import { structures } from "../structures/mod.ts";
|
||||||
|
import {
|
||||||
|
DiscordPayload,
|
||||||
|
PresenceUpdatePayload,
|
||||||
|
ReadyPayload,
|
||||||
|
TypingStartPayload,
|
||||||
|
VoiceStateUpdatePayload,
|
||||||
|
WebhookUpdatePayload,
|
||||||
|
} from "../types/discord.ts";
|
||||||
|
import { UserPayload } from "../types/guild.ts";
|
||||||
import { cache } from "../utils/cache.ts";
|
import { cache } from "../utils/cache.ts";
|
||||||
|
|
||||||
export async function handleInternalReady(data: DiscordPayload, shardID: number) {
|
export async function handleInternalReady(
|
||||||
|
data: DiscordPayload,
|
||||||
|
shardID: number,
|
||||||
|
) {
|
||||||
if (data.t !== "READY") return;
|
if (data.t !== "READY") return;
|
||||||
|
|
||||||
const payload = data.d as ReadyPayload;
|
const payload = data.d as ReadyPayload;
|
||||||
setBotID(payload.user.id);
|
setBotID(payload.user.id);
|
||||||
|
|
||||||
// Triggered on each shard
|
// Triggered on each shard
|
||||||
eventHandlers.shardReady?.(shardID);
|
eventHandlers.shardReady?.(shardID);
|
||||||
if (payload.shard && shardID === payload.shard[1] - 1) {
|
if (payload.shard && shardID === payload.shard[1] - 1) {
|
||||||
// Wait 10 seconds to allow all guild create events to be processed
|
// Wait 10 seconds to allow all guild create events to be processed
|
||||||
@@ -19,7 +31,101 @@ export async function handleInternalReady(data: DiscordPayload, shardID: number)
|
|||||||
eventHandlers.ready?.();
|
eventHandlers.ready?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait 5 seconds to spawn next shard
|
// Wait 5 seconds to spawn next shard
|
||||||
await delay(5000);
|
await delay(5000);
|
||||||
allowNextShard()
|
allowNextShard();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalPresenceUpdate(data: DiscordPayload) {
|
||||||
|
if (data.t !== "PRESENCE_UPDATE") return;
|
||||||
|
|
||||||
|
const payload = data.d as PresenceUpdatePayload;
|
||||||
|
const oldPresence = cache.presences.get(payload.user.id);
|
||||||
|
cache.presences.set(payload.user.id, payload);
|
||||||
|
return eventHandlers.presenceUpdate?.(payload, oldPresence);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalTypingStart(data: DiscordPayload) {
|
||||||
|
if (data.t !== "TYPING_START") return;
|
||||||
|
eventHandlers.typingStart?.(data.d as TypingStartPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalUserUpdate(data: DiscordPayload) {
|
||||||
|
if (data.t !== "USER_UPDATE") return;
|
||||||
|
|
||||||
|
const userData = data.d as UserPayload;
|
||||||
|
|
||||||
|
cache.guilds.forEach((guild) => {
|
||||||
|
const member = guild.members.get(userData.id);
|
||||||
|
if (!member) return;
|
||||||
|
// member.author = userData;
|
||||||
|
Object.entries(userData).forEach(([key, value]) => {
|
||||||
|
// @ts-ignore
|
||||||
|
if (member[key] === value) return;
|
||||||
|
// @ts-ignore
|
||||||
|
member[key] = value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return eventHandlers.botUpdate?.(userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalVoiceStateUpdate(data: DiscordPayload) {
|
||||||
|
if (data.t !== "VOICE_STATE_UPDATE") return;
|
||||||
|
|
||||||
|
const payload = data.d as VoiceStateUpdatePayload;
|
||||||
|
if (!payload.guild_id) return;
|
||||||
|
|
||||||
|
const guild = cache.guilds.get(payload.guild_id);
|
||||||
|
if (!guild) return;
|
||||||
|
|
||||||
|
const member = guild.members.get(payload.user_id) ||
|
||||||
|
(payload.member
|
||||||
|
? structures.createMember(payload.member, guild)
|
||||||
|
: undefined);
|
||||||
|
if (!member) return;
|
||||||
|
|
||||||
|
// No cached state before so lets make one for em
|
||||||
|
const cachedState = guild.voiceStates.get(payload.user_id);
|
||||||
|
|
||||||
|
guild.voiceStates.set(payload.user_id, {
|
||||||
|
...payload,
|
||||||
|
guildID: payload.guild_id,
|
||||||
|
channelID: payload.channel_id,
|
||||||
|
userID: payload.user_id,
|
||||||
|
sessionID: payload.session_id,
|
||||||
|
selfDeaf: payload.self_deaf,
|
||||||
|
selfMute: payload.self_mute,
|
||||||
|
selfStream: payload.self_stream,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cachedState?.channelID !== payload.channel_id) {
|
||||||
|
// Either joined or moved channels
|
||||||
|
if (payload.channel_id) {
|
||||||
|
cachedState?.channelID
|
||||||
|
? // Was in a channel before
|
||||||
|
eventHandlers.voiceChannelSwitch?.(
|
||||||
|
member,
|
||||||
|
payload.channel_id,
|
||||||
|
cachedState.channelID,
|
||||||
|
)
|
||||||
|
: // Was not in a channel before so user just joined
|
||||||
|
eventHandlers.voiceChannelJoin?.(member, payload.channel_id);
|
||||||
|
} // Left the channel
|
||||||
|
else if (cachedState?.channelID) {
|
||||||
|
guild.voiceStates.delete(payload.user_id);
|
||||||
|
eventHandlers.voiceChannelLeave?.(member, cachedState.channelID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventHandlers.voiceStateUpdate?.(member, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalWebhooksUpdate(data: DiscordPayload) {
|
||||||
|
if (data.t !== "WEBHOOKS_UPDATE") return;
|
||||||
|
|
||||||
|
const options = data.d as WebhookUpdatePayload;
|
||||||
|
return eventHandlers.webhooksUpdate?.(
|
||||||
|
options.channel_id,
|
||||||
|
options.guild_id,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-1
@@ -19,7 +19,31 @@ import {
|
|||||||
handleInternalGuildMembersChunk,
|
handleInternalGuildMembersChunk,
|
||||||
handleInternalGuildMemberUpdate,
|
handleInternalGuildMemberUpdate,
|
||||||
} from "./members.ts";
|
} from "./members.ts";
|
||||||
import { handleInternalReady } from "./misc.ts";
|
import {
|
||||||
|
handleInternalMessageCreate,
|
||||||
|
handleInternalMessageDelete,
|
||||||
|
handleInternalMessageDeleteBulk,
|
||||||
|
handleInternalMessageUpdate,
|
||||||
|
} from "./messages.ts";
|
||||||
|
import {
|
||||||
|
handleInternalPresenceUpdate,
|
||||||
|
handleInternalReady,
|
||||||
|
handleInternalTypingStart,
|
||||||
|
handleInternalUserUpdate,
|
||||||
|
handleInternalVoiceStateUpdate,
|
||||||
|
handleInternalWebhooksUpdate,
|
||||||
|
} from "./misc.ts";
|
||||||
|
import {
|
||||||
|
handleInternalMessageReactionAdd,
|
||||||
|
handleInternalMessageReactionRemove,
|
||||||
|
handleInternalMessageReactionRemoveAll,
|
||||||
|
handleInternalMessageReactionRemoveEmoji,
|
||||||
|
} from "./reactions.ts";
|
||||||
|
import {
|
||||||
|
handleInternalGuildRoleCreate,
|
||||||
|
handleInternalGuildRoleDelete,
|
||||||
|
handleInternalGuildRoleUpdate,
|
||||||
|
} from "./roles.ts";
|
||||||
|
|
||||||
export let controllers = {
|
export let controllers = {
|
||||||
READY: handleInternalReady,
|
READY: handleInternalReady,
|
||||||
@@ -36,4 +60,26 @@ export let controllers = {
|
|||||||
GUILD_MEMBER_REMOVE: handleInternalGuildMemberRemove,
|
GUILD_MEMBER_REMOVE: handleInternalGuildMemberRemove,
|
||||||
GUILD_MEMBER_UPDATE: handleInternalGuildMemberUpdate,
|
GUILD_MEMBER_UPDATE: handleInternalGuildMemberUpdate,
|
||||||
GUILD_MEMBERS_CHUNK: handleInternalGuildMembersChunk,
|
GUILD_MEMBERS_CHUNK: handleInternalGuildMembersChunk,
|
||||||
|
GUILD_ROLE_CREATE: handleInternalGuildRoleCreate,
|
||||||
|
GUILD_ROLE_DELETE: handleInternalGuildRoleDelete,
|
||||||
|
GUILD_ROLE_UPDATE: handleInternalGuildRoleUpdate,
|
||||||
|
MESSAGE_CREATE: handleInternalMessageCreate,
|
||||||
|
MESSAGE_DELETE: handleInternalMessageDelete,
|
||||||
|
MESSAGE_DELETE_BULK: handleInternalMessageDeleteBulk,
|
||||||
|
MESSAGE_UPDATE: handleInternalMessageUpdate,
|
||||||
|
MESSAGE_REACTION_ADD: handleInternalMessageReactionAdd,
|
||||||
|
MESSAGE_REACTION_REMOVE: handleInternalMessageReactionRemove,
|
||||||
|
MESSAGE_REACTION_REMOVE_ALL: handleInternalMessageReactionRemoveAll,
|
||||||
|
MESSAGE_REACTION_REMOVE_EMOJI: handleInternalMessageReactionRemoveEmoji,
|
||||||
|
PRESENCE_UPDATE: handleInternalPresenceUpdate,
|
||||||
|
TYPING_START: handleInternalTypingStart,
|
||||||
|
USER_UPDATE: handleInternalUserUpdate,
|
||||||
|
VOICE_STATE_UPDATE: handleInternalVoiceStateUpdate,
|
||||||
|
WEBHOOKS_UPDATE: handleInternalWebhooksUpdate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Controllers = typeof controllers
|
||||||
|
|
||||||
|
export function updateControllers(newControllers: Controllers) {
|
||||||
|
controllers = newControllers
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
import { botID, eventHandlers } from "../module/client.ts";
|
||||||
|
import { structures } from "../structures/mod.ts";
|
||||||
|
import { DiscordPayload } from "../types/discord.ts";
|
||||||
|
import {
|
||||||
|
BaseMessageReactionPayload,
|
||||||
|
MessageReactionPayload,
|
||||||
|
MessageReactionRemoveEmojiPayload,
|
||||||
|
} from "../types/message.ts";
|
||||||
|
import { cache } from "../utils/cache.ts";
|
||||||
|
|
||||||
|
export function handleInternalMessageReactionAdd(data: DiscordPayload) {
|
||||||
|
if (data.t !== "MESSAGE_REACTION_ADD") return;
|
||||||
|
|
||||||
|
const payload = data.d as MessageReactionPayload;
|
||||||
|
const message = cache.messages.get(payload.message_id);
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
const previousReactions = message.reactions;
|
||||||
|
const reactionExisted = previousReactions?.find(
|
||||||
|
(reaction) =>
|
||||||
|
reaction.emoji.id === payload.emoji.id &&
|
||||||
|
reaction.emoji.name === payload.emoji.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (reactionExisted) reactionExisted.count++;
|
||||||
|
else {
|
||||||
|
const newReaction = {
|
||||||
|
count: 1,
|
||||||
|
me: payload.user_id === botID,
|
||||||
|
emoji: { ...payload.emoji, id: payload.emoji.id || undefined },
|
||||||
|
};
|
||||||
|
message.reactions = message.reactions
|
||||||
|
? [...message.reactions, newReaction]
|
||||||
|
: [newReaction];
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.messages.set(payload.message_id, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.member && payload.guild_id) {
|
||||||
|
const guild = cache.guilds.get(payload.guild_id);
|
||||||
|
guild?.members.set(
|
||||||
|
payload.member.user.id,
|
||||||
|
structures.createMember(
|
||||||
|
payload.member,
|
||||||
|
guild,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uncachedOptions = {
|
||||||
|
...payload,
|
||||||
|
id: payload.message_id,
|
||||||
|
channelID: payload.channel_id,
|
||||||
|
guildID: payload.guild_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
eventHandlers.reactionAdd?.(
|
||||||
|
message || uncachedOptions,
|
||||||
|
payload.emoji,
|
||||||
|
payload.user_id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalMessageReactionRemove(data: DiscordPayload) {
|
||||||
|
if (data.t !== "MESSAGE_REACTION_REMOVE") return;
|
||||||
|
|
||||||
|
const payload = data.d as MessageReactionPayload;
|
||||||
|
const message = cache.messages.get(payload.message_id);
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
const previousReactions = message.reactions;
|
||||||
|
const reactionExisted = previousReactions?.find(
|
||||||
|
(reaction) =>
|
||||||
|
reaction.emoji.id === payload.emoji.id &&
|
||||||
|
reaction.emoji.name === payload.emoji.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (reactionExisted) reactionExisted.count--;
|
||||||
|
else {
|
||||||
|
const newReaction = {
|
||||||
|
count: 1,
|
||||||
|
me: payload.user_id === botID,
|
||||||
|
emoji: { ...payload.emoji, id: payload.emoji.id || undefined },
|
||||||
|
};
|
||||||
|
message.reactions = message.reactions
|
||||||
|
? [...message.reactions, newReaction]
|
||||||
|
: [newReaction];
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.messages.set(payload.message_id, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.member && payload.guild_id) {
|
||||||
|
const guild = cache.guilds.get(payload.guild_id);
|
||||||
|
guild?.members.set(
|
||||||
|
payload.member.user.id,
|
||||||
|
structures.createMember(
|
||||||
|
payload.member,
|
||||||
|
guild,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uncachedOptions = {
|
||||||
|
...payload,
|
||||||
|
id: payload.message_id,
|
||||||
|
channelID: payload.channel_id,
|
||||||
|
guildID: payload.guild_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
eventHandlers.reactionRemove?.(
|
||||||
|
message || uncachedOptions,
|
||||||
|
payload.emoji,
|
||||||
|
payload.user_id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalMessageReactionRemoveAll(data: DiscordPayload) {
|
||||||
|
if (data.t !== "MESSAGE_REACTION_REMOVE_ALL") return;
|
||||||
|
|
||||||
|
eventHandlers.reactionRemoveAll?.(data.d as BaseMessageReactionPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleInternalMessageReactionRemoveEmoji(data: DiscordPayload) {
|
||||||
|
if (data.t !== "MESSAGE_REACTION_REMOVE_EMOJI") return;
|
||||||
|
|
||||||
|
eventHandlers.reactionRemoveEmoji?.(data.d as MessageReactionRemoveEmojiPayload);
|
||||||
|
}
|
||||||
@@ -2,42 +2,25 @@ import {
|
|||||||
DiscordBotGatewayData,
|
DiscordBotGatewayData,
|
||||||
DiscordPayload,
|
DiscordPayload,
|
||||||
GatewayOpcode,
|
GatewayOpcode,
|
||||||
PresenceUpdatePayload,
|
|
||||||
TypingStartPayload,
|
|
||||||
VoiceStateUpdatePayload,
|
|
||||||
WebhookUpdatePayload,
|
|
||||||
} from "../types/discord.ts";
|
} from "../types/discord.ts";
|
||||||
import {
|
import {
|
||||||
eventHandlers,
|
eventHandlers,
|
||||||
botGatewayData,
|
botGatewayData,
|
||||||
identifyPayload,
|
identifyPayload,
|
||||||
botID,
|
|
||||||
IdentifyPayload,
|
IdentifyPayload,
|
||||||
} from "./client.ts";
|
} from "./client.ts";
|
||||||
import { delay } from "https://deno.land/std@0.67.0/async/delay.ts";
|
import { delay } from "https://deno.land/std@0.67.0/async/delay.ts";
|
||||||
import { Guild } from "../structures/guild.ts";
|
import { Guild } from "../structures/guild.ts";
|
||||||
import {
|
import {
|
||||||
GuildRolePayload,
|
|
||||||
UserPayload,
|
|
||||||
FetchMembersOptions,
|
FetchMembersOptions,
|
||||||
GuildRoleDeletePayload,
|
|
||||||
} from "../types/guild.ts";
|
} from "../types/guild.ts";
|
||||||
import { cache } from "../utils/cache.ts";
|
import { cache } from "../utils/cache.ts";
|
||||||
import {
|
|
||||||
MessageCreateOptions,
|
|
||||||
MessageDeletePayload,
|
|
||||||
MessageDeleteBulkPayload,
|
|
||||||
MessageReactionPayload,
|
|
||||||
BaseMessageReactionPayload,
|
|
||||||
MessageReactionRemoveEmojiPayload,
|
|
||||||
} from "../types/message.ts";
|
|
||||||
import {
|
import {
|
||||||
createBasicShard,
|
createBasicShard,
|
||||||
requestGuildMembers,
|
requestGuildMembers,
|
||||||
botGatewayStatusRequest,
|
botGatewayStatusRequest,
|
||||||
} from "./basicShard.ts";
|
} from "./basicShard.ts";
|
||||||
import { BotStatusRequest } from "../utils/utils.ts";
|
import { BotStatusRequest } from "../utils/utils.ts";
|
||||||
import { structures } from "../structures/mod.ts";
|
|
||||||
import { controllers } from "../controllers/mod.ts";
|
import { controllers } from "../controllers/mod.ts";
|
||||||
|
|
||||||
let shardCounter = 0;
|
let shardCounter = 0;
|
||||||
@@ -117,256 +100,7 @@ export async function handleDiscordPayload(
|
|||||||
case GatewayOpcode.Dispatch:
|
case GatewayOpcode.Dispatch:
|
||||||
if (!data.t) return;
|
if (!data.t) return;
|
||||||
// Run the appropriate controller for this event.
|
// Run the appropriate controller for this event.
|
||||||
controllers[data.t]?.(data, shardID);
|
return controllers[data.t]?.(data, shardID);
|
||||||
|
|
||||||
if (data.t === "MESSAGE_CREATE") {
|
|
||||||
const options = data.d as MessageCreateOptions;
|
|
||||||
const channel = cache.channels.get(options.channel_id);
|
|
||||||
if (channel) channel.lastMessageID = options.id;
|
|
||||||
|
|
||||||
const message = structures.createMessage(options);
|
|
||||||
// Cache the message
|
|
||||||
cache.messages.set(options.id, message);
|
|
||||||
const guild = options.guild_id
|
|
||||||
? cache.guilds.get(options.guild_id)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
if (options.member) {
|
|
||||||
// If in a guild cache the author as a member
|
|
||||||
guild?.members.set(
|
|
||||||
options.author.id,
|
|
||||||
structures.createMember(
|
|
||||||
{ ...options.member, user: options.author },
|
|
||||||
guild,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
options.mentions.forEach((mention) => {
|
|
||||||
// Cache the member if its a valid member
|
|
||||||
if (mention.member) {
|
|
||||||
guild?.members.set(
|
|
||||||
mention.id,
|
|
||||||
structures.createMember(
|
|
||||||
{ ...mention.member, user: mention },
|
|
||||||
guild,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return eventHandlers.messageCreate?.(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
data.t && ["MESSAGE_DELETE", "MESSAGE_DELETE_BULK"].includes(data.t)
|
|
||||||
) {
|
|
||||||
const options = data.d as MessageDeletePayload;
|
|
||||||
const deletedMessages = data.t === "MESSAGE_DELETE"
|
|
||||||
? [options.id]
|
|
||||||
: (data.d as MessageDeleteBulkPayload).ids;
|
|
||||||
|
|
||||||
const channel = cache.channels.get(options.channel_id);
|
|
||||||
if (!channel) return;
|
|
||||||
|
|
||||||
deletedMessages.forEach((id) => {
|
|
||||||
const message = cache.messages.get(id);
|
|
||||||
if (!message) return;
|
|
||||||
eventHandlers.messageDelete?.(message || { id, channel });
|
|
||||||
cache.messages.delete(id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.t === "MESSAGE_UPDATE") {
|
|
||||||
const options = data.d as MessageCreateOptions;
|
|
||||||
const channel = cache.channels.get(options.channel_id);
|
|
||||||
if (!channel) return;
|
|
||||||
|
|
||||||
const cachedMessage = cache.messages.get(options.id);
|
|
||||||
if (!cachedMessage) return;
|
|
||||||
|
|
||||||
const oldMessage = {
|
|
||||||
attachments: cachedMessage.attachments,
|
|
||||||
content: cachedMessage.content,
|
|
||||||
embeds: cachedMessage.embeds,
|
|
||||||
editedTimestamp: cachedMessage.editedTimestamp,
|
|
||||||
tts: cachedMessage.tts,
|
|
||||||
pinned: cachedMessage.pinned,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Messages with embeds can trigger update but they wont have edited_timestamp
|
|
||||||
if (
|
|
||||||
!options.edited_timestamp ||
|
|
||||||
(cachedMessage.content !== options.content)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return eventHandlers.messageUpdate?.(cachedMessage, oldMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
data.t &&
|
|
||||||
["MESSAGE_REACTION_ADD", "MESSAGE_REACTION_REMOVE"].includes(data.t)
|
|
||||||
) {
|
|
||||||
const options = data.d as MessageReactionPayload;
|
|
||||||
const message = cache.messages.get(options.message_id);
|
|
||||||
const isAdd = data.t === "MESSAGE_REACTION_ADD";
|
|
||||||
|
|
||||||
if (message) {
|
|
||||||
const previousReactions = message.reactions;
|
|
||||||
const reactionExisted = previousReactions?.find(
|
|
||||||
(reaction) =>
|
|
||||||
reaction.emoji.id === options.emoji.id &&
|
|
||||||
reaction.emoji.name === options.emoji.name,
|
|
||||||
);
|
|
||||||
if (reactionExisted) {
|
|
||||||
reactionExisted.count = isAdd
|
|
||||||
? reactionExisted.count + 1
|
|
||||||
: reactionExisted.count - 1;
|
|
||||||
} else {
|
|
||||||
const newReaction = {
|
|
||||||
count: 1,
|
|
||||||
me: options.user_id === botID,
|
|
||||||
emoji: { ...options.emoji, id: options.emoji.id || undefined },
|
|
||||||
};
|
|
||||||
message.reactions = message.reactions
|
|
||||||
? [...message.reactions, newReaction]
|
|
||||||
: [newReaction];
|
|
||||||
}
|
|
||||||
|
|
||||||
cache.messages.set(options.message_id, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.member && options.guild_id) {
|
|
||||||
const guild = cache.guilds.get(options.guild_id);
|
|
||||||
guild?.members.set(
|
|
||||||
options.member.user.id,
|
|
||||||
structures.createMember(
|
|
||||||
options.member,
|
|
||||||
guild,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uncachedOptions = {
|
|
||||||
...options,
|
|
||||||
id: options.message_id,
|
|
||||||
channelID: options.channel_id,
|
|
||||||
guildID: options.guild_id,
|
|
||||||
};
|
|
||||||
|
|
||||||
return isAdd
|
|
||||||
? eventHandlers.reactionAdd?.(
|
|
||||||
message || uncachedOptions,
|
|
||||||
options.emoji,
|
|
||||||
options.user_id,
|
|
||||||
)
|
|
||||||
: eventHandlers.reactionRemove?.(
|
|
||||||
message || uncachedOptions,
|
|
||||||
options.emoji,
|
|
||||||
options.user_id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.t === "MESSAGE_REACTION_REMOVE_ALL") {
|
|
||||||
return eventHandlers.reactionRemoveAll?.(
|
|
||||||
data.d as BaseMessageReactionPayload,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.t === "MESSAGE_REACTION_REMOVE_EMOJI") {
|
|
||||||
return eventHandlers.reactionRemoveEmoji?.(
|
|
||||||
data.d as MessageReactionRemoveEmojiPayload,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.t === "PRESENCE_UPDATE") {
|
|
||||||
const payload = data.d as PresenceUpdatePayload;
|
|
||||||
const oldPresence = cache.presences.get(payload.user.id);
|
|
||||||
cache.presences.set(payload.user.id, payload);
|
|
||||||
return eventHandlers.presenceUpdate?.(payload, oldPresence);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.t === "TYPING_START") {
|
|
||||||
return eventHandlers.typingStart?.(data.d as TypingStartPayload);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.t === "USER_UPDATE") {
|
|
||||||
const userData = data.d as UserPayload;
|
|
||||||
|
|
||||||
cache.guilds.forEach((guild) => {
|
|
||||||
const member = guild.members.get(userData.id);
|
|
||||||
if (!member) return;
|
|
||||||
// member.author = userData;
|
|
||||||
Object.entries(userData).forEach(([key, value]) => {
|
|
||||||
// @ts-ignore
|
|
||||||
if (member[key] === value) return;
|
|
||||||
// @ts-ignore
|
|
||||||
member[key] = value;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return eventHandlers.botUpdate?.(userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.t === "VOICE_STATE_UPDATE") {
|
|
||||||
const payload = data.d as VoiceStateUpdatePayload;
|
|
||||||
if (!payload.guild_id) return;
|
|
||||||
|
|
||||||
const guild = cache.guilds.get(payload.guild_id);
|
|
||||||
if (!guild) return;
|
|
||||||
|
|
||||||
const member = guild.members.get(payload.user_id) ||
|
|
||||||
(payload.member
|
|
||||||
? structures.createMember(payload.member, guild)
|
|
||||||
: undefined);
|
|
||||||
if (!member) return;
|
|
||||||
|
|
||||||
// No cached state before so lets make one for em
|
|
||||||
const cachedState = guild.voiceStates.get(payload.user_id);
|
|
||||||
|
|
||||||
guild.voiceStates.set(payload.user_id, {
|
|
||||||
...payload,
|
|
||||||
guildID: payload.guild_id,
|
|
||||||
channelID: payload.channel_id,
|
|
||||||
userID: payload.user_id,
|
|
||||||
sessionID: payload.session_id,
|
|
||||||
selfDeaf: payload.self_deaf,
|
|
||||||
selfMute: payload.self_mute,
|
|
||||||
selfStream: payload.self_stream,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cachedState?.channelID !== payload.channel_id) {
|
|
||||||
// Either joined or moved channels
|
|
||||||
if (payload.channel_id) {
|
|
||||||
cachedState?.channelID
|
|
||||||
? // Was in a channel before
|
|
||||||
eventHandlers.voiceChannelSwitch?.(
|
|
||||||
member,
|
|
||||||
payload.channel_id,
|
|
||||||
cachedState.channelID,
|
|
||||||
)
|
|
||||||
: // Was not in a channel before so user just joined
|
|
||||||
eventHandlers.voiceChannelJoin?.(member, payload.channel_id);
|
|
||||||
} // Left the channel
|
|
||||||
else if (cachedState?.channelID) {
|
|
||||||
guild.voiceStates.delete(payload.user_id);
|
|
||||||
eventHandlers.voiceChannelLeave?.(member, cachedState.channelID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return eventHandlers.voiceStateUpdate?.(member, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.t === "WEBHOOKS_UPDATE") {
|
|
||||||
const options = data.d as WebhookUpdatePayload;
|
|
||||||
return eventHandlers.webhooksUpdate?.(
|
|
||||||
options.channel_id,
|
|
||||||
options.guild_id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export let structures = {
|
|||||||
createRole,
|
createRole,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Structures = typeof structures[keyof typeof structures];
|
export type Structures = typeof structures;
|
||||||
|
|
||||||
/** This function is used to update/reload/customize the internal structure of Discordeno.
|
/** This function is used to update/reload/customize the internal structure of Discordeno.
|
||||||
*
|
*
|
||||||
|
|||||||
+14
-1
@@ -28,7 +28,20 @@ export interface DiscordPayload {
|
|||||||
| "GUILD_MEMBERS_CHUNK"
|
| "GUILD_MEMBERS_CHUNK"
|
||||||
| "GUILD_ROLE_CREATE"
|
| "GUILD_ROLE_CREATE"
|
||||||
| "GUILD_ROLE_DELETE"
|
| "GUILD_ROLE_DELETE"
|
||||||
| "GUILD_ROLE_UPDATE";
|
| "GUILD_ROLE_UPDATE"
|
||||||
|
| "MESSAGE_CREATE"
|
||||||
|
| "MESSAGE_DELETE"
|
||||||
|
| "MESSAGE_DELETE_BULK"
|
||||||
|
| "MESSAGE_UPDATE"
|
||||||
|
| "MESSAGE_REACTION_ADD"
|
||||||
|
| "MESSAGE_REACTION_REMOVE"
|
||||||
|
| "MESSAGE_REACTION_REMOVE_ALL"
|
||||||
|
| "MESSAGE_REACTION_REMOVE_EMOJI"
|
||||||
|
| "PRESENCE_UPDATE"
|
||||||
|
| "TYPING_START"
|
||||||
|
| "USER_UPDATE"
|
||||||
|
| "VOICE_STATE_UPDATE"
|
||||||
|
| "WEBHOOKS_UPDATE";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DiscordBotGatewayData {
|
export interface DiscordBotGatewayData {
|
||||||
|
|||||||
Reference in New Issue
Block a user