feat: Reminders #44
5 changed files with 92 additions and 70 deletions
|
@ -1,8 +1,8 @@
|
|||
import { ModalActionRowComponentBuilder, SlashCommandBuilder } from '@discordjs/builders';
|
||||
import { Client, ChatInputCommandInteraction, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder } from 'discord.js';
|
||||
import { getLocalizations } from '../../utils/locales';
|
||||
import { ActionRowBuilder, ChatInputCommandInteraction, Client, ModalBuilder, TextInputBuilder, TextInputStyle } from 'discord.js';
|
||||
import { getLocale, getLocalizations } from '../../utils/locales';
|
||||
import { getFilename } from '../../utils/misc';
|
||||
import { strToSeconds } from '../../utils/time';
|
||||
import { newReminder } from '../../utils/reminder';
|
||||
|
||||
export default {
|
||||
data: (client: Client) => {
|
||||
|
@ -140,6 +140,7 @@ export default {
|
|||
interaction: async (interaction: ChatInputCommandInteraction, client: Client) => {
|
||||
const loc_default = client.locales.get(client.config.default_lang);
|
||||
const filename = getFilename(__filename);
|
||||
const loc = getLocale(client, interaction.locale);
|
||||
|
||||
/* Votre code ici */
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
|
@ -147,67 +148,43 @@ export default {
|
|||
// New reminder
|
||||
case loc_default?.get(`c_${filename}_sub1_name`)
|
||||
?.toLowerCase() ?? '': {
|
||||
// TODO: Ici il y a 2 options, l'un pour le temps et l'autre
|
||||
// pour le message, il faut tout le temps un temps, mais pas
|
||||
// tout le temps de message (= message par défaut, le reminder
|
||||
// fait office de compte à rebours tout simple dans ce cas là)
|
||||
// Alors j'avais comme idée de pas mettre le temps comme requis,
|
||||
// et quand pas de temps est spécifié dans la commande, on ouvre
|
||||
// une boîte de dialogue : https://discordjs.guide/interactions/modals.html#building-and-responding-with-modals
|
||||
// et on demande à l'utilisateur de remplir les champs comme ça.
|
||||
// Avec cette technique on a les commandes pour les "poweruser"
|
||||
// qui préfèrent tout faire en ligne de commandes et un truc
|
||||
// plus user-friendly avec une interface (et en plus c'est
|
||||
// nouveau et cool)
|
||||
|
||||
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);
|
||||
let option = OptionReminder.Nothing;
|
||||
let seconds: number;
|
||||
const time = interaction.options.getString(loc_default?.get(`c_${filename}_sub1_opt1_name`) as string);
|
||||
if (time != null) {
|
||||
// Cli
|
||||
|
||||
// Split time
|
||||
if (time?.endsWith('@')) {
|
||||
time = time.slice(0, -1);
|
||||
option = OptionReminder.Mention;
|
||||
} else if (time?.toLowerCase().endsWith('p')) {
|
||||
time = time.slice(0, -1);
|
||||
option = OptionReminder.DirectMessage;
|
||||
}
|
||||
|
||||
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}`);
|
||||
return newReminder(client, time, {
|
||||
message: interaction.options.getString(loc_default?.get('c_reminder_sub1_opt2_name') as string),
|
||||
createdAt: interaction.createdAt.getTime(),
|
||||
channelId: interaction.channelId,
|
||||
userId: interaction.user.id,
|
||||
guildId: interaction.guildId,
|
||||
}).then((msg) => interaction.reply({
|
||||
content: msg as string,
|
||||
ephemeral: true,
|
||||
}));
|
||||
} else {
|
||||
// GUI
|
||||
// TODO: local
|
||||
const modal = new ModalBuilder()
|
||||
.setCustomId('reminderGUI')
|
||||
.setTitle('LOC_reminder');
|
||||
.setTitle(loc?.get('c_reminder_name').capitalize());
|
||||
|
||||
// TODO: local
|
||||
const timeGUI = new TextInputBuilder()
|
||||
.setCustomId('timeGUI')
|
||||
.setLabel('LOC_time')
|
||||
.setCustomId('reminderGUI-time')
|
||||
.setLabel(loc?.get('c_reminder_sub1_opt1_name').capitalize())
|
||||
.setStyle(TextInputStyle.Short)
|
||||
.setPlaceholder('1h')
|
||||
.setRequired(true);
|
||||
|
||||
modal.addComponents(new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(timeGUI));
|
||||
const messageGUI = new TextInputBuilder()
|
||||
.setCustomId('reminderGUI-message')
|
||||
.setLabel(loc?.get('c_reminder_sub1_opt2_name').capitalize())
|
||||
.setStyle(TextInputStyle.Paragraph)
|
||||
.setPlaceholder(loc?.get('c_reminder_sub1_opt2_desc'))
|
||||
.setRequired(false);
|
||||
|
||||
await interaction.showModal(modal);
|
||||
modal.addComponents(new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(timeGUI), new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(messageGUI));
|
||||
|
||||
// Response of the modal in /src/modals/misc/reminder
|
||||
return interaction.showModal(modal);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// List reminders
|
||||
case loc_default?.get(`c_${filename}_sub2_name`)
|
||||
|
@ -236,10 +213,3 @@ export default {
|
|||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
enum OptionReminder {
|
||||
Nothing,
|
||||
Mention,
|
||||
DirectMessage,
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@ export default (interaction: Interaction, client: Client) => {
|
|||
const modal = client.modals.list.get(interaction.customId);
|
||||
if (!modal) {
|
||||
return interaction.reply({
|
||||
// TODO: locale
|
||||
content: `can't find ${interaction.customId}`,
|
||||
content: loc.get('e_interacreate_no_modal'),
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"e_interacreate_no_command": "Désolé, la commande n'existe plus...",
|
||||
"e_interacreate_no_modal": "Désolé, le modèle n'existe plus...",
|
||||
|
||||
"c_ping_name": "Ping",
|
||||
"c_ping_desc": "Pong!",
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
import { ModalSubmitInteraction } from 'discord.js';
|
||||
import { Client, ModalSubmitInteraction } from 'discord.js';
|
||||
import { getFilename } from '../../utils/misc';
|
||||
import { newReminder } from '../../utils/reminder';
|
||||
|
||||
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}`,
|
||||
interaction: async (interaction: ModalSubmitInteraction, client: Client) => {
|
||||
return newReminder(client, interaction.fields.fields.get('reminderGUI-time')?.value as string, {
|
||||
message: interaction.fields.fields.get('reminderGUI-message')?.value ?? null,
|
||||
createdAt: interaction.createdAt.getTime(),
|
||||
channelId: interaction.channelId,
|
||||
userId: interaction.user.id,
|
||||
guildId: interaction.guildId,
|
||||
}).then((msg) => interaction.reply({
|
||||
content: msg as string,
|
||||
ephemeral: true,
|
||||
});
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
|
52
src/utils/reminder.ts
Normal file
52
src/utils/reminder.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { Client } from 'discord.js';
|
||||
import { strToSeconds } from './time';
|
||||
|
||||
export enum OptionReminder {
|
||||
Nothing,
|
||||
Mention,
|
||||
DirectMessage,
|
||||
}
|
||||
|
||||
export type infoReminder = {
|
||||
message: string | null,
|
||||
createdAt: number,
|
||||
channelId: string | null,
|
||||
userId: string,
|
||||
guildId: string | null
|
||||
}
|
||||
|
||||
const splitTime = (time: string) => {
|
||||
if (time?.endsWith('@')) {
|
||||
return { time: time.slice(0, -1), option: OptionReminder.Mention };
|
||||
} else if (time?.toLowerCase().endsWith('p')) {
|
||||
return { time: time.slice(0, -1), option: OptionReminder.DirectMessage };
|
||||
}
|
||||
|
||||
return { time: time, option: OptionReminder.Nothing };
|
||||
};
|
||||
|
||||
export const newReminder = async (client: Client, time: string, info: infoReminder) => {
|
||||
const data = splitTime(time);
|
||||
|
||||
// Add the remind to the db
|
||||
return new Promise((ok, ko) => {
|
||||
const res = client.db.run('INSERT INTO reminder ( \
|
||||
data, expiration_date, option_id, channel_id, creation_date, user_id, guild_id \
|
||||
) VALUES ( ?, ?, ?, ?, ?, ?, ?);', [
|
||||
info.message,
|
||||
info.createdAt + strToSeconds(data.time),
|
||||
data.option.valueOf(),
|
||||
info.channelId,
|
||||
info.createdAt,
|
||||
info.userId,
|
||||
info.guildId], (err) => {
|
||||
if (err) {
|
||||
ko(err);
|
||||
}
|
||||
|
||||
// Send confirmation to user
|
||||
// TODO: local
|
||||
ok(`ratio: ${info.message}, ${data.time}=${strToSeconds(data.time)}, ${data.option}, ${res}`);
|
||||
});
|
||||
});
|
||||
};
|
Loading…
Reference in a new issue