// Modules const { customSlashCommandBuilder } = require('../utilities/customSlashCommandBuilder'); const { DebugBuilder } = require("../utilities/debugBuilder"); const { getMembersInRole, getAllClientIds } = require("../utilities/utils"); const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests"); const { getOnlineNodes, updateNodeInfo, addNodeConnection, getConnectionByNodeId } = require("../utilities/mysqlHandler"); // Global Vars const log = new DebugBuilder("server", "join"); /** * * This wrapper will check if there is an available node with the requested preset and if so checks for an available client ID to join with * * @param {*} presetName The preset name to listen to on the client * @param {*} channelId The channel ID to join the bot to * @param {*} clientIdsUsed EITHER A collection of clients that are currently connected OR a single discord client ID (NOT dev portal ID) that should be used to join the server with * @returns */ async function joinServerWrapper(presetName, channelId, clientIdsUsed) { // Get nodes online var onlineNodes = await new Promise((recordResolve, recordReject) => { getOnlineNodes((nodeRows) => { recordResolve(nodeRows); }); }); // Check which nodes have the selected preset onlineNodes = onlineNodes.filter(node => node.nearbySystems.includes(presetName)); log.DEBUG("Filtered Online Nodes: ", onlineNodes); // Check if any nodes with this preset are available var nodesCurrentlyAvailable = []; for (const node of onlineNodes) { const currentConnection = await getConnectionByNodeId(node.id); log.DEBUG("Checking to see if there is a connection for Node: ", node, currentConnection); if(!currentConnection) nodesCurrentlyAvailable.push(node); } log.DEBUG("Nodes Currently Available: ", nodesCurrentlyAvailable); // If not, let the user know if (!nodesCurrentlyAvailable.length > 0) return Error("All nodes with this channel are unavailable, consider swapping one of the currently joined bots."); // If so, join with the first node var availableClientIds = await getAllClientIds(); log.DEBUG("All clients: ", Object.keys(availableClientIds)); var selectedClientId; if (typeof clientIdsUsed === 'string') { for (const availableClientId of availableClientIds) { if (availableClientId.discordId != clientIdsUsed ) selectedClientId = availableClientId; } } else { log.DEBUG("Client IDs Used: ", clientIdsUsed.keys()); for (const usedClientId of clientIdsUsed.keys()) { log.DEBUG("Used Client ID: ", usedClientId); availableClientIds = availableClientIds.filter(cid => cid.discordId != usedClientId); } log.DEBUG("Available Client IDs: ", availableClientIds); if (!Object.keys(availableClientIds).length > 0) return log.ERROR("All client ID have been used, consider swapping one of the curretly joined bots or adding more Client IDs to the pool.") selectedClientId = availableClientIds[0]; } const selectedNode = nodesCurrentlyAvailable[0]; const reqOptions = new requestOptions("/bot/join", "POST", selectedNode.ip, selectedNode.port); const postObject = { "channelId": channelId, "clientId": selectedClientId.clientId, "presetName": presetName }; log.INFO("Post Object: ", postObject); sendHttpRequest(reqOptions, JSON.stringify(postObject), async (responseObj) => { log.VERBOSE("Response Object from node ", selectedNode, responseObj); if (!responseObj || !responseObj.statusCode == 200) return false; // Node has connected to discord // Updating node Object in DB const updatedNode = await updateNodeInfo(selectedNode); log.DEBUG("Updated Node: ", updatedNode); // Adding a new node connection const nodeConnection = await addNodeConnection(selectedNode, selectedClientId); log.DEBUG("Node Connection: ", nodeConnection); }); } exports.joinServerWrapper = joinServerWrapper; module.exports = { data: new customSlashCommandBuilder() .setName('join') .setDescription('Join the channel you are in with the preset you choose') .addAllSystemPresetOptions(), example: "join", isPrivileged: false, requiresTokens: false, defaultTokenUsage: 0, deferInitialReply: true, async execute(interaction) { try{ const guildId = interaction.guild.id; const presetName = interaction.options.getString('preset'); if (!interaction.member.voice.channel.id) return interaction.editReply(`You need to be in a voice channel, ${interaction.user}`) const channelId = interaction.member.voice.channel.id; log.DEBUG(`Join requested by: ${interaction.user.username}, to: '${presetName}', in channel: ${channelId} / ${guildId}`); const onlineBots = await getMembersInRole(interaction); log.DEBUG("Online Bots: ", onlineBots); await joinServerWrapper(presetName, channelId, onlineBots.online); await interaction.editReply('**Pong.**'); //await interaction.channel.send('**Pong.**'); // This will send a message to the channel of the interaction outside of the initial reply }catch(err){ log.ERROR(err) //await interaction.reply(err.toString()); } } }