From a3178942af08ca4b4bdee147638dd4b3eb26d855 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Wed, 1 May 2024 17:17:32 +0200 Subject: [PATCH] move commands to separate module --- src/bot.ts | 187 +---------------------------------- src/lib/commands/commands.ts | 185 ++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 183 deletions(-) create mode 100644 src/lib/commands/commands.ts diff --git a/src/bot.ts b/src/bot.ts index 8da026e..9e91075 100755 --- a/src/bot.ts +++ b/src/bot.ts @@ -1,18 +1,12 @@ #!/bin/env -S deno run -A --unstable-kv -import { - AutocompleteInteraction, - ChatInputCommandInteraction, - Client, - EmbedBuilder, - SlashCommandBuilder, - TextChannel, -} from "npm:discord.js"; +import { Client } from "npm:discord.js"; import { Storage } from "./lib/storage.ts"; -import { _1d, _1min, Channel, channel, collect, days_to_ms, log_from, trimmed } from "./lib/utils.ts"; +import { channel, log_from } from "./lib/utils.ts"; import { update_loop } from "./lib/board.ts"; import { notification_loop } from "./lib/notification.ts"; +import { declare_commands, handle_autocomplete, handle_command } from "./lib/commands/commands.ts"; const log = log_from(import.meta); @@ -46,7 +40,7 @@ async function main() { await bot.login(token); log("Logged in as", bot.user?.username); - const commands = build_api_commands(subjects); + const commands = declare_commands(subjects); if (debug_server !== undefined) { for (const command of commands) command.setName("dbg-" + command.name); await bot.application?.commands.set(commands, debug_server); @@ -62,177 +56,4 @@ async function main() { log("Oki."); } -function build_api_commands(subjects: Set) { - const subjects_as_choices = [...subjects.values()].map((name) => ({ name, value: name })); - const devoir_command = new SlashCommandBuilder() - .setName("devoir") - .setDescription("Manipuler les devoirs à effectuer.") - .addSubcommand((command) => - command.setName("ajouter") - .setDescription("Ajouter un nouveau devoir à effectuer.") - .addStringOption((option) => - option.setName("matière") - .setDescription("Matière du devoir à effectuer.") - .addChoices(...subjects_as_choices) - .setRequired(true) - ) - .addNumberOption((option) => - option.setName("jours") - .setMinValue(0) - .setDescription("Nombre de jours avant la date du rendu.") - .setRequired(true) - ) - .addStringOption((option) => - option.setName("description") - .setDescription("Description du devoir à effectuer.") - .setRequired(true) - ) - ).addSubcommand((command) => - command.setName("retirer") - .setDescription("Retirer un devoir.") - .addStringOption((option) => - option.setName("devoir") - .setDescription("Devoir à retirer.") - .setAutocomplete(true) - .setRequired(true) - ) - ).addSubcommand((command) => - command.setName("éditer") - .setDescription("Éditer un devoir.") - .addStringOption((option) => - option.setName("devoir") - .setDescription("Devoir à éditer.") - .setAutocomplete(true) - .setRequired(true) - ) - .addStringOption((option) => - option.setName("matière") - .setDescription("Nouvelle matière.") - .addChoices(...subjects_as_choices) - .setRequired(false) - ) - .addNumberOption((option) => - option.setName("jours") - .setMinValue(0) - .setDescription("Nouveau nombre de jours avant la date du rendu.") - .setRequired(false) - ) - .addStringOption((option) => - option.setName("description") - .setDescription("Nouvelle description.") - .setRequired(false) - ) - ); - const adm_command = new SlashCommandBuilder().setName("adm") - .setDescription("Commandes d'administration.") - .addSubcommand((command) => - command.setName("ajouter-feed") - .setDescription("Ajoute un salon comme feed de notifications.") - .addChannelOption((option) => - option.setName("salon") - .setDescription("Salon du nouveau feed.") - .setRequired(true) - ) - ); - return [devoir_command, adm_command]; -} - -async function handle_command( - interaction: ChatInputCommandInteraction, - storage: Storage, - update_display: Channel, -) { - log("Received command", interaction.commandName); - if (interaction.commandName === "devoir") { - const subcommand = interaction.options.getSubcommand(true); - if (subcommand === "ajouter") { - const subject = interaction.options.getString("matière", true); - const days = interaction.options.getNumber("jours", true); - const description = interaction.options.getString("description", true); - const date = Date.now() + days_to_ms(days); - const { id } = await storage.devoirs.add({ date, description, subject }); - const embed = new EmbedBuilder() - .setTitle("`🌟` Ajouté") - .setDescription(`Nouveau devoir ajouté avec succès.`) - .setFooter({ text: `(devoir id:${id})` }); - await interaction.reply({ embeds: [embed], ephemeral: true }); - update_display.send(); - return; - } - if (subcommand === "retirer") { - const id = interaction.options.getString("devoir", true); - await storage.devoirs.delete({ id }); - const embed = new EmbedBuilder() - .setTitle("`🗑️` Retiré") - .setDescription(`Devoir supprimé avec succès.`) - .setFooter({ text: `(devoir id:${id})` }); - await interaction.reply({ embeds: [embed], ephemeral: true }); - update_display.send(); - return; - } - if (subcommand === "éditer") { - const id = interaction.options.getString("devoir", true); - const subject = interaction.options.getString("matière", false); - if (subject !== null) storage.devoirs.update({ id }, (d) => d.subject = subject); - const description = interaction.options.getString("description", false); - if (description !== null) storage.devoirs.update({ id }, (d) => d.description = description); - const days = interaction.options.getNumber("jours", false); - if (days !== null) storage.devoirs.update({ id }, (d) => d.date = Date.now() + days_to_ms(days)); - const embed = new EmbedBuilder() - .setTitle("`🔧` Édité") - .setDescription(`Devoir mis à jour avec succès.`) - .setFooter({ text: `(devoir id:${id})` }); - await interaction.reply({ embeds: [embed], ephemeral: true }); - update_display.send(); - return; - } - return log("Unknown devoir sub command", subcommand); - } - if (interaction.commandName === "adm") { - const subcommand = interaction.options.getSubcommand(true); - if (subcommand === "ajouter-feed") { - const channel = interaction.options.getChannel("salon", true); - const is_text_channel = channel instanceof TextChannel; - if (!is_text_channel) { - await interaction.reply("Channel must be text."); - return; - } - const board_message = await channel.send("[board]"); - const feed_id = await storage.feeds.add({ - channel_id: channel.id, - board_message_id: board_message.id, - notification_ids: new Set(), - }); - await interaction.reply("Added feed " + feed_id.id); - } - return log("Unknown adm sub command", subcommand); - } - log("Unknown command", interaction.commandName); -} - -async function handle_autocomplete(interaction: AutocompleteInteraction, storage: Storage) { - log("Auto completing."); - if (interaction.commandName === "devoir") { - const subcommand = interaction.options.getSubcommand(true); - if (subcommand === "retirer") { - const devoirs = await collect(storage.devoirs.list()); - const mapped = devoirs.map(([{ id }, value]) => ({ - name: trimmed(`[${value.subject}] ${value.description}`, 100), - value: id, - })); - return await interaction.respond(mapped); - } - if (subcommand === "éditer") { - const devoirs = await collect(storage.devoirs.list()); - const mapped = devoirs.map(([{ id }, value]) => ({ - name: trimmed(`[${value.subject}] ${value.description}`, 100), - value: id, - })); - return await interaction.respond(mapped); - } - return log("Unknown devoir sub command", subcommand); - } - log("Unknown command", interaction.commandName); -} - if (import.meta.main) await main(); diff --git a/src/lib/commands/commands.ts b/src/lib/commands/commands.ts new file mode 100644 index 0000000..23e00c9 --- /dev/null +++ b/src/lib/commands/commands.ts @@ -0,0 +1,185 @@ +import { + AutocompleteInteraction, + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandBuilder, + TextChannel, +} from "npm:discord.js"; + +import { Storage } from "../storage.ts"; +import { _1d, _1min, Channel, collect, days_to_ms, log_from, trimmed } from "../utils.ts"; + +const log = log_from(import.meta); + +export function declare_commands(subjects: Set) { + const subjects_as_choices = [...subjects.values()].map((name) => ({ name, value: name })); + const devoir_command = new SlashCommandBuilder() + .setName("devoir") + .setDescription("Manipuler les devoirs à effectuer.") + .addSubcommand((command) => + command.setName("ajouter") + .setDescription("Ajouter un nouveau devoir à effectuer.") + .addStringOption((option) => + option.setName("matière") + .setDescription("Matière du devoir à effectuer.") + .addChoices(...subjects_as_choices) + .setRequired(true) + ) + .addNumberOption((option) => + option.setName("jours") + .setMinValue(0) + .setDescription("Nombre de jours avant la date du rendu.") + .setRequired(true) + ) + .addStringOption((option) => + option.setName("description") + .setDescription("Description du devoir à effectuer.") + .setRequired(true) + ) + ).addSubcommand((command) => + command.setName("retirer") + .setDescription("Retirer un devoir.") + .addStringOption((option) => + option.setName("devoir") + .setDescription("Devoir à retirer.") + .setAutocomplete(true) + .setRequired(true) + ) + ).addSubcommand((command) => + command.setName("éditer") + .setDescription("Éditer un devoir.") + .addStringOption((option) => + option.setName("devoir") + .setDescription("Devoir à éditer.") + .setAutocomplete(true) + .setRequired(true) + ) + .addStringOption((option) => + option.setName("matière") + .setDescription("Nouvelle matière.") + .addChoices(...subjects_as_choices) + .setRequired(false) + ) + .addNumberOption((option) => + option.setName("jours") + .setMinValue(0) + .setDescription("Nouveau nombre de jours avant la date du rendu.") + .setRequired(false) + ) + .addStringOption((option) => + option.setName("description") + .setDescription("Nouvelle description.") + .setRequired(false) + ) + ); + const adm_command = new SlashCommandBuilder().setName("adm") + .setDescription("Commandes d'administration.") + .addSubcommand((command) => + command.setName("ajouter-feed") + .setDescription("Ajoute un salon comme feed de notifications.") + .addChannelOption((option) => + option.setName("salon") + .setDescription("Salon du nouveau feed.") + .setRequired(true) + ) + ); + return [devoir_command, adm_command]; +} + +export async function handle_command( + interaction: ChatInputCommandInteraction, + storage: Storage, + update_display: Channel, +) { + log("Received command", interaction.commandName); + if (interaction.commandName === "devoir") { + const subcommand = interaction.options.getSubcommand(true); + if (subcommand === "ajouter") { + const subject = interaction.options.getString("matière", true); + const days = interaction.options.getNumber("jours", true); + const description = interaction.options.getString("description", true); + const date = Date.now() + days_to_ms(days); + const { id } = await storage.devoirs.add({ date, description, subject }); + const embed = new EmbedBuilder() + .setTitle("`🌟` Ajouté") + .setDescription(`Nouveau devoir ajouté avec succès.`) + .setFooter({ text: `(devoir id:${id})` }); + await interaction.reply({ embeds: [embed], ephemeral: true }); + update_display.send(); + return; + } + if (subcommand === "retirer") { + const id = interaction.options.getString("devoir", true); + await storage.devoirs.delete({ id }); + const embed = new EmbedBuilder() + .setTitle("`🗑️` Retiré") + .setDescription(`Devoir supprimé avec succès.`) + .setFooter({ text: `(devoir id:${id})` }); + await interaction.reply({ embeds: [embed], ephemeral: true }); + update_display.send(); + return; + } + if (subcommand === "éditer") { + const id = interaction.options.getString("devoir", true); + const subject = interaction.options.getString("matière", false); + if (subject !== null) storage.devoirs.update({ id }, (d) => d.subject = subject); + const description = interaction.options.getString("description", false); + if (description !== null) storage.devoirs.update({ id }, (d) => d.description = description); + const days = interaction.options.getNumber("jours", false); + if (days !== null) storage.devoirs.update({ id }, (d) => d.date = Date.now() + days_to_ms(days)); + const embed = new EmbedBuilder() + .setTitle("`🔧` Édité") + .setDescription(`Devoir mis à jour avec succès.`) + .setFooter({ text: `(devoir id:${id})` }); + await interaction.reply({ embeds: [embed], ephemeral: true }); + update_display.send(); + return; + } + return log("Unknown devoir sub command", subcommand); + } + if (interaction.commandName === "adm") { + const subcommand = interaction.options.getSubcommand(true); + if (subcommand === "ajouter-feed") { + const channel = interaction.options.getChannel("salon", true); + const is_text_channel = channel instanceof TextChannel; + if (!is_text_channel) { + await interaction.reply("Channel must be text."); + return; + } + const board_message = await channel.send("[board]"); + const feed_id = await storage.feeds.add({ + channel_id: channel.id, + board_message_id: board_message.id, + notification_ids: new Set(), + }); + await interaction.reply("Added feed " + feed_id.id); + } + return log("Unknown adm sub command", subcommand); + } + log("Unknown command", interaction.commandName); +} + +export async function handle_autocomplete(interaction: AutocompleteInteraction, storage: Storage) { + log("Auto completing."); + if (interaction.commandName === "devoir") { + const subcommand = interaction.options.getSubcommand(true); + if (subcommand === "retirer") { + const devoirs = await collect(storage.devoirs.list()); + const mapped = devoirs.map(([{ id }, value]) => ({ + name: trimmed(`[${value.subject}] ${value.description}`, 100), + value: id, + })); + return await interaction.respond(mapped); + } + if (subcommand === "éditer") { + const devoirs = await collect(storage.devoirs.list()); + const mapped = devoirs.map(([{ id }, value]) => ({ + name: trimmed(`[${value.subject}] ${value.description}`, 100), + value: id, + })); + return await interaction.respond(mapped); + } + return log("Unknown devoir sub command", subcommand); + } + log("Unknown command", interaction.commandName); +}