All Thread-Watcher commands live in /bot/src/commands and implement the Command interface.
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import { RegistrationScope } from "#/interfaces/BaseCommandInterface";
import { CommandContext, type Command } from "#/interfaces/Command";
import { ok, Result } from "neverthrow";
import { CommandError } from "#/utilities/error/def";
async function run(
interaction: ChatInputCommandInteraction,
ctx: CommandContext,
): Promise<Result<unknown, CommandError>> {
return ok();
}
const command_data = new SlashCommandBuilder()
.setName("info")
.setDescription("Learn about Thread-Watcher");
const command: Command = {
command_scope: RegistrationScope.GLOBAL,
access_control: {},
command_data,
run,
};
export default command;the command handler can ensure your command only gets ran by people with the correct permissions and also that the bot itself has any permission it might need. You configure this on the access_control property of the command which expects a AccessControl object
export interface AccessControl {
developer_only?: boolean;
bot_requires_permission?: PermissionResolvable[];
invoker_requires_permission?: PermissionResolvable[];
// The name of the option that might hold the channel / thread
channel_option_name?: string;
required_entitlement_sku?: string;
}Note
The invoker_requires_permission field is ignored if the guild has set the USE_INTEGRATION_PERMISSIONS setting to enabled. In these cases, the Discord Slash Command Permissions system takes over.
Thread-Watcher is built with NeverThrow to allow for type safe errors, and the Command must return an Ok with ok() if everything went according to plan, or an Err with err() if something failed.
Any errors returned with err() are handled by the command handler itself!
You can customize your errors by writing a custom Error Type!
Each command run function is passed an CommandInteraction and a Command Context:
export interface CommandContext {
t: TypedI18Func;
build_embed: (style?: keyof ConfigType["style"]) => EmbedBuilder;
logger: Logger<unknown>;
}the command context includes util functionality, such as Internationalization, which you might find helpful!
Thread-Watcher recursevly loads commands from the commands folder. This means you are free to organize your commands however you please in the directory, as long as your typescript files export an object adhering to the Command interface as the default export.
If you notice you are redifining the same code across multiple commands, consider breaking it out! The Thread-Watcher command loader ignores files & directories starting with _ so you could therefore create a directory such as _shared in your commands directory to keep shared code in a easy to reach location!