Implement basic initial setup and dashboard with web portal
This commit is contained in:
37
client.js
37
client.js
@@ -1,8 +1,7 @@
|
||||
import { generateUniqueID } from './modules/baseUtils.mjs';
|
||||
import { updateId } from './modules/updateConfig.mjs';
|
||||
import { ClientNodeConfig } from './modules/clientObjectDefinitions.mjs';
|
||||
import { initSocketConnection } from './modules/socketClient.mjs';
|
||||
import { checkForUpdates } from './modules/selfUpdater.mjs'
|
||||
import startServer from './express/server.mjs';
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
@@ -11,37 +10,25 @@ var localNodeConfig = new ClientNodeConfig({})
|
||||
|
||||
async function boot() {
|
||||
// Check if there have been any updates
|
||||
await checkForUpdates();
|
||||
await checkForUpdates();
|
||||
|
||||
if (localNodeConfig.node.nuid === undefined || localNodeConfig.node.nuid === '' || localNodeConfig.node.nuid === '0' || localNodeConfig.node.nuid === 0) {
|
||||
// Run the first time boot sequence
|
||||
await firstTimeBoot();
|
||||
return new Promise(res => {res(false)});
|
||||
}
|
||||
|
||||
// Initialize the socket connection with the server
|
||||
return initSocketConnection(localNodeConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the first time the client boots on a pc
|
||||
* @returns {any}
|
||||
*/
|
||||
async function firstTimeBoot() {
|
||||
// Generate a new ID for the node
|
||||
localNodeConfig.node.nuid = await generateUniqueID();
|
||||
console.log(`Generated a new unique ID for this node: '${localNodeConfig.node.nuid}'`);
|
||||
|
||||
// Update the config with the new ID
|
||||
await 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 - Implement web server so users can update radio systems easily
|
||||
// TODO - Implement logic to check if the presets are set
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Boot the client application
|
||||
boot().then((openSocket) => {
|
||||
console.log(openSocket, "Booted Sucessfully");
|
||||
// Start the web server
|
||||
startServer(process.env.WEB_SERVER_PORT || 3000, openSocket);
|
||||
|
||||
if (!openSocket) {
|
||||
console.log(openSocket, "Waiting for setup");
|
||||
}
|
||||
else {
|
||||
console.log(openSocket, "Booted Sucessfully");
|
||||
}
|
||||
})
|
||||
11
express/routes/dashboardRoutes.js
Normal file
11
express/routes/dashboardRoutes.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// dashboardRoutes.js
|
||||
|
||||
import express from 'express';
|
||||
const router = express.Router();
|
||||
|
||||
// Define routes
|
||||
router.get('/', (req, res) => {
|
||||
res.render('dashboard');
|
||||
});
|
||||
|
||||
export default router;
|
||||
136
express/routes/setupRoutes.js
Normal file
136
express/routes/setupRoutes.js
Normal file
@@ -0,0 +1,136 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import express from 'express';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { generateUniqueID } from '../../modules/baseUtils.mjs';
|
||||
import { restartApplication } from '../../modules/selfUpdater.mjs'
|
||||
|
||||
const router = express.Router();
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Define __dirname for ESM
|
||||
|
||||
// Array to store information about added systems
|
||||
let systemsData = [];
|
||||
let nodeData = {};
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
res.render('setup/setup');
|
||||
});
|
||||
|
||||
// Route to serve the page for adding nearby systems
|
||||
router.get('/add-system', (req, res) => {
|
||||
res.render('setup/add_system');
|
||||
});
|
||||
|
||||
router.post('/', (req, res) => {
|
||||
// Handle form submission here
|
||||
const { clientName, clientLocation, clientCapabilities } = req.body;
|
||||
|
||||
console.log(clientName, clientLocation, clientCapabilities);
|
||||
|
||||
nodeData.clientName = clientName;
|
||||
nodeData.clientLocation = clientLocation;
|
||||
nodeData.clientCapabilities = clientCapabilities;
|
||||
|
||||
res.redirect('/setup/add-system');
|
||||
});
|
||||
|
||||
// Route to handle form submission for adding a system
|
||||
router.post('/add-system', (req, res) => {
|
||||
const { systemName, frequencies, mode, trunkFile, whitelistFile } = req.body;
|
||||
|
||||
// Store system information for later use
|
||||
// For now, let's just log the information
|
||||
console.log('System Name:', systemName);
|
||||
console.log('Frequencies:', frequencies);
|
||||
console.log('Mode:', mode);
|
||||
console.log('Trunk File:', trunkFile);
|
||||
console.log('Whitelist File:', whitelistFile);
|
||||
|
||||
// Store system information in the array
|
||||
systemsData.push({
|
||||
systemName,
|
||||
frequencies,
|
||||
mode,
|
||||
trunkFile,
|
||||
whitelistFile
|
||||
});
|
||||
|
||||
// Prompt user to add another system or proceed
|
||||
res.render('setup/prompt_add_another_system');
|
||||
});
|
||||
|
||||
// Route to write collected information to .env file
|
||||
router.post('/finish-setup', async (req, res) => {
|
||||
// Write collected information to .env file
|
||||
// For now, let's just log the collected information
|
||||
console.log('Collected System Information:', nodeData, systemsData);
|
||||
|
||||
if (!await exportCsv(nodeData)) return res.status(500).send('Error writing to .env file');
|
||||
|
||||
if (!await exportSystems(systemsData)) return res.status(500).send('Error writing the systems config file');
|
||||
|
||||
res.send('Setup process completed successfully! Click <a href="/dashboard">here</a> for the dashboard when the service restarts.');
|
||||
restartApplication();
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
|
||||
const exportCsv = (nodeData) => {
|
||||
const nuid = generateUniqueID();
|
||||
console.log(`Generated a new unique ID for this node: '${nuid}'`);
|
||||
const envData = {
|
||||
CLIENT_NUID: nuid,
|
||||
CLIENT_NAME: nodeData.clientName,
|
||||
CLIENT_LOCATION: nodeData.clientCapabilities,
|
||||
CLIENT_CAPABILITIES: nodeData.clientCapabilities,
|
||||
SERVER_IP: "",
|
||||
SERVER_PORT: 0,
|
||||
OP25_FULL_PATH: `${__dirname}/op25/op25/gr-op25_repeater/apps`,
|
||||
CONFIG_PATH: "./config/radioPresets.json",
|
||||
};
|
||||
|
||||
// Generate .env file content
|
||||
const envContent = Object.entries(envData)
|
||||
.map(([key, value]) => `${key}=${value}`)
|
||||
.join('\n');
|
||||
|
||||
// Write to .env file
|
||||
return new Promise(res => {
|
||||
fs.writeFile('.env', envContent, (err) => {
|
||||
if (err) {
|
||||
console.error('Error writing to .env file:', err);
|
||||
res(false);
|
||||
} else {
|
||||
console.log('.env file updated successfully');
|
||||
res(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const exportSystems = (systemsData) => {
|
||||
// Write systems data to radioPresets.json
|
||||
const radioPresetsPath = './config/radioPresets.json';
|
||||
const radioPresetsData = {};
|
||||
|
||||
systemsData.forEach((system, index) => (
|
||||
radioPresetsData[system.systemName] = {
|
||||
frequencies: system.frequencies.split(','),
|
||||
mode: system.mode,
|
||||
trunkFile: system.trunkFile || '',
|
||||
whitelistFile: system.whitelistFile || ''
|
||||
}
|
||||
));
|
||||
return new Promise(res => {
|
||||
fs.writeFile(radioPresetsPath, JSON.stringify(radioPresetsData, null, 4), (err) => {
|
||||
if (err) {
|
||||
console.error('Error writing to radioPresets.json:', err);
|
||||
res(false);
|
||||
} else {
|
||||
console.log('radioPresets.json updated successfully');
|
||||
res(true);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
60
express/server.mjs
Normal file
60
express/server.mjs
Normal file
@@ -0,0 +1,60 @@
|
||||
import express from 'express';
|
||||
import http from 'http';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import bodyParser from 'body-parser';
|
||||
|
||||
import setupRoutes from './routes/setupRoutes.js';
|
||||
import dashboardRoutes from './routes/dashboardRoutes.js';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Define __dirname for ESM
|
||||
|
||||
export var isSetupComplete = false;
|
||||
|
||||
const app = express();
|
||||
const server = http.createServer(app);
|
||||
|
||||
// Start the server
|
||||
const startServer = (port, openSocket) => {
|
||||
if (openSocket) isSetupComplete = true;
|
||||
|
||||
server.listen(port, () => {
|
||||
console.log(`Server running on port ${port}`);
|
||||
});
|
||||
};
|
||||
|
||||
export default startServer;
|
||||
|
||||
// Set EJS as the default template engine
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
// Set the views directory to express/views
|
||||
const viewsPath = path.join(__dirname, 'views');
|
||||
app.set('views', viewsPath);
|
||||
|
||||
// Use body-parser middleware to parse JSON requests
|
||||
app.use(bodyParser.json());
|
||||
|
||||
// Use body-parser middleware to parse URL-encoded form data
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
// Define static folder for serving HTML, CSS, and client-side JavaScript files
|
||||
const staticPath = path.join(__dirname, 'public');
|
||||
app.use(express.static(staticPath));
|
||||
|
||||
// ---------------- Defualt Route
|
||||
app.get('/', (req, res) => {
|
||||
if (!isSetupComplete) {
|
||||
return res.redirect('/setup');
|
||||
}
|
||||
else {
|
||||
return res.redirect('/dashboard');
|
||||
}
|
||||
});
|
||||
|
||||
// ---------------- Routers
|
||||
// Use the setup router for '/setup' routes
|
||||
app.use('/setup', setupRoutes);
|
||||
|
||||
// Use the dashboard router for '/dashboard' routes
|
||||
app.use('/dashboard', dashboardRoutes);
|
||||
15
express/views/dashboard.ejs
Normal file
15
express/views/dashboard.ejs
Normal file
@@ -0,0 +1,15 @@
|
||||
<!-- dashboard.ejs -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Dashboard</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Welcome to the Dashboard</h1>
|
||||
<p>This is a very basic dashboard.</p>
|
||||
<!-- Add more content as needed -->
|
||||
</body>
|
||||
</html>
|
||||
34
express/views/setup/add_system.ejs
Normal file
34
express/views/setup/add_system.ejs
Normal file
@@ -0,0 +1,34 @@
|
||||
<!-- nearby_systems.ejs -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Add Nearby Systems</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Add Nearby Systems</h1>
|
||||
<form action="/setup/add-system" method="post">
|
||||
<label for="systemName">System Name:</label>
|
||||
<input type="text" id="systemName" name="systemName" required>
|
||||
<br>
|
||||
<label for="frequencies">Frequencies (comma-separated):</label>
|
||||
<input type="text" id="frequencies" name="frequencies" required>
|
||||
<br>
|
||||
<label for="mode">Mode:</label>
|
||||
<select id="mode" name="mode" required>
|
||||
<option value="p25">P25</option>
|
||||
<option value="nbfm">NBFM</option>
|
||||
</select>
|
||||
<br>
|
||||
<label for="trunkFile">Trunk File:</label>
|
||||
<input type="text" id="trunkFile" name="trunkFile">
|
||||
<br>
|
||||
<label for="whitelistFile">Whitelist File:</label>
|
||||
<input type="text" id="whitelistFile" name="whitelistFile">
|
||||
<br>
|
||||
<button type="submit">Add System</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
19
express/views/setup/prompt_add_another_system.ejs
Normal file
19
express/views/setup/prompt_add_another_system.ejs
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- prompt_add_another_system.ejs -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Add Another System?</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Add Another System?</h1>
|
||||
<form action="/setup/add-system" method="get">
|
||||
<button type="submit">Add Another System</button>
|
||||
</form>
|
||||
<form action="/setup/finish-setup" method="post">
|
||||
<button type="submit">Finish Setup</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
25
express/views/setup/setup.ejs
Normal file
25
express/views/setup/setup.ejs
Normal file
@@ -0,0 +1,25 @@
|
||||
<!-- setup.ejs -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Setup</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Setup</h1>
|
||||
<form action="/setup" method="post">
|
||||
<label for="clientName">Client Name:</label>
|
||||
<input type="text" id="clientName" name="clientName" required>
|
||||
<br>
|
||||
<label for="clientLocation">Client Location:</label>
|
||||
<input type="text" id="clientLocation" name="clientLocation" required>
|
||||
<br>
|
||||
<label for="clientCapabilities">Client Capabilities (comma-separated):</label>
|
||||
<input type="text" id="clientCapabilities" name="clientCapabilities" required>
|
||||
<br>
|
||||
<button type="submit">Next</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -51,7 +51,7 @@ export const checkForUpdates = async () => {
|
||||
}
|
||||
|
||||
// Function to restart the application
|
||||
const restartApplication = () => {
|
||||
export const restartApplication = () => {
|
||||
console.log('Restarting the application...');
|
||||
restartService('discord-radio-bot');
|
||||
}
|
||||
110
package-lock.json
generated
110
package-lock.json
generated
@@ -10,10 +10,10 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@discordjs/voice": "^0.16.1",
|
||||
"chai-http": "^4.4.0",
|
||||
"convert-units": "^2.3.4",
|
||||
"discord.js": "^14.14.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^4.19.2",
|
||||
"libsodium-wrappers": "^0.7.13",
|
||||
"prism-media": "^1.3.5",
|
||||
@@ -24,6 +24,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^5.1.0",
|
||||
"chai-http": "^4.4.0",
|
||||
"mocha": "^10.4.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
@@ -240,7 +241,8 @@
|
||||
"node_modules/@types/chai": {
|
||||
"version": "4.3.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz",
|
||||
"integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w=="
|
||||
"integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/cookie": {
|
||||
"version": "0.4.1",
|
||||
@@ -250,7 +252,8 @@
|
||||
"node_modules/@types/cookiejar": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz",
|
||||
"integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q=="
|
||||
"integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/cors": {
|
||||
"version": "2.8.17",
|
||||
@@ -272,6 +275,7 @@
|
||||
"version": "4.1.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.13.tgz",
|
||||
"integrity": "sha512-YIGelp3ZyMiH0/A09PMAORO0EBGlF5xIKfDpK74wdYvWUs2o96b5CItJcWPdH409b7SAXIIG6p8NdU/4U2Maww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/cookiejar": "*",
|
||||
"@types/node": "*"
|
||||
@@ -364,7 +368,8 @@
|
||||
"node_modules/asap": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
|
||||
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/assertion-error": {
|
||||
"version": "2.0.1",
|
||||
@@ -375,10 +380,16 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "3.2.5",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
|
||||
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
@@ -525,6 +536,7 @@
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/chai-http/-/chai-http-4.4.0.tgz",
|
||||
"integrity": "sha512-uswN3rZpawlRaa5NiDUHcDZ3v2dw5QgLyAwnQ2tnVNuP7CwIsOFuYJ0xR1WiR7ymD4roBnJIzOUep7w9jQMFJA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/chai": "4",
|
||||
"@types/superagent": "4.1.13",
|
||||
@@ -543,6 +555,7 @@
|
||||
"version": "6.12.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
|
||||
"integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.6"
|
||||
},
|
||||
@@ -572,6 +585,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz",
|
||||
"integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
@@ -645,6 +659,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
@@ -656,10 +671,16 @@
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
|
||||
"integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||
@@ -704,7 +725,8 @@
|
||||
"node_modules/cookiejar": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
|
||||
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw=="
|
||||
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cors": {
|
||||
"version": "2.8.5",
|
||||
@@ -775,6 +797,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
@@ -800,6 +823,7 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
|
||||
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"asap": "^2.0.0",
|
||||
"wrappy": "1"
|
||||
@@ -887,6 +911,20 @@
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||
},
|
||||
"node_modules/ejs": {
|
||||
"version": "3.1.10",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
||||
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
|
||||
"dependencies": {
|
||||
"jake": "^10.8.5"
|
||||
},
|
||||
"bin": {
|
||||
"ejs": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
@@ -1062,7 +1100,16 @@
|
||||
"node_modules/fast-safe-stringify": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
|
||||
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
|
||||
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/filelist": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
|
||||
"integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
|
||||
"dependencies": {
|
||||
"minimatch": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
@@ -1135,6 +1182,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
@@ -1148,6 +1196,7 @@
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz",
|
||||
"integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dezalgo": "^1.0.4",
|
||||
"hexoid": "^1.0.0",
|
||||
@@ -1342,6 +1391,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
|
||||
"integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -1390,6 +1440,7 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
|
||||
"integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
@@ -1447,6 +1498,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-ip/-/is-ip-2.0.0.tgz",
|
||||
"integrity": "sha512-9MTn0dteHETtyUx8pxqMwg5hMBi3pvlyglJ+b79KOCca0po23337LbVV2Hl4xmMvfw++ljnO0/+5G6G+0Szh6g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ip-regex": "^2.0.0"
|
||||
},
|
||||
@@ -1484,6 +1536,43 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/jake": {
|
||||
"version": "10.9.1",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz",
|
||||
"integrity": "sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==",
|
||||
"dependencies": {
|
||||
"async": "^3.2.3",
|
||||
"chalk": "^4.0.2",
|
||||
"filelist": "^1.0.4",
|
||||
"minimatch": "^3.1.2"
|
||||
},
|
||||
"bin": {
|
||||
"jake": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
@@ -1717,6 +1806,7 @@
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
@@ -2173,6 +2263,7 @@
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
@@ -2400,6 +2491,7 @@
|
||||
"resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz",
|
||||
"integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==",
|
||||
"deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"component-emitter": "^1.3.0",
|
||||
"cookiejar": "^2.1.4",
|
||||
@@ -2420,6 +2512,7 @@
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
||||
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
@@ -2599,7 +2692,8 @@
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"convert-units": "^2.3.4",
|
||||
"discord.js": "^14.14.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^4.19.2",
|
||||
"libsodium-wrappers": "^0.7.13",
|
||||
"prism-media": "^1.3.5",
|
||||
@@ -24,9 +25,9 @@
|
||||
"socket.io-client": "^4.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai-http": "^4.4.0",
|
||||
"chai": "^5.1.0",
|
||||
"chai-http": "^4.4.0",
|
||||
"mocha": "^10.4.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user