From 7fed94def817064d706c9826981e976454808fd8 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Mon, 23 Sep 2024 17:51:22 +0200 Subject: [PATCH] chore: merge dev to main (#177) Close #93 May fix #100 Reviewed-on: https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/pulls/177 Co-authored-by: Mylloon Co-committed-by: Mylloon --- src/buttons/music/queueList-prec.ts | 2 +- src/commands/loader.ts | 4 +- src/commands/misc/reminder.ts | 14 +++---- src/commands/music/lyrics.ts | 4 +- src/commands/music/play.ts | 64 +++++++++++++++++++++-------- src/commands/music/queue.ts | 6 +-- src/events/message/messageCreate.ts | 27 +++++------- src/locales/en-US.json | 4 ++ src/locales/fr.json | 4 ++ src/modals/misc/reminderGUI.ts | 2 +- src/utils/misc.ts | 3 +- src/utils/reminder.ts | 1 - src/utils/time.ts | 5 +-- 13 files changed, 82 insertions(+), 58 deletions(-) diff --git a/src/buttons/music/queueList-prec.ts b/src/buttons/music/queueList-prec.ts index 6326dd4..2c4c8ca 100644 --- a/src/buttons/music/queueList-prec.ts +++ b/src/buttons/music/queueList-prec.ts @@ -19,7 +19,7 @@ export default { }, interaction: async (interaction: MessageComponentInteraction, client: Client) => { const loc = getLocale(client, interaction.locale); - const embed_desc = interaction.message.embeds.at(0)?.author?.name as string; + const embed_desc = interaction.message.embeds.at(0)!.author!.name; // Retrieve Pages const pageMax = Number(/(\d+)(?!.*\d)/gm.exec(embed_desc)?.[0]); diff --git a/src/commands/loader.ts b/src/commands/loader.ts index b8b1c24..562a93e 100644 --- a/src/commands/loader.ts +++ b/src/commands/loader.ts @@ -64,14 +64,14 @@ export default async (client: Client) => { scopedCommands.forEach( async (command, guild) => - await rest.put(Routes.applicationGuildCommands(client.user?.id as string, guild), { + await rest.put(Routes.applicationGuildCommands(client.user!.id, guild), { body: command, }), ); // Send global commands to Discord const globalCommands = commands.filter((c) => c.scope().length === 0); - return await rest.put(Routes.applicationCommands(client.user?.id as string), { + return await rest.put(Routes.applicationCommands(client.user!.id), { body: globalCommands.map((c) => c.data.toJSON()), }); }; diff --git a/src/commands/misc/reminder.ts b/src/commands/misc/reminder.ts index 4c2c234..4d9fdc2 100644 --- a/src/commands/misc/reminder.ts +++ b/src/commands/misc/reminder.ts @@ -145,14 +145,14 @@ export default { case loc_default?.get(`c_${filename}_sub1_name`)?.toLowerCase(): { // If time is already renseigned const time = interaction.options.getString( - loc_default?.get(`c_${filename}_sub1_opt1_name`) as string, + loc_default!.get(`c_${filename}_sub1_opt1_name`)!, ); if (time != null) { // Use the cli because we already have enough data return newReminder(client, time, { locale: interaction.locale, message: interaction.options.getString( - loc_default?.get(`c_${filename}_sub1_opt2_name`) as string, + loc_default!.get(`c_${filename}_sub1_opt2_name`)!, ), createdAt: interaction.createdAt.getTime(), channelId: interaction.channelId, @@ -202,17 +202,13 @@ export default { // List reminders case loc_default?.get(`c_${filename}_sub2_name`)?.toLowerCase(): { // Which user to show - let user = interaction.options.getUser( - loc_default?.get(`c_${filename}_sub2_opt1_name`) as string, - ); + let user = interaction.options.getUser(loc_default!.get(`c_${filename}_sub2_opt1_name`)!); if (user === null) { user = interaction.user; } const page = - interaction.options.getInteger( - loc_default?.get(`c_${filename}_sub2_opt2_name`) as string, - ) ?? 1; + interaction.options.getInteger(loc_default!.get(`c_${filename}_sub2_opt2_name`)!) ?? 1; const list = await embedListReminders( client, user, @@ -253,7 +249,7 @@ export default { // Delete a reminder case loc_default?.get(`c_${filename}_sub3_name`)?.toLowerCase(): { const id = interaction.options.getInteger( - loc_default?.get(`c_${filename}_sub3_opt1_name`) as string, + loc_default!.get(`c_${filename}_sub3_opt1_name`)!, ); if (id === null) { return interaction.reply({ diff --git a/src/commands/music/lyrics.ts b/src/commands/music/lyrics.ts index 27088c2..affe0e3 100644 --- a/src/commands/music/lyrics.ts +++ b/src/commands/music/lyrics.ts @@ -74,9 +74,7 @@ export default { const loc = getLocale(client, interaction.locale); - let request = interaction.options.getString( - loc_default?.get(`c_${filename}_opt1_name`) as string, - ); + let request = interaction.options.getString(loc_default!.get(`c_${filename}_opt1_name`)!); let data = null; await interaction.deferReply(); diff --git a/src/commands/music/play.ts b/src/commands/music/play.ts index ed5ab35..0c6311c 100644 --- a/src/commands/music/play.ts +++ b/src/commands/music/play.ts @@ -27,14 +27,42 @@ export default { .setNameLocalizations(getLocalizations(client, `c_${filename}_name`, true)) .setDescriptionLocalizations(getLocalizations(client, `c_${filename}_desc`)) - // Command option - .addStringOption((option) => - option - .setName(loc_default.get(`c_${filename}_opt1_name`)!.toLowerCase()) - .setDescription(loc_default.get(`c_${filename}_opt1_desc`)!) - .setNameLocalizations(getLocalizations(client, `c_${filename}_opt1_name`, true)) - .setDescriptionLocalizations(getLocalizations(client, `c_${filename}_opt1_desc`)) - .setAutocomplete(true), + // Normal + .addSubcommand((subcommand) => + subcommand + .setName(loc_default.get(`c_${filename}_sub1_name`)!.toLowerCase()) + .setDescription(loc_default.get(`c_${filename}_sub1_desc`)!) + .setNameLocalizations(getLocalizations(client, `c_${filename}_sub1_name`, true)) + .setDescriptionLocalizations(getLocalizations(client, `c_${filename}_sub1_desc`)) + + // Command option + .addStringOption((option) => + option + .setName(loc_default.get(`c_${filename}_opt1_name`)!.toLowerCase()) + .setDescription(loc_default.get(`c_${filename}_opt1_desc`)!) + .setNameLocalizations(getLocalizations(client, `c_${filename}_opt1_name`, true)) + .setDescriptionLocalizations(getLocalizations(client, `c_${filename}_opt1_desc`)) + .setAutocomplete(true), + ), + ) + + // Play now + .addSubcommand((subcommand) => + subcommand + .setName(loc_default.get(`c_${filename}_sub2_name`)!.toLowerCase()) + .setDescription(loc_default.get(`c_${filename}_sub2_desc`)!) + .setNameLocalizations(getLocalizations(client, `c_${filename}_sub2_name`, true)) + .setDescriptionLocalizations(getLocalizations(client, `c_${filename}_sub2_desc`)) + + // Command option + .addStringOption((option) => + option + .setName(loc_default.get(`c_${filename}_opt1_name`)!.toLowerCase()) + .setDescription(loc_default.get(`c_${filename}_opt1_desc`)!) + .setNameLocalizations(getLocalizations(client, `c_${filename}_opt1_name`, true)) + .setDescriptionLocalizations(getLocalizations(client, `c_${filename}_opt1_desc`)) + .setAutocomplete(true), + ), ) ); }, @@ -65,9 +93,7 @@ export default { }); } - const query = interaction.options.getString( - loc_default?.get(`c_${filename}_opt1_name`) as string, - ); + const query = interaction.options.getString(loc_default!.get(`c_${filename}_opt1_name`)!); const player = useMainPlayer(); if (!query) { @@ -96,6 +122,7 @@ export default { } const queue = player.nodes.create(interaction.guild!, { + volume: 50, defaultFFmpegFilters: ["silenceremove"], metadata: { channel: interaction.channel, @@ -132,7 +159,15 @@ export default { } else { const track = result.tracks[0]; - queue.addTrack(track); + if ( + interaction.options.getSubcommand() === + loc_default?.get(`c_${filename}_sub2_name`)?.toLowerCase() + ) { + queue.insertTrack(track, 0); + } else { + queue.addTrack(track); + } + title = track.title; } @@ -154,10 +189,7 @@ export default { const filename = getFilename(__filename); const player = useMainPlayer(); - const query = interaction.options.getString( - loc_default?.get(`c_${filename}_opt1_name`) as string, - true, - ); + const query = interaction.options.getString(loc_default!.get(`c_${filename}_opt1_name`)!, true); const limit_value_discord = 100; diff --git a/src/commands/music/queue.ts b/src/commands/music/queue.ts index 5a761c4..17f26cb 100644 --- a/src/commands/music/queue.ts +++ b/src/commands/music/queue.ts @@ -103,9 +103,7 @@ export default { // Show the queue case loc_default?.get(`c_${filename}_sub1_name`)?.toLowerCase(): { const page = - interaction.options.getNumber( - loc_default?.get(`c_${filename}_sub1_opt1_name`) as string, - ) ?? 1; + interaction.options.getNumber(loc_default!.get(`c_${filename}_sub1_opt1_name`)!) ?? 1; embedListQueue(client, embed, queue, page, interaction.locale); @@ -152,7 +150,7 @@ export default { // Remove case loc_default?.get(`c_${filename}_sub3_name`)?.toLowerCase(): { const id = interaction.options.getNumber( - loc_default?.get(`c_${filename}_sub3_opt1_name`) as string, + loc_default!.get(`c_${filename}_sub3_opt1_name`)!, )!; const track = queue.removeTrack(id - 1); diff --git a/src/events/message/messageCreate.ts b/src/events/message/messageCreate.ts index c76e35c..7c1acaa 100644 --- a/src/events/message/messageCreate.ts +++ b/src/events/message/messageCreate.ts @@ -51,10 +51,10 @@ export default async (message: Message, client: Client) => { return data; } - const channel = message.guild.channels.cache.get(channel_id) as TextBasedChannel; + const channel = message.guild.channels.cache.get(channel_id); // If channel doesn't exist in the guild and isn't text - if (!channel) { + if (!channel || !channel.isTextBased()) { return data; } @@ -70,9 +70,10 @@ export default async (message: Message, client: Client) => { // 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; + const channel_reference = client.channels.cache.get(message_reference.channelId); + if (!channel_reference?.isTextBased()) { + return; + } quoted_message = await channel_reference.messages .fetch(message_reference.messageId) @@ -105,12 +106,9 @@ export default async (message: Message, client: Client) => { // Handle attachments if (quoted_post?.attachments.size !== 0) { - if ( - quoted_post?.attachments.size === 1 && - isImage(quoted_post.attachments.first()?.name as string) - ) { + if (quoted_post?.attachments.size === 1 && isImage(quoted_post.attachments.first()!.name)) { // Only contains one image - embed.setImage(quoted_post.attachments.first()?.url as string); + embed.setImage(quoted_post.attachments.first()!.url); } else { // Contains more than one image and/or other files let files = ""; @@ -133,13 +131,9 @@ export default async (message: Message, client: Client) => { } // Footer - let footer = `Posté le ${showDate( - client.config.default_lang, - loc, - quoted_post?.createdAt as Date, - )}`; + let footer = `Posté le ${showDate(loc, quoted_post!.createdAt)}`; if (quoted_post?.editedAt) { - footer += ` et modifié le ${showDate(client.config.default_lang, loc, quoted_post.editedAt)}`; + footer += ` et modifié le ${showDate(loc, quoted_post.editedAt)}`; } let author = "Auteur"; @@ -147,7 +141,6 @@ export default async (message: Message, client: Client) => { author += " & Citateur"; } else { footer += `\nCité par ${userWithNickname(message.member!) ?? "?"} le ${showDate( - client.config.default_lang, loc, message.createdAt, )}`; diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 4f3dd13..1231731 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -81,6 +81,10 @@ "c_play_name": "play", "c_play_desc": "Plays a song/playlist, no query displays the now playing song", + "c_play_sub1_name": "add", + "c_play_sub1_desc": "Adds song/playlist to the queue", + "c_play_sub2_name": "now", + "c_play_sub2_desc": "Adds the song/playlist to the beginning of the queue", "c_play_opt1_name": "query", "c_play_opt1_desc": "What you want to listen to", "c_play1": "You're not on any vocal channels.", diff --git a/src/locales/fr.json b/src/locales/fr.json index d0af1c9..725d499 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -81,6 +81,10 @@ "c_play_name": "play", "c_play_desc": "Joue une chanson/playlist, pas de requête affiche la chanson en cours actuellement", + "c_play_sub1_name": "ajouter", + "c_play_sub1_desc": "Ajoute la chanson/playlist à la file d'attente", + "c_play_sub2_name": "maintenant", + "c_play_sub2_desc": "Ajoute la chanson/playlist au début de la file", "c_play_opt1_name": "requête", "c_play_opt1_desc": "Ce que vous voulez écouter", "c_play1": "Tu n'es dans aucun salon vocal.", diff --git a/src/modals/misc/reminderGUI.ts b/src/modals/misc/reminderGUI.ts index 1d4639b..35d46d8 100644 --- a/src/modals/misc/reminderGUI.ts +++ b/src/modals/misc/reminderGUI.ts @@ -7,7 +7,7 @@ export default { name: getFilename(__filename), }, interaction: async (interaction: ModalSubmitInteraction, client: Client) => - newReminder(client, interaction.fields.fields.get("reminderGUI-time")?.value as string, { + newReminder(client, interaction.fields.fields.get("reminderGUI-time")!.value, { locale: interaction.locale, message: interaction.fields.fields.get("reminderGUI-message")?.value ?? null, createdAt: interaction.createdAt.getTime(), diff --git a/src/utils/misc.ts b/src/utils/misc.ts index e2a7fd2..d186ec6 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -108,8 +108,9 @@ export const cleanCodeBlock = (text: string) => { }); // Keep links + // Reference: https://stackoverflow.com/a/3809435/15436737 text = text.replace( - /(http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)/g, + /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b[-a-zA-Z0-9()@:%_+.~#?&//=]*/g, function (url: string) { return `\`${url}\``; }, diff --git a/src/utils/reminder.ts b/src/utils/reminder.ts index b15318b..ee77218 100644 --- a/src/utils/reminder.ts +++ b/src/utils/reminder.ts @@ -414,7 +414,6 @@ export const embedListReminders = async ( const expiration = `${loc.get("c_reminder8")} ${timeDeltaToString(remind.expiration_date)}`; embed.addFields({ name: `#${remind.id} • ${loc.get("c_reminder9")} ${showDate( - local, loc, new Date(Number(remind.creation_date)), )}\n${expiration}`, diff --git a/src/utils/time.ts b/src/utils/time.ts index b754314..bfec23e 100644 --- a/src/utils/time.ts +++ b/src/utils/time.ts @@ -5,9 +5,8 @@ * @param date Date * @returns String */ -export const showDate = (tz: string, locale: Map, date: Date) => { - return date.toLocaleString(tz).replace(" ", ` ${locale.get("u_time_at")} `); -}; +export const showDate = (locale: Map, date: Date) => + `${date.toDateString()} ${locale.get("u_time_at")} ${date.toTimeString().split(" ")[0]}`; enum TimeSecond { Year = 31536000,