Implement Discord CnC Server into Emmelia

This commit is contained in:
Logan Cusano
2023-02-24 21:27:55 -05:00
parent 0ee5c4293f
commit 24b16d87ea
19 changed files with 926 additions and 135 deletions

17
utilities/debugBuilder.js Normal file
View File

@@ -0,0 +1,17 @@
// Debug
const debug = require('debug');
/**
* Create the different logging methods for a function
* Namespace template = ("[app]:[fileName]:['INFO', 'WARNING', 'DEBUG', 'ERROR']")
* @param {string} appName The name of the app to be used in the 'app' portion of the namespace
* @param {string} fileName The name of the file calling the builder to be used in the 'fileName' portion of the namespace
*/
exports.DebugBuilder = class DebugBuilder {
constructor(appName, fileName) {
this.INFO = debug(`${appName}:${fileName}:INFO`);
this.DEBUG = debug(`${appName}:${fileName}:DEBUG`);
this.WARN = debug(`${appName}:${fileName}:WARNING`);
this.ERROR = debug(`${appName}:${fileName}:ERROR`);
}
}

68
utilities/httpRequests.js Normal file
View File

@@ -0,0 +1,68 @@
// Debug
const { DebugBuilder } = require("../utilities/debugBuilder.js");
const log = new DebugBuilder("server", "httpRequests");
// Modules
const http = require("http");
exports.requestOptions = class requestOptions {
/**
* Construct an HTTP request
* @param {*} method Method of request to use [GET, POST]
* @param {*} headers Headers of the request, not required but will get filled with default values if not set
* @param {*} hostname The destination of the request
* @param {*} port The port for the destination, will use 3001 by default
*/
constructor(path, method, hostname, port = 3001, headers = undefined, timeout = undefined) {
this.hostname = hostname;
this.path = path;
this.port = port;
this.method = method;
this.timeout = timeout;
if (method === "POST"){
this.headers = headers ?? {
'Content-Type': 'application/json',
}
}
}
}
/**
* Send the HTTP request to the server
* @param requestOptions
* @param data
* @param callback
*/
exports.sendHttpRequest = function sendHttpRequest(requestOptions, data, callback){
log.DEBUG("Sending a request to: ", requestOptions.hostname, requestOptions.port)
// Create the request
const req = http.request(requestOptions, res => {
res.on('data', (data) => {
const responseObject = {
"statusCode": res.statusCode,
"body": data
};
try {
responseObject.body = JSON.parse(responseObject.body)
}
catch (err) {
}
log.DEBUG("Response Object: ", responseObject);
callback(responseObject);
})
}).on('error', err => {
log.ERROR('Error: ', err.message)
// TODO need to handle if the server is down
})
if (requestOptions.timeout) {
req.setTimeout(requestOptions.timeout, () => {
callback(false);
});
}
// Write the data to the request and send it
req.write(data)
req.end()
}

134
utilities/mysqlHandler.js Normal file
View File

@@ -0,0 +1,134 @@
const mysql = require('mysql');
const databaseConfig = require('../config/databaseConfig');
const utils = require('./utils');
const connection = mysql.createConnection({
host: databaseConfig.database_host,
user: databaseConfig.database_user,
password: databaseConfig.database_password,
database: databaseConfig.database_database
});
const nodesTable = `${databaseConfig.database_database}.nodes`;
connection.connect()
/** Get all nodes the server knows about regardless of status
* @param {*} callback Callback function
*/
exports.getAllNodes = (callback) => {
const sqlQuery = `SELECT * FROM ${nodesTable}`
runSQL(sqlQuery, (rows) => {
callback(rows);
})
}
/** Get all nodes that have the online status set true (are online)
* @param callback Callback function
*/
exports.getOnlineNodes = (callback) => {
const sqlQuery = `SELECT * FROM ${nodesTable} WHERE online = 1;`
runSQL(sqlQuery, (rows) => {
callback(rows);
})
}
/** Get info on a node based on ID
* @param nodeId The ID of the node
* @param callback Callback function
*/
exports.getNodeInfoFromId = (nodeId, callback) => {
const sqlQuery = `SELECT * FROM ${nodesTable} WHERE id = ${nodeId}`
runSQL(sqlQuery, (rows) => {
// Call back the first (and theoretically only) row
// Specify 0 so downstream functions don't have to worry about it
callback(rows[0]);
})
}
/** Add a new node to the DB
* @param nodeObject Node information object
* @param callback Callback function
*/
exports.addNewNode = (nodeObject, callback) => {
if (!nodeObject.name) throw new Error("No name provided");
const name = nodeObject.name,
ip = nodeObject.ip,
port = nodeObject.port,
location = nodeObject.location,
nearbySystems = utils.JsonToBuffer(nodeObject.nearbySystems),
online = nodeObject.online;
const sqlQuery = `INSERT INTO ${nodesTable} (name, ip, port, location, nearbySystems, online) VALUES ('${name}', '${ip}', ${port}, '${location}', '${nearbySystems}', ${online})`;
runSQL(sqlQuery, (rows) => {
callback(rows);
})
}
/** Update the known info on a node
* @param nodeObject Node information object
* @param callback Callback function
*/
exports.updateNodeInfo = (nodeObject, callback) => {
const name = nodeObject.name,
ip = nodeObject.ip,
port = nodeObject.port,
location = nodeObject.location,
online = nodeObject.online;
let queryParams = [],
nearbySystems = nodeObject.nearbySystems;
if (name) queryParams.push(`name = '${name}'`);
if (ip) queryParams.push(`ip = '${ip}'`);
if (port) queryParams.push(`port = ${port}`);
if (location) queryParams.push(`location = '${location}'`);
if (nearbySystems) {
nearbySystems = utils.JsonToBuffer(nearbySystems)
queryParams.push(`nearbySystems = '${nearbySystems}'`);
}
if (typeof online === "boolean") {
if (online) queryParams.push(`online = 1`);
else queryParams.push(`online = 0`);
}
let sqlQuery = `UPDATE ${nodesTable} SET`
if (!queryParams || queryParams.length === 0) return callback(undefined);
if (queryParams.length === 1) {
sqlQuery = `${sqlQuery} ${queryParams[0]}`
} else {
let i = 0;
for (const param of queryParams) {
if (i === queryParams.length-1) {
sqlQuery = `${sqlQuery} ${param}`
i += 1;
}
else {
sqlQuery = `${sqlQuery} ${param},`
i += 1;
}
}
}
sqlQuery = `${sqlQuery} WHERE id = ${nodeObject.id};`
runSQL(sqlQuery, (rows) => {
if (rows.affectedRows === 1) callback(true);
else callback(rows);
})
}
// Function to run and handle SQL errors
function runSQL(sqlQuery, callback, error = (err) => {
console.log(err);
throw err;
}) {
connection.query(sqlQuery, (err, rows) => {
if (err) return error(err);
//console.log('The rows are:', rows);
return callback(rows);
})
}
exports.closeConnection = () => {
connection.end()
}

19
utilities/utils.js Normal file
View File

@@ -0,0 +1,19 @@
// Convert a JSON object to a buffer for the DB
exports.JsonToBuffer = (jsonObject) => {
return Buffer.from(JSON.stringify(jsonObject))
}
// Convert a buffer from the DB to JSON object
exports.BufferToJson = (buffer) => {
return JSON.parse(buffer.toString());
}
/** Find a key in an object by its value
*
* @param {*} object The object to search
* @param {*} value The value to search the arrays in the object for
* @returns The key of the object that contains the value
*/
exports.getKeyByArrayValue = (object, value) => {
return Object.keys(object).find(key => object[key].includes(value));
}