feat: Reminders #44
5 changed files with 175 additions and 59 deletions
|
@ -2,7 +2,7 @@ import { ModalActionRowComponentBuilder, SlashCommandBuilder } from '@discordjs/
|
||||||
import { ActionRowBuilder, ChatInputCommandInteraction, Client, ModalBuilder, TextInputBuilder, TextInputStyle } from 'discord.js';
|
import { ActionRowBuilder, ChatInputCommandInteraction, Client, ModalBuilder, TextInputBuilder, TextInputStyle } from 'discord.js';
|
||||||
import { getLocale, getLocalizations } from '../../utils/locales';
|
import { getLocale, getLocalizations } from '../../utils/locales';
|
||||||
import { getFilename } from '../../utils/misc';
|
import { getFilename } from '../../utils/misc';
|
||||||
import { newReminder } from '../../utils/reminder';
|
import { checkOwnershipReminder, deleteReminder, getReminderInfo, newReminder } from '../../utils/reminder';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data: (client: Client) => {
|
data: (client: Client) => {
|
||||||
|
@ -207,11 +207,24 @@ export default {
|
||||||
// Delete a reminder
|
// Delete a reminder
|
||||||
case loc_default?.get(`c_${filename}_sub3_name`)
|
case loc_default?.get(`c_${filename}_sub3_name`)
|
||||||
?.toLowerCase() ?? '': {
|
?.toLowerCase() ?? '': {
|
||||||
// TODO: Message simple qui indique que l'on a supprimé
|
const id = interaction.options.getInteger(loc_default?.get(`c_${filename}_sub3_opt1_name`) as string);
|
||||||
// le reminder. Penser à check l'appartenance du reminder.
|
if (id === null) {
|
||||||
// On donne l'ID du reminder en option.
|
return interaction.reply({ content: loc?.get('c_reminder2'), ephemeral: true });
|
||||||
|
}
|
||||||
|
|
||||||
return interaction.reply('TODO');
|
// Check if the ID exists and belongs to the user
|
||||||
|
if (await checkOwnershipReminder(client, id, interaction.user.id, interaction.guildId ?? '0')) {
|
||||||
|
return interaction.reply({ content: loc?.get('c_reminder3'), ephemeral: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop timeout
|
||||||
|
const reminderInfo = await getReminderInfo(client, id);
|
||||||
|
clearTimeout(reminderInfo.timeout_id);
|
||||||
|
|
||||||
|
// Delete from database
|
||||||
|
deleteReminder(client, reminderInfo.creation_date, reminderInfo.user_id);
|
||||||
|
|
||||||
|
return interaction.reply({ content: `Reminder **#${id}** supprimé !`, ephemeral: true });
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
console.error(`${__filename}: unknown subcommand (${subcommand})`);
|
console.error(`${__filename}: unknown subcommand (${subcommand})`);
|
||||||
|
|
|
@ -1,20 +1,8 @@
|
||||||
import { Client } from 'discord.js';
|
import { Client } from 'discord.js';
|
||||||
import { deleteReminder, infoReminder, OptionReminder, sendReminder, setTimeoutReminder } from '../../utils/reminder';
|
import { dbReminder, deleteReminder, infoReminder, OptionReminder, sendReminder, setTimeoutReminder, updateReminder } from '../../utils/reminder';
|
||||||
|
|
||||||
export const once = true;
|
export const once = true;
|
||||||
|
|
||||||
type dbReminder = {
|
|
||||||
id: number,
|
|
||||||
data: string,
|
|
||||||
expiration_date: number,
|
|
||||||
option_id: number,
|
|
||||||
channel_id: number,
|
|
||||||
creation_date: number,
|
|
||||||
user_id: number,
|
|
||||||
guild_id: number,
|
|
||||||
locale: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/** https://discord.js.org/#/docs/discord.js/main/class/Client?scrollTo=e-ready */
|
/** https://discord.js.org/#/docs/discord.js/main/class/Client?scrollTo=e-ready */
|
||||||
export default async (client: Client) => {
|
export default async (client: Client) => {
|
||||||
console.log('Connected to Discord!');
|
console.log('Connected to Discord!');
|
||||||
|
@ -49,11 +37,19 @@ export default async (client: Client) => {
|
||||||
throw res;
|
throw res;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
client.channels.fetch(`${info.channelId}`).then((val) => console.log(val?.url));
|
|
||||||
sendReminder(client, info, element.option_id as OptionReminder);
|
sendReminder(client, info, element.option_id as OptionReminder);
|
||||||
} else {
|
} else {
|
||||||
// Restart timeout
|
// Restart timeout
|
||||||
setTimeoutReminder(client, info, element.option_id, (element.expiration_date - now) / 1000);
|
const timeoutId = setTimeoutReminder(client, info, element.option_id, (element.expiration_date - now) / 1000);
|
||||||
|
|
||||||
|
// Update timeout in database
|
||||||
|
element.timeout_id = timeoutId;
|
||||||
|
updateReminder(client, element).then((res) => {
|
||||||
|
if (res != true) {
|
||||||
|
throw res;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
|
|
|
@ -31,7 +31,9 @@
|
||||||
"c_reminder_sub2_opt1_desc": "Affiche la liste de l'utilisateur en question",
|
"c_reminder_sub2_opt1_desc": "Affiche la liste de l'utilisateur en question",
|
||||||
"c_reminder_sub3_name": "efface",
|
"c_reminder_sub3_name": "efface",
|
||||||
"c_reminder_sub3_desc": "Supprime un rappel",
|
"c_reminder_sub3_desc": "Supprime un rappel",
|
||||||
"c_reminder_sub3_opt1_name": "ID",
|
"c_reminder_sub3_opt1_name": "id",
|
||||||
"c_reminder_sub3_opt1_desc": "Rappel à supprimé",
|
"c_reminder_sub3_opt1_desc": "Rappel à supprimé",
|
||||||
"c_reminder1": "Un rappel a été configuré pour dans"
|
"c_reminder1": "Un rappel a été configuré pour dans",
|
||||||
|
"c_reminder2": "L'ID renseigné n'est pas valide.",
|
||||||
|
"c_reminder3": "Rappel non trouvé, pas sur le bon serveur ou qui ne vous appartiens pas."
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ const initDatabase = (db: Database) => {
|
||||||
creation_date TEXT, \
|
creation_date TEXT, \
|
||||||
user_id TEXT, \
|
user_id TEXT, \
|
||||||
guild_id TEXT, \
|
guild_id TEXT, \
|
||||||
locale TEXT \
|
locale TEXT, \
|
||||||
|
timeout_id TEXT \
|
||||||
);');
|
);');
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,6 +26,19 @@ export type infoReminder = {
|
||||||
guildId: string | null
|
guildId: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type dbReminder = {
|
||||||
|
id: number,
|
||||||
|
data: string | null,
|
||||||
|
expiration_date: number,
|
||||||
|
option_id: OptionReminder,
|
||||||
|
channel_id: string | null,
|
||||||
|
creation_date: number,
|
||||||
|
user_id: string,
|
||||||
|
guild_id: string | null,
|
||||||
|
locale: string,
|
||||||
|
timeout_id: number
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split the time and the extra args `p` and `@`
|
* Split the time and the extra args `p` and `@`
|
||||||
* @param time raw text from user
|
* @param time raw text from user
|
||||||
|
@ -52,12 +65,12 @@ export const newReminder = async (client: Client, time: string, info: infoRemind
|
||||||
new Promise((ok, ko) => {
|
new Promise((ok, ko) => {
|
||||||
const data = splitTime(time);
|
const data = splitTime(time);
|
||||||
const timeout = strToSeconds(data.time);
|
const timeout = strToSeconds(data.time);
|
||||||
setTimeoutReminder(client, info, data.option, timeout);
|
const timeoutId = setTimeoutReminder(client, info, data.option, timeout);
|
||||||
|
|
||||||
// Add the remind to the db
|
// Add the remind to the db
|
||||||
client.db.run('INSERT INTO reminder ( \
|
client.db.run('INSERT INTO reminder ( \
|
||||||
data, expiration_date, option_id, channel_id, creation_date, user_id, guild_id, locale \
|
data, expiration_date, option_id, channel_id, creation_date, user_id, guild_id, locale, timeout_id \
|
||||||
) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? );', [
|
) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? );', [
|
||||||
info.message,
|
info.message,
|
||||||
`${info.createdAt + (timeout * 1000)}`,
|
`${info.createdAt + (timeout * 1000)}`,
|
||||||
data.option.valueOf(),
|
data.option.valueOf(),
|
||||||
|
@ -65,7 +78,8 @@ export const newReminder = async (client: Client, time: string, info: infoRemind
|
||||||
`${info.createdAt}`,
|
`${info.createdAt}`,
|
||||||
info.userId,
|
info.userId,
|
||||||
info.guildId,
|
info.guildId,
|
||||||
info.locale], (err) => {
|
info.locale,
|
||||||
|
timeoutId], (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
ko(err);
|
ko(err);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +91,7 @@ export const newReminder = async (client: Client, time: string, info: infoRemind
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a reminder
|
* Delete a reminder from the database
|
||||||
* @param client Client
|
* @param client Client
|
||||||
* @param createdAt Creation of the reminder
|
* @param createdAt Creation of the reminder
|
||||||
* @param userId User ID who created the reminder
|
* @param userId User ID who created the reminder
|
||||||
|
@ -127,9 +141,10 @@ export const sendReminder = (client: Client, info: infoReminder, option: OptionR
|
||||||
* @param info info about the reminder
|
* @param info info about the reminder
|
||||||
* @param option option used for this reminder (aka location of the response)
|
* @param option option used for this reminder (aka location of the response)
|
||||||
* @param timeout Amout of time before the reminder ends
|
* @param timeout Amout of time before the reminder ends
|
||||||
|
* @returns Timeout's ID
|
||||||
*/
|
*/
|
||||||
export const setTimeoutReminder = (client: Client, info: infoReminder, option: OptionReminder, timeout: number) => {
|
export const setTimeoutReminder = (client: Client, info: infoReminder, option: OptionReminder, timeout: number) => {
|
||||||
setTimeout(() => {
|
return Number(setTimeout(() => {
|
||||||
deleteReminder(client, info.createdAt, info.userId).then((val) => {
|
deleteReminder(client, info.createdAt, info.userId).then((val) => {
|
||||||
if (val != true) {
|
if (val != true) {
|
||||||
throw val;
|
throw val;
|
||||||
|
@ -137,5 +152,94 @@ export const setTimeoutReminder = (client: Client, info: infoReminder, option: O
|
||||||
|
|
||||||
sendReminder(client, info, option);
|
sendReminder(client, info, option);
|
||||||
});
|
});
|
||||||
}, timeout * 1000);
|
}, timeout * 1000));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the owernship of a reminder by a user
|
||||||
|
* @param client Client
|
||||||
|
* @param id ID of the reminder
|
||||||
|
* @param userId user ID to check
|
||||||
|
* @param guildId guild ID where the ownership request as been send, 0 if DM
|
||||||
|
*/
|
||||||
|
export const checkOwnershipReminder = async (client: Client, id: number, userId: string, guildId: string) => {
|
||||||
|
const data = await new Promise((ok, ko) => {
|
||||||
|
// Check the ownership
|
||||||
|
client.db.all('SELECT EXISTS ( \
|
||||||
|
SELECT 1 FROM reminder \
|
||||||
|
WHERE id = ? \
|
||||||
|
AND user_id = ? \
|
||||||
|
AND (guild_id = ? OR guild_id = 0) \
|
||||||
|
)', [
|
||||||
|
id, userId, guildId,
|
||||||
|
], (err, row) => {
|
||||||
|
if (err) {
|
||||||
|
ko(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send all the current reminders
|
||||||
|
ok(row[0]);
|
||||||
|
});
|
||||||
|
}) as { [key: string]: number };
|
||||||
|
return Object.keys(data).map((key) => data[key])[0] === 0 ? true : false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve info about a reminder
|
||||||
|
* @param client Client
|
||||||
|
* @param id Reminder's ID
|
||||||
|
*/
|
||||||
|
export const getReminderInfo = async (client: Client, id: number) => {
|
||||||
|
return await new Promise((ok, ko) => {
|
||||||
|
// Check the ownership
|
||||||
|
client.db.all('SELECT * FROM reminder \
|
||||||
|
WHERE id = ?', [
|
||||||
|
id], (err, row) => {
|
||||||
|
if (err) {
|
||||||
|
ko(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send all the current reminders
|
||||||
|
ok(row[0]);
|
||||||
|
});
|
||||||
|
}) as dbReminder;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an entry of the database
|
||||||
|
* @param client Client
|
||||||
|
* @param data Data who will override the data in database
|
||||||
|
*/
|
||||||
|
export const updateReminder = (client: Client, data: dbReminder) => {
|
||||||
|
// Delete the reminder for the database
|
||||||
|
return new Promise((ok, ko) => {
|
||||||
|
// Update the db
|
||||||
|
client.db.run('UPDATE reminder \
|
||||||
|
SET data = ?, \
|
||||||
|
expiration_date = ?, \
|
||||||
|
option_id = ?, \
|
||||||
|
channel_id = ?, \
|
||||||
|
creation_date = ?, \
|
||||||
|
user_id = ?, \
|
||||||
|
guild_id = ?, \
|
||||||
|
locale = ?, \
|
||||||
|
timeout_id = ? \
|
||||||
|
WHERE ID = ?', [
|
||||||
|
data.data,
|
||||||
|
data.expiration_date,
|
||||||
|
data.option_id,
|
||||||
|
data.channel_id,
|
||||||
|
data.creation_date,
|
||||||
|
data.user_id,
|
||||||
|
data.guild_id,
|
||||||
|
data.locale,
|
||||||
|
data.timeout_id,
|
||||||
|
data.id], (err) => {
|
||||||
|
if (err) {
|
||||||
|
ko(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue