Major updates to core
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { generateUniqueID } from './modules/baseUtils.mjs';
|
||||
import { updateId } from './modules/updateConfig.mjs';
|
||||
import { ClientNodeConfig } from './modules/clientObjectDefinitions.mjs';
|
||||
import { initSocketConnection, initSocketListeners, sendNodeUpdate } from './modules/socketClient.mjs';
|
||||
import { initSocketConnection } from './modules/socketClient.mjs';
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
@@ -9,7 +9,7 @@ dotenv.config()
|
||||
var localNodeConfig = new ClientNodeConfig({})
|
||||
|
||||
async function boot() {
|
||||
if (localNodeConfig.node.id === undefined || localNodeConfig.node.id === '' || localNodeConfig.node.id === 0) {
|
||||
if (localNodeConfig.node.nuid === undefined || localNodeConfig.node.nuid === '' || localNodeConfig.node.nuid === 0) {
|
||||
// Run the first time boot sequence
|
||||
await firstTimeBoot();
|
||||
}
|
||||
@@ -25,10 +25,10 @@ async function boot() {
|
||||
async function firstTimeBoot() {
|
||||
// Generate a new ID for the node
|
||||
localNodeConfig.node.id = generateUniqueID();
|
||||
console.log(`Generated a new unique ID for this node: '${localNodeConfig.node.id}'`);
|
||||
console.log(`Generated a new unique ID for this node: '${localNodeConfig.node.nuid}'`);
|
||||
|
||||
// Update the config with the new ID
|
||||
updateId(localNodeConfig.node.id);
|
||||
updateId(localNodeConfig.node.nuid);
|
||||
console.log("Updated the config with the new node ID");
|
||||
// TODO - Create the config file with the ID given and replace the update above
|
||||
// TODO - Check if the system is linux or windows and set the 'type' param in DAB
|
||||
@@ -41,7 +41,5 @@ async function firstTimeBoot() {
|
||||
|
||||
// Boot the client application
|
||||
boot().then((openSocket) => {
|
||||
initSocketListeners(openSocket, localNodeConfig);
|
||||
//console.log(openSocket, "Open socket");
|
||||
setTimeout(() => {sendNodeUpdate(openSocket);}, 2500);
|
||||
console.log(openSocket, "Booted Sucessfully");
|
||||
})
|
||||
@@ -78,6 +78,7 @@ export async function connectToChannel(channel) {
|
||||
});
|
||||
try {
|
||||
await entersState(connection, VoiceConnectionStatus.Ready, 30_000);
|
||||
await connection.subscribe(player);
|
||||
return connection;
|
||||
} catch (error) {
|
||||
connection.destroy();
|
||||
@@ -100,6 +101,8 @@ export async function initDiscordBotClient(token, readyCallback){
|
||||
readyCallback(client);
|
||||
});
|
||||
|
||||
/* on event create
|
||||
// TODO - Implement methods for discord users to interact directly with the bots for realtime info (last talked ID/TG, etc.)
|
||||
client.on(Events.MessageCreate, async (message) => {
|
||||
if (!message.guild) return;
|
||||
console.log(`New Message:`, message.content);
|
||||
@@ -118,6 +121,7 @@ export async function initDiscordBotClient(token, readyCallback){
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
client.login(token);
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { networkInterfaces } from 'os';
|
||||
import { createHash, randomBytes } from 'crypto';
|
||||
import { promises, constants } from 'fs';
|
||||
import { dirname } from "path";
|
||||
|
||||
/**
|
||||
* Check to see if the input is a valid JSON string
|
||||
@@ -7,7 +9,7 @@ import { createHash, randomBytes } from 'crypto';
|
||||
* @param {*} str The string to check for valud JSON
|
||||
* @returns {true|false}
|
||||
*/
|
||||
export function isJsonString (str) {
|
||||
export const isJsonString = (str) => {
|
||||
try {
|
||||
JSON.parse(str);
|
||||
} catch (e) {
|
||||
@@ -16,12 +18,25 @@ export function isJsonString (str) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a path exists, creating it if it does not
|
||||
* @returns {undefined}
|
||||
*/
|
||||
export const ensureDirectoryExists = async (filePath) => {
|
||||
const directory = dirname(filePath);
|
||||
try {
|
||||
await promises.access(directory, constants.F_OK);
|
||||
} catch (error) {
|
||||
await promises.mkdir(directory, { recursive: true });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generate a unique ID for a given device, this will also be unique on the same device at a different time.
|
||||
* @returns {string} A generated unique ID
|
||||
*/
|
||||
export function generateUniqueID () {
|
||||
export const generateUniqueID = () => {
|
||||
const netInterfaces = networkInterfaces();
|
||||
let macAddress = '';
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { getAllPresets } from "./radioPresetHandler.mjs";
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
|
||||
@@ -7,33 +9,43 @@ dotenv.config()
|
||||
export class ClientNodeObject {
|
||||
/**
|
||||
*
|
||||
* @param {string} param0._id The ID of the node (Assigned by the client on first boot)
|
||||
* @param {string} param0._nuid The ID of the node (Assigned by the client on first boot)
|
||||
* @param {string} param0._name The name of the node (Assigned by the user)
|
||||
* @param {string} param0._location The physical location of the node (Assigned by the user)
|
||||
* @param {object} param0._nearbySystems An object array of nearby systems (Assigned by the user)
|
||||
* @param {string} param0._location The physical location of the node (Assigned by the user)
|
||||
* @param {object} param0._capabilities The capabilities of this node (Assigned by the user, and determined by the hardware)
|
||||
*/
|
||||
constructor({ _id = undefined, _name = undefined, _location = undefined, _nearbySystems = undefined}) {
|
||||
this.id = _id;
|
||||
constructor({ _nuid = undefined, _name = undefined, _location = undefined, _capabilities = undefined }) {
|
||||
this.nuid = _nuid;
|
||||
this.name = _name;
|
||||
this.location = _location;
|
||||
this.nearbySystems = _nearbySystems;
|
||||
this.location = _location;
|
||||
this.capabilities = _capabilities
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** The configuration object for the node */
|
||||
export class ClientNodeConfig {
|
||||
/**
|
||||
*
|
||||
* @param {string} param0._nuid The ID of the node (Assigned by the client on first boot)
|
||||
* @param {string} param0._name The name of the node (Assigned by the user)
|
||||
* @param {string} param0._location The physical location of the node (Assigned by the user)
|
||||
* @param {object} param0._nearbySystems An object array of nearby systems (Assigned by the user)
|
||||
* @param {object} param0._capabilities The capabilities of this node (Assigned by the user, and determined by the hardware)
|
||||
*/
|
||||
constructor({
|
||||
_id = process.env.CLIENT_ID,
|
||||
_name = process.env.CLIENT_NAME,
|
||||
_location = process.env.CLIENT_LOCATION,
|
||||
_nearbySystems = undefined, // TODO - Get the presets when loading the config instead of having to do it after the fact
|
||||
_serverIp = process.env.SERVER_IP,
|
||||
_serverPort = process.env.SERVER_PORT,
|
||||
_nuid = process.env.CLIENT_NUID,
|
||||
_name = process.env.CLIENT_NAME,
|
||||
_location = process.env.CLIENT_LOCATION,
|
||||
_nearbySystems = getAllPresets(),
|
||||
_capabilities = process.env.CLIENT_CAPABILITIES.split(", "),
|
||||
_serverIp = process.env.SERVER_IP,
|
||||
_serverPort = process.env.SERVER_PORT,
|
||||
}) {
|
||||
this.node = new ClientNodeObject({
|
||||
_id:_id, _name:_name, _location:_location, _nearbySystems:_nearbySystems
|
||||
_nuid: _nuid, _name: _name, _location: _location, _capabilities: _capabilities
|
||||
});
|
||||
this.nearbySystems = _nearbySystems;
|
||||
this.serverIp = _serverIp;
|
||||
this.serverPort = _serverPort;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
// Debug
|
||||
const { DebugBuilder } = require("../utilities/debugBuilder.js");
|
||||
const log = new DebugBuilder("client", "updatePresets");
|
||||
// Modules
|
||||
const fs = require('fs');
|
||||
const path = require("path");
|
||||
const converter = require("convert-units");
|
||||
import { writeFile, existsSync, readFileSync } from 'fs';
|
||||
import { resolve } from "path";
|
||||
import { ensureDirectoryExists } from "./baseUtils.mjs";
|
||||
import convert_units from "convert-units";
|
||||
const { converter } = convert_units;
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
|
||||
const configFilePath = process.env.CONFIG_PATH;
|
||||
|
||||
/**
|
||||
* Write the given presets to the JSON file
|
||||
* @param presets The preset or presets to be written
|
||||
* @param {function} callback The function to be called when this wrapper completes
|
||||
*/
|
||||
function writePresets(presets, callback = undefined) {
|
||||
log.DEBUG(`${__dirname}`);
|
||||
fs.writeFile("./config/radioPresets.json", JSON.stringify(presets), (err) => {
|
||||
const writePresets = async (presets, callback = undefined) => {
|
||||
console.log(`${__dirname}`);
|
||||
await ensureDirectoryExists(configFilePath);
|
||||
writeFile(configFilePath, JSON.stringify(presets), (err) => {
|
||||
// Error checking
|
||||
if (err) throw err;
|
||||
log.DEBUG("Write Complete");
|
||||
console.log("Write Complete");
|
||||
if (callback) callback(); else return
|
||||
});
|
||||
}
|
||||
@@ -26,14 +31,14 @@ function writePresets(presets, callback = undefined) {
|
||||
* @param frequenciesArray
|
||||
* @returns {*[]}
|
||||
*/
|
||||
function sanitizeFrequencies(frequenciesArray) {
|
||||
const sanitizeFrequencies = async (frequenciesArray) => {
|
||||
let sanitizedFrequencyArray = [];
|
||||
|
||||
for (const freq of frequenciesArray) {
|
||||
sanitizedFrequencyArray.push(convertFrequencyToHertz(freq));
|
||||
}
|
||||
|
||||
log.DEBUG("Sanitized Frequency Array", sanitizedFrequencyArray);
|
||||
console.log("Sanitized Frequency Array", sanitizedFrequencyArray);
|
||||
return sanitizedFrequencyArray;
|
||||
}
|
||||
|
||||
@@ -42,23 +47,23 @@ function sanitizeFrequencies(frequenciesArray) {
|
||||
* @param frequency Could be a string, number or float,
|
||||
* @returns {number|number|*} Return the value to be saved in Hz format ("154.875"MHz format = "154875000")
|
||||
*/
|
||||
function convertFrequencyToHertz(frequency){
|
||||
const convertFrequencyToHertz = async (frequency) => {
|
||||
// check if the passed value is a number
|
||||
if(typeof frequency == 'number' && !isNaN(frequency)){
|
||||
if (typeof frequency == 'number' && !isNaN(frequency)) {
|
||||
if (Number.isInteger(frequency)) {
|
||||
log.DEBUG(`${frequency} is an integer.`);
|
||||
console.log(`${frequency} is an integer.`);
|
||||
// Check to see if the frequency has the correct length
|
||||
if (frequency >= 1000000) return frequency
|
||||
if (frequency >= 100 && frequency <= 999) return frequency * 1000000
|
||||
log.WARN("Frequency hasn't matched filters: ", frequency);
|
||||
console.log("Frequency hasn't matched filters: ", frequency);
|
||||
}
|
||||
else {
|
||||
log.DEBUG(`${frequency} is a float value.`);
|
||||
console.log(`${frequency} is a float value.`);
|
||||
// Convert to a string to remove the decimal in place and then correct the length
|
||||
return parseInt(converter(frequency).from("MHz").to("Hz"));
|
||||
}
|
||||
} else {
|
||||
log.DEBUG(`${frequency} is not a number`);
|
||||
console.log(`${frequency} is not a number`);
|
||||
frequency = convertFrequencyToHertz(parseFloat(frequency));
|
||||
|
||||
return parseInt(frequency)
|
||||
@@ -69,10 +74,10 @@ function convertFrequencyToHertz(frequency){
|
||||
* Gets the saved presets and returns a preset object
|
||||
* @returns {any} The object containing the different systems the bot is near
|
||||
*/
|
||||
function getPresets() {
|
||||
const presetDir = path.resolve("./config/radioPresets.json");
|
||||
log.DEBUG(`Getting presets from directory: '${presetDir}'`);
|
||||
if (fs.existsSync(presetDir)) return JSON.parse(fs.readFileSync(presetDir));
|
||||
export const getAllPresets = () => {
|
||||
const presetDir = resolve(configFilePath);
|
||||
console.log(`Getting presets from directory: '${presetDir}'`);
|
||||
if (existsSync(presetDir)) return JSON.parse(readFileSync(presetDir));
|
||||
else return {};
|
||||
}
|
||||
|
||||
@@ -86,15 +91,15 @@ function getPresets() {
|
||||
* @param {string} trunkFile The file that contains all trunking information (if applicable to the selected listening mode)
|
||||
* @param {string} whitelistFile The file that contains the whitelisted talkgroups [optional]
|
||||
*/
|
||||
function addNewPreset(systemName, frequencies, mode, callback, trunkFile = undefined, whitelistFile = undefined) {
|
||||
export const addNewPreset = (systemName, frequencies, mode, callback, trunkFile = undefined, whitelistFile = undefined) => {
|
||||
const presets = this.getPresets();
|
||||
// Create the preset for the new system
|
||||
presets[systemName] = {
|
||||
"frequencies": sanitizeFrequencies(frequencies),
|
||||
"mode": mode,
|
||||
"trunkFile": trunkFile ?? "none",
|
||||
"whitelistFile": whitelistFile ?? "none"
|
||||
}
|
||||
"frequencies": sanitizeFrequencies(frequencies),
|
||||
"mode": mode,
|
||||
"trunkFile": trunkFile ?? "none",
|
||||
"whitelistFile": whitelistFile ?? "none"
|
||||
}
|
||||
// Write the changes to the preset config file
|
||||
writePresets(presets, callback);
|
||||
}
|
||||
@@ -109,15 +114,15 @@ function addNewPreset(systemName, frequencies, mode, callback, trunkFile = undef
|
||||
* @param {string} trunkFile The file that contains all trunking information (if applicable to the selected listening mode)
|
||||
* @param {string} whitelistFile The file that contains the whitelisted talkgroups [optional]
|
||||
*/
|
||||
function updatePreset(systemName, callback, { frequencies = undefined, mode = undefined, trunkFile = undefined, whitelistFile = undefined }) {
|
||||
export const updatePreset = (systemName, callback, { frequencies = undefined, mode = undefined, trunkFile = undefined, whitelistFile = undefined }) => {
|
||||
const presets = this.getPresets();
|
||||
// Check if a system name was passed
|
||||
if (systemName in presets) {
|
||||
// System name exists, checking to see if the keys are different
|
||||
if(frequencies && sanitizeFrequencies(frequencies) !== presets[systemName].frequencies) presets[systemName].frequencies = sanitizeFrequencies(frequencies);
|
||||
if(mode && mode !== presets[systemName].mode) presets[systemName].mode = mode;
|
||||
if(trunkFile && trunkFile !== presets[systemName].trunkFile || trunkFile === "") presets[systemName].trunkFile = trunkFile ?? "none";
|
||||
if(whitelistFile && whitelistFile !== presets[systemName].whitelistFile || whitelistFile === "") presets[systemName].whitelistFile = whitelistFile ?? "none";
|
||||
if (frequencies && sanitizeFrequencies(frequencies) !== presets[systemName].frequencies) presets[systemName].frequencies = sanitizeFrequencies(frequencies);
|
||||
if (mode && mode !== presets[systemName].mode) presets[systemName].mode = mode;
|
||||
if (trunkFile && trunkFile !== presets[systemName].trunkFile || trunkFile === "") presets[systemName].trunkFile = trunkFile ?? "none";
|
||||
if (whitelistFile && whitelistFile !== presets[systemName].whitelistFile || whitelistFile === "") presets[systemName].whitelistFile = whitelistFile ?? "none";
|
||||
// Write the changes
|
||||
writePresets(presets, callback);
|
||||
}
|
||||
@@ -129,14 +134,11 @@ function updatePreset(systemName, callback, { frequencies = undefined, mode = un
|
||||
* @param {string} systemName The name of the system being modified
|
||||
* @param {function} callback The callback function to be called when the function completes
|
||||
*/
|
||||
function removePreset(systemName, callback) {
|
||||
export const removePreset = (systemName, callback) => {
|
||||
const presets = this.getPresets();
|
||||
// Check if a system name was passed
|
||||
if (systemName in presets) {
|
||||
delete presets[systemName];
|
||||
writePresets(presets, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,34 +1,28 @@
|
||||
import { io } from "socket.io-client";
|
||||
import { connectToChannel, initDiscordBotClient, getVoiceChannelFromID } from '../discordAudioBot/dab.mjs';
|
||||
import { logIntoServerWrapper, sendNodeUpdateWrapper } from "./socketClientWrappers.mjs";
|
||||
|
||||
export function initSocketConnection(localNodeConfig) {
|
||||
export const initSocketConnection = async (localNodeConfig) => {
|
||||
const serverEndpoint = `http://${localNodeConfig.serverIp}:${localNodeConfig.serverPort}` || 'http://localhost:3000'; // Adjust the server endpoint
|
||||
|
||||
const socket = io.connect(serverEndpoint);
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
export function initSocketListeners(socket, localNodeConfig) {
|
||||
socket.on('connect', () => {
|
||||
socket.on('connect', async () => {
|
||||
console.log('Connected to the server');
|
||||
logIntoServer(socket, localNodeConfig.node);
|
||||
await logIntoServerWrapper(socket, localNodeConfig);
|
||||
});
|
||||
|
||||
socket.on('node-join', async (joinData) => {
|
||||
console.log("Join requested: ", joinData)
|
||||
// TODO - Implement logic to control OP25 for the requested channel
|
||||
// TODO - Implement logic to control OP25 for the requested channel/system
|
||||
|
||||
// Join the requested channel with the requested ID
|
||||
initDiscordBotClient(joinData.clientID, client => {
|
||||
console.log("Client:", client);
|
||||
initDiscordBotClient(joinData.clientID, client => {
|
||||
getVoiceChannelFromID(client, joinData.channelID).then(vc => {
|
||||
console.log("Voice Channel:", vc);
|
||||
console.log("Voice Channel Guild:", vc.Guild);
|
||||
const connection = connectToChannel(vc);
|
||||
console.log("Bot Connected to VC");
|
||||
})
|
||||
});
|
||||
console.log("All done?");
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('node-leave', () => {
|
||||
@@ -39,12 +33,5 @@ export function initSocketListeners(socket, localNodeConfig) {
|
||||
console.log('Disconnected from the server');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export function logIntoServer(socket, nodeData) {
|
||||
socket.emit("node-login", nodeData);
|
||||
}
|
||||
|
||||
export function sendNodeUpdate(socket, nodeData) {
|
||||
socket.emit('node-update', nodeData);
|
||||
return socket;
|
||||
}
|
||||
11
client/modules/socketClientWrappers.mjs
Normal file
11
client/modules/socketClientWrappers.mjs
Normal file
@@ -0,0 +1,11 @@
|
||||
export const logIntoServerWrapper = async (socket, localNodeConfig) => {
|
||||
socket.emit("node-login", localNodeConfig.node);
|
||||
sendNodeUpdateWrapper(socket, localNodeConfig);
|
||||
}
|
||||
|
||||
export const sendNodeUpdateWrapper = async (socket, localNodeConfig) => {
|
||||
socket.emit('node-update', {
|
||||
'node': localNodeConfig.node,
|
||||
'nearbySystems': localNodeConfig.nearbySystems
|
||||
});
|
||||
}
|
||||
@@ -17,8 +17,8 @@ class Options {
|
||||
* @param updatedId The updated ID assigned to the node
|
||||
*/
|
||||
export function updateId (updatedId) {
|
||||
updateConfig('CLIENT_ID', updatedId);
|
||||
process.env.CLIENT_ID = updatedId;
|
||||
updateConfig('CLIENT_NUID', updatedId);
|
||||
process.env.CLIENT_NUID = updatedId;
|
||||
console.log("Updated ID to: ", updatedId);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export function updateClientConfig (runningConfig, newConfigObject) {
|
||||
if (configKeys.includes("id")) {
|
||||
if (runningConfig.id != newConfigObject.id) {
|
||||
this.updateId(newConfigObject.id);
|
||||
updatedKeys.push({ 'CLIENT_ID': newConfigObject.id });
|
||||
updatedKeys.push({ 'CLIENT_NUID': newConfigObject.id });
|
||||
}
|
||||
}
|
||||
if (configKeys.includes("name")) {
|
||||
|
||||
164
client/package-lock.json
generated
164
client/package-lock.json
generated
@@ -10,6 +10,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@discordjs/voice": "^0.16.1",
|
||||
"convert-units": "^2.3.4",
|
||||
"discord.js": "^14.14.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"libsodium-wrappers": "^0.7.13",
|
||||
@@ -321,6 +322,15 @@
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/convert-units": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/convert-units/-/convert-units-2.3.4.tgz",
|
||||
"integrity": "sha512-ERHfdA0UhHJp1IpwE6PnFJx8LqG7B1ZjJ20UvVCmopEnVCfER68Tbe3kvN63dLbYXDA2xFWRE6zd4Wsf0w7POg==",
|
||||
"dependencies": {
|
||||
"lodash.foreach": "2.3.x",
|
||||
"lodash.keys": "2.3.x"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -522,11 +532,165 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash._basebind": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.3.0.tgz",
|
||||
"integrity": "sha512-SHqM7YCuJ+BeGTs7lqpWnmdHEeF4MWxS3dksJctHFNxR81FXPOzA4bS5Vs5CpcGTkBpM8FCl+YEbQEblRw8ABg==",
|
||||
"dependencies": {
|
||||
"lodash._basecreate": "~2.3.0",
|
||||
"lodash._setbinddata": "~2.3.0",
|
||||
"lodash.isobject": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash._basecreate": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.3.0.tgz",
|
||||
"integrity": "sha512-vwZaWldZwS2y9b99D8i9+WtgiZXbHKsBsMrpxJEqTsNW20NhJo5W8PBQkeQO9CmxuqEYn8UkMnfEM2MMT4cVrw==",
|
||||
"dependencies": {
|
||||
"lodash._renative": "~2.3.0",
|
||||
"lodash.isobject": "~2.3.0",
|
||||
"lodash.noop": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash._basecreatecallback": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.3.0.tgz",
|
||||
"integrity": "sha512-Ev+pDzzfVfgbiucpXijconLGRBar7/+KNCf05kSnk4CmdDVhAy1RdbU9efCJ/o9GXI08JdUGwZ+5QJ3QX3kj0g==",
|
||||
"dependencies": {
|
||||
"lodash._setbinddata": "~2.3.0",
|
||||
"lodash.bind": "~2.3.0",
|
||||
"lodash.identity": "~2.3.0",
|
||||
"lodash.support": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash._basecreatewrapper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.3.0.tgz",
|
||||
"integrity": "sha512-YLycQ7k8AB9Wc1EOvLNxuRWcqipDkMXq2GCgnLWQR6qtgTb3gY3LELzEpnFshrEO4LOLs+R2EpcY+uCOZaLQ8Q==",
|
||||
"dependencies": {
|
||||
"lodash._basecreate": "~2.3.0",
|
||||
"lodash._setbinddata": "~2.3.0",
|
||||
"lodash._slice": "~2.3.0",
|
||||
"lodash.isobject": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash._createwrapper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.3.0.tgz",
|
||||
"integrity": "sha512-XjaI/rzg9W+WO4WJDQ+PRlHD5sAMJ1RhJLuT65cBxLCb1kIYs4U20jqvTDGAWyVT3c34GYiLd9AreHYuB/8yJA==",
|
||||
"dependencies": {
|
||||
"lodash._basebind": "~2.3.0",
|
||||
"lodash._basecreatewrapper": "~2.3.0",
|
||||
"lodash.isfunction": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash._objecttypes": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.3.0.tgz",
|
||||
"integrity": "sha512-jbA6QyHt9cw3BzvbWzIcnU3Z12jSneT6xBgz3Y782CJsN1tV5aTBKrFo2B4AkeHBNaxSrbPYZZpi1Lwj3xjdtg=="
|
||||
},
|
||||
"node_modules/lodash._renative": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._renative/-/lodash._renative-2.3.0.tgz",
|
||||
"integrity": "sha512-v44MRirqYqZGK/h5UKoVqXWF2L+LUiLTU+Ogu5rHRVWJUA1uWIlHaMpG8f/OA8j++BzPMQij9+erXHtgFcbuwg=="
|
||||
},
|
||||
"node_modules/lodash._setbinddata": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.3.0.tgz",
|
||||
"integrity": "sha512-xMFfbF7dL+sFtrdE49uHFmfpBAEwlFtfgMp86nQRlAF6aizYL+3MTbnYMKJSkP1W501PhsgiBED5kBbZd8kR2g==",
|
||||
"dependencies": {
|
||||
"lodash._renative": "~2.3.0",
|
||||
"lodash.noop": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash._shimkeys": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.3.0.tgz",
|
||||
"integrity": "sha512-9Iuyi7TiWMGa/9+2rqEE+Zwye4b/U2w7Saw6UX1h6Xs88mEER+uz9FZcEBPKMVKsad9Pw5GNAcIBRnW2jNpneQ==",
|
||||
"dependencies": {
|
||||
"lodash._objecttypes": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash._slice": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.3.0.tgz",
|
||||
"integrity": "sha512-7C61GhzRUv36gTafr+RIb+AomCAYsSATEoK4OP0VkNBcwvsM022Z22AVgqjjzikeNO1U29LzsJZDvLbiNPUYvA=="
|
||||
},
|
||||
"node_modules/lodash.bind": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.3.0.tgz",
|
||||
"integrity": "sha512-goakyOo+FMN8lttMPnZ0UNlr5RlzX4IrUXyTJPT2A0tGCMXySupond9wzvDqTvVmYTcQjIKGrj8naJDS2xWAlQ==",
|
||||
"dependencies": {
|
||||
"lodash._createwrapper": "~2.3.0",
|
||||
"lodash._renative": "~2.3.0",
|
||||
"lodash._slice": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.foreach": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-2.3.0.tgz",
|
||||
"integrity": "sha512-yLnyptVRJd0//AbGp480grgQG9iaDIV5uOgSbpurRy1dYybPbjNTLQ3FyLEQ84buVLPG7jyaiyvpzgfOutRB3Q==",
|
||||
"dependencies": {
|
||||
"lodash._basecreatecallback": "~2.3.0",
|
||||
"lodash.forown": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.forown": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.forown/-/lodash.forown-2.3.0.tgz",
|
||||
"integrity": "sha512-dUnCsuQTtq3Y7bxPNoEEqjJjPL2ftLtcz2PTeRKvhbpdM514AvnqCjewHGsm/W+dwspIwa14KoWEZeizJ7smxA==",
|
||||
"dependencies": {
|
||||
"lodash._basecreatecallback": "~2.3.0",
|
||||
"lodash._objecttypes": "~2.3.0",
|
||||
"lodash.keys": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.identity": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.3.0.tgz",
|
||||
"integrity": "sha512-NYJ2r2cwy3tkx/saqbIZEX6oQUzjWTnGRu7d/zmBjMCZos3eHBxCpbvWFWSetv8jFVrptsp6EbWjzNgBKhUoOA=="
|
||||
},
|
||||
"node_modules/lodash.isfunction": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.3.0.tgz",
|
||||
"integrity": "sha512-X5lteBYlCrVO7Qc00fxP8W90fzRp6Ax9XcHANmU3OsZHdSyIVZ9ZlX5QTTpRq8aGY+9I5Rmd0UTzTIIyWPugEQ=="
|
||||
},
|
||||
"node_modules/lodash.isobject": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.3.0.tgz",
|
||||
"integrity": "sha512-jo1pfV61C4TE8BfEzqaHj6EIKiSkFANJrB6yscwuCJMSRw5tbqjk4Gv7nJzk4Z6nFKobZjGZ8Qd41vmnwgeQqQ==",
|
||||
"dependencies": {
|
||||
"lodash._objecttypes": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.keys": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.3.0.tgz",
|
||||
"integrity": "sha512-c0UW0ffqMxSCtoVbmVt2lERJLkEqgoOn2ejPsWXzr0ZrqRbl3uruGgwHzhtqXxi6K/ei3Ey7zimOqSwXgzazPg==",
|
||||
"dependencies": {
|
||||
"lodash._renative": "~2.3.0",
|
||||
"lodash._shimkeys": "~2.3.0",
|
||||
"lodash.isobject": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.noop": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.3.0.tgz",
|
||||
"integrity": "sha512-NpSm8HRm1WkBBWHUveDukLF4Kfb5P5E3fjHc9Qre9A11nNubozLWD2wH3UBTZbu+KSuX8aSUvy9b+PUyEceJ8g=="
|
||||
},
|
||||
"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/lodash.support": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.3.0.tgz",
|
||||
"integrity": "sha512-etc7VWbB0U3Iya8ixj2xy4sDBN3jvPX7ODi8iXtn4KkkjNpdngrdc7Vlt5jub/Vgqx6/dWtp7Ml9awhCQPYKGQ==",
|
||||
"dependencies": {
|
||||
"lodash._renative": "~2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-bytes.js": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.7.0.tgz",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@discordjs/voice": "^0.16.1",
|
||||
"convert-units": "^2.3.4",
|
||||
"discord.js": "^14.14.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"libsodium-wrappers": "^0.7.13",
|
||||
|
||||
25
server/discordBot/commands/join.mjs
Normal file
25
server/discordBot/commands/join.mjs
Normal file
@@ -0,0 +1,25 @@
|
||||
import { SlashCommandBuilder } from 'discord.js';
|
||||
|
||||
// Exporting data property
|
||||
export const data = new SlashCommandBuilder()
|
||||
.setName('join')
|
||||
.setDescription('Replies with your input!');
|
||||
|
||||
// Exporting other properties
|
||||
export const example = "/join";
|
||||
export const deferInitialReply = false;
|
||||
|
||||
// Exporting execute function
|
||||
export async function execute(nodeIo, interaction) {
|
||||
try {
|
||||
const sockets = await nodeIo.allSockets();
|
||||
console.log("All open sockets: ",sockets);
|
||||
console.log("Open Socket: ", sockets.values(), nodeIo.sockets.sockets.get(sockets[0]))
|
||||
//await interaction.reply(`**Online Sockets: '${sockets}'**`);
|
||||
await interaction.reply('**Pong.**');
|
||||
//await interaction.channel.send('**Pong.**');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
// await interaction.reply(err.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,32 @@
|
||||
import { Client, GatewayIntentBits, Collection } from 'discord.js';
|
||||
import { registerActiveCommands, unregisterAllCommands } from './modules/registerCommands.mjs'
|
||||
import { join, dirname } from 'path';
|
||||
import { readdirSync } from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { Collection } from 'discord.js';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
|
||||
/**
|
||||
* Add the enabled commands to the bot to be used by users in discord
|
||||
* (commands that end in '.mjs' will be enabled, to disable just remove the extension or replace with '.mjs.disabled')
|
||||
* @param {any} serverClient
|
||||
* @param {any} nodeIo
|
||||
* @param {any} _commandsPath="./commands"
|
||||
* @returns {any}
|
||||
*/
|
||||
export function addEnabledCommands(serverClient, nodeIo, _commandsPath = "../commands") {
|
||||
export const addEnabledCommands = async (serverClient, _commandsPath = "./commands") => {
|
||||
// Setup commands for the Discord bot
|
||||
serverClient.commands = new Collection();
|
||||
const commandsPath = join(__dirname, _commandsPath);
|
||||
const commandFiles = readdirSync(commandsPath).filter(file => file.endsWith('.mjs'));
|
||||
|
||||
for (const file of commandFiles) {
|
||||
const filePath = join(commandsPath, file);
|
||||
const filePath = await join(commandsPath, file);
|
||||
console.log(`Adding enabled command: ${filePath}`);
|
||||
import(`file://${filePath}`).then(command => {
|
||||
await import(`file://${filePath}`).then(command => {
|
||||
if (command.data instanceof Promise) {
|
||||
command.data.then(async (builder) => {
|
||||
command.data = builder;
|
||||
@@ -40,17 +43,19 @@ export function addEnabledCommands(serverClient, nodeIo, _commandsPath = "../com
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Register the commands currently in use by the bot
|
||||
await registerActiveCommands(serverClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the enabled event listeners to the bot
|
||||
* (events that end in '.mjs' will be enabled, to disable just remove the extension or replace with '.mjs.disabled')
|
||||
* @param {any} serverClient
|
||||
* @param {any} nodeIo
|
||||
* @param {any} _eventsPath="./events"
|
||||
* @returns {any}
|
||||
*/
|
||||
export function addEnabledEventListeners(serverClient, nodeIo, _eventsPath = "../events") {
|
||||
export function addEnabledEventListeners(serverClient, _eventsPath = "./events") {
|
||||
const eventsPath = join(__dirname, _eventsPath);
|
||||
const eventFiles = readdirSync(eventsPath).filter(file => file.endsWith('.mjs'));
|
||||
|
||||
@@ -60,10 +65,28 @@ export function addEnabledEventListeners(serverClient, nodeIo, _eventsPath = "..
|
||||
import(`file://${filePath}`).then(event => {
|
||||
console.log("Adding event: ", event);
|
||||
if (event.once) {
|
||||
serverClient.once(event.name, (...args) => event.execute(nodeIo, ...args));
|
||||
serverClient.once(event.name, (...args) => event.execute(serverClient.nodeIo, ...args));
|
||||
} else {
|
||||
serverClient.on(event.name, (...args) => event.execute(nodeIo, ...args));
|
||||
serverClient.on(event.name, (...args) => event.execute(serverClient.nodeIo, ...args));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The discord client
|
||||
export const serverClient = new Client({ intents: [GatewayIntentBits.Guilds] });
|
||||
|
||||
// Run when the bot is ready
|
||||
serverClient.on('ready', async () => {
|
||||
console.log(`Logged in as ${serverClient.user.tag}!`);
|
||||
|
||||
// Add and register commands
|
||||
await addEnabledCommands(serverClient);
|
||||
|
||||
// Config the discord bot with events
|
||||
await addEnabledEventListeners(serverClient);
|
||||
});
|
||||
|
||||
// Startup the discord bot
|
||||
console.log(`Logging into discord with ID: ${process.env.DISCORD_TOKEN}`);
|
||||
serverClient.login(process.env.DISCORD_TOKEN);
|
||||
83
server/discordBot/modules/registerCommands.mjs
Normal file
83
server/discordBot/modules/registerCommands.mjs
Normal file
@@ -0,0 +1,83 @@
|
||||
import { REST, Routes } from 'discord.js';
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
|
||||
const discordToken = process.env.DISCORD_TOKEN;
|
||||
|
||||
export const registerActiveCommands = async (serverClient) => {
|
||||
const guildIDs = serverClient.guilds.cache;
|
||||
const clientId = serverClient.user.id;
|
||||
const commands = await serverClient.commands.map(command => command = command.data.toJSON());
|
||||
|
||||
// Construct and prepare an instance of the REST module
|
||||
const rest = new REST({ version: '10' }).setToken(discordToken);
|
||||
|
||||
// and deploy your commands!
|
||||
guildIDs.forEach(guild => {
|
||||
console.log("Deploying commands for: ", guild.id);
|
||||
console.log("Commands", commands);
|
||||
(async () => {
|
||||
try {
|
||||
console.log(`Started refreshing application (/) commands for guild ID: ${guild.id}.`);
|
||||
// The put method is used to fully refresh all commands in the guild with the current set
|
||||
const data = await rest.put(
|
||||
Routes.applicationGuildCommands(clientId, guild.id),
|
||||
{ body: commands },
|
||||
);
|
||||
|
||||
console.log(`Successfully reloaded ${data.length} application (/) commands for guild ID: ${guild.id}.`);
|
||||
} catch (error) {
|
||||
// And of course, make sure you catch and log any errors!
|
||||
console.log("ERROR Deploying commands: ", error, "Body from error: ", commands);
|
||||
}
|
||||
})()
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove all commands for a given bot in a given guild
|
||||
*
|
||||
* @param {any} serverClient The discord bot client
|
||||
*/
|
||||
export const unregisterAllCommands = async (serverClient) => {
|
||||
const guildIDs = serverClient.guilds.cache;
|
||||
const clientId = serverClient.user.id;
|
||||
commands = [];
|
||||
|
||||
const rest = new REST({ version: '10' }).setToken(discordToken);
|
||||
guildIDs.forEach(guild => {
|
||||
console.log("Removing commands for: ", clientId, guild.id);
|
||||
(async () => {
|
||||
try {
|
||||
console.log(`Started removal of ${commands.length} application (/) commands for guild ID: ${guild.id}.`);
|
||||
// The put method is used to fully refresh all commands in the guild with the current set
|
||||
const data = await rest.put(
|
||||
Routes.applicationGuildCommands(clientId, guild.id),
|
||||
{ body: commands },
|
||||
);
|
||||
|
||||
console.log(`Successfully removed ${data.length} application (/) commands for guild ID: ${guild.id}.`);
|
||||
} catch (error) {
|
||||
// And of course, make sure you catch and log any errors!
|
||||
console.log("ERROR removing commands: ", error, "Body from error: ", commands);
|
||||
}
|
||||
})()
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This named wrapper will remove all commands and then re-add the commands back, effectively refreshing them
|
||||
* @param {any} serverClient The discord bot client object
|
||||
* @returns {any}
|
||||
*/
|
||||
export const refreshActiveCommandsWrapper = async (serverClient) => {
|
||||
// Remove all commands
|
||||
console.log("Removing/Unregistering all commands from all connected servers/guilds");
|
||||
await unregisterAllCommands(serverClient);
|
||||
// Deploy the active commands
|
||||
console.log("Adding commands to all connected servers/guilds");
|
||||
await registerActiveCommands(serverClient);
|
||||
return;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { Client, GatewayIntentBits } from 'discord.js';
|
||||
//import { deployActiveCommands } from '../discordBot/modules/deployCommands.mjs'
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
|
||||
export const serverClient = new Client({ intents: [GatewayIntentBits.Guilds] });
|
||||
|
||||
serverClient.on('ready', () => {
|
||||
console.log(`Logged in as ${serverClient.user.tag}!`);
|
||||
});
|
||||
53
server/modules/mongoHandler.mjs
Normal file
53
server/modules/mongoHandler.mjs
Normal file
@@ -0,0 +1,53 @@
|
||||
// Import necessary modules
|
||||
import { MongoClient } from 'mongodb';
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
|
||||
// MongoDB connection URI
|
||||
const uri = process.env.MONGO_URL;
|
||||
|
||||
// Function to connect to the database
|
||||
export const connectToDatabase = async () => {
|
||||
try {
|
||||
const client = await MongoClient.connect(uri);
|
||||
return client;
|
||||
} catch (error) {
|
||||
console.error('Error connecting to the database:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Function to insert a document into the collection
|
||||
export const insertDocument = async (collectionName, document) => {
|
||||
const db = await connectToDatabase();
|
||||
try {
|
||||
const collection = db.db().collection(collectionName);
|
||||
const result = await collection.insertOne(document);
|
||||
console.log('Document inserted:', result.insertedId);
|
||||
return result.insertedId;
|
||||
} catch (error) {
|
||||
console.error('Error inserting document:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Close the connection
|
||||
await db.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Function to retrieve documents from the collection
|
||||
export const getDocuments = async (collectionName) => {
|
||||
const db = await connectToDatabase();
|
||||
try {
|
||||
const collection = db.db().collection(collectionName);
|
||||
const documents = await collection.find({}).toArray();
|
||||
console.log('Documents retrieved:', documents);
|
||||
return documents;
|
||||
} catch (error) {
|
||||
console.error('Error retrieving documents:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Close the connection
|
||||
await db.close();
|
||||
}
|
||||
};
|
||||
75
server/modules/mongoNodesWrappers.mjs
Normal file
75
server/modules/mongoNodesWrappers.mjs
Normal file
@@ -0,0 +1,75 @@
|
||||
import { insertDocument, getDocuments, connectToDatabase } from "./mongoHandler.mjs";
|
||||
|
||||
const collectionName = 'nodes';
|
||||
|
||||
// Wrapper for inserting a node
|
||||
export const createNode = async (node) => {
|
||||
try {
|
||||
const insertedId = await insertDocument(collectionName, node);
|
||||
return insertedId;
|
||||
} catch (error) {
|
||||
console.error('Error creating node:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for retrieving all nodes
|
||||
export const getAllNodes = async () => {
|
||||
try {
|
||||
const nodes = await getDocuments(collectionName);
|
||||
return nodes;
|
||||
} catch (error) {
|
||||
console.error('Error getting all nodes:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for retrieving a node by NUID
|
||||
export const getNodeByNuid = async (nuid) => {
|
||||
const db = await connectToDatabase();
|
||||
try {
|
||||
const collection = db.db().collection(collectionName);
|
||||
const node = await collection.findOne({ nuid });
|
||||
return node;
|
||||
} catch (error) {
|
||||
console.error('Error getting node by NUID:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Close the connection
|
||||
await db.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for updating a node by NUID
|
||||
export const updateNodeByNuid = async (nuid, updatedFields) => {
|
||||
const db = await connectToDatabase();
|
||||
try {
|
||||
const collection = db.db().collection(collectionName);
|
||||
const result = await collection.updateOne({ nuid }, { $set: updatedFields });
|
||||
console.log('Node updated:', result.modifiedCount);
|
||||
return result.modifiedCount;
|
||||
} catch (error) {
|
||||
console.error('Error updating node by NUID:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Close the connection
|
||||
await db.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for deleting a node by NUID
|
||||
export const deleteNodeByNuid = async (nuid) => {
|
||||
const db = await connectToDatabase();
|
||||
try {
|
||||
const collection = db.db().collection(collectionName);
|
||||
const result = await collection.deleteOne({ nuid });
|
||||
console.log('Node deleted:', result.deletedCount);
|
||||
return result.deletedCount;
|
||||
} catch (error) {
|
||||
console.error('Error deleting node by NUID:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Close the connection
|
||||
await db.close();
|
||||
}
|
||||
};
|
||||
111
server/modules/mongoSystemsWrappers.mjs
Normal file
111
server/modules/mongoSystemsWrappers.mjs
Normal file
@@ -0,0 +1,111 @@
|
||||
import { insertDocument, getDocuments, connectToDatabase } from "./mongoHandler.mjs";
|
||||
|
||||
const collectionName = 'radio-systems';
|
||||
|
||||
// Local wrapper to remove any local files from radio systems
|
||||
const removeLocalFilesFromsystem = async (system) => {
|
||||
if (system.trunkFile) delete system.trunkFile;
|
||||
if (system.whitelistFile) delete system.whitelistFile;
|
||||
}
|
||||
|
||||
|
||||
// Wrapper for inserting a system
|
||||
export const createSystem = async (name, system, nuid) => {
|
||||
try {
|
||||
// Remove any local files
|
||||
await removeLocalFilesFromsystem(system);
|
||||
// Add the NUID of the node that created this system
|
||||
system.nodes = [nuid];
|
||||
// Add the name of the system
|
||||
system.name = name
|
||||
const insertedId = await insertDocument(collectionName, system);
|
||||
return insertedId;
|
||||
} catch (error) {
|
||||
console.error('Error creating system:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for retrieving all systems
|
||||
export const getAllSystems = async () => {
|
||||
try {
|
||||
const systems = await getDocuments(collectionName);
|
||||
return systems;
|
||||
} catch (error) {
|
||||
console.error('Error getting all systems:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for retrieving a system by name
|
||||
export const getSystemByName = async (name) => {
|
||||
const db = await connectToDatabase();
|
||||
try {
|
||||
const collection = db.db().collection(collectionName);
|
||||
const system = await collection.findOne({ name });
|
||||
return system;
|
||||
} catch (error) {
|
||||
console.error('Error getting system by name:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Close the connection
|
||||
await db.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper to get all systems from a given node
|
||||
export const getSystemsByNuid = async (nuid) => {
|
||||
const db = await connectToDatabase();
|
||||
try {
|
||||
const collection = db.db().collection(collectionName);
|
||||
|
||||
// Query for documents where the 'nodes' array contains the given nodeID
|
||||
const query = { nodes: nuid };
|
||||
const systems = await collection.find(query).toArray();
|
||||
|
||||
return systems;
|
||||
} catch (error) {
|
||||
console.error('Error finding entries:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Close the connection
|
||||
await db.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for updating a system by name
|
||||
export const updateSystemByName = async (name, updatedSystem) => {
|
||||
// Remove any local files
|
||||
await removeLocalFilesFromsystem(updatedSystem);
|
||||
|
||||
const db = await connectToDatabase();
|
||||
try {
|
||||
const collection = db.db().collection(collectionName);
|
||||
const result = await collection.updateOne({ name }, { $set: updatedSystem });
|
||||
console.log('System updated:', result.modifiedCount);
|
||||
return result.modifiedCount;
|
||||
} catch (error) {
|
||||
console.error('Error updating system by name:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Close the connection
|
||||
await db.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for deleting a system by name
|
||||
export const deleteSystemByName = async (name) => {
|
||||
const db = await connectToDatabase();
|
||||
try {
|
||||
const collection = db.db().collection(collectionName);
|
||||
const result = await collection.deleteOne({ name });
|
||||
console.log('System deleted:', result.deletedCount);
|
||||
return result.deletedCount;
|
||||
} catch (error) {
|
||||
console.error('Error deleting system by name:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Close the connection
|
||||
await db.close();
|
||||
}
|
||||
};
|
||||
@@ -2,6 +2,7 @@ import express from 'express';
|
||||
import { createServer } from 'node:http';
|
||||
import { Server } from 'socket.io';
|
||||
import morgan from 'morgan';
|
||||
import { nodeLoginWrapper, nodeUpdateWrapper, nodeDisconnectWrapper, nearbySystemsUpdateWraper } from "./socketServerWrappers.mjs";
|
||||
|
||||
export const app = express();
|
||||
export const server = createServer(app);
|
||||
@@ -17,48 +18,21 @@ nodeIo.on('connection', (socket) => {
|
||||
console.log('a user connected', socket.id);
|
||||
|
||||
socket.on('node-login', (data) => {
|
||||
nodeLoginWrapper(data);
|
||||
nodeLoginWrapper(data, socket);
|
||||
})
|
||||
|
||||
socket.on('node-update', (data) => {
|
||||
updateNodeData(data);
|
||||
nodeUpdateWrapper(data.node);
|
||||
nearbySystemsUpdateWraper(data.node.nuid, data.nearbySystems)
|
||||
})
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log('user disconnected');
|
||||
nodeDisconnectWrapper(socket.id);
|
||||
});
|
||||
|
||||
// Test commands
|
||||
setTimeout(() => {
|
||||
const joinData = {
|
||||
'clientID': "MTE5NjAwNTM2ODYzNjExMjk3Nw.GuCMXg.24iNNofNNumq46FIj68zMe9RmQgugAgfrvelEA",
|
||||
'channelID': "367396189529833476",
|
||||
'preset': ""
|
||||
}
|
||||
sendNodeCommand(socket, "node-join", joinData);
|
||||
}, 2500)
|
||||
//setTimeout(() => { sendNodeCommand(socket, "node-leave", {}); }, 3500)
|
||||
});
|
||||
|
||||
function sendNodeCommand(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);
|
||||
}
|
||||
|
||||
function loginNode() {
|
||||
|
||||
}
|
||||
|
||||
function registerNode() {
|
||||
|
||||
}
|
||||
|
||||
function updateNodeData(data) {
|
||||
console.log("Data update sent by node: ", data);
|
||||
}
|
||||
|
||||
function nodeLoginWrapper(data) {
|
||||
console.log(`Login requested from node: ${data.id}`, data);
|
||||
}
|
||||
// Startup the node server
|
||||
server.listen(3000, () => {
|
||||
console.log('server running at http://localhost:3000');
|
||||
});
|
||||
167
server/modules/socketServerWrappers.mjs
Normal file
167
server/modules/socketServerWrappers.mjs
Normal file
@@ -0,0 +1,167 @@
|
||||
import { createNode, getNodeByNuid, updateNodeByNuid } from "./mongoNodesWrappers.mjs"
|
||||
import { createSystem, getSystemByName, updateSystemByName, getSystemsByNuid, deleteSystemByName } from "./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) => {
|
||||
console.log(`Login requested from node: ${data.nuid}`, data);
|
||||
// Check to see if node exists
|
||||
var node = await getNodeByNuid(data.nuid);
|
||||
console.log("After grabbing", node);
|
||||
if (!node) {
|
||||
const insertedId = await createNode(data);
|
||||
node = await getNodeByNuid(data.nuid);
|
||||
console.log("Added new node to the database:", insertedId);
|
||||
}
|
||||
// Check for updates if so
|
||||
// Check for System updates
|
||||
|
||||
// Add the socket/node connection
|
||||
socket.node = node;
|
||||
socket.id = node.nuid;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect the client from the server
|
||||
* @param {string} socketId The socket ID that was disconnected
|
||||
* @returns {any}
|
||||
*/
|
||||
export const nodeDisconnectWrapper = async (socketId) => {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update node data in the database
|
||||
* @param {object} nodeData The data object sent from the node
|
||||
* @returns {any}
|
||||
*/
|
||||
export const nodeUpdateWrapper = async (nodeData) => {
|
||||
console.log("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
|
||||
* @returns {any}
|
||||
*/
|
||||
export const nearbySystemsUpdateWraper = async (nuid, nearbySystems) => {
|
||||
console.log("System updates sent by node: ", nuid, nearbySystems);
|
||||
// Check to see if the node removed any systems
|
||||
const existingSystems = await getSystemsByNuid(nuid);
|
||||
console.log("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;
|
||||
}
|
||||
|
||||
console.log("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
|
||||
console.log("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
|
||||
console.log("Other nodes found on this system, removing the given NUID");
|
||||
existingSystem.nodes = existingSystem.nodes.filter(node => node !== nuid);
|
||||
console.log(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)
|
||||
console.log(existingSystem.frequencies, nearbySystems[nearbySystem].frequencies, (JSON.stringify(existingSystem.frequencies) === JSON.stringify(nearbySystems[nearbySystem].frequencies)));
|
||||
|
||||
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) console.log("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) console.log("System updated", nearbySystem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Create a new system
|
||||
const newSystem = await createSystem(nearbySystem, nearbySystems[nearbySystem], nuid);
|
||||
console.log("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
|
||||
*/
|
||||
const getSocketIdByNuid = async (nuid) => {
|
||||
for (const openSocket in openSockets) {
|
||||
if (openSockets[openSocket] == nuid)
|
||||
return openSocket;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const requestNodeJoinPreset = async () => {
|
||||
// Check for System updates
|
||||
// Test commands
|
||||
setTimeout(() => {
|
||||
const joinData = {
|
||||
'clientID': "MTE5NjAwNTM2ODYzNjExMjk3Nw.GuCMXg.24iNNofNNumq46FIj68zMe9RmQgugAgfrvelEA",
|
||||
'channelID': "367396189529833476",
|
||||
'preset': ""
|
||||
}
|
||||
sendNodeCommand(socket, "node-join", joinData);
|
||||
}, 2500)
|
||||
}
|
||||
136
server/package-lock.json
generated
136
server/package-lock.json
generated
@@ -12,6 +12,7 @@
|
||||
"discord.js": "^14.14.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"mongodb": "^6.3.0",
|
||||
"morgan": "^1.10.0",
|
||||
"socket.io": "^4.7.2"
|
||||
}
|
||||
@@ -142,6 +143,14 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@mongodb-js/saslprep": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz",
|
||||
"integrity": "sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw==",
|
||||
"dependencies": {
|
||||
"sparse-bitfield": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@sapphire/async-queue": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.1.tgz",
|
||||
@@ -198,6 +207,19 @@
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/webidl-conversions": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
|
||||
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
|
||||
},
|
||||
"node_modules/@types/whatwg-url": {
|
||||
"version": "11.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz",
|
||||
"integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==",
|
||||
"dependencies": {
|
||||
"@types/webidl-conversions": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz",
|
||||
@@ -279,6 +301,14 @@
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/bson": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz",
|
||||
"integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==",
|
||||
"engines": {
|
||||
"node": ">=16.20.1"
|
||||
}
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
@@ -743,6 +773,11 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/memory-pager": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
|
||||
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
|
||||
},
|
||||
"node_modules/merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
@@ -786,6 +821,60 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mongodb": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz",
|
||||
"integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==",
|
||||
"dependencies": {
|
||||
"@mongodb-js/saslprep": "^1.1.0",
|
||||
"bson": "^6.2.0",
|
||||
"mongodb-connection-string-url": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.20.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@aws-sdk/credential-providers": "^3.188.0",
|
||||
"@mongodb-js/zstd": "^1.1.0",
|
||||
"gcp-metadata": "^5.2.0",
|
||||
"kerberos": "^2.0.1",
|
||||
"mongodb-client-encryption": ">=6.0.0 <7",
|
||||
"snappy": "^7.2.2",
|
||||
"socks": "^2.7.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@aws-sdk/credential-providers": {
|
||||
"optional": true
|
||||
},
|
||||
"@mongodb-js/zstd": {
|
||||
"optional": true
|
||||
},
|
||||
"gcp-metadata": {
|
||||
"optional": true
|
||||
},
|
||||
"kerberos": {
|
||||
"optional": true
|
||||
},
|
||||
"mongodb-client-encryption": {
|
||||
"optional": true
|
||||
},
|
||||
"snappy": {
|
||||
"optional": true
|
||||
},
|
||||
"socks": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/mongodb-connection-string-url": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz",
|
||||
"integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==",
|
||||
"dependencies": {
|
||||
"@types/whatwg-url": "^11.0.2",
|
||||
"whatwg-url": "^13.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/morgan": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",
|
||||
@@ -885,6 +974,14 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
@@ -1098,6 +1195,14 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/sparse-bitfield": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
|
||||
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
|
||||
"dependencies": {
|
||||
"memory-pager": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
@@ -1114,6 +1219,17 @@
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
|
||||
"integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-mixer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz",
|
||||
@@ -1176,6 +1292,26 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz",
|
||||
"integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==",
|
||||
"dependencies": {
|
||||
"tr46": "^4.1.1",
|
||||
"webidl-conversions": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"discord.js": "^14.14.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"mongodb": "^6.3.0",
|
||||
"morgan": "^1.10.0",
|
||||
"socket.io": "^4.7.2"
|
||||
}
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
import { nodeIo, app, server } from './modules/socketServer.mjs';
|
||||
import { addEnabledCommands, addEnabledEventListeners } from './discordBot/modules/discordBotUtils.mjs'
|
||||
import { serverClient } from './modules/discordBot.mjs';
|
||||
import { serverClient, addEnabledEventListeners } from './discordBot/discordBot.mjs';
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
|
||||
// Startup the node server
|
||||
server.listen(3000, () => {
|
||||
console.log('server running at http://localhost:3000');
|
||||
});
|
||||
|
||||
// Config the discord bot with commands and events
|
||||
await addEnabledEventListeners(serverClient, nodeIo);
|
||||
await addEnabledCommands(serverClient, nodeIo);
|
||||
|
||||
// Startup the discord bot
|
||||
console.log(`Logging into discord with ID: ${process.env.DISCORD_TOKEN}`);
|
||||
serverClient.login(process.env.DISCORD_TOKEN);
|
||||
// Add objects to the others
|
||||
serverClient.nodeIo = nodeIo;
|
||||
nodeIo.serverClient = serverClient;
|
||||
Reference in New Issue
Block a user