aboutsummaryrefslogtreecommitdiff
path: root/src/api/Commands/index.ts
diff options
context:
space:
mode:
authorVendicated <vendicated@riseup.net>2022-10-12 22:22:21 +0200
committerVendicated <vendicated@riseup.net>2022-10-12 22:22:21 +0200
commit267b2b1a0703313311da01addafcee28100347ea (patch)
tree8e074ea220ba10d168f69b92ebc40ea608476ae7 /src/api/Commands/index.ts
parent83d480a68cfed2adee18b9a6b74634644cefaacc (diff)
downloadVencord-267b2b1a0703313311da01addafcee28100347ea.tar.gz
Vencord-267b2b1a0703313311da01addafcee28100347ea.tar.bz2
Vencord-267b2b1a0703313311da01addafcee28100347ea.zip
Commands: basic error handling
Diffstat (limited to 'src/api/Commands/index.ts')
-rw-r--r--src/api/Commands/index.ts100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/api/Commands/index.ts b/src/api/Commands/index.ts
new file mode 100644
index 0000000..be65646
--- /dev/null
+++ b/src/api/Commands/index.ts
@@ -0,0 +1,100 @@
+import { makeCodeblock } from "../../utils/misc";
+import { generateId, sendBotMessage } from "./commandHelpers";
+import { ApplicationCommandInputType, ApplicationCommandType, Argument, Command, CommandContext, Option, CommandReturnValue } from "./types";
+
+export * from "./types";
+export * from "./commandHelpers";
+
+export let BUILT_IN: Command[];
+export const commands = {} as Record<string, Command>;
+
+// hack for plugins being evaluated before we can grab these from webpack
+const OptPlaceholder = Symbol("OptionalMessageOption") as any as Option;
+const ReqPlaceholder = Symbol("RequiredMessageOption") as any as Option;
+/**
+ * Optional message option named "message" you can use in commands.
+ * Used in "tableflip" or "shrug"
+ * @see {@link RequiredMessageOption}
+ */
+export let OptionalMessageOption: Option = OptPlaceholder;
+/**
+ * Required message option named "message" you can use in commands.
+ * Used in "me"
+ * @see {@link OptionalMessageOption}
+ */
+export let RequiredMessageOption: Option = ReqPlaceholder;
+
+export const _init = function (cmds: Command[]) {
+ try {
+ BUILT_IN = cmds;
+ OptionalMessageOption = cmds.find(c => c.name === "shrug")!.options![0];
+ RequiredMessageOption = cmds.find(c => c.name === "me")!.options![0];
+ } catch (e) {
+ console.error("Failed to load CommandsApi");
+ }
+ return cmds;
+} as never;
+
+export const _handleCommand = function (cmd: Command, args: Argument[], ctx: CommandContext) {
+ if (!cmd.isVencordCommand)
+ return cmd.execute(args, ctx);
+
+ const handleError = (err: any) => {
+ // TODO: cancel send if cmd.inputType === BUILT_IN_TEXT
+ const msg = `An Error occurred while executing command "${cmd.name}"`;
+ const reason = err instanceof Error ? err.stack || err.message : String(err);
+
+ console.error(msg, err);
+ sendBotMessage(ctx.channel.id, {
+ content: `${msg}:\n${makeCodeblock(reason)}`,
+ author: {
+ username: "Vencord"
+ }
+ });
+ };
+
+ try {
+ const res = cmd.execute(args, ctx);
+ return res instanceof Promise ? res.catch(handleError) : res;
+ } catch (err) {
+ return handleError(err);
+ }
+} as never;
+
+function modifyOpt(opt: Option | Command) {
+ opt.displayName ||= opt.name;
+ opt.displayDescription ||= opt.description;
+ opt.options?.forEach((opt, i, opts) => {
+ // See comment above Placeholders
+ if (opt === OptPlaceholder) opts[i] = OptionalMessageOption;
+ else if (opt === ReqPlaceholder) opts[i] = RequiredMessageOption;
+ modifyOpt(opts[i]);
+ });
+}
+
+export function registerCommand(command: Command, plugin: string) {
+ if (BUILT_IN.some(c => c.name === command.name))
+ throw new Error(`Command '${command.name}' already exists.`);
+
+ command.isVencordCommand = true;
+ command.id ??= generateId();
+ command.applicationId ??= "-1"; // BUILT_IN;
+ command.type ??= ApplicationCommandType.CHAT_INPUT;
+ command.inputType ??= ApplicationCommandInputType.BUILT_IN_TEXT;
+ command.plugin ||= plugin;
+
+ modifyOpt(command);
+ commands[command.name] = command;
+ BUILT_IN.push(command);
+}
+
+export function unregisterCommand(name: string) {
+ const idx = BUILT_IN.findIndex(c => c.name === name);
+ if (idx === -1)
+ return false;
+
+ BUILT_IN.splice(idx, 1);
+ delete commands[name];
+
+ return true;
+}