From 5f66c7950ddad291453980c36b5c5cf0992f8215 Mon Sep 17 00:00:00 2001 From: ITOH Date: Thu, 8 Jul 2021 19:47:54 +0200 Subject: [PATCH 1/5] change(cacheHandlers): forEach logic --- src/cache.ts | 90 ++++++++++++++++++------- src/handlers/channels/CHANNEL_DELETE.ts | 7 +- src/handlers/channels/THREAD_DELETE.ts | 7 +- src/handlers/guilds/GUILD_DELETE.ts | 31 ++------- 4 files changed, 71 insertions(+), 64 deletions(-) diff --git a/src/cache.ts b/src/cache.ts index eeb863a99..13e8cdec3 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -14,6 +14,7 @@ import { GuildMemberWithUser } from "./types/members/guild_member.ts"; import { Message } from "./types/messages/message.ts"; import { Role } from "./types/permissions/role.ts"; import { VoiceState } from "./types/voice/voice_state.ts"; +import { snowflakeToBigint } from "./util/bigint.ts"; export const cache = { isReady: false, @@ -170,32 +171,69 @@ 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( 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 }), + ]); } From ea0673c25962d62baed835f5f2f8cd24051ef29c Mon Sep 17 00:00:00 2001 From: ITOH Date: Thu, 8 Jul 2021 19:54:55 +0200 Subject: [PATCH 2/5] change filter logic --- src/cache.ts | 61 +++++++++++++-------- src/handlers/members/GUILD_MEMBERS_CHUNK.ts | 2 +- src/helpers/channels/category_children.ts | 10 ++-- 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/src/cache.ts b/src/cache.ts index 13e8cdec3..d862d6338 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -236,30 +236,43 @@ async function forEach( } } +// 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 +// ): Promise>; +// async function filter(table: TableName, callback: (value: any, key: bigint) => boolean) { +// return cache[table].filter(callback); +// } + 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/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/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); } From 0ef5f18a6939d5572d38de3b1731dcfa5f9525a9 Mon Sep 17 00:00:00 2001 From: ITOH Date: Thu, 8 Jul 2021 20:00:48 +0200 Subject: [PATCH 3/5] Update cache.ts --- src/cache.ts | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/cache.ts b/src/cache.ts index d862d6338..93d104ab2 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -236,34 +236,6 @@ async function forEach( } } -// 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 -// ): 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: { guildId: bigint } From 05f74d4796e8ac5e62e106a48977dc08f6a740bc Mon Sep 17 00:00:00 2001 From: ITOH Date: Fri, 9 Jul 2021 16:38:49 +0200 Subject: [PATCH 4/5] Update GUILD_ROLE_DELETE.ts --- src/handlers/roles/GUILD_ROLE_DELETE.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) 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 }); } From 307d07b1cf9fe5f343f4b2cd228831958c84bac8 Mon Sep 17 00:00:00 2001 From: ITOH Date: Fri, 9 Jul 2021 16:41:21 +0200 Subject: [PATCH 5/5] unused import --- src/cache.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cache.ts b/src/cache.ts index 93d104ab2..92c53cc66 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -14,7 +14,6 @@ import { GuildMemberWithUser } from "./types/members/guild_member.ts"; import { Message } from "./types/messages/message.ts"; import { Role } from "./types/permissions/role.ts"; import { VoiceState } from "./types/voice/voice_state.ts"; -import { snowflakeToBigint } from "./util/bigint.ts"; export const cache = { isReady: false,