Event before precondition OR access the command via MessageCommandDenied

Hi all, I have extended my Command Options to include a property shouldDeleteOnPost - which should delete the message once it has been posted. I'd like to do this in the most universal way possible - I thought using MessageCommandRun would have fired before any of the preconditions, but it seems it does not. When a precondition returns this.error, the code within MessageCommandRun does not fire. It fires if the precondition is passed, or does not exist. I'm not sure if there is an event that will fire before the precondition is run - pass or fail ? If there is, that's where I would put effectively something like the following
const drpgOptions = request.command.options as IDrpgCommandOptions;
if (drpgOptions.deleteAfterPost) request.message.delete();
const drpgOptions = request.command.options as IDrpgCommandOptions;
if (drpgOptions.deleteAfterPost) request.message.delete();
To get around this, I thought I would try doing effectively the same out of the MessageCommandAccepted and MessageCommandDenied events - which would have worked perfectly, until I realised that MessageCommandDenied doesn't appear to have any context of what the command itself actually was. How can I either... - Run some event before a precondition, pass or fail (preferred) - Access the command inside of MessageCommandDenied (unlikely?) Happy to hear other ideas of how I might achieve the goal of flagging some commands with shouldDeleteOnPost and deleting them, regardless of precondition status.
Solution:
I think I found it actually, PreMessageCommandRun - though still open to feedback about whether this is the best possible place for it ```ts import { Events, Listener, ListenerOptions, PreMessageCommandRunPayload } from "@sapphire/framework"; ...
Jump to solution
5 Replies
Solution
Bejasc
Bejasc•3mo ago
I think I found it actually, PreMessageCommandRun - though still open to feedback about whether this is the best possible place for it
import { Events, Listener, ListenerOptions, PreMessageCommandRunPayload } from "@sapphire/framework";

import { IDrpgCommandOptions } from "../../lib/structures";

export class MessageCommandAccepted extends Listener<typeof Events.PreMessageCommandRun> {
public constructor(context: Listener.LoaderContext, options?: ListenerOptions) {
super(context, { ...options, event: Events.PreMessageCommandRun });
}

public run(payload: PreMessageCommandRunPayload): void {
const drpgOptions = payload.command?.options as IDrpgCommandOptions;
if (drpgOptions?.deleteAfterPost) payload.message.delete();
}
}
import { Events, Listener, ListenerOptions, PreMessageCommandRunPayload } from "@sapphire/framework";

import { IDrpgCommandOptions } from "../../lib/structures";

export class MessageCommandAccepted extends Listener<typeof Events.PreMessageCommandRun> {
public constructor(context: Listener.LoaderContext, options?: ListenerOptions) {
super(context, { ...options, event: Events.PreMessageCommandRun });
}

public run(payload: PreMessageCommandRunPayload): void {
const drpgOptions = payload.command?.options as IDrpgCommandOptions;
if (drpgOptions?.deleteAfterPost) payload.message.delete();
}
}
Bejasc
Bejasc•3mo ago
(More snippets, for context)
const DEFAULT_COMMAND_OPTIONS: IDrpgCommandOptions = {
//others
};

export interface IDrpgCommandOptions extends CommandOptions {
//others
deleteAfterPost?: boolean;
}

export abstract class DrpgCommand extends Command {
public readonly fullCategory: readonly string[] = [];

public constructor(context: Command.LoaderContext, options: IDrpgCommandOptions) {
super(context, { ...DEFAULT_COMMAND_OPTIONS, ...options });
}
}
const DEFAULT_COMMAND_OPTIONS: IDrpgCommandOptions = {
//others
};

export interface IDrpgCommandOptions extends CommandOptions {
//others
deleteAfterPost?: boolean;
}

export abstract class DrpgCommand extends Command {
public readonly fullCategory: readonly string[] = [];

public constructor(context: Command.LoaderContext, options: IDrpgCommandOptions) {
super(context, { ...DEFAULT_COMMAND_OPTIONS, ...options });
}
}
@ApplyOptions<IDrpgCommandOptions>({
name: "test",
preconditions: ["PreconditionGoesHere"],
deleteAfterPost: true,
//others
})
export class TestCommand extends Command {
public async messageRun(message: Message, args: Args): Promise<Message> {
//Do things
}
@ApplyOptions<IDrpgCommandOptions>({
name: "test",
preconditions: ["PreconditionGoesHere"],
deleteAfterPost: true,
//others
})
export class TestCommand extends Command {
public async messageRun(message: Message, args: Args): Promise<Message> {
//Do things
}
Favna
Favna•3mo ago
You say you're open to suggestions and I have to be that guy and I'm sorry but the suggestion is to use slash commands because you could just reply with an emphemeral reply saying "you cannot do this". No shenigans required, just handle it in the command. This is just one more of those situations where slash commands prove to be better than message commands.
Bejasc
Bejasc•3mo ago
I know 🙂 We've spoken a few times about this in the past - I'm supporting both and pushing people towards using slash commands. They're definitely easier as a developer, but my community is built from a platform and a time that just does not get along with them.
Favna
Favna•3mo ago
anyway yes you'll have to overwrite PreMessageCommandRun by naming the piece CorePreMessageCommandRun and reimplementing the listener
Want results from more Discord servers?
Add your server