mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-16 03:18:17 +00:00
handlers
This commit is contained in:
+40
-2
@@ -293,6 +293,8 @@ import {
|
|||||||
validDiscoveryTerm,
|
validDiscoveryTerm,
|
||||||
} from "./helpers/mod.ts";
|
} from "./helpers/mod.ts";
|
||||||
import { DiscordenoEmoji, transformEmoji } from "./transformers/emoji.ts";
|
import { DiscordenoEmoji, transformEmoji } from "./transformers/emoji.ts";
|
||||||
|
import { transformActivity } from "./transformers/activity.ts";
|
||||||
|
import { DiscordenoPresence, transformPresence } from "./transformers/presence.ts";
|
||||||
|
|
||||||
export async function createBot(options: CreateBotOptions) {
|
export async function createBot(options: CreateBotOptions) {
|
||||||
return {
|
return {
|
||||||
@@ -309,6 +311,9 @@ export async function createBot(options: CreateBotOptions) {
|
|||||||
cache: {
|
cache: {
|
||||||
execute: async function (
|
execute: async function (
|
||||||
type:
|
type:
|
||||||
|
| "DELETE_MESSAGES_FROM_CHANNEL"
|
||||||
|
| "DELETE_ROLE_FROM_MEMBER"
|
||||||
|
| "BULK_DELETE_MESSAGES"
|
||||||
| "GUILD_MEMBER_CHUNK"
|
| "GUILD_MEMBER_CHUNK"
|
||||||
| "GUILD_MEMBER_COUNT_DECREMENT"
|
| "GUILD_MEMBER_COUNT_DECREMENT"
|
||||||
| "GUILD_MEMBER_COUNT_INCREMENT"
|
| "GUILD_MEMBER_COUNT_INCREMENT"
|
||||||
@@ -374,6 +379,20 @@ export async function createBot(options: CreateBotOptions) {
|
|||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
presence: {
|
||||||
|
get: async function (id: bigint): Promise<DiscordenoPresence | undefined> {
|
||||||
|
return {} as any as DiscordenoPresence;
|
||||||
|
},
|
||||||
|
has: async function (id: bigint): Promise<boolean> {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
set: async function (id: bigint, guild: DiscordenoPresence): Promise<void> {
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
delete: async function (id: bigint): Promise<void> {
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
},
|
||||||
users: {
|
users: {
|
||||||
get: async function (id: bigint): Promise<DiscordenoUser | undefined> {
|
get: async function (id: bigint): Promise<DiscordenoUser | undefined> {
|
||||||
return {} as any as DiscordenoUser;
|
return {} as any as DiscordenoUser;
|
||||||
@@ -440,6 +459,9 @@ export function createEventHandlers(events: Partial<EventHandlers>): EventHandle
|
|||||||
reactionRemove: events.reactionRemove ?? ignore,
|
reactionRemove: events.reactionRemove ?? ignore,
|
||||||
reactionRemoveAll: events.reactionRemoveAll ?? ignore,
|
reactionRemoveAll: events.reactionRemoveAll ?? ignore,
|
||||||
reactionRemoveEmoji: events.reactionRemoveEmoji ?? ignore,
|
reactionRemoveEmoji: events.reactionRemoveEmoji ?? ignore,
|
||||||
|
presenceUpdate: events.presenceUpdate ?? ignore,
|
||||||
|
voiceServerUpdate: events.voiceServerUpdate ?? ignore,
|
||||||
|
voiceStateUpdate: events.voiceStateUpdate ?? ignore,
|
||||||
channelCreate: events.channelCreate ?? ignore,
|
channelCreate: events.channelCreate ?? ignore,
|
||||||
voiceChannelLeave: events.voiceChannelLeave ?? ignore,
|
voiceChannelLeave: events.voiceChannelLeave ?? ignore,
|
||||||
channelDelete: events.channelDelete ?? ignore,
|
channelDelete: events.channelDelete ?? ignore,
|
||||||
@@ -1018,10 +1040,13 @@ export interface Transformers {
|
|||||||
application: typeof transformApplication;
|
application: typeof transformApplication;
|
||||||
team: typeof transformTeam;
|
team: typeof transformTeam;
|
||||||
emoji: typeof transformEmoji;
|
emoji: typeof transformEmoji;
|
||||||
|
activity: typeof transformActivity;
|
||||||
|
presence: typeof transformPresence;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTransformers(options: Partial<Transformers>) {
|
export function createTransformers(options: Partial<Transformers>) {
|
||||||
return {
|
return {
|
||||||
|
activity: options.activity || transformActivity,
|
||||||
application: options.application || transformApplication,
|
application: options.application || transformApplication,
|
||||||
channel: options.channel || transformChannel,
|
channel: options.channel || transformChannel,
|
||||||
emoji: options.emoji || transformEmoji,
|
emoji: options.emoji || transformEmoji,
|
||||||
@@ -1031,6 +1056,7 @@ export function createTransformers(options: Partial<Transformers>) {
|
|||||||
invite: options.invite || transformInvite,
|
invite: options.invite || transformInvite,
|
||||||
member: options.member || transformMember,
|
member: options.member || transformMember,
|
||||||
message: options.message || transformMessage,
|
message: options.message || transformMessage,
|
||||||
|
presence: options.presence || transformPresence,
|
||||||
role: options.role || transformRole,
|
role: options.role || transformRole,
|
||||||
user: options.user || transformUser,
|
user: options.user || transformUser,
|
||||||
team: options.team || transformTeam,
|
team: options.team || transformTeam,
|
||||||
@@ -1149,7 +1175,7 @@ export interface EventHandlers {
|
|||||||
interactionCreate: (bot: Bot, interaction: DiscordenoInteraction) => any;
|
interactionCreate: (bot: Bot, interaction: DiscordenoInteraction) => any;
|
||||||
integrationCreate: (bot: Bot, integration: DiscordenoIntegration) => any;
|
integrationCreate: (bot: Bot, integration: DiscordenoIntegration) => any;
|
||||||
integrationDelete: (bot: Bot, payload: { id: bigint; guildId: bigint; applicationId?: bigint }) => any;
|
integrationDelete: (bot: Bot, payload: { id: bigint; guildId: bigint; applicationId?: bigint }) => any;
|
||||||
integrationUpdate: (bot: Bot, integration: DiscordenoIntegration) => any;
|
integrationUpdate: (bot: Bot, payload: { guildId: bigint }) => any;
|
||||||
inviteCreate: (bot: Bot, invite: DiscordenoInvite) => any;
|
inviteCreate: (bot: Bot, invite: DiscordenoInvite) => any;
|
||||||
inviteDelete: (
|
inviteDelete: (
|
||||||
bot: Bot,
|
bot: Bot,
|
||||||
@@ -1207,9 +1233,21 @@ export interface EventHandlers {
|
|||||||
guildId?: bigint;
|
guildId?: bigint;
|
||||||
}
|
}
|
||||||
) => any;
|
) => any;
|
||||||
|
presenceUpdate: (bot: Bot, presence: DiscordenoPresence, oldPresence?: DiscordenoPresence) => any;
|
||||||
|
voiceServerUpdate: (bot: Bot, payload: { token: string; endpoint?: string; guildId: bigint }) => any;
|
||||||
|
voiceStateUpdate: (
|
||||||
|
bot: Bot,
|
||||||
|
voiceState: DiscordenoVoiceState,
|
||||||
|
payload: { guild?: DiscordenoGuild; member?: DiscordenoMember; user?: DiscordenoUser }
|
||||||
|
) => any;
|
||||||
channelCreate: (bot: Bot, channel: DiscordenoChannel) => any;
|
channelCreate: (bot: Bot, channel: DiscordenoChannel) => any;
|
||||||
dispatchRequirements: (bot: Bot, data: GatewayPayload, shardId: number) => any;
|
dispatchRequirements: (bot: Bot, data: GatewayPayload, shardId: number) => any;
|
||||||
voiceChannelLeave: (bot: Bot, voiceState: DiscordenoVoiceState, channel: DiscordenoChannel) => any;
|
voiceChannelLeave: (
|
||||||
|
bot: Bot,
|
||||||
|
voiceState: DiscordenoVoiceState,
|
||||||
|
guild: DiscordenoGuild,
|
||||||
|
channel?: DiscordenoChannel
|
||||||
|
) => any;
|
||||||
channelDelete: (bot: Bot, channel: DiscordenoChannel) => any;
|
channelDelete: (bot: Bot, channel: DiscordenoChannel) => any;
|
||||||
channelPinsUpdate: (bot: Bot, data: { guildId?: bigint; channelId: bigint; lastPinTimestamp?: number }) => any;
|
channelPinsUpdate: (bot: Bot, data: { guildId?: bigint; channelId: bigint; lastPinTimestamp?: number }) => any;
|
||||||
channelUpdate: (bot: Bot, channel: DiscordenoChannel, oldChannel: DiscordenoChannel) => any;
|
channelUpdate: (bot: Bot, channel: DiscordenoChannel, oldChannel: DiscordenoChannel) => any;
|
||||||
|
|||||||
@@ -6,18 +6,22 @@ import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
|||||||
|
|
||||||
export async function handleChannelDelete(bot: Bot, data: SnakeCasedPropertiesDeep<DiscordGatewayPayload>) {
|
export async function handleChannelDelete(bot: Bot, data: SnakeCasedPropertiesDeep<DiscordGatewayPayload>) {
|
||||||
const payload = data.d as SnakeCasedPropertiesDeep<Channel>;
|
const payload = data.d as SnakeCasedPropertiesDeep<Channel>;
|
||||||
|
if (!payload.guild_id) return;
|
||||||
|
|
||||||
const channel = await bot.cache.channels.get(bot.transformers.snowflake(payload.id));
|
const [channel, guild] = await Promise.all([
|
||||||
|
bot.cache.channels.get(bot.transformers.snowflake(payload.id)),
|
||||||
|
bot.cache.guilds.get(bot.transformers.snowflake(payload.guild_id)),
|
||||||
|
]);
|
||||||
if (!channel) return;
|
if (!channel) return;
|
||||||
|
|
||||||
if ([DiscordChannelTypes.GuildVoice, DiscordChannelTypes.GuildStageVoice].includes(channel.type)) {
|
if (guild && [DiscordChannelTypes.GuildVoice, DiscordChannelTypes.GuildStageVoice].includes(channel.type)) {
|
||||||
channel.voiceStates?.forEach((vs, key) => {
|
guild.voiceStates?.forEach((vs, key) => {
|
||||||
if (vs.channelId !== channel.id) return;
|
if (vs.channelId !== channel.id) return;
|
||||||
|
|
||||||
// Since this channel was deleted all voice states for this channel should be deleted
|
// Since this channel was deleted all voice states for this channel should be deleted
|
||||||
channel.voiceStates?.delete(key);
|
guild.voiceStates?.delete(key);
|
||||||
|
|
||||||
bot.events.voiceChannelLeave(bot, vs, channel);
|
bot.events.voiceChannelLeave(bot, vs, guild, channel);
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
[
|
[
|
||||||
@@ -27,7 +31,7 @@ export async function handleChannelDelete(bot: Bot, data: SnakeCasedPropertiesDe
|
|||||||
DiscordChannelTypes.GuildNews,
|
DiscordChannelTypes.GuildNews,
|
||||||
].includes(payload.type)
|
].includes(payload.type)
|
||||||
) {
|
) {
|
||||||
await bot.cache.channels.forEach("DELETE_MESSAGES_FROM_CHANNEL", {
|
await bot.cache.execute("DELETE_MESSAGES_FROM_CHANNEL", {
|
||||||
channelId: bot.transformers.snowflake(payload.id),
|
channelId: bot.transformers.snowflake(payload.id),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
|||||||
export async function handleGuildIntegrationsUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
export async function handleGuildIntegrationsUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as SnakeCasedPropertiesDeep<GuildIntegrationsUpdate>;
|
const payload = data.d as SnakeCasedPropertiesDeep<GuildIntegrationsUpdate>;
|
||||||
|
|
||||||
bot.events.integrationsUpdate(bot, { guildId: bot.transformers.snowflake(payload.guild_id) });
|
bot.events.integrationUpdate(bot, { guildId: bot.transformers.snowflake(payload.guild_id) });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
|
||||||
import type { PresenceUpdate } from "../../types/activity/presence_update.ts";
|
import type { PresenceUpdate } from "../../types/activity/presence_update.ts";
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||||
|
|
||||||
export async function handlePresenceUpdate(data: DiscordGatewayPayload) {
|
export async function handlePresenceUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as PresenceUpdate;
|
const payload = data.d as SnakeCasedPropertiesDeep<PresenceUpdate>;
|
||||||
|
|
||||||
const oldPresence = await cacheHandlers.get("presences", snowflakeToBigint(payload.user.id));
|
const id = bot.transformers.snowflake(payload.user.id);
|
||||||
await cacheHandlers.set("presences", snowflakeToBigint(payload.user.id), payload);
|
|
||||||
|
|
||||||
eventHandlers.presenceUpdate?.(payload, oldPresence);
|
const oldPresence = await bot.cache.presence.get(id);
|
||||||
|
const presence = bot.transformers.presence(bot, payload);
|
||||||
|
await bot.cache.presence.set(id, presence)
|
||||||
|
|
||||||
|
|
||||||
|
bot.events.presenceUpdate(bot, presence, oldPresence);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-62
@@ -1,67 +1,20 @@
|
|||||||
import { eventHandlers, setApplicationId, setBotId } from "../../bot.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
import { cache } from "../../cache.ts";
|
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import type { Ready } from "../../types/gateway/ready.ts";
|
import type { DiscordReady } from "../../types/gateway/ready.ts";
|
||||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
|
||||||
import { DiscordenoShard, ws } from "../../ws/ws.ts";
|
|
||||||
|
|
||||||
export function handleReady(data: DiscordGatewayPayload, shardId: number) {
|
export function handleReady(bot: Bot, data: DiscordGatewayPayload, shardId: number) {
|
||||||
|
const payload = data.d as DiscordReady;
|
||||||
// Triggered on each shard
|
// Triggered on each shard
|
||||||
eventHandlers.shardReady?.(shardId);
|
bot.events.ready(bot, {
|
||||||
|
shardId,
|
||||||
|
v: payload.v,
|
||||||
|
user: bot.transformers.user(bot, payload.user),
|
||||||
|
guilds: payload.guilds.map((p) => bot.transformers.snowflake(p.id)),
|
||||||
|
sessionId: payload.session_id,
|
||||||
|
shard: payload.shard,
|
||||||
|
applicationId: bot.transformers.snowflake(payload.application.id),
|
||||||
|
}, payload);
|
||||||
|
|
||||||
// The bot has already started, the last shard is resumed, however.
|
if (!bot.id) bot.id = bot.transformers.snowflake(payload.user.id);
|
||||||
if (cache.isReady) return;
|
if (!bot.applicationId) bot.applicationId = bot.transformers.snowflake(payload.application.id);
|
||||||
|
|
||||||
const shard = ws.shards.get(shardId);
|
|
||||||
if (!shard) return;
|
|
||||||
|
|
||||||
const payload = data.d as Ready;
|
|
||||||
setBotId(payload.user.id);
|
|
||||||
setApplicationId(payload.application.id);
|
|
||||||
|
|
||||||
// Set ready to false just to go sure
|
|
||||||
shard.ready = false;
|
|
||||||
// All guilds are unavailable at first
|
|
||||||
shard.unavailableGuildIds = new Set(payload.guilds.map((g) => snowflakeToBigint(g.id)));
|
|
||||||
|
|
||||||
// Falied to load check
|
|
||||||
shard.failedToLoadTimeoutId = setTimeout(() => {
|
|
||||||
eventHandlers.shardFailedToLoad?.(shard.id, shard.unavailableGuildIds);
|
|
||||||
// Force execute the loaded function to prevent infinite loop
|
|
||||||
return loaded(shard);
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function guildAvailable(shard: DiscordenoShard, guildId: bigint) {
|
|
||||||
if (!shard.failedToLoadTimeoutId) return;
|
|
||||||
|
|
||||||
clearTimeout(shard.failedToLoadTimeoutId);
|
|
||||||
shard.unavailableGuildIds.delete(guildId);
|
|
||||||
if (!shard.unavailableGuildIds.size) return loaded(shard);
|
|
||||||
|
|
||||||
shard.failedToLoadTimeoutId = setTimeout(() => {
|
|
||||||
eventHandlers.shardFailedToLoad?.(shard.id, shard.unavailableGuildIds);
|
|
||||||
// Force execute the loaded function to prevent infinite loop
|
|
||||||
return loaded(shard);
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function loaded(shard: DiscordenoShard) {
|
|
||||||
shard.ready = true;
|
|
||||||
|
|
||||||
// If it is not the last shard we can't go full ready
|
|
||||||
if (shard.id !== ws.lastShardId) return;
|
|
||||||
|
|
||||||
// Still some shards are loading so wait another 2 seconds for them
|
|
||||||
if (ws.shards.some((shard) => !shard.ready)) {
|
|
||||||
setTimeout(() => {
|
|
||||||
eventHandlers.debug?.("loop", `3. Running setTimeout in READY file.`);
|
|
||||||
loaded(shard);
|
|
||||||
}, 2000);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cache.isReady = true;
|
|
||||||
eventHandlers.ready?.();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import type { TypingStart } from "../../types/misc/typing_start.ts";
|
import type { TypingStart } from "../../types/misc/typing_start.ts";
|
||||||
|
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||||
|
|
||||||
export function handleTypingStart(data: DiscordGatewayPayload) {
|
export function handleTypingStart(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
eventHandlers.typingStart?.(data.d as TypingStart);
|
const payload = data.d as SnakeCasedPropertiesDeep<TypingStart>;
|
||||||
|
|
||||||
|
const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined;
|
||||||
|
|
||||||
|
bot.events.typingStart(bot, {
|
||||||
|
guildId,
|
||||||
|
channelId: bot.transformers.snowflake(payload.channel_id),
|
||||||
|
userId: bot.transformers.snowflake(payload.user_id),
|
||||||
|
timestamp: payload.timestamp,
|
||||||
|
member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId) : undefined,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,12 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
|
||||||
import { memberToggles } from "../../structures/member.ts";
|
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import type { User } from "../../types/users/user.ts";
|
import type { User } from "../../types/users/user.ts";
|
||||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||||
import { iconHashToBigInt } from "../../util/hash.ts";
|
|
||||||
|
|
||||||
export async function handleUserUpdate(data: DiscordGatewayPayload) {
|
export async function handleUserUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
const userData = data.d as User;
|
const payload = data.d as SnakeCasedPropertiesDeep<User>;
|
||||||
|
const user = bot.transformers.user(bot, payload);
|
||||||
|
await bot.cache.users.set(user.id, user);
|
||||||
|
|
||||||
const member = await cacheHandlers.get("members", snowflakeToBigint(userData.id));
|
bot.events.botUpdate(bot, user);
|
||||||
if (!member) return;
|
|
||||||
|
|
||||||
// Update username
|
|
||||||
member.username = userData.username;
|
|
||||||
// Update discriminator
|
|
||||||
member.discriminator = Number(userData.discriminator);
|
|
||||||
|
|
||||||
// Check if a avatar is available
|
|
||||||
const hash = userData.avatar ? iconHashToBigInt(userData.avatar) : undefined;
|
|
||||||
// Update the avatar
|
|
||||||
member.avatar = hash?.bigint || 0n;
|
|
||||||
// Update the animated status if its animated
|
|
||||||
if (hash?.animated) member.bitfield |= memberToggles.animatedAvatar;
|
|
||||||
else member.bitfield &= ~memberToggles.animatedAvatar;
|
|
||||||
|
|
||||||
member.flags = userData.flags;
|
|
||||||
member.premiumType = userData.premiumType;
|
|
||||||
member.publicFlags = userData.publicFlags;
|
|
||||||
|
|
||||||
await cacheHandlers.set("members", snowflakeToBigint(userData.id), member);
|
|
||||||
|
|
||||||
eventHandlers.botUpdate?.(userData);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
|
||||||
import { structures } from "../../structures/mod.ts";
|
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import type { GuildRoleCreate } from "../../types/guilds/guild_role_create.ts";
|
import type { GuildRoleCreate } from "../../types/guilds/guild_role_create.ts";
|
||||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||||
|
|
||||||
export async function handleGuildRoleCreate(data: DiscordGatewayPayload) {
|
export async function handleGuildRoleCreate(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as GuildRoleCreate;
|
const payload = data.d as SnakeCasedPropertiesDeep<GuildRoleCreate>;
|
||||||
const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId));
|
|
||||||
|
const guildId = bot.transformers.snowflake(payload.guild_id);
|
||||||
|
const guild = await bot.cache.guilds.get(guildId);
|
||||||
if (!guild) return;
|
if (!guild) return;
|
||||||
|
|
||||||
const role = await structures.createDiscordenoRole({
|
const role = bot.transformers.role(bot, { role: payload.role, guildId });
|
||||||
...payload,
|
|
||||||
guildId: guild.id,
|
|
||||||
});
|
|
||||||
guild.roles = guild.roles.set(snowflakeToBigint(payload.role.id), role);
|
|
||||||
await cacheHandlers.set("guilds", guild.id, guild);
|
|
||||||
|
|
||||||
eventHandlers.roleCreate?.(guild, role);
|
guild.roles = guild.roles.set(role.id, role);
|
||||||
|
await bot.cache.guilds.set(guild.id, guild);
|
||||||
|
|
||||||
|
bot.events.roleCreate(bot, guild, role);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import type { GuildRoleDelete } from "../../types/guilds/guild_role_delete.ts";
|
import type { GuildRoleDelete } from "../../types/guilds/guild_role_delete.ts";
|
||||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||||
|
|
||||||
export async function handleGuildRoleDelete(data: DiscordGatewayPayload) {
|
export async function handleGuildRoleDelete(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as GuildRoleDelete;
|
const payload = data.d as SnakeCasedPropertiesDeep<GuildRoleDelete>;
|
||||||
const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId));
|
const guildId = bot.transformers.snowflake(payload.guild_id);
|
||||||
|
const guild = await bot.cache.guilds.get(guildId);
|
||||||
if (!guild) return;
|
if (!guild) return;
|
||||||
|
|
||||||
const roleId = snowflakeToBigint(payload.roleId);
|
const roleId = bot.transformers.snowflake(payload.role_id);
|
||||||
|
|
||||||
const cachedRole = guild.roles.get(roleId)!;
|
const cachedRole = guild.roles.get(roleId);
|
||||||
guild.roles.delete(roleId);
|
guild.roles.delete(roleId);
|
||||||
|
|
||||||
if (cachedRole) eventHandlers.roleDelete?.(guild, cachedRole);
|
await bot.cache.guilds.set(guild.id, guild);
|
||||||
|
|
||||||
|
if (cachedRole) bot.events.roleDelete(bot, guild, cachedRole);
|
||||||
|
|
||||||
// For bots without GUILD_MEMBERS member.roles is never updated breaking permissions checking.
|
// For bots without GUILD_MEMBERS member.roles is never updated breaking permissions checking.
|
||||||
await cacheHandlers.forEach("DELETE_ROLE_FROM_MEMBER", { guildId: guild.id, roleId });
|
await bot.cache.execute("DELETE_ROLE_FROM_MEMBER", { guildId: guild.id, roleId });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,17 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
|
||||||
import { structures } from "../../structures/mod.ts";
|
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import type { GuildRoleUpdate } from "../../types/guilds/guild_role_update.ts";
|
import type { GuildRoleUpdate } from "../../types/guilds/guild_role_update.ts";
|
||||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||||
|
|
||||||
export async function handleGuildRoleUpdate(data: DiscordGatewayPayload) {
|
export async function handleGuildRoleUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as GuildRoleUpdate;
|
const payload = data.d as SnakeCasedPropertiesDeep<GuildRoleUpdate>;
|
||||||
const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId));
|
const guildId = bot.transformers.snowflake(payload.guild_id);
|
||||||
|
const guild = await bot.cache.guilds.get(guildId);
|
||||||
if (!guild) return;
|
if (!guild) return;
|
||||||
|
|
||||||
const cachedRole = guild.roles.get(snowflakeToBigint(payload.role.id));
|
const role = bot.transformers.role(bot, { role: payload.role, guildId });
|
||||||
if (!cachedRole) return;
|
guild.roles = guild.roles.set(role.id, role);
|
||||||
|
await bot.cache.guilds.set(guild.id, guild);
|
||||||
|
|
||||||
const role = await structures.createDiscordenoRole({
|
bot.events.roleUpdate(bot, guild, role, guild.roles.get(role.id));
|
||||||
...payload,
|
|
||||||
guildId: guild.id,
|
|
||||||
});
|
|
||||||
guild.roles.set(snowflakeToBigint(payload.role.id), role);
|
|
||||||
await cacheHandlers.set("guilds", guild.id, guild);
|
|
||||||
|
|
||||||
eventHandlers.roleUpdate?.(guild, role, cachedRole);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import type { VoiceServerUpdate } from "../../types/voice/voice_server_update.ts";
|
import type { VoiceServerUpdate } from "../../types/voice/voice_server_update.ts";
|
||||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
|
||||||
|
|
||||||
export async function handleVoiceServerUpdate(data: DiscordGatewayPayload) {
|
export async function handleVoiceServerUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as VoiceServerUpdate;
|
const payload = data.d as SnakeCasedPropertiesDeep<VoiceServerUpdate>;
|
||||||
|
|
||||||
const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId));
|
bot.events.voiceServerUpdate(bot, {
|
||||||
if (!guild) return;
|
token: payload.token,
|
||||||
|
guildId: bot.transformers.snowflake(payload.guild_id),
|
||||||
eventHandlers.voiceServerUpdate?.(payload, guild);
|
endpoint: payload.endpoint ?? undefined,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,23 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
|
||||||
import { structures } from "../../structures/mod.ts";
|
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import type { VoiceState } from "../../types/voice/voice_state.ts";
|
import type { VoiceState } from "../../types/voice/voice_state.ts";
|
||||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
|
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||||
|
|
||||||
export async function handleVoiceStateUpdate(data: DiscordGatewayPayload) {
|
export async function handleVoiceStateUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as VoiceState;
|
const payload = data.d as SnakeCasedPropertiesDeep<VoiceState>;
|
||||||
if (!payload.guildId) return;
|
if (!payload.guild_id) return;
|
||||||
|
|
||||||
const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId));
|
const guildId = bot.transformers.snowflake(payload.guild_id);
|
||||||
if (!guild) return;
|
const voiceState = bot.transformers.voiceState(bot, { voiceState: payload, guildId });
|
||||||
|
|
||||||
const member = payload.member
|
const guild = await bot.cache.guilds.get(guildId);
|
||||||
? await structures.createDiscordenoMember(payload.member, guild.id)
|
if (guild) {
|
||||||
: await cacheHandlers.get("members", snowflakeToBigint(payload.userId));
|
guild.voiceStates.set(voiceState.userId, voiceState);
|
||||||
if (!member) return;
|
await bot.cache.guilds.set(guild.id, guild);
|
||||||
|
|
||||||
if (!payload.member?.joinedAt) return eventHandlers.lurkerVoiceStateUpdate?.(member, payload);
|
|
||||||
|
|
||||||
// No cached state before so lets make one for em
|
|
||||||
const cachedState = guild.voiceStates.get(snowflakeToBigint(payload.userId));
|
|
||||||
|
|
||||||
guild.voiceStates.set(
|
|
||||||
snowflakeToBigint(payload.userId),
|
|
||||||
await structures.createDiscordenoVoiceState(guild.id, payload)
|
|
||||||
);
|
|
||||||
|
|
||||||
await cacheHandlers.set("guilds", guild.id, guild);
|
|
||||||
|
|
||||||
if (cachedState?.channelId !== (payload.channelId ? snowflakeToBigint(payload.channelId) : null)) {
|
|
||||||
// Either joined or moved channels
|
|
||||||
if (payload.channelId) {
|
|
||||||
if (cachedState?.channelId) {
|
|
||||||
// Was in a channel before
|
|
||||||
eventHandlers.voiceChannelSwitch?.(member, snowflakeToBigint(payload.channelId), cachedState.channelId);
|
|
||||||
} else {
|
|
||||||
// Was not in a channel before so user just joined
|
|
||||||
eventHandlers.voiceChannelJoin?.(member, snowflakeToBigint(payload.channelId));
|
|
||||||
}
|
|
||||||
} // Left the channel
|
|
||||||
else if (cachedState?.channelId) {
|
|
||||||
guild.voiceStates.delete(snowflakeToBigint(payload.userId));
|
|
||||||
eventHandlers.voiceChannelLeave?.(member, cachedState.channelId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eventHandlers.voiceStateUpdate?.(member, payload);
|
const member = payload.member ? bot.transformers.member(bot, payload.member, guildId) : undefined;
|
||||||
|
const user = payload.member ? bot.transformers.user(bot, payload.member.user) : undefined;
|
||||||
|
|
||||||
|
bot.events.voiceStateUpdate(bot, voiceState, { guild, member, user });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
|
||||||
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import type { WebhookUpdate } from "../../types/webhooks/webhooks_update.ts";
|
import type { WebhookUpdate } from "../../types/webhooks/webhooks_update.ts";
|
||||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
import { Bot } from "../../bot.ts";
|
||||||
|
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||||
|
|
||||||
export function handleWebhooksUpdate(data: DiscordGatewayPayload) {
|
export function handleWebhooksUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||||
const options = data.d as WebhookUpdate;
|
const payload = data.d as SnakeCasedPropertiesDeep<WebhookUpdate>;
|
||||||
eventHandlers.webhooksUpdate?.(snowflakeToBigint(options.channelId), snowflakeToBigint(options.guildId));
|
bot.events.webhooksUpdate(bot, {
|
||||||
|
channelId: bot.transformers.snowflake(payload.channel_id),
|
||||||
|
guildId: bot.transformers.snowflake(payload.guild_id),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import { Bot } from "../bot.ts";
|
||||||
|
import { Activity } from "../types/activity/activity.ts";
|
||||||
|
import { DiscordActivityTypes } from "../types/activity/activity_types.ts";
|
||||||
|
import { SnakeCasedPropertiesDeep } from "../types/util.ts";
|
||||||
|
import { DiscordenoEmoji } from "./emoji.ts";
|
||||||
|
|
||||||
|
export function transformActivity(bot: Bot, payload: SnakeCasedPropertiesDeep<Activity>): DiscordenoActivity {
|
||||||
|
return {
|
||||||
|
name: payload.name,
|
||||||
|
type: payload.type,
|
||||||
|
url: payload.url ?? undefined,
|
||||||
|
createdAt: payload.created_at,
|
||||||
|
startedAt: payload.timestamps?.start,
|
||||||
|
endedAt: payload.timestamps?.end,
|
||||||
|
applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined,
|
||||||
|
details: payload.details ?? undefined,
|
||||||
|
state: payload.state ?? undefined,
|
||||||
|
emoji: payload.emoji ? bot.transformers.emoji(bot, payload.emoji) : undefined,
|
||||||
|
partyId: payload.party?.id,
|
||||||
|
partyCurrentSize: payload.party?.size?.[0],
|
||||||
|
partyMaxSize: payload.party?.size?.[1],
|
||||||
|
largeImage: payload.assets?.large_image,
|
||||||
|
largeText: payload.assets?.large_text,
|
||||||
|
smallImage: payload.assets?.small_image,
|
||||||
|
smallText: payload.assets?.small_text,
|
||||||
|
join: payload.secrets?.join,
|
||||||
|
spectate: payload.secrets?.spectate,
|
||||||
|
match: payload.secrets?.match,
|
||||||
|
instance: payload.instance,
|
||||||
|
flags: payload.flags,
|
||||||
|
buttonLabels: payload.buttons?.map((button) => button.label),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DiscordenoActivity {
|
||||||
|
/** The activity's name */
|
||||||
|
name: string;
|
||||||
|
/** Activity type */
|
||||||
|
type: DiscordActivityTypes;
|
||||||
|
/** Stream url, is validated when type is 1 */
|
||||||
|
url?: string;
|
||||||
|
/** Unix timestamp of when the activity was added to the user's session */
|
||||||
|
createdAt: number;
|
||||||
|
/** Unix time (in milliseconds) of when the activity started */
|
||||||
|
startedAt?: number;
|
||||||
|
/** Unix time (in milliseconds) of when the activity ends */
|
||||||
|
endedAt?: number;
|
||||||
|
/** Application id for the game */
|
||||||
|
applicationId?: bigint;
|
||||||
|
/** What the player is currently doing */
|
||||||
|
details?: string;
|
||||||
|
/** The user's current party status */
|
||||||
|
state?: string;
|
||||||
|
/** The emoji used for a custom status */
|
||||||
|
emoji?: DiscordenoEmoji;
|
||||||
|
/** the id of the party */
|
||||||
|
partyId?: string;
|
||||||
|
/** The current size of the party if one exists */
|
||||||
|
partyCurrentSize?: number;
|
||||||
|
/** The max size of the party if one exists */
|
||||||
|
partyMaxSize?: number;
|
||||||
|
/** The id for a large asset of the activity, usually a snowflake */
|
||||||
|
largeImage?: string;
|
||||||
|
/** Text displayed when hovering over the large image of the activity */
|
||||||
|
largeText?: string;
|
||||||
|
/** The id for a small asset of the activity, usually a snowflake */
|
||||||
|
smallImage?: string;
|
||||||
|
/** Text displayed when hovering over the small image of the activity */
|
||||||
|
smallText?: string;
|
||||||
|
/** The secret for joining a party */
|
||||||
|
join?: string;
|
||||||
|
/** The secret for spectating a game */
|
||||||
|
spectate?: string;
|
||||||
|
/** The secret for a specific instanced match */
|
||||||
|
match?: string;
|
||||||
|
/** Whether or not the activity is an instanced game session */
|
||||||
|
instance?: boolean;
|
||||||
|
/** Activity flags `OR`d together, describes what the payload includes */
|
||||||
|
flags?: number;
|
||||||
|
/** The custom button's labels shown in the Rich Presence */
|
||||||
|
buttonLabels?: string[];
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { Bot } from "../bot.ts";
|
||||||
|
import { PresenceUpdate } from "../types/activity/presence_update.ts";
|
||||||
|
import { SnakeCasedPropertiesDeep } from "../types/util.ts";
|
||||||
|
import { DiscordenoActivity } from "./activity.ts";
|
||||||
|
import { DiscordenoUser } from "./member.ts";
|
||||||
|
|
||||||
|
export const statusTypes = {
|
||||||
|
online: 0,
|
||||||
|
dnd: 1,
|
||||||
|
idle: 2,
|
||||||
|
invisible: 3,
|
||||||
|
offline: 4,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export function transformPresence(bot: Bot, payload: SnakeCasedPropertiesDeep<PresenceUpdate>): DiscordenoPresence {
|
||||||
|
return {
|
||||||
|
user: bot.transformers.user(bot, payload.user),
|
||||||
|
guildId: bot.transformers.snowflake(payload.guild_id),
|
||||||
|
status: statusTypes[payload.status],
|
||||||
|
activities: payload.activities.map((activity) => bot.transformers.activity(bot, activity)),
|
||||||
|
desktop: payload.client_status.desktop,
|
||||||
|
mobile: payload.client_status.mobile,
|
||||||
|
web: payload.client_status.web,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DiscordenoPresence {
|
||||||
|
/** The user presence is being updated for */
|
||||||
|
user: DiscordenoUser;
|
||||||
|
/** id of the guild */
|
||||||
|
guildId: bigint;
|
||||||
|
/** Either online: 0, dnd: 1, idle: 2, invisible: 3, offline: 4 */
|
||||||
|
status: 0 | 1 | 2 | 3 | 4;
|
||||||
|
/** User's current activities */
|
||||||
|
activities: DiscordenoActivity[];
|
||||||
|
/** The user's status set for an active desktop (Windows, Linux, Mac) application session */
|
||||||
|
desktop?: string;
|
||||||
|
/** The user's status set for an active mobile (iOS, Android) application session */
|
||||||
|
mobile?: string;
|
||||||
|
/** The user's status set for an active web (browser, bot account) application session */
|
||||||
|
web?: string;
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ export function transformVoiceState(
|
|||||||
(payload.voiceState.self_video ? 32n : 0n) |
|
(payload.voiceState.self_video ? 32n : 0n) |
|
||||||
(payload.voiceState.suppress ? 64n : 0n),
|
(payload.voiceState.suppress ? 64n : 0n),
|
||||||
|
|
||||||
requestToSpeakTimestamp: payload.voiceState.request_to_speak_timestamp,
|
requestToSpeakTimestamp: payload.voiceState.request_to_speak_timestamp ? Date.parse(payload.voiceState.request_to_speak_timestamp) : undefined,
|
||||||
sessionId: payload.voiceState.session_id,
|
sessionId: payload.voiceState.session_id,
|
||||||
|
|
||||||
channelId: payload.voiceState.channel_id ? bot.transformers.snowflake(payload.voiceState.channel_id) : undefined,
|
channelId: payload.voiceState.channel_id ? bot.transformers.snowflake(payload.voiceState.channel_id) : undefined,
|
||||||
@@ -27,7 +27,7 @@ export function transformVoiceState(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DiscordenoVoiceState extends Omit<VoiceState, "channelId" | "guildId" | "userId" | "member"> {
|
export interface DiscordenoVoiceState {
|
||||||
/** The guild id */
|
/** The guild id */
|
||||||
guildId: bigint;
|
guildId: bigint;
|
||||||
/** The channel id this user is connected to */
|
/** The channel id this user is connected to */
|
||||||
@@ -36,4 +36,6 @@ export interface DiscordenoVoiceState extends Omit<VoiceState, "channelId" | "gu
|
|||||||
userId: bigint;
|
userId: bigint;
|
||||||
/** Holds all the boolean toggles. */
|
/** Holds all the boolean toggles. */
|
||||||
bitfield: bigint;
|
bitfield: bigint;
|
||||||
|
/** The time at which the user requested to speak */
|
||||||
|
requestToSpeakTimestamp?: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
/** https://discord.com/developers/docs/topics/gateway#update-status-status-types */
|
/** https://discord.com/developers/docs/topics/gateway#update-status-status-types */
|
||||||
export type DiscordStatusTypes = "online" | "dnd" | "idle" | "invisible" | "offline";
|
export type DiscordStatusTypes = "online" | "dnd" | "idle" | "invisible" | "offline";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user