added status command

This commit is contained in:
valentijn
2024-01-04 16:18:10 +01:00
parent 5fa398bffe
commit 78a9688276
6 changed files with 441 additions and 0 deletions

2
.gitignore vendored
View File

@@ -125,3 +125,5 @@ dist
.yarn/build-state.yml .yarn/build-state.yml
.yarn/install-state.gz .yarn/install-state.gz
.pnp.* .pnp.*
config.json

55
bot.js Normal file
View File

@@ -0,0 +1,55 @@
const { Client, Collection, Events, GatewayIntentBits } = require('discord.js');
const { updateCommands } = require("./updateCommands");
const { token } = require('./config.json');
const fs = require('node:fs');
const path = require('node:path');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
updateCommands();
/** REGISTER COMMANDS **/
client.commands = new Collection();
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.`);
}
}
}
/** SLASH COMMAND HANDLER **/
client.on(Events.InteractionCreate, async interaction => {
if (interaction.isChatInputCommand()) {
const command = client.commands.get(interaction.commandName);
if (command) {
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
if (!(interaction.replied || interaction.deferred)) {
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
}
} else {
console.error(`No command matching ${interaction.commandName} was found.`);
}
}
});
/** READY SEQUENCE **/
client.once(Events.ClientReady, c => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
client.login(token);

58
commands/mc/status.js Normal file
View File

@@ -0,0 +1,58 @@
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
const dgram = require('dgram');
const { server_ip, server_port } = require('../../config.json');
module.exports = {
data: new SlashCommandBuilder()
.setName('server-status')
.setDescription('shows you some information about the minecraft server'),
async execute(interaction) {
try {
const serverInfo = await getServerInfo(server_ip, server_port);
const embed = new EmbedBuilder()
.setColor('#0099ff')
.setTitle('Minecraft Server Status')
.addField('Description', serverInfo.description.text)
.addField('Players', `${serverInfo.players.online}/${serverInfo.players.max}`, true)
.addField('Version', serverInfo.version.name, true)
.addField('Online Players', serverInfo.players.sample.map(player => player.name).join(', '));
await interaction.reply({ embeds: [embed] });
} catch (error) {
console.error(error.message || 'Failed to retrieve Minecraft server info.');
await interaction.reply('Failed to retrieve Minecraft server info.');
}
},
};
async function getServerInfo(ip, port) {
const client = dgram.createSocket('udp4');
// Send a Handshake packet to the server
const handshakePacket = Buffer.from([0xFE, 0xFD, 0x09, 0x74, 0x65, 0x73, 0x74, 0x00, 0x4D, 0x49, 0x4E, 0x45, 0x43, 0x52, 0x41, 0x46, 0x54, 0x00]);
client.send(handshakePacket, port, ip);
return new Promise((resolve, reject) => {
client.on('message', (response) => {
if (response.slice(0, 2).equals(Buffer.from([0xFF, 0xFD])) && response.length > 35) {
const jsonResponse = response.toString('utf8', 35);
try {
const parsedResponse = JSON.parse(jsonResponse);
resolve(parsedResponse);
} catch (error) {
reject(new Error('Failed to parse player list.'));
}
} else {
reject(new Error('Failed to retrieve player list.'));
}
client.close();
});
client.on('error', (err) => {
reject(err);
});
});
}

276
package-lock.json generated Normal file
View File

@@ -0,0 +1,276 @@
{
"name": "PS-Discord-MinecraftServer",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"dgram": "^1.0.1",
"discord.js": "^14.14.1"
}
},
"node_modules/@discordjs/builders": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.7.0.tgz",
"integrity": "sha512-GDtbKMkg433cOZur8Dv6c25EHxduNIBsxeHrsRoIM8+AwmEZ8r0tEpckx/sHwTLwQPOF3e2JWloZh9ofCaMfAw==",
"dependencies": {
"@discordjs/formatters": "^0.3.3",
"@discordjs/util": "^1.0.2",
"@sapphire/shapeshift": "^3.9.3",
"discord-api-types": "0.37.61",
"fast-deep-equal": "^3.1.3",
"ts-mixer": "^6.0.3",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/collection": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz",
"integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==",
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/formatters": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.3.tgz",
"integrity": "sha512-wTcI1Q5cps1eSGhl6+6AzzZkBBlVrBdc9IUhJbijRgVjCNIIIZPgqnUj3ntFODsHrdbGU8BEG9XmDQmgEEYn3w==",
"dependencies": {
"discord-api-types": "0.37.61"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/rest": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.2.0.tgz",
"integrity": "sha512-nXm9wT8oqrYFRMEqTXQx9DUTeEtXUDMmnUKIhZn6O2EeDY9VCdwj23XCPq7fkqMPKdF7ldAfeVKyxxFdbZl59A==",
"dependencies": {
"@discordjs/collection": "^2.0.0",
"@discordjs/util": "^1.0.2",
"@sapphire/async-queue": "^1.5.0",
"@sapphire/snowflake": "^3.5.1",
"@vladfrangu/async_event_emitter": "^2.2.2",
"discord-api-types": "0.37.61",
"magic-bytes.js": "^1.5.0",
"tslib": "^2.6.2",
"undici": "5.27.2"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/rest/node_modules/@discordjs/collection": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz",
"integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==",
"engines": {
"node": ">=18"
}
},
"node_modules/@discordjs/util": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.2.tgz",
"integrity": "sha512-IRNbimrmfb75GMNEjyznqM1tkI7HrZOf14njX7tCAAUetyZM1Pr8hX/EK2lxBCOgWDRmigbp24fD1hdMfQK5lw==",
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/ws": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.2.tgz",
"integrity": "sha512-+XI82Rm2hKnFwAySXEep4A7Kfoowt6weO6381jgW+wVdTpMS/56qCvoXyFRY0slcv7c/U8My2PwIB2/wEaAh7Q==",
"dependencies": {
"@discordjs/collection": "^2.0.0",
"@discordjs/rest": "^2.1.0",
"@discordjs/util": "^1.0.2",
"@sapphire/async-queue": "^1.5.0",
"@types/ws": "^8.5.9",
"@vladfrangu/async_event_emitter": "^2.2.2",
"discord-api-types": "0.37.61",
"tslib": "^2.6.2",
"ws": "^8.14.2"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/ws/node_modules/@discordjs/collection": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz",
"integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==",
"engines": {
"node": ">=18"
}
},
"node_modules/@fastify/busboy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
"integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==",
"engines": {
"node": ">=14"
}
},
"node_modules/@sapphire/async-queue": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz",
"integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/@sapphire/shapeshift": {
"version": "3.9.3",
"resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.3.tgz",
"integrity": "sha512-WzKJSwDYloSkHoBbE8rkRW8UNKJiSRJ/P8NqJ5iVq7U2Yr/kriIBx2hW+wj2Z5e5EnXL1hgYomgaFsdK6b+zqQ==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"lodash": "^4.17.21"
},
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/@sapphire/snowflake": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz",
"integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/@types/node": {
"version": "20.10.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.1.tgz",
"integrity": "sha512-T2qwhjWwGH81vUEx4EXmBKsTJRXFXNZTL4v0gi01+zyBmCwzE6TyHszqX01m+QHTEq+EZNo13NeJIdEqf+Myrg==",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/@types/ws": {
"version": "8.5.9",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz",
"integrity": "sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@vladfrangu/async_event_emitter": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.2.tgz",
"integrity": "sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ==",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/dgram": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dgram/-/dgram-1.0.1.tgz",
"integrity": "sha512-zJVFL1EWfKtE0z2VN6qfpn/a+qG1viEzcwJA0EjtzS76ONSE3sEyWBwEbo32hS4IFw/EWVuWN+8b89aPW6It2A==",
"deprecated": "npm is holding this package for security reasons. As it's a core Node module, we will not transfer it over to other users. You may safely remove the package from your dependencies."
},
"node_modules/discord-api-types": {
"version": "0.37.61",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz",
"integrity": "sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw=="
},
"node_modules/discord.js": {
"version": "14.14.1",
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.14.1.tgz",
"integrity": "sha512-/hUVzkIerxKHyRKopJy5xejp4MYKDPTszAnpYxzVVv4qJYf+Tkt+jnT2N29PIPschicaEEpXwF2ARrTYHYwQ5w==",
"dependencies": {
"@discordjs/builders": "^1.7.0",
"@discordjs/collection": "1.5.3",
"@discordjs/formatters": "^0.3.3",
"@discordjs/rest": "^2.1.0",
"@discordjs/util": "^1.0.2",
"@discordjs/ws": "^1.0.2",
"@sapphire/snowflake": "3.5.1",
"@types/ws": "8.5.9",
"discord-api-types": "0.37.61",
"fast-deep-equal": "3.1.3",
"lodash.snakecase": "4.1.1",
"tslib": "2.6.2",
"undici": "5.27.2",
"ws": "8.14.2"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.snakecase": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
},
"node_modules/magic-bytes.js": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.5.0.tgz",
"integrity": "sha512-wJkXvutRbNWcc37tt5j1HyOK1nosspdh3dj6LUYYAvF6JYNqs53IfRvK9oEpcwiDA1NdoIi64yAMfdivPeVAyw=="
},
"node_modules/ts-mixer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz",
"integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ=="
},
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/undici": {
"version": "5.27.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz",
"integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
},
"node_modules/ws": {
"version": "8.14.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
"integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}

6
package.json Normal file
View File

@@ -0,0 +1,6 @@
{
"dependencies": {
"dgram": "^1.0.1",
"discord.js": "^14.14.1"
}
}

44
updateCommands.js Normal file
View File

@@ -0,0 +1,44 @@
const { REST, Routes } = require('discord.js');
const { clientId, token } = require('./config.json');
const fs = require('node:fs');
const path = require('node:path');
const updateCommands = () => {
const commands = [];
const foldersPath = path.join(__dirname, 'commands');
for (const folder of fs.readdirSync(foldersPath)) {
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) {
commands.push(command.data.toJSON());
} else {
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
}
const rest = new REST().setToken(token);
(async () => {
try {
console.log(`⚙️ Started refreshing ${commands.length} application (/) commands.`);
const data = await rest.put(
Routes.applicationCommands(clientId),
{ body: commands },
);
console.log(`✅ Successfully reloaded ${data.length} application (/) commands.`);
} catch (error) {
console.error(`${error}`);
}
})();
}
module.exports = {
updateCommands
}