djshandler-core
Version:
Core command handler framework for Discord.js bots
355 lines (351 loc) • 10.8 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
CommandClass: () => CommandClass,
CommandHandler: () => DJSHandler,
DJSHandler: () => DJSHandler,
EventClass: () => EventClass,
Execute: () => Execute,
Logger: () => Logger,
On: () => On,
Once: () => Once,
ensureDir: () => ensureDir,
extractCommand: () => extractCommand,
extractEvent: () => extractEvent,
fileExists: () => fileExists,
formatCommandName: () => formatCommandName,
importModule: () => importModule,
isValidCommandName: () => isValidCommandName,
loadFiles: () => loadFiles,
logger: () => logger
});
module.exports = __toCommonJS(index_exports);
// src/handler.ts
var import_discord = require("discord.js");
var DJSHandler = class {
constructor(options) {
this.options = options;
this.commands = new import_discord.Collection();
this.events = new import_discord.Collection();
this.client = new import_discord.Client({
intents: this.options.intents || [
import_discord.GatewayIntentBits.Guilds,
import_discord.GatewayIntentBits.GuildMessages,
import_discord.GatewayIntentBits.MessageContent
]
});
if (this.options.token) {
this.rest = new import_discord.REST().setToken(this.options.token);
}
this.setupDefaultEvents();
}
/**
* Register a command with the handler
*/
registerCommand(command) {
this.commands.set(command.data.name, command);
return this;
}
/**
* Register an event with the handler
*/
registerEvent(event) {
this.events.set(event.name, event);
if (event.once) {
this.client.once(event.name, (...args) => event.execute(...args));
} else {
this.client.on(event.name, (...args) => event.execute(...args));
}
return this;
}
/**
* Load all commands from a directory
*/
async loadCommands(commandsPath) {
return this;
}
/**
* Load all events from a directory
*/
async loadEvents(eventsPath) {
return this;
}
/**
* Deploy slash commands to Discord
*/
async deployCommands(guildId) {
if (!this.rest || !this.options.clientId) {
throw new Error("REST client not initialized or clientId not provided");
}
const commandsData = Array.from(this.commands.values()).map(
(command) => command.data.toJSON()
);
try {
console.log(`Started refreshing ${commandsData.length} application (/) commands.`);
const route = guildId ? import_discord.Routes.applicationGuildCommands(this.options.clientId, guildId) : import_discord.Routes.applicationCommands(this.options.clientId);
await this.rest.put(route, { body: commandsData });
console.log(`Successfully reloaded ${commandsData.length} application (/) commands.`);
} catch (error) {
console.error("Error deploying commands:", error);
throw error;
}
}
/**
* Start the bot
*/
async start() {
if (!this.options.token) {
throw new Error("Bot token is required to start the client");
}
try {
await this.client.login(this.options.token);
console.log("Bot started successfully!");
} catch (error) {
console.error("Error starting bot:", error);
throw error;
}
}
/**
* Get the Discord.js client instance
*/
getClient() {
return this.client;
}
/**
* Get registered commands
*/
getCommands() {
return this.commands;
}
/**
* Get registered events
*/
getEvents() {
return this.events;
}
/**
* Setup default event handlers
*/
setupDefaultEvents() {
this.client.on(import_discord.Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
const command = this.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(`Error executing command ${interaction.commandName}:`, error);
const reply = {
content: "There was an error while executing this command!",
ephemeral: true
};
if (interaction.replied || interaction.deferred) {
await interaction.followUp(reply);
} else {
await interaction.reply(reply);
}
}
});
this.client.on(import_discord.Events.ClientReady, () => {
console.log(`Ready! Logged in as ${this.client.user?.tag}`);
});
}
};
// src/decorators.ts
var import_reflect_metadata = require("reflect-metadata");
var import_discord2 = require("discord.js");
var COMMAND_METADATA_KEY = Symbol("command");
var EVENT_METADATA_KEY = Symbol("event");
function CommandClass(metadata) {
return function(constructor) {
Reflect.defineMetadata(COMMAND_METADATA_KEY, metadata, constructor);
return constructor;
};
}
function Execute() {
return function(target, propertyKey, descriptor) {
Reflect.defineMetadata("execute", true, target, propertyKey);
};
}
function EventClass(metadata) {
return function(constructor) {
Reflect.defineMetadata(EVENT_METADATA_KEY, metadata, constructor);
return constructor;
};
}
function On(eventName) {
return function(target, propertyKey, descriptor) {
Reflect.defineMetadata("eventName", eventName, target, propertyKey);
Reflect.defineMetadata("once", false, target, propertyKey);
};
}
function Once(eventName) {
return function(target, propertyKey, descriptor) {
Reflect.defineMetadata("eventName", eventName, target, propertyKey);
Reflect.defineMetadata("once", true, target, propertyKey);
};
}
function extractCommand(CommandClass2) {
const metadata = Reflect.getMetadata(COMMAND_METADATA_KEY, CommandClass2);
if (!metadata) return null;
const instance = new CommandClass2();
const prototype = Object.getPrototypeOf(instance);
const methods = Object.getOwnPropertyNames(prototype);
let executeMethod = null;
for (const method of methods) {
if (Reflect.getMetadata("execute", prototype, method)) {
executeMethod = instance[method].bind(instance);
break;
}
}
if (!executeMethod) return null;
const commandBuilder = new import_discord2.SlashCommandBuilder().setName(metadata.name).setDescription(metadata.description);
return {
data: commandBuilder,
execute: executeMethod,
category: metadata.category,
disabled: metadata.disabled,
cooldown: metadata.cooldown
};
}
function extractEvent(EventClass2) {
const metadata = Reflect.getMetadata(EVENT_METADATA_KEY, EventClass2);
if (!metadata) return null;
const instance = new EventClass2();
const prototype = Object.getPrototypeOf(instance);
const methods = Object.getOwnPropertyNames(prototype);
let executeMethod = null;
for (const method of methods) {
const eventName = Reflect.getMetadata("eventName", prototype, method);
if (eventName) {
executeMethod = instance[method].bind(instance);
break;
}
}
if (!executeMethod) return null;
return {
name: metadata.name,
once: metadata.once,
execute: executeMethod
};
}
// src/utils.ts
var fs = __toESM(require("fs/promises"));
var path = __toESM(require("path"));
async function loadFiles(dirPath, extension = ".js") {
const files = [];
try {
const items = await fs.readdir(dirPath, { withFileTypes: true });
for (const item of items) {
const fullPath = path.join(dirPath, item.name);
if (item.isDirectory()) {
const subFiles = await loadFiles(fullPath, extension);
files.push(...subFiles);
} else if (item.isFile() && item.name.endsWith(extension)) {
files.push(fullPath);
}
}
} catch (error) {
console.warn(`Could not read directory ${dirPath}:`, error);
}
return files;
}
async function importModule(filePath) {
try {
const module2 = await import(filePath);
return module2.default || module2;
} catch (error) {
console.warn(`Could not import module from ${filePath}:`, error);
return null;
}
}
async function fileExists(filePath) {
try {
await fs.access(filePath);
return true;
} catch {
return false;
}
}
async function ensureDir(dirPath) {
try {
await fs.mkdir(dirPath, { recursive: true });
} catch (error) {
console.warn(`Could not create directory ${dirPath}:`, error);
}
}
function formatCommandName(name) {
return name.toLowerCase().replace(/[^a-z0-9-_]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
}
function isValidCommandName(name) {
return /^[a-z0-9-_]{1,32}$/.test(name);
}
var Logger = class {
constructor(prefix = "DJSHandler") {
this.prefix = prefix;
}
info(message, ...args) {
console.log(`[${this.prefix}] ${message}`, ...args);
}
warn(message, ...args) {
console.warn(`[${this.prefix}] ${message}`, ...args);
}
error(message, ...args) {
console.error(`[${this.prefix}] ${message}`, ...args);
}
debug(message, ...args) {
if (process.env.NODE_ENV === "development") {
console.debug(`[${this.prefix}] ${message}`, ...args);
}
}
};
var logger = new Logger();
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
CommandClass,
CommandHandler,
DJSHandler,
EventClass,
Execute,
Logger,
On,
Once,
ensureDir,
extractCommand,
extractEvent,
fileExists,
formatCommandName,
importModule,
isValidCommandName,
loadFiles,
logger
});
//# sourceMappingURL=index.js.map