mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-04 09:50:07 +00:00
remaining collectors
This commit is contained in:
107
src/controllers/messages.ts
Normal file
107
src/controllers/messages.ts
Normal file
@@ -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);
|
||||
}
|
||||
@@ -1,16 +1,28 @@
|
||||
import { delay } from "https://deno.land/std@0.67.0/async/delay.ts";
|
||||
import { eventHandlers, setBotID } from "../module/client.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";
|
||||
|
||||
export async function handleInternalReady(data: DiscordPayload, shardID: number) {
|
||||
export async function handleInternalReady(
|
||||
data: DiscordPayload,
|
||||
shardID: number,
|
||||
) {
|
||||
if (data.t !== "READY") return;
|
||||
|
||||
const payload = data.d as ReadyPayload;
|
||||
setBotID(payload.user.id);
|
||||
|
||||
// Triggered on each shard
|
||||
// Triggered on each shard
|
||||
eventHandlers.shardReady?.(shardID);
|
||||
if (payload.shard && shardID === payload.shard[1] - 1) {
|
||||
// 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?.();
|
||||
}
|
||||
|
||||
// Wait 5 seconds to spawn next shard
|
||||
await delay(5000);
|
||||
allowNextShard()
|
||||
// Wait 5 seconds to spawn next shard
|
||||
await delay(5000);
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,31 @@ import {
|
||||
handleInternalGuildMembersChunk,
|
||||
handleInternalGuildMemberUpdate,
|
||||
} 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 = {
|
||||
READY: handleInternalReady,
|
||||
@@ -36,4 +60,26 @@ export let controllers = {
|
||||
GUILD_MEMBER_REMOVE: handleInternalGuildMemberRemove,
|
||||
GUILD_MEMBER_UPDATE: handleInternalGuildMemberUpdate,
|
||||
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
|
||||
}
|
||||
|
||||
129
src/controllers/reactions.ts
Normal file
129
src/controllers/reactions.ts
Normal file
@@ -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,
|
||||
DiscordPayload,
|
||||
GatewayOpcode,
|
||||
PresenceUpdatePayload,
|
||||
TypingStartPayload,
|
||||
VoiceStateUpdatePayload,
|
||||
WebhookUpdatePayload,
|
||||
} from "../types/discord.ts";
|
||||
import {
|
||||
eventHandlers,
|
||||
botGatewayData,
|
||||
identifyPayload,
|
||||
botID,
|
||||
IdentifyPayload,
|
||||
} from "./client.ts";
|
||||
import { delay } from "https://deno.land/std@0.67.0/async/delay.ts";
|
||||
import { Guild } from "../structures/guild.ts";
|
||||
import {
|
||||
GuildRolePayload,
|
||||
UserPayload,
|
||||
FetchMembersOptions,
|
||||
GuildRoleDeletePayload,
|
||||
} from "../types/guild.ts";
|
||||
import { cache } from "../utils/cache.ts";
|
||||
import {
|
||||
MessageCreateOptions,
|
||||
MessageDeletePayload,
|
||||
MessageDeleteBulkPayload,
|
||||
MessageReactionPayload,
|
||||
BaseMessageReactionPayload,
|
||||
MessageReactionRemoveEmojiPayload,
|
||||
} from "../types/message.ts";
|
||||
import {
|
||||
createBasicShard,
|
||||
requestGuildMembers,
|
||||
botGatewayStatusRequest,
|
||||
} from "./basicShard.ts";
|
||||
import { BotStatusRequest } from "../utils/utils.ts";
|
||||
import { structures } from "../structures/mod.ts";
|
||||
import { controllers } from "../controllers/mod.ts";
|
||||
|
||||
let shardCounter = 0;
|
||||
@@ -117,256 +100,7 @@ export async function handleDiscordPayload(
|
||||
case GatewayOpcode.Dispatch:
|
||||
if (!data.t) return;
|
||||
// Run the appropriate controller for this event.
|
||||
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;
|
||||
return controllers[data.t]?.(data, shardID);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export let structures = {
|
||||
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.
|
||||
*
|
||||
|
||||
@@ -28,7 +28,20 @@ export interface DiscordPayload {
|
||||
| "GUILD_MEMBERS_CHUNK"
|
||||
| "GUILD_ROLE_CREATE"
|
||||
| "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 {
|
||||
|
||||
Reference in New Issue
Block a user