all repos — stealth-developers @ eea31754b6ebbd92fd77be1f9394696bec84c30a

src/handlers/interactions.ts (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
import type { ApplicationCommandData, Client, Snowflake } from "discord.js";
import { Collection, REST, Routes } from "discord.js";

import cfg from "@/config.ts";
import type { ICommand } from "@/types.ts";
import _logger from "@/utils/logging.ts";
import { crawlDirectory, getHandlerPath } from "./common.ts";

const logger = _logger.child({ name: "interactions" });
export const commands = new Collection<string, ICommand>();

async function getCommands(): Promise<ICommand[]> {
	const processFile = async (fileUrl: string) => {
		const { default: interaction } = await import(fileUrl);
		if (!interaction) return;

		if (
			!interaction.data &&
			!interaction.buttonExecute &&
			!interaction.modalExecute
		) {
			logger.info(`${fileUrl} does not have a data property, skipping`);
			return;
		}

		let commandName = interaction.data?.name;

		if (!commandName) {
			const urlPath = new URL(fileUrl).pathname;
			const filename = urlPath.split("/").pop();
			commandName = filename?.replace(".ts", "");
		}
		if (!commandName) return;

		if (interaction.enabled === false) {
			logger.info(`${commandName} was disabled, skipping`);
			return;
		}

		commands.set(commandName, interaction);
		return interaction;
	};

	return await crawlDirectory<ICommand>(
		getHandlerPath("interactions"),
		processFile,
	);
}

async function registerInteractions(
	client: Client,
	interactions: ApplicationCommandData[],
) {
	if (!client.user) return logger.error("client user is not available");
	if (!client.application)
		return logger.error("client application is not available");
	if (interactions.length === 0) return;

	logger.info("registering interactions...");
	const rest = new REST({ version: "9" }).setToken(cfg.discord.token);

	try {
		logger.info("registering commands...");
		await rest.put(Routes.applicationCommands(<Snowflake>client.user.id), {
			body: interactions,
		});
		logger.info(`registered ${interactions.length} commands`);
	} catch (error) {
		logger.error(error, "failed to register commands");
	}
}

async function registerCommands(client: Client) {
	await getCommands();
	const slashCommands = commands
		.map((command) => command.data)
		.filter((data): data is ApplicationCommandData => !!data);

	if (slashCommands.length === 0) return logger.warn("no commands found");

	logger.info(`found ${slashCommands.length} commands`);
	for (const command of slashCommands) {
		logger.info(`  * ${command.name}`);
	}

	await registerInteractions(client, slashCommands);
}

export default registerCommands;