diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a0d7a9f45..0ba15ed97 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1 +1,6 @@ **Please describe the changes this PR makes and why it should be merged:** + +This pull request updates the `additional-features` code samples to include the individual event +files that were added in previous steps of the guide. This change makes reading the reference code +more consistent, clearer, and easier for the user who has followed the previous steps in case they +wanted to cross-reference their own work. \ No newline at end of file diff --git a/code-samples/additional-features/cooldowns/events/interactionCreate.js b/code-samples/additional-features/cooldowns/events/interactionCreate.js new file mode 100644 index 000000000..eb9c79182 --- /dev/null +++ b/code-samples/additional-features/cooldowns/events/interactionCreate.js @@ -0,0 +1,52 @@ +const { Events, Collection, MessageFlags } = require('discord.js'); + +module.exports = { + name: Events.InteractionCreate, + async execute(interaction) { + if (!interaction.isChatInputCommand()) return; + + const command = interaction.client.commands.get(interaction.commandName); + + if (!command) { + console.error(`No command matching ${interaction.commandName} was found.`); + return; + } + + const { cooldowns } = interaction.client; + + if (!cooldowns.has(command.data.name)) { + cooldowns.set(command.data.name, new Collection()); + } + + const now = Date.now(); + const timestamps = cooldowns.get(command.data.name); + const defaultCooldownDuration = 3; + const cooldownAmount = (command.cooldown ?? defaultCooldownDuration) * 1000; + + if (timestamps.has(interaction.user.id)) { + const expirationTime = timestamps.get(interaction.user.id) + cooldownAmount; + + if (now < expirationTime) { + const expiredTimestamp = Math.round(expirationTime / 1000); + return interaction.reply({ + content: `Please wait, you are on a cooldown for \`${command.data.name}\`. You can use it again .`, + flags: MessageFlags.Ephemeral, + }); + } + } + + timestamps.set(interaction.user.id, now); + setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount); + + try { + await command.execute(interaction); + } catch (error) { + console.error(error); + if (interaction.replied || interaction.deferred) { + await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); + } else { + await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); + } + } + }, +}; diff --git a/code-samples/additional-features/cooldowns/events/ready.js b/code-samples/additional-features/cooldowns/events/ready.js new file mode 100644 index 000000000..e59e552a9 --- /dev/null +++ b/code-samples/additional-features/cooldowns/events/ready.js @@ -0,0 +1,9 @@ +const { Events } = require('discord.js'); + +module.exports = { + name: Events.ClientReady, + once: true, + execute(client) { + console.log(`Ready! Logged in as ${client.user.tag}`); + }, +}; diff --git a/code-samples/additional-features/cooldowns/index.js b/code-samples/additional-features/cooldowns/index.js index 101d8037d..7cca2ff26 100644 --- a/code-samples/additional-features/cooldowns/index.js +++ b/code-samples/additional-features/cooldowns/index.js @@ -1,12 +1,13 @@ const fs = require('node:fs'); const path = require('node:path'); -const { Client, Collection, Events, GatewayIntentBits, MessageFlags } = require('discord.js'); +const { Client, Collection, GatewayIntentBits } = require('discord.js'); const { token } = require('./config.json'); const client = new Client({ intents: [GatewayIntentBits.Guilds] }); client.cooldowns = new Collection(); client.commands = new Collection(); + const foldersPath = path.join(__dirname, 'commands'); const commandFolders = fs.readdirSync(foldersPath); @@ -24,52 +25,19 @@ for (const folder of commandFolders) { } } -client.once(Events.ClientReady, readyClient => { - console.log(`Ready! Logged in as ${readyClient.user.tag}`); -}); - -client.on(Events.InteractionCreate, async interaction => { - if (!interaction.isChatInputCommand()) return; - const command = client.commands.get(interaction.commandName); - - if (!command) { - console.error(`No command matching ${interaction.commandName} was found.`); - return; +const eventsPath = path.join(__dirname, 'events'); +const eventFiles = fs + .readdirSync(eventsPath) + .filter(file => file.endsWith('.js')); + +for (const file of eventFiles) { + const filePath = path.join(eventsPath, file); + const event = require(filePath); + if (event.once) { + client.once(event.name, (...args) => event.execute(...args)); + } else { + client.on(event.name, (...args) => event.execute(...args)); } - - const { cooldowns } = interaction.client; - - if (!cooldowns.has(command.data.name)) { - cooldowns.set(command.data.name, new Collection()); - } - - const now = Date.now(); - const timestamps = cooldowns.get(command.data.name); - const defaultCooldownDuration = 3; - const cooldownAmount = (command.cooldown ?? defaultCooldownDuration) * 1000; - - if (timestamps.has(interaction.user.id)) { - const expirationTime = timestamps.get(interaction.user.id) + cooldownAmount; - - if (now < expirationTime) { - const expiredTimestamp = Math.round(expirationTime / 1000); - return interaction.reply({ content: `Please wait, you are on a cooldown for \`${command.data.name}\`. You can use it again .`, flags: MessageFlags.Ephemeral }); - } - } - - timestamps.set(interaction.user.id, now); - setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount); - - try { - await command.execute(interaction); - } catch (error) { - console.error(error); - if (interaction.replied || interaction.deferred) { - await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); - } else { - await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); - } - } -}); +} client.login(token); diff --git a/code-samples/additional-features/reloading-commands/events/interactionCreate.js b/code-samples/additional-features/reloading-commands/events/interactionCreate.js new file mode 100644 index 000000000..eb9c79182 --- /dev/null +++ b/code-samples/additional-features/reloading-commands/events/interactionCreate.js @@ -0,0 +1,52 @@ +const { Events, Collection, MessageFlags } = require('discord.js'); + +module.exports = { + name: Events.InteractionCreate, + async execute(interaction) { + if (!interaction.isChatInputCommand()) return; + + const command = interaction.client.commands.get(interaction.commandName); + + if (!command) { + console.error(`No command matching ${interaction.commandName} was found.`); + return; + } + + const { cooldowns } = interaction.client; + + if (!cooldowns.has(command.data.name)) { + cooldowns.set(command.data.name, new Collection()); + } + + const now = Date.now(); + const timestamps = cooldowns.get(command.data.name); + const defaultCooldownDuration = 3; + const cooldownAmount = (command.cooldown ?? defaultCooldownDuration) * 1000; + + if (timestamps.has(interaction.user.id)) { + const expirationTime = timestamps.get(interaction.user.id) + cooldownAmount; + + if (now < expirationTime) { + const expiredTimestamp = Math.round(expirationTime / 1000); + return interaction.reply({ + content: `Please wait, you are on a cooldown for \`${command.data.name}\`. You can use it again .`, + flags: MessageFlags.Ephemeral, + }); + } + } + + timestamps.set(interaction.user.id, now); + setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount); + + try { + await command.execute(interaction); + } catch (error) { + console.error(error); + if (interaction.replied || interaction.deferred) { + await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); + } else { + await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); + } + } + }, +}; diff --git a/code-samples/additional-features/reloading-commands/events/ready.js b/code-samples/additional-features/reloading-commands/events/ready.js new file mode 100644 index 000000000..e59e552a9 --- /dev/null +++ b/code-samples/additional-features/reloading-commands/events/ready.js @@ -0,0 +1,9 @@ +const { Events } = require('discord.js'); + +module.exports = { + name: Events.ClientReady, + once: true, + execute(client) { + console.log(`Ready! Logged in as ${client.user.tag}`); + }, +}; diff --git a/code-samples/additional-features/reloading-commands/index.js b/code-samples/additional-features/reloading-commands/index.js index a2ab97353..7cca2ff26 100644 --- a/code-samples/additional-features/reloading-commands/index.js +++ b/code-samples/additional-features/reloading-commands/index.js @@ -1,12 +1,13 @@ const fs = require('node:fs'); const path = require('node:path'); -const { Client, Collection, Events, GatewayIntentBits, MessageFlags } = require('discord.js'); +const { Client, Collection, GatewayIntentBits } = require('discord.js'); const { token } = require('./config.json'); const client = new Client({ intents: [GatewayIntentBits.Guilds] }); client.cooldowns = new Collection(); client.commands = new Collection(); + const foldersPath = path.join(__dirname, 'commands'); const commandFolders = fs.readdirSync(foldersPath); @@ -24,52 +25,19 @@ for (const folder of commandFolders) { } } -client.once(Events.ClientReady, c => { - console.log(`Ready! Logged in as ${c.user.tag}`); -}); - -client.on(Events.InteractionCreate, async interaction => { - if (!interaction.isChatInputCommand()) return; - const command = client.commands.get(interaction.commandName); - - if (!command) { - console.error(`No command matching ${interaction.commandName} was found.`); - return; +const eventsPath = path.join(__dirname, 'events'); +const eventFiles = fs + .readdirSync(eventsPath) + .filter(file => file.endsWith('.js')); + +for (const file of eventFiles) { + const filePath = path.join(eventsPath, file); + const event = require(filePath); + if (event.once) { + client.once(event.name, (...args) => event.execute(...args)); + } else { + client.on(event.name, (...args) => event.execute(...args)); } - - const { cooldowns } = interaction.client; - - if (!cooldowns.has(command.data.name)) { - cooldowns.set(command.data.name, new Collection()); - } - - const now = Date.now(); - const timestamps = cooldowns.get(command.data.name); - const defaultCooldownDuration = 3; - const cooldownAmount = (command.cooldown ?? defaultCooldownDuration) * 1000; - - if (timestamps.has(interaction.user.id)) { - const expirationTime = timestamps.get(interaction.user.id) + cooldownAmount; - - if (now < expirationTime) { - const expiredTimestamp = Math.round(expirationTime / 1000); - return interaction.reply({ content: `Please wait, you are on a cooldown for \`${command.data.name}\`. You can use it again .`, flags: MessageFlags.Ephemeral }); - } - } - - timestamps.set(interaction.user.id, now); - setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount); - - try { - await command.execute(interaction); - } catch (error) { - console.error(error); - if (interaction.replied || interaction.deferred) { - await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); - } else { - await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); - } - } -}); +} client.login(token);