This repository has been archived on 2025-11-10. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
CommandBot/src/Parameter.ts
T
2021-08-31 01:17:58 +02:00

169 lines
5.2 KiB
TypeScript

import { CategoryChannel, Guild, GuildMember, NewsChannel, Role, StageChannel, StoreChannel, TextChannel, VoiceChannel } from "discord.js";
import { ParameterType, ParameterResolvable } from "./types.js";
/**
* @interface
* Properties required to build a {@link Parameter} object
* @exports
*/
export interface ParameterSchema {
/**
* Parameter name
* @type {string}
*/
name: string;
/**
* Parameter description
* @type {string}
*/
description?: string;
/**
* Whether this parameter is optional
* @type {boolean}
*/
optional: boolean;
type: ParameterType;
/**
* List of value choices (available only when type is set to "STRING")
*/
choices?: string[];
}
/**
* @class Representation of command parameter
* @exports
*/
export class Parameter {
/**
* Parameter name
* @type {string}
*/
name: string;
/**
* Parameter description
* @type {string}
*/
description: string;
/**
* Whether this parameter is optional
* @type {boolean}
*/
optional: boolean;
/**
* Parameter input type
* @type {ParameterType}
*/
type: ParameterType;
/**
* List of value choices (available only when type is set to "STRING")
*/
choices?: string[];
constructor(options: ParameterSchema) {
this.name = options.name;
this.description = options.description || "No description";
this.optional = options.optional;
this.type = options.type;
this.choices = options.choices;
if (!/^[\w-]{1,32}$/.test(this.name)) {
throw new Error(`Parameter name ${this.name} doesn't match the pattern`);
}
if (this.description.length > 100) {
throw new Error(`Parameter ${this.name}: Description too long`);
}
return;
}
}
export class DefaultParameter extends Parameter {
constructor() {
super({
name: "input",
description: "No description",
type: "string",
optional: true,
});
}
}
/**
* @class Representation of input parameter (argument) coming from a message or an interaction
* @extends Parameter
* @exports
*/
export class InputParameter extends Parameter {
/**
* Input value
* @type {ParameterResolvable}
*/
value: ParameterResolvable;
constructor(parameter: Parameter, value: ParameterResolvable) {
super(parameter);
this.value = value;
}
}
export class StringParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) {
if (parameter.type != "string") {
throw new Error(`Parameter type mismatch`);
}
if (parameter.choices) {
const match = parameter.choices.filter((c) => c.toLowerCase() === value?.toString().toLowerCase());
if (match.length === 0) {
throw new Error(`Parameter "${parameter.name}" has incorrect value. Please enter one of the following values: ${parameter.choices.join(", ")}`);
} else {
super(parameter, match[0]);
return;
}
}
super(parameter, value?.toString());
}
}
export class BooleanParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) {
if (parameter.type != "boolean") {
throw new Error(`Parameter type mismatch`);
}
if (value?.toString().toLowerCase() === "true") {
super(parameter, true);
} else if (value?.toString().toLowerCase() === "false") {
super(parameter, false);
} else {
throw new Error(`Cannot convert "${parameter.name}" parameter to boolean. Please enter either "true" or "false".`);
}
}
}
export class NumberParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) {
if (parameter.type != "number") {
throw new Error(`Parameter type mismatch`);
}
super(parameter, parseFloat(value ? value.toString() : ""));
}
}
export class ObjectParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) {
if (parameter.type != "channel" && parameter.type != "mentionable" && parameter.type != "user" && parameter.type != "role") {
throw new Error(`Parameter type mismatch`);
}
super(parameter, new ObjectID(value?.toString() || ""));
}
}
export class ObjectID {
id: string;
constructor(id: string) {
this.id = id.replace(">", "").replace("<@!", "").replace("<#!", "");
}
async toObject(
guild: Guild,
type: "channel" | "user" | "role"
): Promise<Role | TextChannel | VoiceChannel | CategoryChannel | GuildMember | NewsChannel | StoreChannel | StageChannel | null> {
switch (type) {
case "channel":
return (await guild.channels.fetch(this.id.toString() || "")) || null;
case "role":
return (await guild.roles.fetch(this.id.toString() || "")) || null;
case "user":
return (await guild.members.fetch(this.id.toString() || "")) || null;
}
}
}