discord-module-loader
Version:
A package that lets you load events and commands easily and fast.
317 lines • 17.8 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = __importDefault(require("debug"));
const discord_js_1 = require("discord.js");
const node_fs_1 = require("node:fs");
const promises_1 = require("node:fs/promises");
const node_path_1 = require("node:path");
const DiscordCommand_1 = __importDefault(require("./DiscordCommand"));
const DiscordEvent_1 = __importDefault(require("./DiscordEvent"));
const DiscordGuild_1 = __importDefault(require("./DiscordGuild"));
const DiscordModule_1 = __importDefault(require("./DiscordModule"));
class DiscordModuleLoader {
constructor(client, options) {
this.client = client;
this.unknownCommandMessage = "Couldn't find executed command. Please try again later, or report the issue.";
this.disabledCommandMessage = "This command is currently disabled. Please try again later.";
this.disallowedChannelMessage = "You're not allowed to execute this command in this channel!";
this.commandCooldownMessage = "Please wait % seconds before using this command again.";
this.commands = new discord_js_1.Collection();
this.modules = new discord_js_1.Collection();
this.guilds = new discord_js_1.Collection();
this.cooldowns = new discord_js_1.Collection();
this.log = (0, debug_1.default)("Discord-Module-Loader");
if (options === null || options === void 0 ? void 0 : options.unknownCommandMessage)
this.unknownCommandMessage = options.unknownCommandMessage;
if (options === null || options === void 0 ? void 0 : options.disabledCommandMessage)
this.disabledCommandMessage = options.disabledCommandMessage;
if (options === null || options === void 0 ? void 0 : options.disallowedChannelMessage)
this.disallowedChannelMessage = options.disallowedChannelMessage;
if (options === null || options === void 0 ? void 0 : options.commandCooldownMessage)
this.commandCooldownMessage = options.commandCooldownMessage;
client.setMaxListeners(Infinity);
client.on("interactionCreate", int => void this.handleInteraction(int));
}
loadAll() {
return __awaiter(this, void 0, void 0, function* () {
yield this.loadCommands();
yield this.loadEvents();
yield this.loadModules();
yield this.loadGuilds();
});
}
loadGuilds(dir = "guilds") {
return __awaiter(this, void 0, void 0, function* () {
dir = (0, node_path_1.resolve)(dir);
if (!(0, node_fs_1.existsSync)(dir))
return [];
const guilds = yield (0, promises_1.readdir)(dir), log = this.log.extend((0, node_path_1.basename)(dir));
log("Loading %d guilds modules", guilds.length);
const returnGuilds = [];
for (const folder of guilds) {
if (!(yield (0, promises_1.lstat)((0, node_path_1.resolve)(dir, folder))).isDirectory())
throw new Error(`${folder} is not a directory.`);
if (!(0, node_fs_1.existsSync)((0, node_path_1.resolve)(dir, folder, "index.js")))
throw new Error(`Couldn't find index.js in ${folder}`);
let guild = (yield Promise.resolve().then(() => __importStar(require((0, node_path_1.resolve)(dir, folder, "index.js"))))).default;
if (typeof guild === "function")
guild = yield guild();
if (!(guild instanceof DiscordGuild_1.default))
throw new Error(`Guild ${folder} is not an Guild.`);
if (!this.client.guilds.cache.get(guild.id))
throw new Error(`Guild ${guild.id} is not cached.`);
if (this.guilds.has(guild.id))
throw new Error(`Cannot add ${guild.id} more than once.`);
this.guilds.set(guild.id, guild);
returnGuilds.push([guild.id, guild]);
if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(dir, folder, "events")))
this.addToColl(guild.events, yield this.loadEvents((0, node_path_1.resolve)(dir, folder, "events"), guild.id));
if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(dir, folder, "commands")))
this.addToColl(guild.commands, yield this.loadCommands((0, node_path_1.resolve)(dir, folder, "commands"), guild.id));
if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(dir, folder, "modules")))
this.addToColl(guild.modules, yield this.loadModules((0, node_path_1.resolve)(dir, folder, "modules"), guild.id));
if (guild.callback)
yield guild.callback();
log("Loaded guild module for guild: %s", guild.id);
}
return returnGuilds;
});
}
loadModules(dir = "modules", guildId) {
return __awaiter(this, void 0, void 0, function* () {
dir = (0, node_path_1.resolve)(dir);
if (!(0, node_fs_1.existsSync)(dir))
return [];
const modules = yield (0, promises_1.readdir)(dir), log = this.log.extend((0, node_path_1.basename)(dir));
log("Loading %d modules", modules.length);
const returnModules = [];
for (const folder of modules) {
if (!(yield (0, promises_1.lstat)((0, node_path_1.resolve)(dir, folder))).isDirectory())
throw new Error(`${folder} is not a directory.`);
if (!(0, node_fs_1.existsSync)((0, node_path_1.resolve)(dir, folder, "index.js")))
throw new Error(`Couldn't find index.js in ${folder}`);
let module = (yield Promise.resolve().then(() => __importStar(require((0, node_path_1.resolve)(dir, folder, "index.js"))))).default;
if (typeof module === "function")
module = yield module();
if (!(module instanceof DiscordModule_1.default))
throw new Error(`Module ${folder} is not an Module`);
if (this.modules.has(module.name))
throw new Error(`Cannot add ${module.name} more than once.`);
if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(dir, folder, "events")))
this.addToColl(module.events, yield this.loadEvents((0, node_path_1.resolve)(dir, folder, "events"), guildId));
if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(dir, folder, "commands")))
this.addToColl(module.commands, yield this.loadCommands((0, node_path_1.resolve)(dir, folder, "commands"), guildId));
if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(dir, folder, "modules")))
this.addToColl(module.modules, yield this.loadModules((0, node_path_1.resolve)(dir, folder, "modules")));
if (module.callback)
yield module.callback();
this.modules.set(module.name, module);
returnModules.push([module.name, module]);
log("Loaded module %s", module.name);
}
return returnModules;
});
}
addToColl(coll, add) {
for (const [key, value] of add)
coll.set(key, value);
}
loadEvents(dir = "events", guildId) {
return __awaiter(this, void 0, void 0, function* () {
dir = (0, node_path_1.resolve)(dir);
if (!(0, node_fs_1.existsSync)(dir))
return [];
const events = (yield (0, promises_1.readdir)(dir)).filter(file => file.endsWith(".js")), log = this.log.extend((0, node_path_1.basename)(dir));
log("Loading %d events", events.length);
const returnEvents = [];
for (const file of events) {
let event = (yield Promise.resolve().then(() => __importStar(require((0, node_path_1.resolve)(dir, file))))).default;
if (typeof event === "function")
event = yield event();
if (!(event instanceof DiscordEvent_1.default))
throw new Error(`Event ${file} is not an Event`);
if (guildId) {
this.guilds.get(guildId).events.set(event.event, event);
event.guildId = guildId;
}
this.client.on(event.event, (...args) => {
var _a, _b;
if (!event.disabled &&
event.guildId &&
((_b = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.guild) === null || _b === void 0 ? void 0 : _b.id) === event.guildId)
event.listener(...args);
if (!event.disabled && !event.guildId)
event.listener(...args);
});
returnEvents.push([event.event, event]);
log("Loaded event %s", event.event);
}
return returnEvents;
});
}
loadCommands(dir = "commands", guildId, subDirectoryOf) {
return __awaiter(this, void 0, void 0, function* () {
dir = (0, node_path_1.resolve)(dir);
if (!(0, node_fs_1.existsSync)(dir))
return [];
const directory = yield (0, promises_1.readdir)(dir, { withFileTypes: true }), commands = directory
.filter(file => file.isFile() && file.name.endsWith(".js"))
.map(f => f.name), subDirectories = directory
.filter(file => file.isDirectory())
.map(f => f.name), log = subDirectoryOf
? this.log.extend(subDirectoryOf).extend((0, node_path_1.basename)(dir))
: this.log.extend((0, node_path_1.basename)(dir));
log("Loading %d commands", commands.length);
const returnCommands = [];
for (const file of commands) {
let discordCommand = (yield Promise.resolve().then(() => __importStar(require((0, node_path_1.resolve)(dir, file))))).default;
if (typeof discordCommand === "function")
discordCommand = yield discordCommand();
if (!(discordCommand instanceof DiscordCommand_1.default))
throw new Error(`Command ${file} is not a Command`);
if (this.commands.has(discordCommand.command.name.toLowerCase()))
throw new Error(`Cannot add ${discordCommand.command.name} more than once.`);
if (guildId) {
this.guilds
.get(guildId)
.commands.set(discordCommand.command.name.toLowerCase(), discordCommand);
discordCommand.guildId = guildId;
}
this.commands.set(discordCommand.command.name.toLowerCase(), discordCommand);
returnCommands.push([
discordCommand.command.name.toLowerCase(),
discordCommand
]);
log("Loaded command %s", discordCommand.command.name);
}
if (!subDirectoryOf) {
log("Loading %s sub-directories", subDirectories.length);
for (const subDirectory of subDirectories)
returnCommands.push(...(yield this.loadCommands((0, node_path_1.resolve)(dir, subDirectory), guildId, (0, node_path_1.basename)(dir))));
}
return returnCommands;
});
}
updateSlashCommands() {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (!this.client.isReady())
throw new Error("Client is not ready.");
const localGlobalCommands = this.commands.filter(c => !c.guildId), log = this.log.extend("SlashCommands");
log("Setting %d global commands...", localGlobalCommands.size);
yield this.client.application.commands.set(localGlobalCommands.map(c => c.command));
for (const [id, guild] of this.client.guilds.cache) {
const dGuild = this.guilds.get(id);
if (dGuild === null || dGuild === void 0 ? void 0 : dGuild.commands.size)
log("Setting %d commands for guild %s...", dGuild.commands.size, guild.name);
yield guild.commands.set((_a = dGuild === null || dGuild === void 0 ? void 0 : dGuild.commands.map(c => c.command)) !== null && _a !== void 0 ? _a : []);
}
});
}
handleInteraction(interaction) {
return __awaiter(this, void 0, void 0, function* () {
if (interaction.isAutocomplete()) {
const command = this.commands.get(interaction.commandName.toLowerCase());
if (!command)
return yield interaction.respond([]);
try {
yield command.execute(interaction);
}
catch (err) {
console.error(err);
}
}
if (interaction.isCommand() ||
interaction.isContextMenuCommand() ||
interaction.isChatInputCommand() ||
interaction.isUserContextMenuCommand()) {
const discordCommand = this.commands.get(interaction.commandName.toLowerCase());
if (!discordCommand)
return yield interaction.reply({
content: this.unknownCommandMessage,
ephemeral: true
});
if (discordCommand.disabled)
return yield interaction.reply({
content: this.disabledCommandMessage,
ephemeral: true
});
let allowed = true;
if (discordCommand.channelDenylist &&
discordCommand.channelDenylist.includes(interaction.channelId))
allowed = false;
else if (discordCommand.channelAllowlist &&
!discordCommand.channelAllowlist.includes(interaction.channelId))
allowed = false;
if (!allowed) {
if (!this.disallowedChannelMessage.length)
return;
return yield interaction.reply({
content: this.disallowedChannelMessage,
ephemeral: true
});
}
if (discordCommand.cooldown) {
if (!this.cooldowns.has(discordCommand.command.name))
this.cooldowns.set(discordCommand.command.name, new discord_js_1.Collection());
const timestamps = this.cooldowns.get(discordCommand.command.name);
if (timestamps.has(interaction.user.id)) {
const expirationTime = timestamps.get(interaction.user.id) +
discordCommand.cooldown * 1000;
if (Date.now() < expirationTime) {
return yield interaction.reply({
content: this.commandCooldownMessage.replace("%", Math.ceil((expirationTime - Date.now()) / 1000).toString()),
ephemeral: true
});
}
}
timestamps.set(interaction.user.id, Date.now());
setTimeout(() => timestamps.delete(interaction.user.id), discordCommand.cooldown * 1000);
}
try {
yield discordCommand.execute(interaction);
}
catch (err) {
console.error(err);
}
}
});
}
}
exports.default = DiscordModuleLoader;
//# sourceMappingURL=ModuleLoader.js.map