From 53892a230dc471deb0f26c6551148c6fd4ea64c9 Mon Sep 17 00:00:00 2001 From: Jeroen Claassens Date: Sat, 6 Apr 2024 16:31:15 +0200 Subject: [PATCH 1/3] feat: add option to retry bulk overwrites --- src/index.ts | 4 + .../ApplicationCommandRegistries.ts | 123 +++++++++++------- 2 files changed, 82 insertions(+), 45 deletions(-) diff --git a/src/index.ts b/src/index.ts index 295c2c031..876a414aa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,10 @@ import { acquire, + getBulkRegisterCommandRetries, getDefaultBehaviorWhenNotIdentical, getDefaultGuildIds, registries, + setBulkRegisterCommandRetries, setDefaultBehaviorWhenNotIdentical, setDefaultGuildIds } from './lib/utils/application-commands/ApplicationCommandRegistries'; @@ -27,8 +29,10 @@ const ApplicationCommandRegistries = { acquire, setDefaultBehaviorWhenNotIdentical, setDefaultGuildIds, + setBulkRegisterCommandRetries, getDefaultGuildIds, getDefaultBehaviorWhenNotIdentical, + getBulkRegisterCommandRetries, get registries(): ReadonlyMap { return registries; } diff --git a/src/lib/utils/application-commands/ApplicationCommandRegistries.ts b/src/lib/utils/application-commands/ApplicationCommandRegistries.ts index 789e9fec1..092014c23 100644 --- a/src/lib/utils/application-commands/ApplicationCommandRegistries.ts +++ b/src/lib/utils/application-commands/ApplicationCommandRegistries.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/dot-notation */ import { container } from '@sapphire/pieces'; +import { retry } from '@sapphire/utilities'; import type { RESTPostAPIApplicationCommandsJSONBody } from 'discord-api-types/v10'; import { ApplicationCommandType, type ApplicationCommandManager } from 'discord.js'; import type { Command } from '../../structures/Command'; @@ -13,6 +14,7 @@ import { bulkOverwriteDebug, bulkOverwriteInfo, bulkOverwriteWarn } from './regi export let defaultBehaviorWhenNotIdentical = RegisterBehavior.Overwrite; export let defaultGuildIds: ApplicationCommandRegistry.RegisterOptions['guildIds'] = undefined; +let bulkRegisterCommandRetries = 1; export const registries = new Map(); @@ -62,6 +64,20 @@ export function getDefaultGuildIds() { return defaultGuildIds; } +/** + * Sets the amount of retries for when registering commands, only applies when {@link defaultBehaviorWhenNotIdentical} + * is set to {@link RegisterBehavior.BulkOverwrite}. This is used if registering the commands fails. + * The default value is `1`, which means no retries are performed. + * @param newAmountOfRetries The new amount of retries to set. Set this to `null` to reset it to the default + */ +export function setBulkRegisterCommandRetries(newAmountOfRetries: number | null) { + bulkRegisterCommandRetries = newAmountOfRetries ?? 1; +} + +export function getBulkRegisterCommandRetries() { + return bulkRegisterCommandRetries; +} + export async function handleRegistryAPICalls() { container.client.emit(Events.ApplicationCommandRegistriesInitialising); @@ -115,6 +131,21 @@ export async function handleBulkOverwrite(commandStore: CommandStore, applicatio } // Handle global commands + await retry(() => handleBulkOverwriteGlobalCommands(commandStore, applicationCommands, foundGlobalCommands), bulkRegisterCommandRetries); + + // Handle guild commands + for (const [guildId, guildCommands] of Object.entries(foundGuildCommands)) { + await retry(() => handleBulkOverwriteGuildCommands(commandStore, applicationCommands, guildId, guildCommands), bulkRegisterCommandRetries); + } + + container.client.emit(Events.ApplicationCommandRegistriesRegistered, registries, Date.now() - now); +} + +async function handleBulkOverwriteGlobalCommands( + commandStore: CommandStore, + applicationCommands: ApplicationCommandManager, + foundGlobalCommands: BulkOverwriteData[] +) { try { bulkOverwriteDebug(`Overwriting global application commands, now at ${foundGlobalCommands.length} commands`); const result = await applicationCommands.set(foundGlobalCommands.map((x) => x.data)); @@ -152,57 +183,59 @@ export async function handleBulkOverwrite(commandStore: CommandStore, applicatio } catch (error) { emitBulkOverwriteError(error, null); } +} - // Handle guild commands - for (const [guildId, guildCommands] of Object.entries(foundGuildCommands)) { - try { - bulkOverwriteDebug(`Overwriting guild application commands for guild ${guildId}, now at ${guildCommands.length} commands`); - const result = await applicationCommands.set( - guildCommands.map((x) => x.data), - guildId - ); - - // Go through each registered command, find its piece and alias it - for (const [id, guildCommand] of result.entries()) { - // I really hope nobody has a guild command with the same name as another command -.- - // Not like they could anyways as Discord would throw an error for duplicate names - // But yknow... If you're reading this and you did this... Why? - const piece = guildCommands.find((x) => x.data.name === guildCommand.name)?.piece; - - if (piece) { - const registry = piece.applicationCommandRegistry; - - switch (guildCommand.type) { - case ApplicationCommandType.ChatInput: { - registry['handleIdAddition'](InternalRegistryAPIType.ChatInput, id, guildId); - break; - } - case ApplicationCommandType.User: - case ApplicationCommandType.Message: { - registry['handleIdAddition'](InternalRegistryAPIType.ContextMenu, id, guildId); - break; - } - } +async function handleBulkOverwriteGuildCommands( + commandStore: CommandStore, + applicationCommands: ApplicationCommandManager, + guildId: string, + guildCommands: BulkOverwriteData[] +) { + try { + bulkOverwriteDebug(`Overwriting guild application commands for guild ${guildId}, now at ${guildCommands.length} commands`); + const result = await applicationCommands.set( + guildCommands.map((x) => x.data), + guildId + ); - // idHints are useless, and any manually added ids or names could no longer be valid if you use bulk overwrites. - // That said, this might be an issue, so we might need to do it like `handleAppendOrUpdate` - commandStore.aliases.set(id, piece); - } else { - bulkOverwriteWarn( - `Registered guild command "${guildCommand.name}" (${id}) but failed to find the piece in the command store. This should not happen` - ); + // Go through each registered command, find its piece and alias it + for (const [id, guildCommand] of result.entries()) { + // I really hope nobody has a guild command with the same name as another command -.- + // Not like they could anyways as Discord would throw an error for duplicate names + // But yknow... If you're reading this and you did this... Why? + const piece = guildCommands.find((x) => x.data.name === guildCommand.name)?.piece; + + if (piece) { + const registry = piece.applicationCommandRegistry; + + switch (guildCommand.type) { + case ApplicationCommandType.ChatInput: { + registry['handleIdAddition'](InternalRegistryAPIType.ChatInput, id, guildId); + break; + } + case ApplicationCommandType.User: + case ApplicationCommandType.Message: { + registry['handleIdAddition'](InternalRegistryAPIType.ContextMenu, id, guildId); + break; + } } - } - bulkOverwriteInfo( - `Successfully overwrote guild application commands for guild ${guildId}. The application now has ${result.size} guild commands for guild ${guildId}` - ); - } catch (error) { - emitBulkOverwriteError(error, guildId); + // idHints are useless, and any manually added ids or names could no longer be valid if you use bulk overwrites. + // That said, this might be an issue, so we might need to do it like `handleAppendOrUpdate` + commandStore.aliases.set(id, piece); + } else { + bulkOverwriteWarn( + `Registered guild command "${guildCommand.name}" (${id}) but failed to find the piece in the command store. This should not happen` + ); + } } - } - container.client.emit(Events.ApplicationCommandRegistriesRegistered, registries, Date.now() - now); + bulkOverwriteInfo( + `Successfully overwrote guild application commands for guild ${guildId}. The application now has ${result.size} guild commands for guild ${guildId}` + ); + } catch (error) { + emitBulkOverwriteError(error, guildId); + } } async function handleAppendOrUpdate( From 8960ed081948a54b6ebf8e5f4ca5cb961b83c64c Mon Sep 17 00:00:00 2001 From: Jeroen Claassens Date: Sat, 6 Apr 2024 16:34:50 +0200 Subject: [PATCH 2/3] chore: fixed unnecessary bug. --- src/index.ts | 8 ++++---- .../ApplicationCommandRegistries.ts | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/index.ts b/src/index.ts index 876a414aa..fff1238ff 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,10 @@ import { acquire, - getBulkRegisterCommandRetries, + getBulkOverwriteRetries, getDefaultBehaviorWhenNotIdentical, getDefaultGuildIds, registries, - setBulkRegisterCommandRetries, + setBulkOverwriteRetries, setDefaultBehaviorWhenNotIdentical, setDefaultGuildIds } from './lib/utils/application-commands/ApplicationCommandRegistries'; @@ -29,10 +29,10 @@ const ApplicationCommandRegistries = { acquire, setDefaultBehaviorWhenNotIdentical, setDefaultGuildIds, - setBulkRegisterCommandRetries, + setBulkRegisterCommandRetries: setBulkOverwriteRetries, getDefaultGuildIds, getDefaultBehaviorWhenNotIdentical, - getBulkRegisterCommandRetries, + getBulkRegisterCommandRetries: getBulkOverwriteRetries, get registries(): ReadonlyMap { return registries; } diff --git a/src/lib/utils/application-commands/ApplicationCommandRegistries.ts b/src/lib/utils/application-commands/ApplicationCommandRegistries.ts index 092014c23..d281c7151 100644 --- a/src/lib/utils/application-commands/ApplicationCommandRegistries.ts +++ b/src/lib/utils/application-commands/ApplicationCommandRegistries.ts @@ -14,7 +14,7 @@ import { bulkOverwriteDebug, bulkOverwriteInfo, bulkOverwriteWarn } from './regi export let defaultBehaviorWhenNotIdentical = RegisterBehavior.Overwrite; export let defaultGuildIds: ApplicationCommandRegistry.RegisterOptions['guildIds'] = undefined; -let bulkRegisterCommandRetries = 1; +let bulkOVerwriteRetries = 1; export const registries = new Map(); @@ -70,12 +70,12 @@ export function getDefaultGuildIds() { * The default value is `1`, which means no retries are performed. * @param newAmountOfRetries The new amount of retries to set. Set this to `null` to reset it to the default */ -export function setBulkRegisterCommandRetries(newAmountOfRetries: number | null) { - bulkRegisterCommandRetries = newAmountOfRetries ?? 1; +export function setBulkOverwriteRetries(newAmountOfRetries: number | null) { + bulkOVerwriteRetries = newAmountOfRetries ?? 1; } -export function getBulkRegisterCommandRetries() { - return bulkRegisterCommandRetries; +export function getBulkOverwriteRetries() { + return bulkOVerwriteRetries; } export async function handleRegistryAPICalls() { @@ -131,11 +131,11 @@ export async function handleBulkOverwrite(commandStore: CommandStore, applicatio } // Handle global commands - await retry(() => handleBulkOverwriteGlobalCommands(commandStore, applicationCommands, foundGlobalCommands), bulkRegisterCommandRetries); + await retry(() => handleBulkOverwriteGlobalCommands(commandStore, applicationCommands, foundGlobalCommands), bulkOVerwriteRetries); // Handle guild commands for (const [guildId, guildCommands] of Object.entries(foundGuildCommands)) { - await retry(() => handleBulkOverwriteGuildCommands(commandStore, applicationCommands, guildId, guildCommands), bulkRegisterCommandRetries); + await retry(() => handleBulkOverwriteGuildCommands(commandStore, applicationCommands, guildId, guildCommands), bulkOVerwriteRetries); } container.client.emit(Events.ApplicationCommandRegistriesRegistered, registries, Date.now() - now); From 5391a8aee052c96dec7529fc08466252097c43c9 Mon Sep 17 00:00:00 2001 From: Jeroen Claassens Date: Sat, 6 Apr 2024 16:52:28 +0200 Subject: [PATCH 3/3] chore: improvements --- src/index.ts | 4 ++-- .../ApplicationCommandRegistries.ts | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index fff1238ff..c8c00df1a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,10 +29,10 @@ const ApplicationCommandRegistries = { acquire, setDefaultBehaviorWhenNotIdentical, setDefaultGuildIds, - setBulkRegisterCommandRetries: setBulkOverwriteRetries, + setBulkOverwriteRetries, getDefaultGuildIds, getDefaultBehaviorWhenNotIdentical, - getBulkRegisterCommandRetries: getBulkOverwriteRetries, + getBulkOverwriteRetries, get registries(): ReadonlyMap { return registries; } diff --git a/src/lib/utils/application-commands/ApplicationCommandRegistries.ts b/src/lib/utils/application-commands/ApplicationCommandRegistries.ts index d281c7151..95b58c79a 100644 --- a/src/lib/utils/application-commands/ApplicationCommandRegistries.ts +++ b/src/lib/utils/application-commands/ApplicationCommandRegistries.ts @@ -66,12 +66,16 @@ export function getDefaultGuildIds() { /** * Sets the amount of retries for when registering commands, only applies when {@link defaultBehaviorWhenNotIdentical} - * is set to {@link RegisterBehavior.BulkOverwrite}. This is used if registering the commands fails. + * is set to {@link RegisterBehavior.BulkOverwrite}. This is used if registering the commands times out. * The default value is `1`, which means no retries are performed. * @param newAmountOfRetries The new amount of retries to set. Set this to `null` to reset it to the default */ export function setBulkOverwriteRetries(newAmountOfRetries: number | null) { - bulkOVerwriteRetries = newAmountOfRetries ?? 1; + newAmountOfRetries ??= 1; + + if (newAmountOfRetries <= 0) throw new RangeError('The amount of retries must be greater than 0'); + + bulkOVerwriteRetries = newAmountOfRetries; } export function getBulkOverwriteRetries() { @@ -181,6 +185,8 @@ async function handleBulkOverwriteGlobalCommands( bulkOverwriteInfo(`Successfully overwrote global application commands. The application now has ${result.size} global commands`); } catch (error) { + if (error instanceof Error && error.name === 'AbortError') throw error; + emitBulkOverwriteError(error, null); } } @@ -234,6 +240,8 @@ async function handleBulkOverwriteGuildCommands( `Successfully overwrote guild application commands for guild ${guildId}. The application now has ${result.size} guild commands for guild ${guildId}` ); } catch (error) { + if (error instanceof Error && error.name === 'AbortError') throw error; + emitBulkOverwriteError(error, guildId); } }