Precondition not triggering "chatInputCommandDenied"

I have setup the following precondition:
Solution:
Ah I also see where you're going wrong here. Yes you land on the breakpoint for this.error, however because you're using Array#forEach which accepts a callback function that returns void you're not actually returning this.error for the function chatInputRun but rather for the anonymous arrow function that is provided to Array#forEach. You can solve this by using for...of instead....
Jump to solution
4 Replies
Teixeira
TeixeiraOP3d ago
ValidAutocompletedObjectIdArguments.ts
import { Precondition } from '@sapphire/framework';
import { ChatInputCommandInteraction, inlineCode } from 'discord.js';
import { Types } from 'mongoose';
import { RealmAutocompleteInteractionHandler } from '../interaction-handlers/RealmAutocompleteInteractionHandler.js';
import ZoneModeAutocompleteInteractionHandler from '../interaction-handlers/ZoneModeAutocompleteInteractionHandler.js';
import { RaidAutocompleteInteractionHandler } from '../interaction-handlers/RaidAutocompleteInteractionHandler.js';

export class ValidAutocompletedObjectIdArgumentsPrecondition extends Precondition {
private _autocompletedObjectIdOptionNames: string[] = [
RealmAutocompleteInteractionHandler.optionName,
ZoneModeAutocompleteInteractionHandler.optionName,
RaidAutocompleteInteractionHandler.optionName
];

public constructor(context: Precondition.LoaderContext, options: Precondition.Options) {
super(context, {
...options
});
}

public override async chatInputRun(interaction: ChatInputCommandInteraction) {
interaction.options.data.forEach((option) => {
if (
this._autocompletedObjectIdOptionNames.includes(option.name) &&
option.value &&
typeof option.value === 'string' &&
!Types.ObjectId.isValid(option.value)
) {
return this.error({
message: `Invalid parameter value for ${inlineCode(option.name)}. Please select one of the autocompleted options.`
});
}

return;
});

return this.ok();
}
}

declare module '@sapphire/framework' {
interface Preconditions {
ValidAutocompletedObjectIdArguments: never;
}
}
import { Precondition } from '@sapphire/framework';
import { ChatInputCommandInteraction, inlineCode } from 'discord.js';
import { Types } from 'mongoose';
import { RealmAutocompleteInteractionHandler } from '../interaction-handlers/RealmAutocompleteInteractionHandler.js';
import ZoneModeAutocompleteInteractionHandler from '../interaction-handlers/ZoneModeAutocompleteInteractionHandler.js';
import { RaidAutocompleteInteractionHandler } from '../interaction-handlers/RaidAutocompleteInteractionHandler.js';

export class ValidAutocompletedObjectIdArgumentsPrecondition extends Precondition {
private _autocompletedObjectIdOptionNames: string[] = [
RealmAutocompleteInteractionHandler.optionName,
ZoneModeAutocompleteInteractionHandler.optionName,
RaidAutocompleteInteractionHandler.optionName
];

public constructor(context: Precondition.LoaderContext, options: Precondition.Options) {
super(context, {
...options
});
}

public override async chatInputRun(interaction: ChatInputCommandInteraction) {
interaction.options.data.forEach((option) => {
if (
this._autocompletedObjectIdOptionNames.includes(option.name) &&
option.value &&
typeof option.value === 'string' &&
!Types.ObjectId.isValid(option.value)
) {
return this.error({
message: `Invalid parameter value for ${inlineCode(option.name)}. Please select one of the autocompleted options.`
});
}

return;
});

return this.ok();
}
}

declare module '@sapphire/framework' {
interface Preconditions {
ValidAutocompletedObjectIdArguments: never;
}
}
However, my chatInputCommandDenied listener isn't firing: ChatInputCommandDenied.ts
import { ChatInputCommandDeniedPayload, Events, Listener, type UserError } from '@sapphire/framework';
import Utils from '../lib/Utils.js';
import { CustomEmbedType } from '../ui/embeds/CustomEmbed.js';

export class ChatInputCommandDeniedListener extends Listener<typeof Events.ChatInputCommandDenied> {
public constructor(context: Listener.LoaderContext, options: Listener.Options) {
super(context, {
...options,
event: 'chatInputCommandDenied'
});
}

public async run(error: UserError, payload: ChatInputCommandDeniedPayload) {
try {
if (!payload.interaction.deferred) await payload.interaction.deferReply({ ephemeral: true });

const reply = await payload.interaction.editReply({
embeds: [
(await this.container.ui.embeds.create(CustomEmbedType.Error)) //
.setDescription(error.message)
],
components: []
});

Utils.deleteAfterDelay(reply, payload.interaction.webhook);
} catch (reason) {
this.container.logger.error(reason);
}
}
}
import { ChatInputCommandDeniedPayload, Events, Listener, type UserError } from '@sapphire/framework';
import Utils from '../lib/Utils.js';
import { CustomEmbedType } from '../ui/embeds/CustomEmbed.js';

export class ChatInputCommandDeniedListener extends Listener<typeof Events.ChatInputCommandDenied> {
public constructor(context: Listener.LoaderContext, options: Listener.Options) {
super(context, {
...options,
event: 'chatInputCommandDenied'
});
}

public async run(error: UserError, payload: ChatInputCommandDeniedPayload) {
try {
if (!payload.interaction.deferred) await payload.interaction.deferReply({ ephemeral: true });

const reply = await payload.interaction.editReply({
embeds: [
(await this.container.ui.embeds.create(CustomEmbedType.Error)) //
.setDescription(error.message)
],
components: []
});

Utils.deleteAfterDelay(reply, payload.interaction.webhook);
} catch (reason) {
this.container.logger.error(reason);
}
}
}
I know for a fact that the precondition is firing & returning an error in my test, as I've added a breakpoint to the return this.error (...) statement And here's the setting of the precondition on the command: CMServerDefaults.ts
export class CMServerDefaultsCommand extends Command {
public constructor(context: Command.LoaderContext, options: Command.Options) {
super(context, { ...options, preconditions: ['ValidAutocompletedObjectIdArguments'] });
}

(...)
export class CMServerDefaultsCommand extends Command {
public constructor(context: Command.LoaderContext, options: Command.Options) {
super(context, { ...options, preconditions: ['ValidAutocompletedObjectIdArguments'] });
}

(...)
Favna
Favna3d ago
FYI if youu name the file chatInputCommandDenied (camel cased) then you dont need to set the event property at all anymore and you can fully omit the constructor. Alternatively you can also use the enum that you already use as a type instead of the hard coded string: event: Events.ChatInputCommandDenied
Solution
Favna
Favna3d ago
Ah I also see where you're going wrong here. Yes you land on the breakpoint for this.error, however because you're using Array#forEach which accepts a callback function that returns void you're not actually returning this.error for the function chatInputRun but rather for the anonymous arrow function that is provided to Array#forEach. You can solve this by using for...of instead.
Teixeira
TeixeiraOP3d ago
Oh man. Of course... what a rookie mistake! Thank you, this fixed it!
Want results from more Discord servers?
Add your server