Archived
CommandBot 3.1.1 (merging)
CommandBot 3.1.1 - improved code safety, warnings in README
This commit was merged in pull request #3.
This commit is contained in:
9 files changed
+68
-43
No files matched your search
@@ -117,6 +117,8 @@ bot.start(
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **WARNING!** All commands have to be added to the instance **before starting the bot**. Adding commands while the bot is running is not possible and can cause issues.
|
||||||
|
|
||||||
# Commands
|
# Commands
|
||||||
|
|
||||||
## Creating and registering a command
|
## Creating and registering a command
|
||||||
@@ -340,6 +342,8 @@ You can customize the help message with these properties (\* - required):
|
|||||||
- **usage\*** - _string_ - usage displayed in the message itself
|
- **usage\*** - _string_ - usage displayed in the message itself
|
||||||
- **visible\*** - _boolean_ - whether to show the help command in the list
|
- **visible\*** - _boolean_ - whether to show the help command in the list
|
||||||
|
|
||||||
|
> **WARNING!** You can't customize these messages after starting the bot. Changing these properties while the bot is running will have no effect.
|
||||||
|
|
||||||
# Issues
|
# Issues
|
||||||
|
|
||||||
Since this package is created by only 1 person it may contain some bugs or behave weirdly. If you notice any problem, typo etc, please create an issue in the _Issues_ tab on GitHub.
|
Since this package is created by only 1 person it may contain some bugs or behave weirdly. If you notice any problem, typo etc, please create an issue in the _Issues_ tab on GitHub.
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "commandbot",
|
"name": "commandbot",
|
||||||
"version": "3.1.0",
|
"version": "3.1.1",
|
||||||
"description": "A framework that helps you create your own Discord bot easier.",
|
"description": "A framework that helps you create your own Discord bot easier.",
|
||||||
"main": "dist/cjs/index.js",
|
"main": "dist/cjs/index.js",
|
||||||
"module": "dist/mjs/index.js",
|
"module": "dist/mjs/index.js",
|
||||||
|
|||||||
+13
-8
@@ -26,32 +26,32 @@ export class Bot extends EventEmitter {
|
|||||||
* Bot name
|
* Bot name
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
name: string;
|
public readonly name: string;
|
||||||
/**
|
/**
|
||||||
* Discord.js {@link Client} instance
|
* Discord.js {@link Client} instance
|
||||||
* @type {Client}
|
* @type {Client}
|
||||||
*/
|
*/
|
||||||
client: Client;
|
public readonly client: Client;
|
||||||
/**
|
/**
|
||||||
* Instance command manager
|
* Instance command manager
|
||||||
* @type {CommandManager}
|
* @type {CommandManager}
|
||||||
*/
|
*/
|
||||||
commands: CommandManager;
|
public readonly commands: CommandManager;
|
||||||
/**
|
/**
|
||||||
* Discord bot token
|
* Discord bot token
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
token: string;
|
public readonly token: string;
|
||||||
/**
|
/**
|
||||||
* Discord API application ID
|
* Discord API application ID
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
applicationId: string;
|
public readonly applicationId: string;
|
||||||
/**
|
/**
|
||||||
* Built-in messages configuration
|
* Built-in messages configuration
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
messages: {
|
public readonly messages: {
|
||||||
/**
|
/**
|
||||||
* Help message configuration
|
* Help message configuration
|
||||||
* @type {HelpMessageParams}
|
* @type {HelpMessageParams}
|
||||||
@@ -132,6 +132,7 @@ export class Bot extends EventEmitter {
|
|||||||
const helpMsg: Command = new HelpMessage(this.commands, this.messages.help, this.name);
|
const helpMsg: Command = new HelpMessage(this.commands, this.messages.help, this.name);
|
||||||
this.commands.add(helpMsg);
|
this.commands.add(helpMsg);
|
||||||
}
|
}
|
||||||
|
this.commands.freezeList();
|
||||||
process.stdout.write("Connecting to Discord... ");
|
process.stdout.write("Connecting to Discord... ");
|
||||||
this.client.login(this.token);
|
this.client.login(this.token);
|
||||||
this.client.on("ready", async () => {
|
this.client.on("ready", async () => {
|
||||||
@@ -247,11 +248,15 @@ export class Bot extends EventEmitter {
|
|||||||
process.stdout.write("Registering commands... ");
|
process.stdout.write("Registering commands... ");
|
||||||
await axios.put(
|
await axios.put(
|
||||||
`https://discord.com/api/v8/applications/${this.applicationId}/commands`,
|
`https://discord.com/api/v8/applications/${this.applicationId}/commands`,
|
||||||
this.commands.list.filter((c) => !Array.isArray(c.guilds) && c.slash).map((c) => c.toCommandObject()),
|
this.commands
|
||||||
|
.getList()
|
||||||
|
.filter((c) => !Array.isArray(c.guilds) && c.slash)
|
||||||
|
.map((c) => c.toCommandObject()),
|
||||||
{ headers: { Authorization: `Bot ${this.token}` } }
|
{ headers: { Authorization: `Bot ${this.token}` } }
|
||||||
);
|
);
|
||||||
const guilds: any = {};
|
const guilds: any = {};
|
||||||
await this.commands.list
|
await this.commands
|
||||||
|
.getList()
|
||||||
.filter((c) => Array.isArray(c.guilds) && c.guilds.length > 0)
|
.filter((c) => Array.isArray(c.guilds) && c.guilds.length > 0)
|
||||||
.map((c) => {
|
.map((c) => {
|
||||||
c.guilds?.map(async (g) => {
|
c.guilds?.map(async (g) => {
|
||||||
|
|||||||
+12
-12
@@ -14,58 +14,58 @@ export class Command {
|
|||||||
* Command name
|
* Command name
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
name: string;
|
public readonly name: string;
|
||||||
/**
|
/**
|
||||||
* List of parameters that can passed to this command
|
* List of parameters that can passed to this command
|
||||||
* @type {Array} {@link Parameter}
|
* @type {Array} {@link Parameter}
|
||||||
*/
|
*/
|
||||||
parameters: Parameter[];
|
public readonly parameters: Parameter[];
|
||||||
/**
|
/**
|
||||||
* List of different names that can be used to invoke a command (when using prefix interactions)
|
* List of different names that can be used to invoke a command (when using prefix interactions)
|
||||||
* @type {Array} *string*
|
* @type {Array} *string*
|
||||||
*/
|
*/
|
||||||
aliases?: string[];
|
public readonly aliases?: string[];
|
||||||
/**
|
/**
|
||||||
* Command description displayed in the help message (Default description: "No description")
|
* Command description displayed in the help message (Default description: "No description")
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
description: string;
|
public readonly description: string;
|
||||||
/**
|
/**
|
||||||
* Command usage displayed in the help message
|
* Command usage displayed in the help message
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
usage?: string;
|
public readonly usage?: string;
|
||||||
/**
|
/**
|
||||||
* Whether to check if a caller has all defined in *permissions* property permissions or at least one of them (doesn't apply to custom function permissions)
|
* Whether to check if a caller has all defined in *permissions* property permissions or at least one of them (doesn't apply to custom function permissions)
|
||||||
* @type {PermissionCheckTypes} "ALL" | "ANY"
|
* @type {PermissionCheckTypes} "ALL" | "ANY"
|
||||||
*/
|
*/
|
||||||
permissionCheck: PermissionCheckTypes;
|
public readonly permissionCheck: PermissionCheckTypes;
|
||||||
/**
|
/**
|
||||||
* Command permissions (if *undefined*, no permissions check will be performed)
|
* Command permissions (if *undefined*, no permissions check will be performed)
|
||||||
* @type {PermissionResolvable}
|
* @type {PermissionResolvable}
|
||||||
* @type {Function} should return boolean value
|
* @type {Function} should return boolean value
|
||||||
*/
|
*/
|
||||||
permissions?: Permissions | ((m?: Message | CommandInteraction) => boolean);
|
public readonly permissions?: Permissions | ((m?: Message | CommandInteraction) => boolean);
|
||||||
/**
|
/**
|
||||||
* List of Discord guild (server) IDs in which this command can be used
|
* List of Discord guild (server) IDs in which this command can be used
|
||||||
* @type {Array} *string*
|
* @type {Array} *string*
|
||||||
*/
|
*/
|
||||||
guilds?: string[];
|
public readonly guilds?: string[];
|
||||||
/**
|
/**
|
||||||
* Whether this command is visible in the help message (default: true)
|
* Whether this command is visible in the help message (default: true)
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
visible: boolean;
|
public readonly visible: boolean;
|
||||||
/**
|
/**
|
||||||
* Whether this command should be registered as a slash command (default: true)
|
* Whether this command should be registered as a slash command (default: true)
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
slash: boolean;
|
public readonly slash: boolean;
|
||||||
/**
|
/**
|
||||||
* Whether to send a SUCCESS message if no other response is defined (default: true)
|
* Whether to send a SUCCESS message if no other response is defined (default: true)
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
announceSuccess: boolean;
|
public readonly announceSuccess: boolean;
|
||||||
/**
|
/**
|
||||||
* Command execution function (triggered when someone invokes the command)
|
* Command execution function (triggered when someone invokes the command)
|
||||||
* @type {Function}
|
* @type {Function}
|
||||||
@@ -73,7 +73,7 @@ export class Command {
|
|||||||
* @param {Message | CommandInteraction} i - interaction object
|
* @param {Message | CommandInteraction} i - interaction object
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private function: (
|
private readonly function: (
|
||||||
params: (query: string, returnType?: "value" | "object") => ParameterResolvable | InputParameter | null,
|
params: (query: string, returnType?: "value" | "object") => ParameterResolvable | InputParameter | null,
|
||||||
interaction?: Message | CommandInteraction
|
interaction?: Message | CommandInteraction
|
||||||
) => void | string | MessageEmbed | ReplyMessageOptions | Promise<void | string | MessageEmbed | ReplyMessageOptions>;
|
) => void | string | MessageEmbed | ReplyMessageOptions | Promise<void | string | MessageEmbed | ReplyMessageOptions>;
|
||||||
|
|||||||
+19
-3
@@ -12,17 +12,17 @@ export class CommandManager {
|
|||||||
* List of commands registered in the manager
|
* List of commands registered in the manager
|
||||||
* @type {Array} {@link Command}
|
* @type {Array} {@link Command}
|
||||||
*/
|
*/
|
||||||
list: Command[];
|
private readonly list: Command[];
|
||||||
/**
|
/**
|
||||||
* Prefix used as a way to trigger the bot using messages
|
* Prefix used as a way to trigger the bot using messages
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
prefix?: string;
|
public readonly prefix?: string;
|
||||||
/**
|
/**
|
||||||
* Separator used to split user input to a list of {@link InputParameter}s (applies to prefix interactions)
|
* Separator used to split user input to a list of {@link InputParameter}s (applies to prefix interactions)
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
parameterSeparator: string;
|
public readonly parameterSeparator: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
@@ -56,6 +56,15 @@ export class CommandManager {
|
|||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list (array) of all {@link Command}s registered in a manager
|
||||||
|
* @returns {Command[]} Array of {@link Command}s registered in a manager
|
||||||
|
*/
|
||||||
|
getList(): Command[] {
|
||||||
|
const list = [...this.list];
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given {@link Command} to the instance manager with initial processing
|
* Adds the given {@link Command} to the instance manager with initial processing
|
||||||
* @param {Command} command - {@link Command} instance object
|
* @param {Command} command - {@link Command} instance object
|
||||||
@@ -203,6 +212,13 @@ export class CommandManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
freezeList(): void {
|
||||||
|
if (!Object.isFrozen(this.list)) {
|
||||||
|
Object.freeze(this.list);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
private findPhraseOccurrence(phrase?: string): PhraseOccurrenceData | null {
|
private findPhraseOccurrence(phrase?: string): PhraseOccurrenceData | null {
|
||||||
let returnValue: PhraseOccurrenceData | null = null;
|
let returnValue: PhraseOccurrenceData | null = null;
|
||||||
this.list.map((c) => {
|
this.list.map((c) => {
|
||||||
|
|||||||
+1
-1
@@ -61,7 +61,7 @@ export class HelpMessage extends Command {
|
|||||||
helpMsg.setTitle(params.title);
|
helpMsg.setTitle(params.title);
|
||||||
helpMsg.setDescription(params.bottomText);
|
helpMsg.setDescription(params.bottomText);
|
||||||
|
|
||||||
cmdManager.list.map((c) => {
|
cmdManager.getList().map((c) => {
|
||||||
if (
|
if (
|
||||||
c.visible &&
|
c.visible &&
|
||||||
((Array.isArray(c.guilds) && c.guilds.length > 0 && c.guilds.find((g) => i?.guild?.id === g)) || !Array.isArray(c.guilds) || c.guilds.length === 0)
|
((Array.isArray(c.guilds) && c.guilds.length > 0 && c.guilds.find((g) => i?.guild?.id === g)) || !Array.isArray(c.guilds) || c.guilds.length === 0)
|
||||||
|
|||||||
+7
-7
@@ -37,26 +37,26 @@ export class Parameter {
|
|||||||
* Parameter name
|
* Parameter name
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
name: string;
|
public readonly name: string;
|
||||||
/**
|
/**
|
||||||
* Parameter description
|
* Parameter description
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
description: string;
|
public readonly description: string;
|
||||||
/**
|
/**
|
||||||
* Whether this parameter is optional
|
* Whether this parameter is optional
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
optional: boolean;
|
public readonly optional: boolean;
|
||||||
/**
|
/**
|
||||||
* Parameter input type
|
* Parameter input type
|
||||||
* @type {ParameterType}
|
* @type {ParameterType}
|
||||||
*/
|
*/
|
||||||
type: ParameterType;
|
public readonly type: ParameterType;
|
||||||
/**
|
/**
|
||||||
* List of value choices (available only when type is set to "STRING")
|
* List of value choices (available only when type is set to "STRING")
|
||||||
*/
|
*/
|
||||||
choices?: string[];
|
public readonly choices?: string[];
|
||||||
|
|
||||||
constructor(options: ParameterSchema) {
|
constructor(options: ParameterSchema) {
|
||||||
this.name = options.name;
|
this.name = options.name;
|
||||||
@@ -93,7 +93,7 @@ export class InputParameter extends Parameter {
|
|||||||
* Input value
|
* Input value
|
||||||
* @type {ParameterResolvable}
|
* @type {ParameterResolvable}
|
||||||
*/
|
*/
|
||||||
value: ParameterResolvable;
|
public readonly value: ParameterResolvable;
|
||||||
|
|
||||||
constructor(parameter: Parameter, value: ParameterResolvable) {
|
constructor(parameter: Parameter, value: ParameterResolvable) {
|
||||||
super(parameter);
|
super(parameter);
|
||||||
@@ -148,7 +148,7 @@ export class ObjectParameter extends InputParameter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class ObjectID {
|
export class ObjectID {
|
||||||
id: string;
|
public readonly id: string;
|
||||||
constructor(id: string) {
|
constructor(id: string) {
|
||||||
this.id = id.replace(">", "").replace("<@!", "").replace("<#!", "");
|
this.id = id.replace(">", "").replace("<@!", "").replace("<#!", "");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,27 +84,27 @@ export class SystemMessageManager {
|
|||||||
* "Insufficient permissions" message
|
* "Insufficient permissions" message
|
||||||
* @type {SystemMessageAppearance}
|
* @type {SystemMessageAppearance}
|
||||||
*/
|
*/
|
||||||
PERMISSION: SystemMessageAppearance;
|
public PERMISSION: SystemMessageAppearance;
|
||||||
/**
|
/**
|
||||||
* Error message
|
* Error message
|
||||||
* @type {SystemMessageAppearance}
|
* @type {SystemMessageAppearance}
|
||||||
*/
|
*/
|
||||||
ERROR: SystemMessageAppearance;
|
public ERROR: SystemMessageAppearance;
|
||||||
/**
|
/**
|
||||||
* "Command not found" message
|
* "Command not found" message
|
||||||
* @type {SystemMessageAppearance}
|
* @type {SystemMessageAppearance}
|
||||||
*/
|
*/
|
||||||
NOT_FOUND: SystemMessageAppearance;
|
public NOT_FOUND: SystemMessageAppearance;
|
||||||
/**
|
/**
|
||||||
* "Task completed successfully" message
|
* "Task completed successfully" message
|
||||||
* @type {SystemMessageAppearance}
|
* @type {SystemMessageAppearance}
|
||||||
*/
|
*/
|
||||||
SUCCESS: SystemMessageAppearance;
|
public SUCCESS: SystemMessageAppearance;
|
||||||
/**
|
/**
|
||||||
* Global time (in ms) after a message gets deleted
|
* Global time (in ms) after a message gets deleted
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
deleteTimeout: number;
|
public deleteTimeout: number;
|
||||||
|
|
||||||
constructor(botName?: string) {
|
constructor(botName?: string) {
|
||||||
this.PERMISSION = {
|
this.PERMISSION = {
|
||||||
|
|||||||
+6
-6
@@ -9,8 +9,8 @@ import { ParameterType } from "./types.js";
|
|||||||
* @exports
|
* @exports
|
||||||
*/
|
*/
|
||||||
export class PermissionsError extends Error {
|
export class PermissionsError extends Error {
|
||||||
private command: Command;
|
private readonly command: Command;
|
||||||
private user: GuildMember | null;
|
private readonly user: GuildMember | null;
|
||||||
constructor(command: Command, user?: GuildMember | null) {
|
constructor(command: Command, user?: GuildMember | null) {
|
||||||
super();
|
super();
|
||||||
this.command = command;
|
this.command = command;
|
||||||
@@ -27,8 +27,8 @@ export class PermissionsError extends Error {
|
|||||||
* @exports
|
* @exports
|
||||||
*/
|
*/
|
||||||
export class ParameterTypeError extends TypeError {
|
export class ParameterTypeError extends TypeError {
|
||||||
private stringContent: string;
|
private readonly stringContent: string;
|
||||||
private type: ParameterType;
|
private readonly type: ParameterType;
|
||||||
constructor(s: string, type: ParameterType) {
|
constructor(s: string, type: ParameterType) {
|
||||||
super();
|
super();
|
||||||
this.stringContent = s;
|
this.stringContent = s;
|
||||||
@@ -45,7 +45,7 @@ export class ParameterTypeError extends TypeError {
|
|||||||
* @exports
|
* @exports
|
||||||
*/
|
*/
|
||||||
export class MissingParameterError extends ReferenceError {
|
export class MissingParameterError extends ReferenceError {
|
||||||
private argument: Parameter;
|
private readonly argument: Parameter;
|
||||||
constructor(a: Parameter) {
|
constructor(a: Parameter) {
|
||||||
super();
|
super();
|
||||||
this.argument = a;
|
this.argument = a;
|
||||||
@@ -60,7 +60,7 @@ export class MissingParameterError extends ReferenceError {
|
|||||||
* @exports
|
* @exports
|
||||||
*/
|
*/
|
||||||
export class OperationSuccess {
|
export class OperationSuccess {
|
||||||
command: Command;
|
public readonly command: Command;
|
||||||
constructor(c: Command) {
|
constructor(c: Command) {
|
||||||
this.command = c;
|
this.command = c;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user