diff --git a/src/commands/misc/reminder.ts b/src/commands/misc/reminder.ts index 3138a34..0bf35b0 100644 --- a/src/commands/misc/reminder.ts +++ b/src/commands/misc/reminder.ts @@ -158,12 +158,19 @@ export default { channelId: interaction.channelId, userId: interaction.user.id, guildId: interaction.guildId, - }).then((msg) => - interaction.reply({ - content: msg as string, - ephemeral: true, - }), - ); + }) + .then((msg) => + interaction.reply({ + content: msg as string, + ephemeral: true, + }), + ) + .catch((err) => { + interaction.reply({ + content: err, + ephemeral: true, + }); + }); } else { // Show modal to user to get at least the time const modal = new ModalBuilder() diff --git a/src/events/message/messageCreate.ts b/src/events/message/messageCreate.ts index 13892ef..2afe9fb 100644 --- a/src/events/message/messageCreate.ts +++ b/src/events/message/messageCreate.ts @@ -65,7 +65,19 @@ export default async (message: Message, client: Client) => { [], ) .map(async ({ message_id, channel }) => { - const quoted_message = await channel.messages.fetch(message_id).catch(() => undefined); + let quoted_message = await channel.messages.fetch(message_id).catch(() => undefined); + + // If it's a reference, we only check for reference once + const message_reference = quoted_message?.reference; + if (message_reference && message_reference.messageId) { + const channel_reference = client.channels.cache.get( + message_reference.channelId, + ) as TextBasedChannel; + + quoted_message = await channel_reference.messages + .fetch(message_reference.messageId) + .catch(() => undefined); + } // If message doesn't exist or empty if ( diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 807ac06..4f3dd13 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -77,6 +77,7 @@ "c_reminder15": "Message sent in DM because you have left", "c_reminder16": "Message sent in DM because the Discord guild is no longer available.", "c_reminder17": "Message from", + "c_reminder18": "Invalid time, try again.", "c_play_name": "play", "c_play_desc": "Plays a song/playlist, no query displays the now playing song", diff --git a/src/locales/fr.json b/src/locales/fr.json index 9354717..d0af1c9 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -77,6 +77,7 @@ "c_reminder15": "Message envoyé en DM car vous avez quitté", "c_reminder16": "Message envoyé en DM car le serveur Discord n'est plus disponible.", "c_reminder17": "Message d'il y a", + "c_reminder18": "Temps invalide, réessayez.", "c_play_name": "play", "c_play_desc": "Joue une chanson/playlist, pas de requête affiche la chanson en cours actuellement", diff --git a/src/utils/client.ts b/src/utils/client.ts index b096546..badb018 100644 --- a/src/utils/client.ts +++ b/src/utils/client.ts @@ -1,5 +1,5 @@ import { Player } from "discord-player"; -import { Client, Collection, GatewayIntentBits } from "discord.js"; +import { ActivityType, Client, Collection, GatewayIntentBits } from "discord.js"; import { readFileSync } from "fs"; import { Database } from "sqlite3"; import "../modules/client"; @@ -16,6 +16,9 @@ export default async () => { GatewayIntentBits.MessageContent, GatewayIntentBits.GuildVoiceStates, ], + presence: { + activities: [{ name: "/help", type: ActivityType.Watching }], + }, }); client.config = { diff --git a/src/utils/misc.ts b/src/utils/misc.ts index 8364a59..4e863f8 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -98,7 +98,7 @@ export const cleanCodeBlock = (text: string) => { ); // Fix issues - text = text.replace("``", ""); + text = text.replaceAll("``", ""); return text; }; diff --git a/src/utils/reminder.ts b/src/utils/reminder.ts index 1d065bf..f735920 100644 --- a/src/utils/reminder.ts +++ b/src/utils/reminder.ts @@ -64,8 +64,15 @@ const splitTime = (time: string) => { */ export const newReminder = async (client: Client, time: string, info: infoReminder) => new Promise((ok, ko) => { + const loc = getLocale(client, info.locale); + const data = splitTime(time); const timeout = strToSeconds(data.time); + if (timeout < 0) { + ko(loc.get("c_reminder18")); + return; + } + const timeoutId = setTimeoutReminder(client, info, data.option, timeout); // Add the remind to the db @@ -90,7 +97,6 @@ export const newReminder = async (client: Client, time: string, info: infoRemind } // Send confirmation to user - const loc = getLocale(client, info.locale); ok(`${loc.get("c_reminder1")} ${data.time}.`); }, ); @@ -202,8 +208,19 @@ export const setTimeoutReminder = ( option: OptionReminder, timeout: number, ) => { - return Number( - setTimeout(() => { + const setChunkedTimeout = (remainingTime: number) => { + // Maximum for setTimeout is Int32 + if (remainingTime > 2147483647) { + // Schedule a 24-hour delay (24 * 60 * 60 * 1000), then check again + const dayChunk = 86400000; + + return setTimeout(() => { + setChunkedTimeout(remainingTime - dayChunk); + }, dayChunk); + } + + // Final timeout when remaining time is within limit + return setTimeout(() => { deleteReminder(client, String(info.createdAt), info.userId).then((val) => { if (val != true) { throw val; @@ -211,8 +228,11 @@ export const setTimeoutReminder = ( sendReminder(client, info, option); }); - }, timeout * 1000), - ); + }, remainingTime); + }; + + // Convert to milliseconds + return Number(setChunkedTimeout(timeout * 1000)); }; /** diff --git a/src/utils/time.ts b/src/utils/time.ts index 95d8728..b754314 100644 --- a/src/utils/time.ts +++ b/src/utils/time.ts @@ -24,6 +24,11 @@ enum TimeSecond { * @returns time in seconds */ export const strToSeconds = (time: string) => { + if (time.length > 15) { + // 15 is a magic value, weird to be this long + return -1; + } + const regex = new RegExp( `(?<${TimeSecond[TimeSecond.Year]}>[0-9]+(?=[y|a]))|(?<${ TimeSecond[TimeSecond.Week] @@ -34,7 +39,12 @@ export const strToSeconds = (time: string) => { }>[0-9]+(?=[s]?))`, ); - const data = Object.assign({}, regex.exec(time)?.groups); + const data = Object.assign({}, regex.exec(time.toLowerCase())?.groups); + + if (Object.keys(data).length === 0) { + // Regex returned an invalid time + return -1; + } let res = 0; Object.entries(data).forEach(([key, value]) => {