From 1c6ab2a0bf1dda03094676f1a0a9b67e6de22a73 Mon Sep 17 00:00:00 2001 From: ChrisChrome Date: Thu, 27 Jun 2024 01:10:07 -0600 Subject: [PATCH] Add server history autocomplete --- .gitignore | 1 + findMc.js | 5 +- index.js | 161 +++++++++++++++++++++++++++++++++-------------------- 3 files changed, 106 insertions(+), 61 deletions(-) diff --git a/.gitignore b/.gitignore index c6bba59..3de7d65 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,4 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* +history.json \ No newline at end of file diff --git a/findMc.js b/findMc.js index b284a10..51378af 100644 --- a/findMc.js +++ b/findMc.js @@ -7,7 +7,10 @@ const checkSrv = (hostname) => { hostname = `_minecraft._tcp.${hostname}`; return new Promise((resolve, reject) => { dns.resolveSrv(hostname, (err, addresses) => { - if (err) reject(err); + if (err) { + return reject(err); + } + if (!addresses || addresses.length <= 0) return reject("No SRV record found."); resolve(addresses[0]); }); }); diff --git a/index.js b/index.js index 19903c7..f169f73 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const findMc = require("./findMc"); const colors = require("colors"); require("dotenv").config(); const Discord = require("discord.js"); +const fs = require("fs"); const client = new Discord.Client({ intents: ["Guilds"] }); unavailEmote = "<:unreachable:1255354739382816798>" @@ -27,7 +28,8 @@ const commands = [{ name: "address", description: "The address of the server", type: 3, - required: true + required: true, + autocomplete: true }], integration_types: [0, 1], contexts: [0, 1, 2] @@ -65,67 +67,106 @@ client.on('ready', () => { })(); }) +// Try reading the history file, if it doesnt exist or is invalid, set addressHistory to an empty object. +let addressHistory = {}; +try { + addressHistory = JSON.parse(fs.readFileSync("./history.json")); +} catch (err) { + addressHistory = {}; +} +// addressHistory[userid] = [address1, address2, address3, address4, address5]. Addresses never repeat, move them to the front of the array when they are used. Max of 10 addresses per user. + +const doAddressHistory = (userid, address) => { + if (!addressHistory[userid]) { + addressHistory[userid] = [address]; + fs.writeFileSync("./history.json", JSON.stringify(addressHistory)); + return; + } + if (addressHistory[userid].length >= 10) { + addressHistory[userid].pop(); + } + // Check if the address is already in the array, if it is, remove it. + if (addressHistory[userid].includes(address)) { + addressHistory[userid].splice(addressHistory[userid].indexOf(address), 1); + } + addressHistory[userid].unshift(address); + // Save history to file for future use + fs.writeFileSync("./history.json", JSON.stringify(addressHistory)); +} + client.on('interactionCreate', async interaction => { - if (!interaction.isCommand()) return; - console.log(`${colors.cyan("[INFO]")} Command ${colors.green(interaction.commandName)} executed by ${colors.green(interaction.user.displayName)}`); - switch (interaction.commandName) { - case "check": - await interaction.deferReply(); - const address = interaction.options.getString("address"); - findMc(address, 5000).then((data) => { - data.description = filterMOTD(data.description); - msgData = { - embeds: [{ - title: `Server Info for ${address}`, - description: `Ping: ${pingEmote(data.ping)} ${data.ping}ms`, - fields: [ - { - name: "Server Version", - value: data.version.name, - inline: true - }, - { - name: "Players", - value: `${data.players?.online}/${data.players?.max}`, - inline: true - }, - { - name: "MOTD", - value: `\`${data.description?.split("\n")[0]}\`\n\`${data.description?.split("\n")[1]}\`` - }, - data.players.sample?.length > 0 ? { - name: "Players", - value: `\`\`\`\n${data.players.sample.map(player => player.name).join("\n")}\n\`\`\`` - } : { - name: "Players", - value: "No players online." - } - ] - }] - } - // if data.favicon is not null, decode the base64 as a buffer, and make the json object for the attachment - if (data.favicon) { - const buffer = Buffer.from(data.favicon.split(",")[1], "base64"); - msgData.files = [{ - attachment: buffer, - name: "favicon.png" - }] - msgData.embeds[0].thumbnail = { - url: "attachment://favicon.png" + if (interaction.isCommand()) { + switch (interaction.commandName) { + case "check": + await interaction.deferReply(); + const address = interaction.options.getString("address"); + doAddressHistory(interaction.user.id, address); + findMc(address, 5000).then((data) => { + data.description = filterMOTD(data.description); + msgData = { + embeds: [{ + title: `Server Info for ${address}`, + description: `Ping: ${pingEmote(data.ping)} ${data.ping}ms`, + fields: [ + { + name: "Server Version", + value: data.version.name, + inline: true + }, + { + name: "Players", + value: `${data.players?.online}/${data.players?.max}`, + inline: true + }, + { + name: "MOTD", + value: `\`${data.description?.split("\n")[0]}\`\n\`${data.description?.split("\n")[1]}\`` + }, + data.players.sample?.length > 0 ? { + name: "Players", + value: `\`\`\`\n${data.players.sample.map(player => player.name).join("\n")}\n\`\`\`` + } : { + name: "Players", + value: "No players online." + } + ] + }] } - } - interaction.editReply(msgData); - }).catch((err) => { - if (err.toString().startsWith("Error: The client timed out")) { - return interaction.editReply({ content: `${unavailEmote} The server did not respond or is offline.`, ephemeral: true }); - } - if (err.toString().startsWith("Error: Invalid hostname")) { - return interaction.editReply({ content: "Invalid hostname.", ephemeral: true }); - } - console.log(err) - return interaction.editReply({ content: "An error occurred while trying to ping the server.", ephemeral: true }); - }) - break; + // if data.favicon is not null, decode the base64 as a buffer, and make the json object for the attachment + if (data.favicon) { + const buffer = Buffer.from(data.favicon.split(",")[1], "base64"); + msgData.files = [{ + attachment: buffer, + name: "favicon.png" + }] + msgData.embeds[0].thumbnail = { + url: "attachment://favicon.png" + } + } + interaction.editReply(msgData); + }).catch((err) => { + if (err.toString().startsWith("Error: The client timed out")) { + return interaction.editReply({ content: `${unavailEmote} The server did not respond or is offline.`, ephemeral: true }); + } + if (err.toString().startsWith("Error: Invalid hostname")) { + return interaction.editReply({ content: "Invalid hostname.", ephemeral: true }); + } + console.log(err) + return interaction.editReply({ content: "An error occurred while trying to ping the server.", ephemeral: true }); + }) + break; + } + } + if(interaction.isAutocomplete()) { + // Send their history as options + const history = addressHistory[interaction.user.id] || []; + // Map the history to options + interaction.respond(history.map((address) => { + return { + name: address, + value: address + } + })); } });