djs-commander
Version:
A command and event handler that works seamlessly with Discord.js
372 lines (364 loc) • 11.6 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
var __esm = (fn, res) => function __init() {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/utils/getPaths.ts
var getPaths_exports = {};
__export(getPaths_exports, {
getFilePaths: () => getFilePaths,
getFolderPaths: () => getFolderPaths
});
function getFilePaths(directory, nesting) {
let filePaths = [];
if (!directory)
return filePaths;
const files = fs.readdirSync(directory, { withFileTypes: true });
for (const file of files) {
const filePath = path.join(directory, file.name);
if (file.isFile()) {
filePaths.push(filePath);
}
if (nesting && file.isDirectory()) {
filePaths = [...filePaths, ...getFilePaths(filePath, true)];
}
}
return filePaths;
}
function getFolderPaths(directory, nesting) {
let folderPaths = [];
if (!directory)
return folderPaths;
const folders = fs.readdirSync(directory, { withFileTypes: true });
for (const folder of folders) {
const folderPath = path.join(directory, folder.name);
if (folder.isDirectory()) {
folderPaths.push(folderPath);
if (nesting) {
folderPaths = [...folderPaths, ...getFolderPaths(folderPath, true)];
}
}
}
return folderPaths;
}
var fs, path;
var init_getPaths = __esm({
"src/utils/getPaths.ts"() {
"use strict";
fs = require("fs");
path = require("path");
}
});
// src/index.ts
var src_exports = {};
__export(src_exports, {
CommandHandler: () => CommandHandler
});
module.exports = __toCommonJS(src_exports);
init_getPaths();
// src/utils/buildCommandTree.ts
var { getFilePaths: getFilePaths2 } = (init_getPaths(), __toCommonJS(getPaths_exports));
function buildCommandTree(commandsDir) {
const commandTree = [];
if (!commandsDir)
return [];
const commandFilePaths = getFilePaths2(commandsDir, true);
for (const commandFilePath of commandFilePaths) {
let _a = require(commandFilePath), { data, run, deleted } = _a, rest = __objRest(_a, ["data", "run", "deleted"]);
if (!data)
throw new Error(`File ${commandFilePath} must export "data".`);
if (!run)
throw new Error(`File ${commandFilePath} must export a "run" function.`);
if (!data.name)
throw new Error(`File ${commandFilePath} must have a command name.`);
if (!data.description)
throw new Error(`File ${commandFilePath} must have a command description.`);
try {
data = data.toJSON();
} catch (error) {
}
commandTree.push(__spreadProps(__spreadValues(__spreadValues({}, data), rest), {
deleted,
run
}));
}
return commandTree;
}
// src/utils/getAppCommands.ts
function getAppCommands(client, guildId) {
return __async(this, null, function* () {
let applicationCommands;
if (guildId) {
const guild = yield client.guilds.fetch(guildId);
applicationCommands = guild.commands;
} else {
applicationCommands = yield client.application.commands;
}
yield applicationCommands.fetch();
return applicationCommands;
});
}
// src/utils/areCommandsDifferent.ts
function areCommandsDifferent(existingCommand, localCommand) {
var _a, _b;
if (localCommand.description !== existingCommand.description || (((_a = localCommand.options) == null ? void 0 : _a.length) || 0) !== ((_b = existingCommand.options) == null ? void 0 : _b.length)) {
return true;
} else {
return false;
}
}
// src/utils/registerCommands.ts
function registerCommands(_0) {
return __async(this, arguments, function* ({
client,
commands: localCommands,
testServer,
logger
}) {
const applicationCommands = yield getAppCommands(client, testServer);
for (const localCommand of localCommands) {
const {
name,
name_localizations,
description,
description_localizations,
default_member_permissions,
dm_permission,
options
} = localCommand;
const existingCommand = applicationCommands.cache.find((cmd) => cmd.name === name);
if (existingCommand) {
if (localCommand.deleted) {
yield applicationCommands.delete(existingCommand.id);
let message = `\u{1F5D1} Deleted command "${name}".`;
if (logger) {
logger.info(message);
} else {
console.log(message);
}
continue;
}
if (areCommandsDifferent(existingCommand, localCommand)) {
yield applicationCommands.edit(existingCommand.id, {
description,
options
});
let message = `\u{1F501} Edited command "${name}".`;
if (logger) {
logger.info(message);
} else {
console.log(message);
}
}
} else {
if (localCommand.deleted) {
let message2 = `\u23E9 Skipping registering command "${name}" as it's set to delete.`;
if (logger) {
logger.info(message2);
} else {
console.log(message2);
}
continue;
}
yield applicationCommands.create({
name,
name_localizations,
description,
description_localizations,
default_member_permissions,
dm_permission,
options
});
let message = `\u2705 Registered command "${name}".`;
if (logger) {
logger.info(message);
} else {
console.log(message);
}
}
}
});
}
// src/index.ts
var CommandHandler = class {
constructor({
client,
commandsPath,
eventsPath,
validationsPath,
testServer,
logger
}) {
if (!client)
throw new Error('Property "client" is required when instantiating CommandHandler.');
this._client = client;
this._commandsPath = commandsPath;
this._eventsPath = eventsPath;
this._validationsPath = validationsPath;
this._testServer = testServer;
this._commands = [];
this._validationFuncs = [];
this._logger = logger;
if (this._validationsPath && !commandsPath) {
throw new Error(
'Command validations are only available in the presence of a commands path. Either add "commandsPath" or remove "validationsPath"'
);
}
if (this._commandsPath) {
this._commandsInit();
this._client.once("ready", () => {
this._registerSlashCommands();
this._validationsPath && this._validationsInit();
this._handleCommands();
});
}
if (this._eventsPath) {
this._eventsInit();
}
}
_commandsInit() {
let commands = buildCommandTree(this._commandsPath);
this._commands = commands;
}
_registerSlashCommands() {
registerCommands({
client: this._client,
commands: this._commands,
testServer: this._testServer,
logger: this._logger
});
}
_eventsInit() {
const eventPaths = getFolderPaths(this._eventsPath);
for (const eventPath of eventPaths) {
const eventName = eventPath.replace(/\\/g, "/").split("/").pop();
const eventFuncPaths = getFilePaths(eventPath, true);
eventFuncPaths.sort();
if (!eventName)
continue;
this._client.on(eventName, (...arg) => __async(this, null, function* () {
for (const eventFuncPath of eventFuncPaths) {
const eventFunc = require(eventFuncPath);
const cantRunEvent = yield eventFunc(...arg, this._client, this);
if (cantRunEvent)
break;
}
}));
}
}
_validationsInit() {
const validationFilePaths = getFilePaths(this._validationsPath);
validationFilePaths.sort();
for (const validationFilePath of validationFilePaths) {
const validationFunc = require(validationFilePath);
if (typeof validationFunc !== "function") {
throw new Error(`Validation file ${validationFilePath} must export a function by default.`);
}
this._validationFuncs.push(validationFunc);
}
}
_handleCommands() {
this._client.on("interactionCreate", (interaction) => __async(this, null, function* () {
if (!interaction.isChatInputCommand())
return;
const command = this._commands.find((cmd) => cmd.name === interaction.commandName);
if (command) {
if (this._validationFuncs.length) {
let canRun = true;
for (const validationFunc of this._validationFuncs) {
const cantRunCommand = yield validationFunc(interaction, command, this, this._client);
if (cantRunCommand) {
canRun = false;
break;
}
}
if (canRun) {
yield command.run({
interaction,
client: this._client,
handler: this
});
}
} else {
yield command.run({
interaction,
client: this._client,
handler: this
});
}
}
}));
}
get commands() {
return this._commands;
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
CommandHandler
});