375 lines
12 KiB
JavaScript
375 lines
12 KiB
JavaScript
import { DebugBuilder } from "../modules/debugger.mjs";
|
|
const log = new DebugBuilder("server", "socketServerWrappers");
|
|
import {
|
|
createNode,
|
|
getNodeByNuid,
|
|
updateNodeByNuid,
|
|
} from "./mongo-wrappers/mongoNodesWrappers.mjs";
|
|
import {
|
|
createSystem,
|
|
getSystemByName,
|
|
updateSystemByName,
|
|
getSystemsByNuid,
|
|
deleteSystemByName,
|
|
} from "./mongo-wrappers/mongoSystemsWrappers.mjs";
|
|
|
|
/**
|
|
* Description
|
|
* @param {any} socket
|
|
* @param {any} command
|
|
* @param {any} data
|
|
* @returns {any}
|
|
*/
|
|
const sendNodeCommand = async (socket, command, data) => {
|
|
// TODO - Check to see if the command exists
|
|
// TODO - Check to see if the socket is alive?
|
|
// TODO - Validate the given data
|
|
socket.emit(command, data);
|
|
};
|
|
|
|
/**
|
|
* Log the node into the network
|
|
* @param {object} data The data sent from the node
|
|
* @param {any} socket The socket the node is connected from
|
|
* @returns {any}
|
|
*/
|
|
export const nodeLoginWrapper = async (data, socket) => {
|
|
log.INFO(`Login requested from node: ${data.nuid}`, data);
|
|
// Check to see if node exists
|
|
var node = await getNodeByNuid(data.nuid);
|
|
if (!node) {
|
|
const insertedId = await createNode(data);
|
|
log.DEBUG("Added new node to the database:", insertedId);
|
|
} else {
|
|
// Check for updates
|
|
const updatedNode = await updateNodeByNuid(data.nuid, data);
|
|
log.DEBUG("Updated node:", updatedNode);
|
|
}
|
|
|
|
node = await getNodeByNuid(data.nuid);
|
|
|
|
// Add the socket/node connection
|
|
socket.node = node;
|
|
|
|
return;
|
|
};
|
|
|
|
/**
|
|
* Disconnect the client from the server
|
|
* @param {string} socketId The socket ID that was disconnected
|
|
* @returns {any}
|
|
*/
|
|
export const nodeDisconnectWrapper = async (socketId) => {
|
|
// TODO - Let any server know that a bot has disconnected if the bot was joined to vc? might not be worth cpu lol
|
|
return;
|
|
};
|
|
|
|
/**
|
|
* Update node data in the database
|
|
* @param {object} nodeData The data object sent from the node
|
|
* @returns {any}
|
|
*/
|
|
export const nodeUpdateWrapper = async (nodeData) => {
|
|
log.DEBUG("Data update sent by node: ", nodeData);
|
|
const updateResults = await updateNodeByNuid(nodeData.nuid, nodeData);
|
|
return;
|
|
};
|
|
|
|
/**
|
|
* Wrapper to update the systems from the nearbySystems object passed from clients
|
|
* @param {string} nuid The NUID of the node that sent the update
|
|
* @param {object} nearbySystems The nearby systems object passed from the node to be updated
|
|
*/
|
|
export const nearbySystemsUpdateWraper = async (nuid, nearbySystems) => {
|
|
log.DEBUG("System updates sent by node: ", nuid, nearbySystems);
|
|
// Check to see if the node removed any systems
|
|
const existingSystems = await getSystemsByNuid(nuid);
|
|
log.DEBUG("Existing systems:", existingSystems);
|
|
if (existingSystems !== nearbySystems) {
|
|
for (const existingSystem of existingSystems) {
|
|
if (existingSystem.name in nearbySystems) {
|
|
// Skip this system if it's in the given systems update
|
|
continue;
|
|
}
|
|
|
|
log.DEBUG("System exists that was not given by node", existingSystem);
|
|
// Check if this node was the only node on this system
|
|
if (existingSystem.nodes.filter((node) => node !== nuid).length === 0) {
|
|
// Remove the system if so
|
|
log.INFO(
|
|
"Given node was the only node on this system, removing the system...",
|
|
);
|
|
await deleteSystemByName(existingSystem.name);
|
|
} else {
|
|
// Remove the node from the array if there are other nodes with this system
|
|
log.INFO("Other nodes found on this system, removing the given NUID");
|
|
existingSystem.nodes = existingSystem.nodes.filter(
|
|
(node) => node !== nuid,
|
|
);
|
|
log.DEBUG(existingSystem);
|
|
await updateSystemByName(existingSystem.name, existingSystem);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add and update the given systems
|
|
for (const nearbySystem in nearbySystems) {
|
|
// Check if the system exists already on another node
|
|
const existingSystem = await getSystemByName(nearbySystem);
|
|
if (existingSystem) {
|
|
// Verify the frequencies match (to make sure the name isn't just the same)
|
|
if (
|
|
JSON.stringify(existingSystem.frequencies) ===
|
|
JSON.stringify(nearbySystems[nearbySystem].frequencies)
|
|
) {
|
|
// The systems are the same
|
|
|
|
// Check if the current node is listed in the nodes, if not add it
|
|
if (!existingSystem.nodes.includes(nuid)) {
|
|
existingSystem.nodes.push(nuid);
|
|
// Update the system with the added node
|
|
const updateResults = await updateSystemByName(
|
|
nearbySystem,
|
|
existingSystem,
|
|
);
|
|
if (updateResults) log.INFO("System updated", nearbySystem);
|
|
}
|
|
} else {
|
|
// The systems are not the same
|
|
// TODO - Implement logic to handle if system names match, but they are for different frequencies or have additional freqs
|
|
|
|
// Check if the current node is listed in the nodes, if not add it
|
|
if (!existingSystem.nodes.includes(nuid)) {
|
|
existingSystem.nodes.push(nuid);
|
|
nearbySystems[nearbySystem].nodes = existingSystem.nodes;
|
|
}
|
|
|
|
// Update the system with the added node
|
|
const updateResults = await updateSystemByName(
|
|
nearbySystem,
|
|
nearbySystems[nearbySystem],
|
|
);
|
|
if (updateResults) log.INFO("System updated", nearbySystem);
|
|
}
|
|
} else {
|
|
// Create a new system
|
|
const newSystem = await createSystem(
|
|
nearbySystem,
|
|
nearbySystems[nearbySystem],
|
|
nuid,
|
|
);
|
|
log.INFO("New system created", nearbySystem, newSystem);
|
|
}
|
|
}
|
|
return;
|
|
};
|
|
|
|
/**
|
|
* Get the open socket connection ID for a node from the NUID
|
|
* @param {string} nuid The NUID to find within the open sockets
|
|
* @returns {string|null} Will return the open socket ID or NULL
|
|
*/
|
|
export const getSocketIdByNuid = async (nodeIo, nuid) => {
|
|
const openSockets = await nodeIo.allSockets();
|
|
for (const openSocketId of openSockets) {
|
|
log.DEBUG(openSockets);
|
|
const openSocket = await nodeIo.sockets.sockets.get(openSocketId);
|
|
if (openSocket.node.nuid == nuid) return openSocket;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Get all nodes that are connected to a voice channel
|
|
* @param {any} nodeIo The nodeIo object that contains the IO server
|
|
* @param {string} guildId The guild ID string for the guild we are looking in
|
|
* @returns {Array} The sockets connected to VC in a given server
|
|
*/
|
|
export const getAllSocketsConnectedToVC = async (nodeIo, guildId) => {
|
|
// Get all open socket nodes
|
|
// TODO - require a server guild to filter the results, ie this would be able to check what server the VCs the nodes are connected are in
|
|
const openSockets = [...(await nodeIo.allSockets())]; // TODO - Filter the returned nodes to only nodes that have the radio capability
|
|
// Check each open socket to see if the node has the requested system
|
|
const socketsConnectedToVC = [];
|
|
await Promise.all(
|
|
openSockets.map(async (openSocket) => {
|
|
openSocket = await nodeIo.sockets.sockets.get(openSocket);
|
|
await new Promise((res) => {
|
|
openSocket.emit("node-check-connected-status", guildId, (status) => {
|
|
if (status) {
|
|
log.INFO(
|
|
"Socket is connected to VC:",
|
|
openSocket.node.name,
|
|
status,
|
|
);
|
|
socketsConnectedToVC.push(openSocket);
|
|
} else {
|
|
log.INFO("Socket is NOT connected to VC:", openSocket.node.name);
|
|
}
|
|
res();
|
|
});
|
|
});
|
|
}),
|
|
);
|
|
|
|
return socketsConnectedToVC;
|
|
};
|
|
|
|
/**
|
|
* Check if the given node has an open discord client
|
|
* @param {any} openSocket The open socket connection with the node to check
|
|
* @returns {boolean} If the given node has an open discord client or not
|
|
*/
|
|
export const checkIfNodeHasOpenDiscordClient = async (openSocket) => {
|
|
// Check the open socket to see if the node has an open discord client
|
|
let hasOpenDiscordClient = false;
|
|
await new Promise((res) => {
|
|
log.INFO(
|
|
"Checking if socket has an open connection:",
|
|
openSocket.node.name,
|
|
);
|
|
openSocket.emit("node-check-discord-open-client", (status) => {
|
|
if (status) {
|
|
log.INFO(
|
|
"Socket has an open discord client:",
|
|
openSocket.node.name,
|
|
status,
|
|
);
|
|
hasOpenDiscordClient = true;
|
|
} else {
|
|
log.INFO(
|
|
"Socket does NOT have an open discord client:",
|
|
openSocket.node.name,
|
|
);
|
|
}
|
|
res();
|
|
});
|
|
});
|
|
|
|
return hasOpenDiscordClient;
|
|
};
|
|
|
|
export const getNodeCurrentListeningSystem = async (openSocket) => {
|
|
const hasOpenClient = checkIfNodeHasOpenDiscordClient(openSocket);
|
|
if (!hasOpenClient) return undefined;
|
|
|
|
// check what system the socket is listening to
|
|
let currentSystem = undefined;
|
|
await new Promise((res) => {
|
|
log.INFO(
|
|
"Checking system node is currently listening to:",
|
|
openSocket.node.name,
|
|
);
|
|
openSocket.emit("node-check-current-system", (system) => {
|
|
if (system) {
|
|
log.INFO(
|
|
"Socket is listening to system:",
|
|
openSocket.node.name,
|
|
system,
|
|
);
|
|
currentSystem = system;
|
|
} else {
|
|
log.INFO(
|
|
"Socket is not currently listening to a system:",
|
|
openSocket.node.name,
|
|
);
|
|
}
|
|
res();
|
|
});
|
|
});
|
|
|
|
return currentSystem;
|
|
};
|
|
|
|
/**
|
|
* Wrapper to check if the given NUID is connected to a VC
|
|
* @param {any} nodeIo The nodeIo object that contains the IO server
|
|
* @param {string} nuid The NUID string that we would like to find in the open socket connections
|
|
* @returns {boolean} If the node is connected to VC in the given server
|
|
*/
|
|
export const checkIfNodeIsConnectedToVC = async (nodeIo, guildId, nuid) => {
|
|
const socketsConnectedToVC = await getAllSocketsConnectedToVC(
|
|
nodeIo,
|
|
guildId,
|
|
);
|
|
for (const socket of socketsConnectedToVC) {
|
|
if (socket.node.nuid === nuid) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Get the discord username from a given socket
|
|
* @param {any} socket The socket object of the node to check the username of
|
|
* * @param {string} guildId The guild ID to check the username in
|
|
* @returns {string} The username of the bot in the requested server
|
|
*/
|
|
export const getNodeDiscordUsername = async (socket, guildId) => {
|
|
return await new Promise((res) => {
|
|
socket.emit("node-get-discord-username", guildId, (username) => {
|
|
res(username);
|
|
});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Get the discord ID from a given socket
|
|
* @param {any} socket The socket object of the node to check the ID of
|
|
* @returns {string} The ID of the bot
|
|
*/
|
|
export const getNodeDiscordID = async (socket) => {
|
|
return await new Promise((res) => {
|
|
socket.emit("node-get-discord-id", (discordID) => {
|
|
res(discordID);
|
|
});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Request a given socket node to join a given voice channel
|
|
* @param {any} socket The socket object of the node the request should be sent to
|
|
* @param {any} systemName The system preset name that we would like to listen to
|
|
* @param {string} discordChanelId The Discord channel ID to join the listening bot to
|
|
*/
|
|
export const requestNodeJoinSystem = async (
|
|
socket,
|
|
systemName,
|
|
discordChanelId,
|
|
discordToken = "MTE5NjAwNTM2ODYzNjExMjk3Nw.GuCMXg.24iNNofNNumq46FIj68zMe9RmQgugAgfrvelEA",
|
|
) => {
|
|
// Join the system
|
|
const joinData = {
|
|
clientID: discordToken,
|
|
channelID: discordChanelId,
|
|
system: systemName,
|
|
};
|
|
// Send the command to the node
|
|
await sendNodeCommand(socket, "node-join", joinData);
|
|
};
|
|
|
|
/**
|
|
* Request a given socket node to leave VC in a given server
|
|
* @param {any} socket The socket object of the node the request should be sent to
|
|
* @param {string} guildId The guild ID to disconnect the socket node from
|
|
*/
|
|
export const requestBotLeaveServer = async (socket, guildId) => {
|
|
// Send the command to the node
|
|
await sendNodeCommand(socket, "node-leave", guildId);
|
|
};
|
|
|
|
/**
|
|
* Requset a given socket node to update themselves
|
|
* @param {any} socket The socket object of the node to request to update
|
|
*/
|
|
export const requestNodeUpdate = async (socket) => {
|
|
await sendNodeCommand(socket, "node-update", (status) => {
|
|
if (status) {
|
|
log.INFO("Node is out of date, updating now", socket.node.name);
|
|
} else {
|
|
log.INFO("Node is up to date", socket.node.name);
|
|
}
|
|
});
|
|
};
|