diff --git a/src/cache.ts b/src/cache.ts index eeb863a99..92c53cc66 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -170,58 +170,80 @@ async function get(table: TableName, key: bigint) { return cache[table].get(key); } -function forEach( - table: "threads", - callback: (value: DiscordenoThread, key: bigint, map: Map) => unknown -): void; -function forEach( - table: "guilds", - callback: (value: DiscordenoGuild, key: bigint, map: Map) => unknown -): void; -function forEach( - table: "unavailableGuilds", - callback: (value: number, key: bigint, map: Map) => unknown -): void; -function forEach( - table: "channels", - callback: (value: DiscordenoChannel, key: bigint, map: Map) => unknown -): void; -function forEach( - table: "messages", - callback: (value: DiscordenoMessage, key: bigint, map: Map) => unknown -): void; -function forEach( - table: "members", - callback: (value: DiscordenoMember, key: bigint, map: Map) => unknown -): void; -function forEach(table: TableName, callback: (value: any, key: bigint, map: Map) => unknown) { - return cache[table].forEach(callback); +// callback: (value: DiscordenoThread, key: bigint, map: Map) => void +async function forEach(type: "DELETE_MESSAGES_FROM_CHANNEL", options: { channelId: bigint }): Promise; +async function forEach(type: "DELETE_MESSAGES_FROM_GUILD", options: { guildId: bigint }): Promise; +async function forEach(type: "DELETE_CHANNELS_FROM_GUILD", options: { guildId: bigint }): Promise; +async function forEach(type: "DELETE_GUILD_FROM_MEMBER", options: { guildId: bigint }): Promise; +async function forEach(type: "DELETE_ROLE_FROM_MEMBER", options: { guildId: bigint; roleId: bigint }): Promise; +async function forEach( + type: + | "DELETE_MESSAGES_FROM_CHANNEL" + | "DELETE_MESSAGES_FROM_GUILD" + | "DELETE_CHANNELS_FROM_GUILD" + | "DELETE_GUILD_FROM_MEMBER" + | "DELETE_ROLE_FROM_MEMBER", + options?: Record +) { + if (type === "DELETE_MESSAGES_FROM_CHANNEL") { + cache.messages.forEach((message) => { + if (message.channelId === options?.channelId) cache.messages.delete(message.id); + }); + return; + } + + if (type === "DELETE_MESSAGES_FROM_GUILD") { + cache.messages.forEach((message) => { + if (message.guildId === options?.guildId) cache.messages.delete(message.id); + }); + return; + } + + if (type === "DELETE_CHANNELS_FROM_GUILD") { + cache.channels.forEach((channel) => { + if (channel.guildId === options?.guildId) cache.channels.delete(channel.id); + }); + return; + } + + if (type === "DELETE_GUILD_FROM_MEMBER") { + cache.members.forEach((member) => { + if (!member.guilds.has(options?.guildId as bigint)) return; + + member.guilds.delete(options?.guildId as bigint); + + if (!member.guilds.size) { + return cache.members.delete(member.id); + } + + cache.members.set(member.id, member); + }); + return; + } + + if (type === "DELETE_ROLE_FROM_MEMBER") { + cache.members.forEach((member) => { + // Not in the relevant guild so just skip + if (!member.guilds.has(options?.guildId as bigint)) return; + + const guildMember = member.guilds.get(options?.guildId as bigint)!; + + guildMember.roles = guildMember.roles.filter((id) => id !== (options?.roleId as bigint)); + cache.members.set(member.id, member); + }); + return; + } } async function filter( - table: "threads", - callback: (value: DiscordenoThread, key: bigint) => boolean -): Promise>; -async function filter( - table: "guilds", - callback: (value: DiscordenoGuild, key: bigint) => boolean -): Promise>; -async function filter( - table: "unavailableGuilds", - callback: (value: number, key: bigint) => boolean -): Promise>; -async function filter( - table: "channels", - callback: (value: DiscordenoChannel, key: bigint) => boolean -): Promise>; -async function filter( - table: "messages", - callback: (value: DiscordenoMessage, key: bigint) => boolean -): Promise>; -async function filter( - table: "members", - callback: (value: DiscordenoMember, key: bigint) => boolean + type: "GET_MEMBERS_IN_GUILD", + options: { guildId: bigint } ): Promise>; -async function filter(table: TableName, callback: (value: any, key: bigint) => boolean) { - return cache[table].filter(callback); +async function filter( + type: "GET_MEMBERS_IN_GUILD", + options?: Record +): Promise | undefined> { + if (type === "GET_MEMBERS_IN_GUILD") { + return cache.members.filter((member) => member.guilds.has(options?.guildId as bigint)); + } } diff --git a/src/handlers/channels/CHANNEL_DELETE.ts b/src/handlers/channels/CHANNEL_DELETE.ts index 72feac12a..d0626aabf 100644 --- a/src/handlers/channels/CHANNEL_DELETE.ts +++ b/src/handlers/channels/CHANNEL_DELETE.ts @@ -40,12 +40,7 @@ export async function handleChannelDelete(data: DiscordGatewayPayload) { ].includes(payload.type) ) { await cacheHandlers.delete("channels", snowflakeToBigint(payload.id)); - cacheHandlers.forEach("messages", (message) => { - eventHandlers.debug?.("loop", `Running forEach messages loop in CHANNEL_DELTE file.`); - if (message.channelId === snowflakeToBigint(payload.id)) { - cacheHandlers.delete("messages", message.id); - } - }); + await cacheHandlers.forEach("DELETE_MESSAGES_FROM_CHANNEL", { channelId: snowflakeToBigint(payload.id) }); } await cacheHandlers.delete("channels", snowflakeToBigint(payload.id)); diff --git a/src/handlers/channels/THREAD_DELETE.ts b/src/handlers/channels/THREAD_DELETE.ts index 96a2d7ac6..a713e742f 100644 --- a/src/handlers/channels/THREAD_DELETE.ts +++ b/src/handlers/channels/THREAD_DELETE.ts @@ -11,12 +11,7 @@ export async function handleThreadDelete(data: DiscordGatewayPayload) { if (!cachedChannel) return; await cacheHandlers.delete("threads", snowflakeToBigint(payload.id)); - cacheHandlers.forEach("messages", (message) => { - eventHandlers.debug?.("loop", `Running forEach messages loop in THREAD_DELETE file.`); - if (message.channelId === snowflakeToBigint(payload.id)) { - cacheHandlers.delete("messages", message.id); - } - }); + await cacheHandlers.forEach("DELETE_MESSAGES_FROM_CHANNEL", { channelId: snowflakeToBigint(payload.id) }); eventHandlers.threadDelete?.(cachedChannel); } diff --git a/src/handlers/guilds/GUILD_DELETE.ts b/src/handlers/guilds/GUILD_DELETE.ts index 4235e351e..b2d96db48 100644 --- a/src/handlers/guilds/GUILD_DELETE.ts +++ b/src/handlers/guilds/GUILD_DELETE.ts @@ -23,30 +23,9 @@ export async function handleGuildDelete(data: DiscordGatewayPayload, shardId: nu eventHandlers.guildDelete?.(guild); } - cacheHandlers.forEach("messages", (message) => { - eventHandlers.debug?.("loop", `1. Running forEach messages loop in CHANNEL_DELTE file.`); - if (message.guildId === guild.id) { - cacheHandlers.delete("messages", message.id); - } - }); - - cacheHandlers.forEach("channels", (channel) => { - eventHandlers.debug?.("loop", `2. Running forEach channels loop in CHANNEL_DELTE file.`); - if (channel.guildId === guild.id) { - cacheHandlers.delete("channels", channel.id); - } - }); - - cacheHandlers.forEach("members", (member) => { - eventHandlers.debug?.("loop", `3. Running forEach members loop in CHANNEL_DELTE file.`); - if (!member.guilds.has(guild.id)) return; - - member.guilds.delete(guild.id); - - if (!member.guilds.size) { - return cacheHandlers.delete("members", member.id); - } - - cacheHandlers.set("members", member.id, member); - }); + await Promise.all([ + cacheHandlers.forEach("DELETE_MESSAGES_FROM_GUILD", { guildId: guild.id }), + cacheHandlers.forEach("DELETE_CHANNELS_FROM_GUILD", { guildId: guild.id }), + cacheHandlers.forEach("DELETE_GUILD_FROM_MEMBER", { guildId: guild.id }), + ]); } diff --git a/src/handlers/members/GUILD_MEMBERS_CHUNK.ts b/src/handlers/members/GUILD_MEMBERS_CHUNK.ts index 006eda9f8..61a326e8f 100644 --- a/src/handlers/members/GUILD_MEMBERS_CHUNK.ts +++ b/src/handlers/members/GUILD_MEMBERS_CHUNK.ts @@ -31,7 +31,7 @@ export async function handleGuildMembersChunk(data: DiscordGatewayPayload) { return resolve(new Collection(members.map((m) => [m.id, m]))); } - return resolve(await cacheHandlers.filter("members", (m) => m.guilds.has(guildId))); + return resolve(await cacheHandlers.filter("GET_MEMBERS_IN_GUILD", { guildId })); } } } diff --git a/src/handlers/roles/GUILD_ROLE_DELETE.ts b/src/handlers/roles/GUILD_ROLE_DELETE.ts index 171286373..24f914d50 100644 --- a/src/handlers/roles/GUILD_ROLE_DELETE.ts +++ b/src/handlers/roles/GUILD_ROLE_DELETE.ts @@ -17,18 +17,5 @@ export async function handleGuildRoleDelete(data: DiscordGatewayPayload) { if (cachedRole) eventHandlers.roleDelete?.(guild, cachedRole); // For bots without GUILD_MEMBERS member.roles is never updated breaking permissions checking. - cacheHandlers.forEach("members", (member) => { - eventHandlers.debug?.("loop", `1. Running forEach members loop in GUILD_ROLE_DELETE file.`); - // Not in the relevant guild so just skip. - if (!member.guilds.has(guild.id)) return; - - member.guilds.forEach((g) => { - eventHandlers.debug?.("loop", `2. Running forEach loop in CHANNEL_DELTE file.`); - // Member does not have this role - if (!g.roles.includes(roleId)) return; - // Remove this role from the members cache - g.roles = g.roles.filter((id) => id !== roleId); - cacheHandlers.set("members", member.id, member); - }); - }); + await cacheHandlers.forEach("DELETE_ROLE_FROM_MEMBER", { guildId: guild.id, roleId }); } diff --git a/src/helpers/channels/category_children.ts b/src/helpers/channels/category_children.ts index b3c32e520..c0f31ad83 100644 --- a/src/helpers/channels/category_children.ts +++ b/src/helpers/channels/category_children.ts @@ -1,6 +1,8 @@ -import { cacheHandlers } from "../../cache.ts"; +import { cache } from "../../cache.ts"; -/** Gets an array of all the channels ids that are the children of this category. */ -export async function categoryChildren(id: bigint) { - return await cacheHandlers.filter("channels", (channel) => channel.parentId === id); +/** Gets an array of all the channels ids that are the children of this category. + * ⚠️ This does not work for custom cache users! + */ +export function categoryChildren(parentChannelId: bigint) { + return cache.channels.filter((channel) => channel.parentId === parentChannelId); }