diff --git a/src/client/base.ts b/src/client/base.ts index 534b2e3..fe3dc19 100644 --- a/src/client/base.ts +++ b/src/client/base.ts @@ -470,6 +470,8 @@ export interface BaseClientOptions { globalMiddlewares?: readonly (keyof RegisteredMiddlewares)[]; commands?: { defaults?: { + onBeforeMiddlewares?: (context: CommandContext | MenuCommandContext) => unknown; + onBeforeOptions?: Command['onBeforeOptions']; onRunError?: (context: MenuCommandContext | CommandContext, error: unknown) => unknown; onPermissionsFail?: Command['onPermissionsFail']; onBotPermissionsFail?: ( @@ -489,6 +491,7 @@ export interface BaseClientOptions { }; components?: { defaults?: { + onBeforeMiddlewares?: ComponentCommand['onBeforeMiddlewares']; onRunError?: ComponentCommand['onRunError']; onInternalError?: ComponentCommand['onInternalError']; onMiddlewaresError?: ComponentCommand['onMiddlewaresError']; @@ -497,6 +500,7 @@ export interface BaseClientOptions { }; modals?: { defaults?: { + onBeforeMiddlewares?: ModalCommand['onBeforeMiddlewares']; onRunError?: ModalCommand['onRunError']; onInternalError?: ModalCommand['onInternalError']; onMiddlewaresError?: ModalCommand['onMiddlewaresError']; diff --git a/src/commands/applications/chat.ts b/src/commands/applications/chat.ts index cf0dd4f..db3b1f4 100644 --- a/src/commands/applications/chat.ts +++ b/src/commands/applications/chat.ts @@ -285,6 +285,8 @@ export class BaseCommand { Object.setPrototypeOf(this, __tempCommand.prototype); } + onBeforeMiddlewares?(context: CommandContext): any; + onBeforeOptions?(context: CommandContext): any; run?(context: CommandContext): any; onAfterRun?(context: CommandContext, error: unknown | undefined): any; onRunError?(context: CommandContext, error: unknown): any; diff --git a/src/commands/applications/entryPoint.ts b/src/commands/applications/entryPoint.ts index 70b825c..77136de 100644 --- a/src/commands/applications/entryPoint.ts +++ b/src/commands/applications/entryPoint.ts @@ -54,6 +54,7 @@ export abstract class EntryPointCommand { Object.setPrototypeOf(this, __tempCommand.prototype); } + onBeforeMiddlewares?(context: EntryPointContext): any; abstract run?(context: EntryPointContext): any; onAfterRun?(context: EntryPointContext, error: unknown | undefined): any; onRunError(context: EntryPointContext, error: unknown): any { diff --git a/src/commands/applications/menu.ts b/src/commands/applications/menu.ts index a17516f..9ea09ca 100644 --- a/src/commands/applications/menu.ts +++ b/src/commands/applications/menu.ts @@ -53,6 +53,7 @@ export abstract class ContextMenuCommand { Object.setPrototypeOf(this, __tempCommand.prototype); } + onBeforeMiddlewares?(context: MenuCommandContext): any; abstract run?(context: MenuCommandContext): any; onAfterRun?(context: MenuCommandContext, error: unknown | undefined): any; onRunError?(context: MenuCommandContext, error: unknown): any; diff --git a/src/commands/handle.ts b/src/commands/handle.ts index 8f6d224..c59bee2 100644 --- a/src/commands/handle.ts +++ b/src/commands/handle.ts @@ -91,7 +91,7 @@ export class HandleCommand { await optionsResolver.getCommand()?.onInternalError?.(this.client, optionsResolver.getCommand()!, error); } } catch (error) { - // pass + this.client.logger.error(`[${optionsResolver.fullCommandName}] Internal error:`, error); } } @@ -100,17 +100,18 @@ export class HandleCommand { interaction: MessageCommandInteraction | UserCommandInteraction, context: MenuCommandContext, ) { - if (context.guildId && command.botPermissions) { - const permissions = this.checkPermissions(interaction.appPermissions, command.botPermissions); - if (permissions) return command.onBotPermissionsFail?.(context, permissions); - } - - const resultGlobal = await this.runGlobalMiddlewares(command, context); - if (typeof resultGlobal === 'boolean') return; - const resultMiddle = await this.runMiddlewares(command, context); - if (typeof resultMiddle === 'boolean') return; - try { + if (context.guildId && command.botPermissions) { + const permissions = this.checkPermissions(interaction.appPermissions, command.botPermissions); + if (permissions) return await command.onBotPermissionsFail?.(context, permissions); + } + + await command.onBeforeMiddlewares?.(context); + const resultGlobal = await this.runGlobalMiddlewares(command, context); + if (typeof resultGlobal === 'boolean') return; + const resultMiddle = await this.runMiddlewares(command, context); + if (typeof resultMiddle === 'boolean') return; + try { await command.run!(context); await command.onAfterRun?.(context, undefined); @@ -121,8 +122,8 @@ export class HandleCommand { } catch (error) { try { await command.onInternalError?.(this.client, command, error); - } catch { - // pass + } catch (err) { + this.client.logger.error(`[${command.name}] Internal error:`, err); } } } @@ -144,17 +145,18 @@ export class HandleCommand { } async entryPoint(command: EntryPointCommand, interaction: EntryPointInteraction, context: EntryPointContext) { - if (context.guildId && command.botPermissions) { - const permissions = this.checkPermissions(interaction.appPermissions, command.botPermissions); - if (permissions) return command.onBotPermissionsFail(context, permissions); - } - - const resultGlobal = await this.runGlobalMiddlewares(command, context); - if (typeof resultGlobal === 'boolean') return; - const resultMiddle = await this.runMiddlewares(command, context); - if (typeof resultMiddle === 'boolean') return; - try { + if (context.guildId && command.botPermissions) { + const permissions = this.checkPermissions(interaction.appPermissions, command.botPermissions); + if (permissions) return await command.onBotPermissionsFail(context, permissions); + } + + await command.onBeforeMiddlewares?.(context); + const resultGlobal = await this.runGlobalMiddlewares(command, context); + if (typeof resultGlobal === 'boolean') return; + const resultMiddle = await this.runMiddlewares(command, context); + if (typeof resultMiddle === 'boolean') return; + try { await command.run!(context); await command.onAfterRun?.(context, undefined); @@ -165,8 +167,8 @@ export class HandleCommand { } catch (error) { try { await command.onInternalError(this.client, command, error); - } catch { - // pass + } catch (err) { + this.client.logger.error(`[${command.name}] Internal error:`, err); } } } @@ -177,26 +179,28 @@ export class HandleCommand { resolver: OptionResolverStructure, context: CommandContext, ) { - if (context.guildId) { - if (command.botPermissions) { - const permissions = this.checkPermissions(interaction.appPermissions, command.botPermissions); - if (permissions) return command.onBotPermissionsFail?.(context, permissions); - } - - if (command.defaultMemberPermissions) { - const permissions = this.checkPermissions(interaction.member!.permissions, command.defaultMemberPermissions); - if (permissions) return command.onPermissionsFail?.(context, permissions); - } - } - - if (!(await this.runOptions(command, context, resolver))) return; - - const resultGlobal = await this.runGlobalMiddlewares(command, context); - if (typeof resultGlobal === 'boolean') return; - const resultMiddle = await this.runMiddlewares(command, context); - if (typeof resultMiddle === 'boolean') return; - try { + if (context.guildId) { + if (command.botPermissions) { + const permissions = this.checkPermissions(interaction.appPermissions, command.botPermissions); + if (permissions) return await command.onBotPermissionsFail?.(context, permissions); + } + + if (command.defaultMemberPermissions) { + const permissions = this.checkPermissions(interaction.member!.permissions, command.defaultMemberPermissions); + if (permissions) return await command.onPermissionsFail?.(context, permissions); + } + } + + await command.onBeforeOptions?.(context); + if (!(await this.runOptions(command, context, resolver))) return; + + await command.onBeforeMiddlewares?.(context); + const resultGlobal = await this.runGlobalMiddlewares(command, context); + if (typeof resultGlobal === 'boolean') return; + const resultMiddle = await this.runMiddlewares(command, context); + if (typeof resultMiddle === 'boolean') return; + try { await command.run!(context); await command.onAfterRun?.(context, undefined); @@ -207,8 +211,8 @@ export class HandleCommand { } catch (error) { try { await command.onInternalError?.(this.client, command, error); - } catch { - // pass + } catch (err) { + this.client.logger.error(`[${command.name}] Internal error:`, err); } } } @@ -350,17 +354,17 @@ export class HandleCommand { attachments: {}, }; - const args = this.argsParser(argsContent, command, message); - const { options, errors } = await this.argsOptionsParser(command, rawMessage, args, resolved); - const optionsResolver = this.makeResolver(self, options, parent as Command, rawMessage.guild_id, resolved); - const context = new CommandContext(self, message, optionsResolver, shardId, command); - //@ts-expect-error - const extendContext = self.options?.context?.(message) ?? {}; - Object.assign(context, extendContext); - try { + const args = this.argsParser(argsContent, command, message); + const { options, errors } = await this.argsOptionsParser(command, rawMessage, args, resolved); + const optionsResolver = this.makeResolver(self, options, parent as Command, rawMessage.guild_id, resolved); + const context = new CommandContext(self, message, optionsResolver, shardId, command); + //@ts-expect-error + const extendContext = self.options?.context?.(message) ?? {}; + Object.assign(context, extendContext); + if (errors.length) { - return command.onOptionsError?.( + return await command.onOptionsError?.( context, Object.fromEntries( errors.map(x => { @@ -383,7 +387,7 @@ export class HandleCommand { const permissions = this.checkPermissions(memberPermissions, command.defaultMemberPermissions); const guild = await this.client.guilds.raw(rawMessage.guild_id); if (permissions && guild.owner_id !== rawMessage.author.id) { - return command.onPermissionsFail?.(context, memberPermissions.keys(permissions)); + return await command.onPermissionsFail?.(context, memberPermissions.keys(permissions)); } } @@ -391,13 +395,15 @@ export class HandleCommand { const appPermissions = await self.members.permissions(rawMessage.guild_id, self.botId); const permissions = this.checkPermissions(appPermissions, command.botPermissions); if (permissions) { - return command.onBotPermissionsFail?.(context, permissions); + return await command.onBotPermissionsFail?.(context, permissions); } } } + await command.onBeforeOptions?.(context); if (!(await this.runOptions(command, context, optionsResolver))) return; + await command.onBeforeMiddlewares?.(context); const resultGlobal = await this.runGlobalMiddlewares(command, context); if (typeof resultGlobal === 'boolean') return; const resultMiddle = await this.runMiddlewares(command, context); @@ -412,8 +418,8 @@ export class HandleCommand { } catch (error) { try { await command.onInternalError?.(this.client, command, error); - } catch { - // http 418 + } catch (err) { + this.client.logger.error(`[${command.name}] Internal error:`, err); } } } @@ -574,8 +580,8 @@ export class HandleCommand { } catch (e) { try { await command.onInternalError?.(this.client, command as never, e); - } catch { - // http 418 + } catch (err) { + this.client.logger.error(`[${command.name}] Internal error:`, err); } } return false; @@ -602,8 +608,8 @@ export class HandleCommand { } catch (e) { try { await command.onInternalError?.(this.client, command as never, e); - } catch { - // http 418 + } catch (err) { + this.client.logger.error(`[${command.name}] Internal error:`, err); } } return false; @@ -627,15 +633,7 @@ export class HandleCommand { async runOptions(command: Command | SubCommand, context: CommandContext, resolver: OptionResolverStructure) { const [erroredOptions, result] = await command.__runOptions(context, resolver); if (erroredOptions) { - try { - await command.onOptionsError?.(context, result); - } catch (e) { - try { - await command.onInternalError?.(this.client, command, e); - } catch { - // http 418 - } - } + await command.onOptionsError?.(context, result); return false; } return true; diff --git a/src/commands/handler.ts b/src/commands/handler.ts index 4d4c99a..4246ce6 100644 --- a/src/commands/handler.ts +++ b/src/commands/handler.ts @@ -466,6 +466,8 @@ export class CommandHandler extends BaseHandler { stablishContextCommandDefaults(commandInstance: InstanceType): ContextMenuCommand | false { if (!(commandInstance instanceof ContextMenuCommand)) return false; + commandInstance.onBeforeMiddlewares ??= this.client.options.commands?.defaults?.onBeforeMiddlewares; + commandInstance.onAfterRun ??= this.client.options.commands?.defaults?.onAfterRun; commandInstance.onBotPermissionsFail ??= this.client.options.commands?.defaults?.onBotPermissionsFail; @@ -482,6 +484,8 @@ export class CommandHandler extends BaseHandler { commandInstance: InstanceType, ): OmitInsert }> | false { if (!(commandInstance instanceof Command)) return false; + commandInstance.onBeforeMiddlewares ??= this.client.options.commands?.defaults?.onBeforeMiddlewares; + commandInstance.onBeforeOptions ??= this.client.options.commands?.defaults?.onBeforeOptions; commandInstance.onAfterRun ??= this.client.options.commands?.defaults?.onAfterRun; commandInstance.onBotPermissionsFail ??= this.client.options.commands?.defaults?.onBotPermissionsFail; commandInstance.onInternalError ??= this.client.options.commands?.defaults?.onInternalError; @@ -495,6 +499,14 @@ export class CommandHandler extends BaseHandler { stablishSubCommandDefaults(commandInstance: Command, option: SubCommand): SubCommand { option.middlewares = (commandInstance.middlewares ?? []).concat(option.middlewares ?? []); + option.onBeforeMiddlewares = + option.onBeforeMiddlewares?.bind(option) ?? + commandInstance.onBeforeMiddlewares?.bind(commandInstance) ?? + this.client.options.commands?.defaults?.onBeforeMiddlewares; + option.onBeforeOptions = + option.onBeforeOptions?.bind(option) ?? + commandInstance.onBeforeOptions?.bind(commandInstance) ?? + this.client.options.commands?.defaults?.onBeforeOptions; option.onMiddlewaresError = option.onMiddlewaresError?.bind(option) ?? commandInstance.onMiddlewaresError?.bind(commandInstance) ?? diff --git a/src/components/componentcommand.ts b/src/components/componentcommand.ts index 60cba08..be2989b 100644 --- a/src/components/componentcommand.ts +++ b/src/components/componentcommand.ts @@ -33,6 +33,7 @@ export abstract class ComponentCommand { return ComponentType[this.componentType]; } + onBeforeMiddlewares?(context: ComponentContext): any; onAfterRun?(context: ComponentContext, error: unknown | undefined): any; onRunError?(context: ComponentContext, error: unknown): any; onMiddlewaresError?(context: ComponentContext, error: string): any; diff --git a/src/components/handler.ts b/src/components/handler.ts index 300ffe0..b577cba 100644 --- a/src/components/handler.ts +++ b/src/components/handler.ts @@ -204,6 +204,7 @@ export class ComponentHandler extends BaseHandler { component.onMiddlewaresError ??= this.client.options?.[is]?.defaults?.onMiddlewaresError; component.onRunError ??= this.client.options?.[is]?.defaults?.onRunError; component.onAfterRun ??= this.client.options?.[is]?.defaults?.onAfterRun; + component.onBeforeMiddlewares ??= this.client.options?.[is]?.defaults?.onBeforeMiddlewares; } set(instances: (new () => ComponentCommands)[]) { @@ -289,6 +290,7 @@ export class ComponentHandler extends BaseHandler { async execute(i: ComponentCommands, context: ComponentContext | ModalContext) { try { + await i.onBeforeMiddlewares?.(context as never); const resultRunGlobalMiddlewares = await BaseCommand.__runMiddlewares( context, (context.client.options?.globalMiddlewares ?? []) as keyof RegisteredMiddlewares, @@ -298,7 +300,7 @@ export class ComponentHandler extends BaseHandler { return; } if ('error' in resultRunGlobalMiddlewares) { - return i.onMiddlewaresError?.(context as never, resultRunGlobalMiddlewares.error ?? 'Unknown error'); + return await i.onMiddlewaresError?.(context as never, resultRunGlobalMiddlewares.error ?? 'Unknown error'); } const resultRunMiddlewares = await BaseCommand.__runMiddlewares(context, i.middlewares, false); @@ -306,7 +308,7 @@ export class ComponentHandler extends BaseHandler { return; } if ('error' in resultRunMiddlewares) { - return i.onMiddlewaresError?.(context as never, resultRunMiddlewares.error ?? 'Unknown error'); + return await i.onMiddlewaresError?.(context as never, resultRunMiddlewares.error ?? 'Unknown error'); } try { @@ -319,9 +321,8 @@ export class ComponentHandler extends BaseHandler { } catch (error) { try { await i.onInternalError?.(this.client, error); - } catch (e) { - // supress error - this.logger.error(e); + } catch (err) { + this.client.logger.error(`[${i.customId ?? 'Component/Modal command'}] Internal error:`, err); } } } diff --git a/src/components/modalcommand.ts b/src/components/modalcommand.ts index af50764..96a5bcf 100644 --- a/src/components/modalcommand.ts +++ b/src/components/modalcommand.ts @@ -23,6 +23,7 @@ export abstract class ModalCommand { props!: ExtraProps; + onBeforeMiddlewares?(context: ModalContext): any; onAfterRun?(context: ModalContext, error: unknown | undefined): any; onRunError?(context: ModalContext, error: unknown): any; onMiddlewaresError?(context: ModalContext, error: string): any;