diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml new file mode 100644 index 0000000..541945b --- /dev/null +++ b/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/commands/server/start-mc.js b/commands/server/start-mc.js index 938c98f..b324c6f 100644 --- a/commands/server/start-mc.js +++ b/commands/server/start-mc.js @@ -1,58 +1,64 @@ -const { ButtonBuilder, ButtonStyle, SlashCommandBuilder, ActionRow, ActionRowBuilder} = require('discord.js') -const config = require('../../config.json') +const { ButtonBuilder, ButtonStyle, SlashCommandBuilder, ActionRowBuilder } = require('discord.js'); +const config = require('../../config.json'); if (!config.proxmoxUser || !config.proxmoxPass || !config.proxmoxHostname) { - console.error("Proxmox credentials not found in config.json. Exiting."); - process.exit(1); + console.error('Proxmox credentials not found in config.json. Exiting.'); + process.exit(1); } -proxmox = require("proxmox")(config.proxmoxUser, config.proxmoxPass, config.proxmoxHostname); +// eslint-disable-next-line no-undef +proxmox = require('proxmox')(config.proxmoxUser, config.proxmoxPass, config.proxmoxHostname); module.exports = { - cooldowns: 60, - data: new SlashCommandBuilder() - .setName('start-mc') - .setDescription('Starts the minecraft server machine.'), - async execute(interaction) { - const confirm = new ButtonBuilder() - .setCustomId('confirm') - .setLabel('Confirm') - .setStyle(ButtonStyle.Primary) - const cancel = new ButtonBuilder() - .setCustomId('cancel') - .setLabel('Cancel') - .setStyle(ButtonStyle.Danger) + cooldowns: 60, + data: new SlashCommandBuilder() + .setName('start-mc') + .setDescription('Starts the minecraft server machine.'), + async execute(interaction) { + const confirm = new ButtonBuilder() + .setCustomId('confirm') + .setLabel('Confirm') + .setStyle(ButtonStyle.Primary); + const cancel = new ButtonBuilder() + .setCustomId('cancel') + .setLabel('Cancel') + .setStyle(ButtonStyle.Danger); - const row = new ActionRowBuilder() - .addComponents(cancel, confirm) + const row = new ActionRowBuilder() + .addComponents(cancel, confirm); - const response = await interaction.reply({ - content: 'Are you sure you want to start the Minecraft server?', - components: [row] - }) + const response = await interaction.reply({ + content: 'Are you sure you want to start the Minecraft server?', + components: [row], + }); - const collectorFilter = i => i.user.id === interaction.user.id; - try { - const confirmation = await response.awaitMessageComponent({ filter: collectorFilter, time: 30_000 }); - if (confirmation.customId === 'confirm') { - proxmox.qemu.start("pve", "102", function(err, res) { - if (err) { - confirmation.update("Error starting the Minecraft server: " + err); - } else { - const linkButton = new ButtonBuilder() - .setStyle(ButtonStyle.Link) - .setLabel('Web Interface') - .setURL('https://mc.louisgallet.fr') - const row = new ActionRowBuilder() - .addComponents(linkButton) - confirmation.update({content: "Minecraft server started successfully. Please wait a few minutes for it to boot.", components: [row]}); - } - }) - } else if (confirmation.customId === 'cancel') { - await confirmation.update({ content: 'Minecraft server start cancelled.', components: [] }); - } - } catch (e) { - await confirmation.update({ content: 'You took too long to respond.', components: [] }); - } + const collectorFilter = i => i.user.id === interaction.user.id; + try { + const confirmation = await response.awaitMessageComponent({ filter: collectorFilter, time: 30_000 }); + if (confirmation.customId === 'confirm') { + // eslint-disable-next-line no-undef + proxmox.qemu.start('pve', '102', function(err) { + if (err) { + confirmation.update('Error starting the Minecraft server: ' + err); + } + else { + const linkButton = new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel('Web Interface') + .setURL('https://mc.louisgallet.fr'); + const linkRow = new ActionRowBuilder() + .addComponents(linkButton); + confirmation.update({ content: 'Minecraft server started successfully. Please wait a few minutes for it to boot.', components: [linkRow] }); + } + }); + } + else if (confirmation.customId === 'cancel') { + await confirmation.update({ content: 'Minecraft server start cancelled.', components: [] }); + } + } + catch (e) { + // eslint-disable-next-line no-undef + await confirmation.update({ content: 'You took too long to respond.', components: [] }); + } - } -} + }, +}; diff --git a/commands/server/stop-mc.js b/commands/server/stop-mc.js index fb9861b..26e5995 100644 --- a/commands/server/stop-mc.js +++ b/commands/server/stop-mc.js @@ -1,23 +1,24 @@ -const { SlashCommandBuilder } = require('discord.js') -const config = require('../../config.json') +const { SlashCommandBuilder } = require('discord.js'); +const config = require('../../config.json'); if (!config.proxmoxUser || !config.proxmoxPass || !config.proxmoxHostname) { - console.error("Proxmox credentials not found in config.json. Exiting."); - process.exit(1); + console.error('Proxmox credentials not found in config.json. Exiting.'); + process.exit(1); } -proxmox = require("proxmox")(config.proxmoxUser, config.proxmoxPass, config.proxmoxHostname); +const proxmox = require('proxmox')(config.proxmoxUser, config.proxmoxPass, config.proxmoxHostname); module.exports = { - data: new SlashCommandBuilder() - .setName('stop-mc') - .setDescription('Stops the minecraft server machine.'), - async execute(interaction) { - proxmox.qemu.shutdown("pve", "102", function(err, res) { - if (err) { - interaction.reply("Error starting the Minecraft server: " + err); - } else { - interaction.reply("Minecraft server stopped successfully."); - } - }) - } -} + data: new SlashCommandBuilder() + .setName('stop-mc') + .setDescription('Stops the minecraft server machine.'), + async execute(interaction) { + proxmox.qemu.shutdown('pve', '102', function(err) { + if (err) { + interaction.reply('Error starting the Minecraft server: ' + err); + } + else { + interaction.reply('Minecraft server stopped successfully.'); + } + }); + }, +}; diff --git a/commands/utility/ping.js b/commands/utility/ping.js index 27edf1b..0d51012 100644 --- a/commands/utility/ping.js +++ b/commands/utility/ping.js @@ -1,10 +1,10 @@ -const { SlashCommandBuilder } = require('discord.js') +const { SlashCommandBuilder } = require('discord.js'); module.exports = { - data: new SlashCommandBuilder() - .setName('ping') - .setDescription('Replies with Pong'), - async execute(interaction) { - await interaction.reply('Pong') - }, -} \ No newline at end of file + data: new SlashCommandBuilder() + .setName('ping') + .setDescription('Replies with Pong'), + async execute(interaction) { + await interaction.reply('Pong'); + }, +}; \ No newline at end of file diff --git a/commands/utility/reload.js b/commands/utility/reload.js index 61384cc..c7d9f94 100644 --- a/commands/utility/reload.js +++ b/commands/utility/reload.js @@ -1,32 +1,33 @@ const { SlashCommandBuilder } = require('discord.js'); module.exports = { - category: 'utility', - data: new SlashCommandBuilder() - .setName('reload') - .setDescription('Reloads a command.') - .addStringOption(option => - option.setName('command') - .setDescription('The command to reload.') - .setRequired(true)), - async execute(interaction) { - const commandName = interaction.options.getString('command', true).toLowerCase(); - const command = interaction.client.commands.get(commandName); + category: 'utility', + data: new SlashCommandBuilder() + .setName('reload') + .setDescription('Reloads a command.') + .addStringOption(option => + option.setName('command') + .setDescription('The command to reload.') + .setRequired(true)), + async execute(interaction) { + const commandName = interaction.options.getString('command', true).toLowerCase(); + const command = interaction.client.commands.get(commandName); - if (!command) { - return interaction.reply(`There is no command with name \`${commandName}\`!`); - } + if (!command) { + return interaction.reply(`There is no command with name \`${commandName}\`!`); + } - delete require.cache[require.resolve(`../${command.category}/${command.data.name}.js`)]; + delete require.cache[require.resolve(`../${command.category}/${command.data.name}.js`)]; - try { - await interaction.client.commands.delete(command.data.name); - const newCommand = require(`../${command.category}/${command.data.name}.js`); - await interaction.client.commands.set(newCommand.data.name, newCommand); - await interaction.reply(`Command \`${newCommand.data.name}\` was reloaded!`); - } catch (error) { - console.error(error); - await interaction.reply(`There was an error while reloading a command \`${command.data.name}\`:\n\`${error.message}\``); - } - }, + try { + await interaction.client.commands.delete(command.data.name); + const newCommand = require(`../${command.category}/${command.data.name}.js`); + await interaction.client.commands.set(newCommand.data.name, newCommand); + await interaction.reply(`Command \`${newCommand.data.name}\` was reloaded!`); + } + catch (error) { + console.error(error); + await interaction.reply(`There was an error while reloading a command \`${command.data.name}\`:\n\`${error.message}\``); + } + }, }; \ No newline at end of file diff --git a/commands/utility/server.js b/commands/utility/server.js index db682b4..67411cf 100644 --- a/commands/utility/server.js +++ b/commands/utility/server.js @@ -1,11 +1,11 @@ const { SlashCommandBuilder } = require('discord.js'); module.exports = { - data: new SlashCommandBuilder() - .setName('server') - .setDescription('Provides information about the server.'), - async execute(interaction) { - // interaction.guild is the object representing the Guild in which the command was run - await interaction.reply(`This server is ${interaction.guild.name} and has ${interaction.guild.memberCount} members.`); - }, + data: new SlashCommandBuilder() + .setName('server') + .setDescription('Provides information about the server.'), + async execute(interaction) { + // interaction.guild is the object representing the Guild in which the command was run + await interaction.reply(`This server is ${interaction.guild.name} and has ${interaction.guild.memberCount} members.`); + }, }; diff --git a/commands/utility/user.js b/commands/utility/user.js index fdd3097..6ef0ba8 100644 --- a/commands/utility/user.js +++ b/commands/utility/user.js @@ -1,12 +1,12 @@ const { SlashCommandBuilder } = require('discord.js'); module.exports = { - data: new SlashCommandBuilder() - .setName('user') - .setDescription('Provides information about the user.'), - async execute(interaction) { - // interaction.user is the object representing the User who ran the command - // interaction.member is the GuildMember object, which represents the user in the specific guild - await interaction.reply(`This command was run by ${interaction.user.username}, who joined on ${interaction.member.joinedAt}.`); - }, + data: new SlashCommandBuilder() + .setName('user') + .setDescription('Provides information about the user.'), + async execute(interaction) { + // interaction.user is the object representing the User who ran the command + // interaction.member is the GuildMember object, which represents the user in the specific guild + await interaction.reply(`This command was run by ${interaction.user.username}, who joined on ${interaction.member.joinedAt}.`); + }, }; diff --git a/deploy-commands.js b/deploy-commands.js index dad7f8c..3fc81b4 100644 --- a/deploy-commands.js +++ b/deploy-commands.js @@ -9,19 +9,20 @@ const foldersPath = path.join(__dirname, 'commands'); const commandFolders = fs.readdirSync(foldersPath); for (const folder of commandFolders) { - // Grab all the command files from the commands directory you created earlier - const commandsPath = path.join(foldersPath, folder); - const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); - // Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment - for (const file of commandFiles) { - const filePath = path.join(commandsPath, file); - const command = require(filePath); - if ('data' in command && 'execute' in command) { - commands.push(command.data.toJSON()); - } else { - console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); - } - } + // Grab all the command files from the commands directory you created earlier + const commandsPath = path.join(foldersPath, folder); + const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); + // Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment + for (const file of commandFiles) { + const filePath = path.join(commandsPath, file); + const command = require(filePath); + if ('data' in command && 'execute' in command) { + commands.push(command.data.toJSON()); + } + else { + console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); + } + } } // Construct and prepare an instance of the REST module @@ -29,18 +30,19 @@ const rest = new REST().setToken(token); // and deploy your commands! (async () => { - try { - console.log(`Started refreshing ${commands.length} application (/) commands.`); + try { + console.log(`Started refreshing ${commands.length} application (/) commands.`); - // The put method is used to fully refresh all commands in the guild with the current set - const data = await rest.put( - Routes.applicationGuildCommands(clientId, guildId), - { body: commands }, - ); + // The put method is used to fully refresh all commands in the guild with the current set + const data = await rest.put( + Routes.applicationGuildCommands(clientId, guildId), + { body: commands }, + ); - console.log(`Successfully reloaded ${data.length} application (/) commands.`); - } catch (error) { - // And of course, make sure you catch and log any errors! - console.error(error); - } + console.log(`Successfully reloaded ${data.length} application (/) commands.`); + } + catch (error) { + // And of course, make sure you catch and log any errors! + console.error(error); + } })(); diff --git a/events/interactionCreate.js b/events/interactionCreate.js index 5f445f1..624db14 100644 --- a/events/interactionCreate.js +++ b/events/interactionCreate.js @@ -1,26 +1,28 @@ const { Events } = require('discord.js'); module.exports = { - name: Events.InteractionCreate, - async execute(interaction) { - if (!interaction.isChatInputCommand()) return; + name: Events.InteractionCreate, + async execute(interaction) { + if (!interaction.isChatInputCommand()) return; - const command = interaction.client.commands.get(interaction.commandName); + const command = interaction.client.commands.get(interaction.commandName); - if (!command) { - console.error(`No command matching ${interaction.commandName} was found.`); - return; - } + if (!command) { + console.error(`No command matching ${interaction.commandName} was found.`); + return; + } - 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!', ephemeral: true }); - } else { - await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); - } - } - }, + 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!', ephemeral: true }); + } + else { + await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); + } + } + }, }; diff --git a/events/ready.js b/events/ready.js index ea615aa..e59e552 100644 --- a/events/ready.js +++ b/events/ready.js @@ -1,9 +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}`); - }, + name: Events.ClientReady, + once: true, + execute(client) { + console.log(`Ready! Logged in as ${client.user.tag}`); + }, }; diff --git a/index.js b/index.js index 6449c3d..bf521c1 100644 --- a/index.js +++ b/index.js @@ -11,65 +11,68 @@ const foldersPath = path.join(__dirname, 'commands'); const commandFolders = fs.readdirSync(foldersPath); for (const folder of commandFolders) { - const commandsPath = path.join(foldersPath, folder); - const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); - for (const file of commandFiles) { - const filePath = path.join(commandsPath, file); - const command = require(filePath); - if ('data' in command && 'execute' in command) { - client.commands.set(command.data.name, command); - } else { - console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); - } - } + const commandsPath = path.join(foldersPath, folder); + const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); + for (const file of commandFiles) { + const filePath = path.join(commandsPath, file); + const command = require(filePath); + if ('data' in command && 'execute' in command) { + client.commands.set(command.data.name, command); + } + else { + console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); + } + } } client.once(Events.ClientReady, c => { - console.log(`Ready! Logged in as ${c.user.tag}`); + 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 (!interaction.isChatInputCommand()) return; + const command = client.commands.get(interaction.commandName); - if (!command) { - console.error(`No command matching ${interaction.commandName} was found.`); - return; - } + if (!command) { + console.error(`No command matching ${interaction.commandName} was found.`); + return; + } - const { cooldowns } = interaction.client; + const { cooldowns } = interaction.client; - if (!cooldowns.has(command.data.name)) { - cooldowns.set(command.data.name, new Collection()); - } + 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; + 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 (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 .`, ephemeral: true }); - } - } + 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 .`, ephemeral: true }); + } + } - timestamps.set(interaction.user.id, now); - setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount); + 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!', ephemeral: true }); - } else { - await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); - } - } + 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!', ephemeral: true }); + } + else { + await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); + } + } }); client.login(token); diff --git a/package.json b/package.json index 10e7908..c535b1a 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "node deploy-commands.js && nodemon index.js", "start": "node deploy-commands.js && node index.js", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "lint": "eslint . --fix" }, "keywords": [], "author": "",