Files
tts_bot/src/classes/Handler.ts
Claude Owner 35569ddd88 fix(handler): filter command files and guard non-command modules
Handler.ts iterated readdirSync(COMMANDS_PATH) without filtering, so
any .d.ts declaration file, .js.map source map, or non-class module
that landed in commands/ would crash startup with 'mod.default is not
a constructor'. Restrict loading to .ts/.js (excluding .d.ts and maps)
and skip modules without a default-exported constructor.
2026-05-26 14:40:29 +09:00

33 lines
1.3 KiB
TypeScript

import { ChatInputCommandInteraction, Collection } from "discord.js";
import { readdirSync } from "node:fs";
import { Command } from "../types/Command";
import { COMMAND_PATH, COMMANDS_PATH } from "../utils/Config";
export class Handler {
public commands: Collection<string, Command> = new Collection();
public coolDown: Map<string, number> = new Map();
public constructor() {
const commandFiles = readdirSync(COMMANDS_PATH).filter((f) => {
// ts-node로 dev 실행 시 .ts, 빌드 후엔 .js. 둘 다 허용하고
// 선언 파일(.d.ts)/소스맵(.js.map)은 제외한다.
if (f.endsWith(".d.ts")) return false;
if (f.endsWith(".js.map") || f.endsWith(".ts.map")) return false;
return f.endsWith(".ts") || f.endsWith(".js");
});
for (const commandFile of commandFiles) {
const mod = require(COMMAND_PATH(commandFile));
if (typeof mod.default !== "function") continue; // not a command module
const command = new mod.default() as Command;
this.commands.set(command.metaData.name, command);
}
}
public runCommand(interaction: ChatInputCommandInteraction) {
const commandName = interaction.commandName;
const command = this.commands.get(commandName);
if (!command) return;
if (command.slashRun) command.slashRun(interaction);
}
}