@tryforge/forgescript
Version:
ForgeScript is a comprehensive package that empowers you to effortlessly interact with Discord's API. It ensures scripting remains easy to learn and consistently effective.
277 lines • 12.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationCommandManager = exports.RegistrationType = void 0;
/* eslint-disable indent */
const discord_js_1 = require("discord.js");
const ApplicationCommand_1 = require("../structures/base/ApplicationCommand");
const EventManager_1 = require("./EventManager");
const fs_1 = require("fs");
const path_1 = require("path");
const process_1 = require("process");
var RegistrationType;
(function (RegistrationType) {
RegistrationType[RegistrationType["Global"] = 0] = "Global";
RegistrationType[RegistrationType["Guild"] = 1] = "Guild";
RegistrationType[RegistrationType["All"] = 2] = "All";
})(RegistrationType || (exports.RegistrationType = RegistrationType = {}));
class ApplicationCommandManager {
client;
/**
* If:
* - value is app command = slash command
* - value is collection:
* - value is slash command = subcommands
* - value is collection = group with subcommands
*/
commands = new discord_js_1.Collection();
path;
constructor(client) {
this.client = client;
}
/**
* PATH TREE MATTERS
* @param path
*/
load(path = this.path) {
if (!path)
return;
this.path ??= path;
this.commands.clear();
for (const mainPath of (0, fs_1.readdirSync)(path)) {
const resolved = (0, path_1.join)(path, mainPath);
const stats = (0, fs_1.statSync)(resolved);
if (stats.isDirectory()) {
const col = new discord_js_1.Collection();
for (const secondPath of (0, fs_1.readdirSync)(resolved)) {
const secondResolved = (0, path_1.join)(resolved, secondPath);
const stats = (0, fs_1.statSync)(secondResolved);
if (stats.isDirectory()) {
const nextCol = new discord_js_1.Collection();
for (const lastPath of (0, fs_1.readdirSync)(secondResolved)) {
const thirdResolved = (0, path_1.join)(secondResolved, lastPath);
const stats = (0, fs_1.statSync)(thirdResolved);
if (stats.isDirectory())
throw new Error(`Disallowed folder found for slash command tree: ${thirdResolved}`);
const loaded = this.loadOne((0, path_1.join)((0, process_1.cwd)(), thirdResolved));
if (!loaded)
continue;
else if (loaded.options.independent) {
this.commands.set(loaded.name, loaded);
continue;
}
nextCol.set(loaded.name, loaded);
}
if (nextCol.size === 0)
continue;
col.set(secondPath, nextCol);
}
else {
const loaded = this.loadOne((0, path_1.join)((0, process_1.cwd)(), secondResolved));
if (!loaded)
continue;
else if (loaded.options.independent) {
this.commands.set(loaded.name, loaded);
continue;
}
col.set(loaded.name, loaded);
}
}
if (col.size === 0)
continue;
this.commands.set(mainPath, col);
}
else {
const loaded = this.loadOne((0, path_1.join)((0, process_1.cwd)(), resolved));
if (!loaded)
continue;
this.commands.set(loaded.name, loaded);
}
}
}
getDisplayOptions(input, hideName) {
const arr = new Array();
for (const data of input) {
if (data.value !== undefined) {
arr.push(`${hideName ? "" : `${data.name}: `}${data.value}`);
}
else if (data.options?.length)
arr.push(...this.getDisplayOptions(data.options, hideName));
}
return arr;
}
getDisplay(input, hideName) {
if (input instanceof discord_js_1.ChatInputCommandInteraction) {
const commandName = input.commandName;
const subcommandName = input.options.getSubcommand(false);
const subcommandGroupName = input.options.getSubcommandGroup(false);
const filteredOptions = this.getDisplayOptions(input.options.data, hideName);
return `/${commandName}${subcommandGroupName
? subcommandName
? ` ${subcommandGroupName} ${subcommandName}`
: ` ${subcommandGroupName}`
: subcommandName
? ` ${subcommandName}`
: ""} ${filteredOptions.join(" ")}`;
}
else if (input instanceof discord_js_1.ContextMenuCommandInteraction)
return `/${input.commandName}`;
return null;
}
get(input) {
const commandName = input.commandName;
if (!input.isChatInputCommand())
return this.commands.get(commandName);
const subcommandName = input.options.getSubcommand(false);
const subcommandGroupName = input.options.getSubcommandGroup(false);
const cmd = this.commands.get(commandName) ?? null;
if (cmd instanceof discord_js_1.Collection) {
const col = cmd.get(subcommandGroupName ?? subcommandName);
if (col instanceof discord_js_1.Collection) {
return col.get(subcommandName) ?? null;
}
return col ?? null;
}
return cmd;
}
/**
* **WARNING** This function does not allow subcommand & subcommand group options. Consider using ApplicationCommandManager#load to load a tree from a folder.
* @param values
* @returns
*/
add(...values) {
for (const value of values) {
if (Array.isArray(value))
return this.add(...value);
const resolved = this.resolve(value, null);
this.commands.set(resolved.name, resolved);
}
}
loadOne(reqPath) {
if (!reqPath.endsWith(".js"))
return null;
delete require.cache[require.resolve(reqPath)];
const req = require(reqPath);
let value = req.default ?? req;
if (!value || !Object.keys(value).length)
return null;
else if (Array.isArray(value))
throw new Error("Disallowed");
return this.resolve(value, reqPath);
}
validate(app, path) {
const json = app.toJSON();
if (json.options?.some((x) => x.type === discord_js_1.ApplicationCommandOptionType.Subcommand ||
x.type === discord_js_1.ApplicationCommandOptionType.SubcommandGroup)) {
throw new Error(`Attempted to define subcommand / subcommand group without using path tree definition. (${path ?? "index file"})`);
}
}
resolve(value, path) {
const v = value instanceof ApplicationCommand_1.ApplicationCommand ? value : new ApplicationCommand_1.ApplicationCommand({ ...value, path });
this.validate(v, path);
return v;
}
toJSON(type) {
const arr = new Array();
// Helper function to read config.json
const readConfig = (folderPath) => {
const configPath = (0, path_1.join)(folderPath, "config.json");
if ((0, fs_1.existsSync)(configPath)) {
try {
return JSON.parse((0, fs_1.readFileSync)(configPath, "utf-8"));
}
catch (err) {
throw new Error(`Error reading config.json in ${folderPath}: ${err}`);
}
}
return null;
};
for (const [commandName, value] of this.commands) {
if (value instanceof ApplicationCommand_1.ApplicationCommand) {
if (!value.mustRegisterAs(type))
continue;
const folderPath = (0, path_1.join)(this.path, commandName);
const config = readConfig(folderPath);
const commandData = {
...value.options.data,
...(config ? config : {}),
};
arr.push(commandData);
}
else {
const folderPath = (0, path_1.join)(this.path, commandName);
const config = readConfig(folderPath);
const json = {
...config,
name: commandName,
description: config?.description || "none",
type: discord_js_1.ApplicationCommandType.ChatInput,
options: [],
};
for (const [nextName, values] of value) {
if (values instanceof discord_js_1.Collection) {
const subFolderPath = (0, path_1.join)(folderPath, nextName);
const subConfig = readConfig(subFolderPath);
// Apply only for subcommand groups
const raw = {
...subConfig,
name: nextName,
description: subConfig?.description || "none",
type: discord_js_1.ApplicationCommandOptionType.SubcommandGroup,
options: [],
};
// Only assign `options` if this is a SubcommandGroup
if (raw.type === discord_js_1.ApplicationCommandOptionType.SubcommandGroup) {
raw.options = [];
for (const [lastName, command] of values) {
if (!command.mustRegisterAs(type))
continue;
const commandData = command.toJSON();
raw.options.push({
...commandData,
name: lastName,
type: discord_js_1.ApplicationCommandOptionType.Subcommand,
});
}
}
// Only push `json.options` if it contains valid data
if (raw.options?.length) {
json.options.push(raw);
}
}
else {
if (!values.mustRegisterAs(type))
continue;
const subFolderPath = (0, path_1.join)(folderPath, nextName);
const subConfig = readConfig(subFolderPath);
// Add subcommand if available
const raw = values.toJSON();
json.options.push({
...raw,
...subConfig,
type: discord_js_1.ApplicationCommandOptionType.Subcommand,
});
}
}
// Only push JSON if it contains valid options
if (json.options?.length) {
arr.push(json);
}
}
}
return arr;
}
registerGlobal() {
if (!this.commands.size)
return;
this.client.events.load(EventManager_1.NativeEventName, discord_js_1.Events.InteractionCreate);
return this.client.application.commands.set(this.toJSON(RegistrationType.Global));
}
registerGuild(g) {
if (!this.commands.size)
return;
this.client.events.load(EventManager_1.NativeEventName, discord_js_1.Events.InteractionCreate);
return g.commands.set(this.toJSON(RegistrationType.Guild));
}
}
exports.ApplicationCommandManager = ApplicationCommandManager;
//# sourceMappingURL=ApplicationCommandManager.js.map