Skip to content

Commit

Permalink
feat: more responses
Browse files Browse the repository at this point in the history
  • Loading branch information
zaida04 committed Apr 9, 2024
1 parent 1b4ad5a commit d41a268
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 3 deletions.
4 changes: 3 additions & 1 deletion packages/gil/lib/arguments/ArgumentParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import number from "./args/number";
import role from "./args/role";
import string from "./args/string";

export type Result<T> = ({ error: false } & T) | { error: true; reason_code: string };
export type Result<T> = ({ error: false } & T) | { error: true; reason_code: string; extra_info?: unknown };
export type CommandArgument = string | number | boolean | PartialMember | Message | Channel | Role | null;
export type CommandArgumentType = "string" | "number" | "boolean" | "member" | "channel" | "role";
export type CommandArgumentValidator = {
Expand Down Expand Up @@ -55,6 +55,8 @@ export async function convertArguments(params: {
castedArguments[currentArg.name] = null;
continue;
}

return { error: true, reason_code: "MISSING_ARGUMENT", extra_info: { argument: currentArg } };
}

const validator = validators[currentArg.type].validate;
Expand Down
7 changes: 6 additions & 1 deletion packages/gil/lib/listeners/CommandMessageListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ export default class CommandMessageListener extends Listener {

if (attemptConvertArguments.error) {
this.gil.logger.debug(`Error converting arguments for command ${name}, reason: ${attemptConvertArguments.reason_code}`, params.message.id);
// TODO: in-depth error messages for users
await this.gil.send(params.message, "invalidArguments", {
args: {
reason_code: attemptConvertArguments.reason_code,
extra_info: attemptConvertArguments.extra_info,
},
});
return;
}

Expand Down
4 changes: 3 additions & 1 deletion packages/gil/lib/structures/Command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface CommandOptions {
// A brief description of the command
description?: string;
// The arguments this command takes
args?: { name: string; type: CommandArgumentType; optional?: boolean }[];
args?: CommandArg[];
// The category the command belongs to
category?: string;
// The command's aliases
Expand All @@ -37,6 +37,8 @@ export interface CommandOptions {
// The premium level the user must have to run this command
premiumUserLevel?: string;
}
export type CommandArg = { name: string; type: CommandArgumentType; optional?: boolean };

export abstract class Command {
public constructor(
public readonly gil: GilClient,
Expand Down
92 changes: 92 additions & 0 deletions packages/gil/lib/structures/Responses.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Embed, MessageContent } from "guilded.js";
import { strip } from "../utils/string";
import { CommandArg } from "./Command";

export type Response = (...args: any[]) => MessageContent;
export type ParamsObject<T> = T extends (...args: infer P) => any ? { [K in keyof P]: P[K] } : never;
Expand All @@ -12,6 +14,96 @@ export const defaultResponses = {
userNotPremium: (p: { tier: string }) => new Embed().setTitle("You are not premium").setDescription(`You do not have premium. To use this command, you must be on the ${p.tier} tier.`),
userMissingRole: (p: { requiredRole: string[] }) =>
new Embed().setTitle("You can't run this!").setDescription(`You do not have a role with the ${inlineCode(p.requiredRole.join(", "))} permission.`),
invalidArguments: (p: { reason_code: string; extra_info: unknown }) => {
const embed = new Embed().setTitle("Invalid Usage!").setColor("RED");

switch (p.reason_code) {
case "MISSING_ARGUMENT": {
const extra_info = p.extra_info as { argument: CommandArg };
embed.setDescription(strip`
You are missing the required argument: ${inlineCode(extra_info.argument.name)}.
It should be of type ${inlineCode(extra_info.argument.type)}.
`);
break;
}
case "INVALID_NUMBER":
embed.setDescription("I was unable to understand the number you provided.\n\nPlease ensure your numbers are formatted like so: `123`, `111`, or `1e4`. Do not include commands or decimals.");
break;
case "NUMBER_OUT_OF_RANGE":
embed.setDescription("The number you provided is out of acceptable range.\n\nPlease make sure your number is between `-2,147,483,648` and `2,147,483,647`.");
break;
case "BAD_STRING":
embed.setDescription("You provided an invalid string.");
break;
case "INVALID_MEMBER_INPUT":
embed.setDescription(strip`
I was expecting a mention or ID of a user. It may look something like this: \`@user\` or \`pmbOB8VA\`
This user **must** currently be in the server.
Don't know how to get IDs? Refer to this [Guilded Post](https://support.guilded.gg/hc/en-us/articles/6183962129303-Developer-mode#:~:text=Once%20you've%20enabled%20Developer,by%20right%2Dclicking%20on%20it.).
`);
break;
case "MEMBER_NOT_FOUND":
embed.setDescription(strip`
The user you provided was not found. It may look something like this: \`@user\` or \`pmbOB8VA\`
This user **must** currently be in the server.
`);
break;
case "NO_USER_IN_MENTIONS":
embed.setDescription("You did not mention a user.");
break;
case "INVALID_ROLE_INPUT":
embed.setDescription(strip`
I was expecting the mention or ID of a role in this server. It may look something like this: \`@role\` or \`28086957\`
Don't know how to get IDs? Refer to this [Guilded Post](https://support.guilded.gg/hc/en-us/articles/6183962129303-Developer-mode#:~:text=Once%20you've%20enabled%20Developer,by%20right%2Dclicking%20on%20it.).
`);
break;
case "ROLE_NOT_FOUND":
embed.setDescription(strip`
The role you provided was not found. It may look something like this: \`@role\` or \`28086957\`
This role **must** exist in the server.
`);
break;
case "NO_ROLE_IN_MENTIONS":
embed.setDescription("You did not mention a role.");
break;
case "INVALID_CHANNEL_ETC":
embed.setDescription(strip`
I was expecting either a mention or ID of a channel. It may look something like this: \`#channel\` or \`8942a219-6fde-49f0-8d11-13974df4681c\`
**The bot must have read, send, & manage permission on the channel**
Ensure **none** of the bot's roles deny these permissions.
Don't know how to get IDs? Refer to this [Guilded Post](https://support.guilded.gg/hc/en-us/articles/6183962129303-Developer-mode#:~:text=Once%20you've%20enabled%20Developer,by%20right%2Dclicking%20on%20it.).
`);
break;
case "CHANNEL_NOT_FOUND":
embed.setDescription(strip`
The channel you provided was not found. It may look something like this: \`#channel\` or \`8942a219-6fde-49f0-8d11-13974df4681c\`
This channel **must** exist in the server.
`);
break;
case "NO_CHANNEL_IN_MENTIONS":
embed.setDescription("You did not mention a channel.");
break;
case "INVALID_TIME":
embed.setDescription("You provided an invalid time. Please ensure your time is formatted like so: `1d`, `1h`, `1m`, or `1s`.");
break;
case "INVALID_BOOLEAN":
embed.setDescription("You provided an invalid boolean. Please ensure your input is either `true` or `false`.");
break;
default:
embed.setDescription("You provided invalid arguments.");
break;
}

return embed;
},
noop: () => "",
} as const;

Expand Down
14 changes: 14 additions & 0 deletions packages/gil/lib/utils/string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export function strip(strings: TemplateStringsArray, ...values: any[]): string {
let slices: string[] = strings.map((x) => x);
if (strings[0] === "") {
slices = strings.slice(1);
}
const fullString = slices.reduce((acc, str, i) => acc + str + (values[i] || ""), "");
const trimmedLines = fullString.split("\n").map((x) => x.trim());

if (trimmedLines[0] === "") {
trimmedLines.shift();
}

return trimmedLines.join("\n");
}

0 comments on commit d41a268

Please sign in to comment.