* Better handle of errors
* Add Modal support * Use modal for reminder * Add TODOs
This commit is contained in:
parent
8c7b87dbac
commit
694d41a128
9 changed files with 159 additions and 24 deletions
|
@ -1,5 +1,5 @@
|
||||||
import { SlashCommandBuilder } from '@discordjs/builders';
|
import { ModalActionRowComponentBuilder, SlashCommandBuilder } from '@discordjs/builders';
|
||||||
import { Client, ChatInputCommandInteraction } from 'discord.js';
|
import { Client, ChatInputCommandInteraction, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder } from 'discord.js';
|
||||||
import { getLocalizations } from '../../utils/locales';
|
import { getLocalizations } from '../../utils/locales';
|
||||||
import { getFilename } from '../../utils/misc';
|
import { getFilename } from '../../utils/misc';
|
||||||
import { strToSeconds } from '../../utils/time';
|
import { strToSeconds } from '../../utils/time';
|
||||||
|
@ -160,7 +160,6 @@ export default {
|
||||||
// plus user-friendly avec une interface (et en plus c'est
|
// plus user-friendly avec une interface (et en plus c'est
|
||||||
// nouveau et cool)
|
// nouveau et cool)
|
||||||
|
|
||||||
// eslint-disable-next-line no-case-declarations
|
|
||||||
let time = interaction.options.getString(loc_default?.get(`c_${filename}_sub1_opt1_name`) as string);
|
let time = interaction.options.getString(loc_default?.get(`c_${filename}_sub1_opt1_name`) as string);
|
||||||
const message = interaction.options.getString(loc_default?.get(`c_${filename}_sub1_opt2_name`) as string);
|
const message = interaction.options.getString(loc_default?.get(`c_${filename}_sub1_opt2_name`) as string);
|
||||||
let option = OptionReminder.Nothing;
|
let option = OptionReminder.Nothing;
|
||||||
|
@ -178,16 +177,36 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
seconds = strToSeconds(time);
|
seconds = strToSeconds(time);
|
||||||
|
|
||||||
|
// Add the remind to the db
|
||||||
|
client.db.run('INSERT INTO reminder ( \
|
||||||
|
data, expiration_date, option_id, channel_id, creation_date, user_id, guild_id \
|
||||||
|
) VALUES ( ?, ?, ?, ?, ?, ?, ?);', [message, interaction.createdAt.getTime() + seconds, option.valueOf(), interaction.channelId, interaction.createdAt.getTime(), interaction.user.id, interaction.guildId]);
|
||||||
|
|
||||||
|
// Send confirmation to user
|
||||||
|
// TODO: local
|
||||||
await interaction.reply(`${option} - ${seconds}`);
|
await interaction.reply(`${option} - ${seconds}`);
|
||||||
} else {
|
} else {
|
||||||
// Boîte de dialogue
|
// GUI
|
||||||
seconds = 0;
|
// TODO: local
|
||||||
|
const modal = new ModalBuilder()
|
||||||
|
.setCustomId('reminderGUI')
|
||||||
|
.setTitle('LOC_reminder');
|
||||||
|
|
||||||
|
// TODO: local
|
||||||
|
const timeGUI = new TextInputBuilder()
|
||||||
|
.setCustomId('timeGUI')
|
||||||
|
.setLabel('LOC_time')
|
||||||
|
.setStyle(TextInputStyle.Short)
|
||||||
|
.setPlaceholder('1h')
|
||||||
|
.setRequired(true);
|
||||||
|
|
||||||
|
modal.addComponents(new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(timeGUI));
|
||||||
|
|
||||||
|
await interaction.showModal(modal);
|
||||||
|
|
||||||
|
// Response of the modal in /src/modals/misc/reminder
|
||||||
}
|
}
|
||||||
|
|
||||||
client.db.run('INSERT INTO reminder ( \
|
|
||||||
data, expiration_date, option_id, channel_id, creation_date, user_id, guild_id \
|
|
||||||
) VALUES ( ?, ?, ?, ?, ?, ?, ?);', [message, interaction.createdAt.getTime() + seconds, option.valueOf(), interaction.channelId, interaction.createdAt.getTime(), interaction.user.id, interaction.guildId]);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// List reminders
|
// List reminders
|
||||||
|
|
|
@ -3,16 +3,34 @@ import { getLocale } from '../../utils/locales';
|
||||||
|
|
||||||
/** https://discord.js.org/#/docs/discord.js/main/class/Client?scrollTo=e-interactionCreate */
|
/** https://discord.js.org/#/docs/discord.js/main/class/Client?scrollTo=e-interactionCreate */
|
||||||
export default (interaction: Interaction, client: Client) => {
|
export default (interaction: Interaction, client: Client) => {
|
||||||
if (interaction.type === InteractionType.ApplicationCommand) {
|
const loc = getLocale(client, interaction.locale);
|
||||||
const command = client.commands.list.get(interaction.commandName);
|
switch (interaction.type) {
|
||||||
if (!command) {
|
case InteractionType.ApplicationCommand: {
|
||||||
const loc = getLocale(client, interaction.locale);
|
const command = client.commands.list.get(interaction.commandName);
|
||||||
return interaction.reply({
|
if (!command) {
|
||||||
content: loc.get('e_interacreate_no_command'),
|
return interaction.reply({
|
||||||
ephemeral: true,
|
content: loc.get('e_interacreate_no_command'),
|
||||||
});
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return command.interaction(interaction, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return command.interaction(interaction, client);
|
case InteractionType.ModalSubmit: {
|
||||||
|
const modal = client.modals.list.get(interaction.customId);
|
||||||
|
if (!modal) {
|
||||||
|
return interaction.reply({
|
||||||
|
// TODO: locale
|
||||||
|
content: `can't find ${interaction.customId}`,
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return modal.interaction(interaction, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,7 @@ export default async (client: Client) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Remove extension
|
// Remove extension
|
||||||
|
// TODO: use utils functions
|
||||||
const event_type_ext = event_file.split('.');
|
const event_type_ext = event_file.split('.');
|
||||||
const ext = event_type_ext.pop();
|
const ext = event_type_ext.pop();
|
||||||
if (!(ext === 'js' || ext === 'ts')) {
|
if (!(ext === 'js' || ext === 'ts')) {
|
||||||
|
|
22
src/index.ts
22
src/index.ts
|
@ -1,5 +1,6 @@
|
||||||
import loadClient, { quit } from './utils/client';
|
import loadClient, { quit } from './utils/client';
|
||||||
import loadEvents from './events/loader';
|
import loadEvents from './events/loader';
|
||||||
|
import loadModals from './modals/loader';
|
||||||
import loadCommands from './commands/loader';
|
import loadCommands from './commands/loader';
|
||||||
|
|
||||||
import { logStart } from './utils/misc';
|
import { logStart } from './utils/misc';
|
||||||
|
@ -19,27 +20,37 @@ const run = async () => {
|
||||||
const client_name = 'Client';
|
const client_name = 'Client';
|
||||||
await loadClient()
|
await loadClient()
|
||||||
.then(async client => {
|
.then(async client => {
|
||||||
console.log(logStart(client_name, true));
|
|
||||||
|
|
||||||
// Events Discord.JS
|
// Events Discord.JS
|
||||||
const events_name = 'Events';
|
const events_name = 'Events';
|
||||||
await loadEvents(client)
|
await loadEvents(client)
|
||||||
.then(() => console.log(logStart(events_name, true)))
|
.then(() => console.log(logStart(events_name, true)))
|
||||||
.catch(() => {
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
throw logStart(events_name, false);
|
throw logStart(events_name, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Connect the bot to Discord.com
|
// Connect the bot to Discord.com
|
||||||
await client.login(client.config.token_discord);
|
await client.login(client.config.token_discord);
|
||||||
|
|
||||||
|
// Modals Discord.JS
|
||||||
|
const modals_name = 'Modals';
|
||||||
|
await loadModals(client)
|
||||||
|
.then(() => console.log(logStart(modals_name, true)))
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
throw logStart(modals_name, false);
|
||||||
|
});
|
||||||
|
|
||||||
// Commands Slash Discord.JS
|
// Commands Slash Discord.JS
|
||||||
const commands_name = 'Commands';
|
const commands_name = 'Commands';
|
||||||
await loadCommands(client)
|
await loadCommands(client)
|
||||||
.then(() => console.log(logStart(commands_name, true)))
|
.then(() => console.log(logStart(commands_name, true)))
|
||||||
.catch(() => {
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
throw logStart(commands_name, false);
|
throw logStart(commands_name, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(logStart(client_name, true));
|
||||||
console.log(`Botanique "${client.user?.username}" v${client.config.version} started!`);
|
console.log(`Botanique "${client.user?.username}" v${client.config.version} started!`);
|
||||||
|
|
||||||
// ^C
|
// ^C
|
||||||
|
@ -48,7 +59,8 @@ const run = async () => {
|
||||||
// Container force closed
|
// Container force closed
|
||||||
process.on('SIGTERM', () => quit(client));
|
process.on('SIGTERM', () => quit(client));
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
throw logStart(client_name, false);
|
throw logStart(client_name, false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
36
src/modals/loader.ts
Normal file
36
src/modals/loader.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import { removeExtension } from '../utils/misc';
|
||||||
|
import { Client } from 'discord.js';
|
||||||
|
|
||||||
|
export default async (client: Client) => {
|
||||||
|
// Dossier des modals
|
||||||
|
const modals_categories = (await readdir(__dirname))
|
||||||
|
.filter(element => !element.endsWith('.js') && !element.endsWith('.ts'));
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
// For each categorie
|
||||||
|
modals_categories.map(async modals_category => {
|
||||||
|
// Retrieve all the commands
|
||||||
|
const modal_files = await readdir(`${__dirname}/${modals_category}`);
|
||||||
|
|
||||||
|
// Add the category to the collection for the help command
|
||||||
|
client.modals.categories.set(
|
||||||
|
modals_category,
|
||||||
|
modal_files.map(removeExtension),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the modal
|
||||||
|
return Promise.all(
|
||||||
|
modal_files.map(async modal_file => {
|
||||||
|
const modal = (
|
||||||
|
await import(`../modals/${modals_category}/${modal_file}`)
|
||||||
|
).default;
|
||||||
|
|
||||||
|
// Add it to the collection so the interaction will work
|
||||||
|
client.modals.list.set(modal.data.name, modal);
|
||||||
|
return modal.data;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
21
src/modals/misc/reminderGUI.ts
Normal file
21
src/modals/misc/reminderGUI.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { ModalSubmitInteraction } from 'discord.js';
|
||||||
|
import { getFilename } from '../../utils/misc';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data: {
|
||||||
|
name: getFilename(__filename),
|
||||||
|
},
|
||||||
|
interaction: async (interaction: ModalSubmitInteraction) => {
|
||||||
|
if (!interaction.isModalSubmit()) {
|
||||||
|
console.log('not modal called modal :/');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const time = interaction.fields.fields.get('timeGUI')?.value;
|
||||||
|
|
||||||
|
return interaction.reply({
|
||||||
|
content: `${time}`,
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
|
@ -16,6 +16,28 @@ declare module 'discord.js' {
|
||||||
/** Default lang used */
|
/** Default lang used */
|
||||||
default_lang: string
|
default_lang: string
|
||||||
},
|
},
|
||||||
|
/** Store all the modals */
|
||||||
|
modals: {
|
||||||
|
categories: Collection<
|
||||||
|
/** Category name */
|
||||||
|
string,
|
||||||
|
/** Name of the modals in the category */
|
||||||
|
string[]
|
||||||
|
>,
|
||||||
|
list: Collection<
|
||||||
|
/** Modal name */
|
||||||
|
string,
|
||||||
|
/** Modal itself */
|
||||||
|
{
|
||||||
|
/** Data about the modal */
|
||||||
|
data: {
|
||||||
|
name: string
|
||||||
|
},
|
||||||
|
/** How the modal interact */
|
||||||
|
interaction: (interaction: ModalSubmitInteraction, client: Client) => unknown
|
||||||
|
}
|
||||||
|
>,
|
||||||
|
}
|
||||||
/** Store all the slash commands */
|
/** Store all the slash commands */
|
||||||
commands: {
|
commands: {
|
||||||
categories: Collection<
|
categories: Collection<
|
||||||
|
|
|
@ -19,6 +19,11 @@ export default async () => {
|
||||||
default_lang: process.env.DEFAULT_LANG ?? 'fr',
|
default_lang: process.env.DEFAULT_LANG ?? 'fr',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
client.modals = {
|
||||||
|
categories: new Collection(),
|
||||||
|
list: new Collection(),
|
||||||
|
};
|
||||||
|
|
||||||
client.commands = {
|
client.commands = {
|
||||||
categories: new Collection(),
|
categories: new Collection(),
|
||||||
list: new Collection(),
|
list: new Collection(),
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { GuildMember } from 'discord.js';
|
||||||
* @returns String
|
* @returns String
|
||||||
*/
|
*/
|
||||||
export const logStart = (name: string, status: boolean) => {
|
export const logStart = (name: string, status: boolean) => {
|
||||||
|
// TODO Handle precision about the error if status is false
|
||||||
return `> ${name} ${status === true ? '✅' : '❌'}`;
|
return `> ${name} ${status === true ? '✅' : '❌'}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue