Compare commits

..

45 Commits

Author SHA1 Message Date
Logan Cusano
a4d07db766 #16 Update variable name
Some checks failed
DRB Server Build / drb_server_build (push) Successful in 36s
DRB Tests / drb_mocha_tests (push) Failing after 1m13s
2024-05-11 14:40:10 -04:00
Logan Cusano
03c940e07c Update PDAB handler
- Move PDAB socket server startup to function
- Updated join server wrapper to start the server before opening the python app
2024-05-05 23:39:05 -04:00
Logan Cusano
fee40dd609 #16 Updated join
-  After getting all available IDs, it now checks if there are IDs. If not telling the user
2024-05-05 22:00:04 -04:00
Logan Cusano
5671503594 Omitting OP25 update in the post update for now 2024-05-05 18:29:06 -04:00
Logan Cusano
0fd511cfaf Adding handlers for discord presense 2024-05-05 18:24:59 -04:00
Logan Cusano
9d0aa0191f Resolve bug when selecting ID on join 2024-05-05 18:24:11 -04:00
Logan Cusano
9ce8928d82 Revert base image and add global gyp install
Some checks failed
DRB Server Build / drb_server_build (push) Successful in 24s
DRB Tests / drb_mocha_tests (push) Failing after 59s
2024-04-29 23:25:34 -04:00
Logan Cusano
abadcf5cb5 Change base image of the dockerfile
Some checks failed
DRB Server Build / drb_server_build (push) Failing after 9s
DRB Tests / drb_mocha_tests (push) Failing after 1m38s
2024-04-29 22:16:17 -04:00
Logan Cusano
4b18df9e2c Fix server build name and removed clean and run code, just update
Some checks failed
DRB Server Build / drb_server_build (push) Successful in 6s
DRB Tests / drb_mocha_tests (push) Failing after 58s
2024-04-29 01:28:18 -04:00
Logan Cusano
26a8d8a172 Update build to clean and run the container
All checks were successful
DRB Server Build / drb_mocha_tests (push) Successful in 6s
2024-04-29 01:20:50 -04:00
Logan Cusano
26f3493c8f Remove node setup from build action
Some checks failed
DRB Tests / drb_mocha_tests (push) Failing after 58s
DRB Server Build / drb_mocha_tests (push) Successful in 8s
2024-04-29 01:17:14 -04:00
Logan Cusano
fd261ef015 Missed addition
Some checks failed
DRB Server Build / drb_mocha_tests (push) Failing after 7s
DRB Tests / drb_mocha_tests (push) Failing after 55s
- Server build action
2024-04-29 01:13:00 -04:00
Logan Cusano
91201c3527 Update tests
- Update test names
- Added new action to build the latest server code on the server it's running on
- Removed unnecessary vars from makefile
2024-04-29 01:12:30 -04:00
Logan Cusano
dfb4c6afa1 Remove build from tests 2024-04-28 22:52:39 -04:00
Logan Cusano
3b8e70208a Update build tests
Some checks failed
DRB Build Tests / build (push) Failing after 5s
DRB Build Tests / drb_build_and_test (push) Failing after 53s
Start docker in the test
2024-04-28 22:22:01 -04:00
Logan Cusano
99b60bf02c Update build tests
Some checks failed
DRB Build Tests / build (push) Failing after 5s
DRB Build Tests / drb_build_and_test (push) Failing after 58s
2024-04-28 22:19:09 -04:00
Logan Cusano
831317b9f0 Update build test
Some checks failed
DRB Build Tests / build (push) Failing after 7s
DRB Build Tests / drb_build_and_test (push) Failing after 56s
- Switch to installing docker io
2024-04-28 20:13:25 -04:00
Logan Cusano
2477b10900 Add docker install step to build test
Some checks failed
DRB Build Tests / build (push) Failing after 1m17s
DRB Build Tests / drb_build_and_test (push) Failing after 57s
2024-04-28 06:08:57 -04:00
Logan Cusano
67c29f1d72 Remove gitea debug after potential resolution
Some checks failed
DRB Build Tests / build (push) Failing after 8s
DRB Build Tests / drb_build_and_test (push) Failing after 1m1s
2024-04-28 06:07:06 -04:00
Logan Cusano
91ed4fb1dc gitea debug 2
Some checks failed
DRB Build Tests / build (push) Failing after 1m3s
DRB Build Tests / drb_build_and_test (push) Failing after 1m31s
2024-04-28 05:50:52 -04:00
Logan Cusano
8ea02d1c0b gitea debug
Some checks failed
DRB Build Tests / build (push) Failing after 16s
DRB Build Tests / drb_build_and_test (push) Has been cancelled
2024-04-28 05:49:57 -04:00
Logan Cusano
b15ac7c973 Added working directory to build step
Some checks failed
DRB Build Tests / build (push) Failing after 14s
DRB Build Tests / drb_build_and_test (push) Failing after 52s
2024-04-28 05:32:54 -04:00
Logan Cusano
c2c90019d7 Update tests
Some checks failed
DRB Build Tests / build (push) Failing after 32s
DRB Build Tests / drb_build_and_test (push) Failing after 58s
2024-04-28 05:30:13 -04:00
Logan Cusano
686ddc8a0f Gitea runner debug
Some checks failed
DRB Build Tests / build (push) Failing after 25s
DRB Build Tests / drb_build_and_test (push) Failing after 41s
2024-04-28 05:22:20 -04:00
Logan Cusano
463ccc1bd5 Setup docker in the test
Some checks failed
DRB Build Tests / build (push) Failing after 1m13s
DRB Build Tests / drb_build_and_test (push) Failing after 59s
2024-04-28 05:17:08 -04:00
Logan Cusano
14a2b4a1b9 Update tests
Some checks failed
DRB Build Tests / build (push) Failing after 41s
DRB Build Tests / drb_build_and_test (push) Failing after 43s
- Output docker ps before curl
2024-04-28 05:13:40 -04:00
Logan Cusano
0c1f6cd867 Update dockerfile
Some checks failed
DRB Build Tests / build (push) Failing after 34s
DRB Build Tests / drb_build_and_test (push) Failing after 51s
- Use the startup command used in the terminal
2024-04-28 05:11:49 -04:00
Logan Cusano
7175487d77 Update makefile
Some checks failed
DRB Build Tests / build (push) Failing after 31s
DRB Build Tests / drb_build_and_test (push) Failing after 43s
- Run docker detached
2024-04-28 05:06:50 -04:00
Logan Cusano
f0eac45955 Replace space with tab in makefile
Some checks failed
DRB Build Tests / build (push) Failing after 12s
DRB Build Tests / drb_build_and_test (push) Has been cancelled
2024-04-28 05:05:43 -04:00
Logan Cusano
c81dce99e2 Update makefile with clean step
Some checks failed
DRB Build Tests / build (push) Failing after 7s
DRB Build Tests / drb_build_and_test (push) Has been cancelled
2024-04-28 05:04:52 -04:00
Logan Cusano
38cb1054e0 Add DISCORD_TOKEN var to tests and makefile
Some checks failed
DRB Build Tests / build (push) Failing after 12s
DRB Build Tests / drb_build_and_test (push) Failing after 59s
2024-04-28 05:00:10 -04:00
Logan Cusano
12441c5c6d Update makefile
Some checks failed
DRB Build Tests / build (push) Failing after 1m38s
DRB Build Tests / drb_build_and_test (push) Failing after 56s
- Mistake in the docker build path
2024-04-28 04:54:53 -04:00
Logan Cusano
1c1b071bd7 Update makefile
Some checks failed
DRB Build Tests / build (push) Failing after 9s
DRB Build Tests / drb_build_and_test (push) Has been cancelled
- Removed all spaces for tabs
2024-04-28 04:53:55 -04:00
Logan Cusano
961c5c19e2 Update drb tests
Some checks failed
DRB Build Tests / build (push) Failing after 7s
DRB Build Tests / drb_build_and_test (push) Failing after 56s
- Update working directory for make
2024-04-28 04:49:56 -04:00
Logan Cusano
49e52d8944 Add makefile for server and related action build test
Some checks failed
DRB Build Tests / build (push) Failing after 7s
DRB Build Tests / drb_build_and_test (push) Failing after 58s
2024-04-28 04:46:08 -04:00
Logan Cusano
63ccfa70d3 Add server docker file and related action tests
Some checks failed
DRB Build Tests / build (push) Failing after 15s
DRB Build Tests / drb_build_and_test (push) Failing after 1m2s
2024-04-28 04:34:15 -04:00
Logan Cusano
4bb8038a1d Update variables in test action
Some checks failed
DRB Build Tests / drb_build_and_test (push) Failing after 57s
2024-04-28 03:26:06 -04:00
Logan Cusano
a353b9adbb Improvements to tests and from testing
- Moved OP25 start outside of PDAB start callback
- Added more logging
- Set the pdabProcess variable to false when closing the discord client
- Update test variable names
- Added new WIP pdabWrappers tests to test the full wrappers as the client would
2024-04-28 03:21:03 -04:00
Logan Cusano
bf69e93e29 Improve subprocess handler
- Will now output the subprocess console when in dev mode
2024-04-28 03:18:13 -04:00
Logan Cusano
6cae18e70c Update PDAB tests
Some checks failed
DRB Build Tests / drb_build_and_test (push) Failing after 58s
- These new tests will likely not run in actions due to pyaudio
2024-04-27 23:34:30 -04:00
Logan Cusano
e7229322e4 Update pdab handler
- Updated socket close
- Took server outside of the init (server is always running)
- initDiscordBotClient just starts the PDAB process
2024-04-27 23:33:53 -04:00
Logan Cusano
34aa5d17dc Updates to setup from testing
All checks were successful
DRB Build Tests / drb_build_and_test (push) Successful in 52s
2024-04-26 23:46:13 -04:00
Logan Cusano
565fd5af37 Updated join voice log
All checks were successful
DRB Build Tests / drb_build_and_test (push) Successful in 1m27s
2024-04-26 21:30:27 -04:00
Logan Cusano
f04154d361 Remove client build test for now 2024-04-26 21:29:10 -04:00
Logan Cusano
383663e980 #30 Update discordBot
- Added voice states intent
2024-04-26 21:28:49 -04:00
17 changed files with 536 additions and 61 deletions

View File

@@ -0,0 +1,24 @@
name: DRB Server Build
on:
push:
branches:
- master
env:
NODE_ENV: production
SERVER_PORT: 3000
MONGO_URL: ${{ secrets.MONGO_URL }}
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
jobs:
drb_server_build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build the latest code
working-directory: './server'
run: make build

View File

@@ -1,4 +1,4 @@
name: DRB Build Tests name: DRB Tests
on: on:
pull_request: pull_request:
@@ -13,16 +13,19 @@ env:
MONGO_INITDB_ROOT_USERNAME: admin MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: admin MONGO_INITDB_ROOT_PASSWORD: admin
MONGO_INITDB_DATABASE: drb MONGO_INITDB_DATABASE: drb
SERVER_PORT: 6000 SERVER_PORT: 3000
MONGO_URL: "mongodb://mongodb:27017/drb" MONGO_URL: "mongodb://mongodb:27017/drb"
DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
TEST_CHANNEL_ID: ${{ secrets.TEST_CHANNEL_ID }}
TEST_GUILD_ID: ${{ secrets.TEST_GUILD_ID }} TEST_GUILD_ID: ${{ secrets.TEST_GUILD_ID }}
EXPECTED_CLIENT_ID: ${{ secrets.EXPECTED_CLIENT_ID }} TEST_CLIENT_TOKEN: ${{ secrets.TEST_CLIENT_TOKEN }}
TEST_CHANNEL_ID: ${{ secrets.TEST_CHANNEL_ID }}
TEST_SYSTEM: ${{ secrets.TEST_SYSTEM }}
EXPECTED_CLIENT_ID: ${{ secrets.TEST_CLIENT_ID }}
EXPECTED_USERNAME: ${{ secrets.EXPECTED_USERNAME }}
PDAB_PORT: ${{ vars.PDAB_PORT }} PDAB_PORT: ${{ vars.PDAB_PORT }}
jobs: jobs:
drb_build_and_test: drb_mocha_tests:
runs-on: ubuntu-latest runs-on: ubuntu-latest
services: services:

View File

@@ -17,7 +17,16 @@ let pdabProcess = false;
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename); const __dirname = dirname(__filename);
export const initDiscordBotClient = (clientId, callback) => { let botCallback;
export const initDiscordBotClient = (clientId, callback, runPDAB = true) => {
botCallback = callback;
if (runPDAB) launchProcess("python", [join(__dirname, "./pdab/main.py"), process.env.AUDIO_DEVICE_ID, clientId, port], false, join(__dirname, "./pdab"));
pdabProcess = true; // TODO - Make this more dynamic
}
export const startPdabSocketServer = () => {
const port = process.env.PDAB_PORT || 3000; const port = process.env.PDAB_PORT || 3000;
io.on('connection', (socket) => { io.on('connection', (socket) => {
@@ -30,25 +39,25 @@ export const initDiscordBotClient = (clientId, callback) => {
// Listen for the discord client ready event // Listen for the discord client ready event
socket.on('discord_ready', (message) => { socket.on('discord_ready', (message) => {
console.log("Message from local client", message); console.log("Message from local client", message);
callback(); botCallback();
}); });
}); });
server.listen(port, async () => { server.listen(port, async () => {
console.log(`Server is running on port ${port}`); console.log(`Server is running on port ${port}`);
if (process.env.NODE_ENV == "production") {
launchProcess("python", [join(__dirname, "./pdab/main.py"), process.env.AUDIO_DEVICE_ID, clientId, port], false, join(__dirname, "./pdab"));
}
pdabProcess = true; // TODO - Make this more dynamic
}); });
return
} }
export const closePdabSocketServer = () => { export const closePdabSocketServer = () => {
if (io.sockets && io.sockets.length > 0) {
io.sockets.forEach(socket => {
socket.destroy();
})
}
return io.close(); return io.close();
} }
// Function to emit a command to join a voice channel // Function to emit a command to join a voice channel
export const connectToChannel = (channelId) => { export const connectToChannel = (channelId) => {
return new Promise((res) => { return new Promise((res) => {
@@ -69,6 +78,15 @@ export const leaveVoiceChannel = async (guildId) => {
}); });
}; };
// Set the presense of the discord client
export const setDiscordClientPrsense = (system) => {
return new Promise((res) => {
io.timeout(25000).emit('set_system', { system: system }, (status) => {
res();
});
});
};
// Placeholder functions (replace with actual implementation) // Placeholder functions (replace with actual implementation)
export const checkIfConnectedToVC = async (guildId) => { export const checkIfConnectedToVC = async (guildId) => {
console.log("Pdab process var:", pdabProcess); console.log("Pdab process var:", pdabProcess);
@@ -114,6 +132,7 @@ export const requestDiscordID = () => {
export const requestDiscordClientClose = () => { export const requestDiscordClientClose = () => {
return new Promise((res) => { return new Promise((res) => {
io.timeout(25000).emit('request_client_close'); io.timeout(25000).emit('request_client_close');
pdabProcess = false;
res(); res();
}); });
}; };

View File

@@ -1,4 +1,4 @@
import { connectToChannel, leaveVoiceChannel, checkIfConnectedToVC, initDiscordBotClient, requestDiscordUsername, requestDiscordID, requestDiscordClientClose, closePdabSocketServer } from './pdabHandler.mjs'; import { connectToChannel, leaveVoiceChannel, checkIfConnectedToVC, initDiscordBotClient, requestDiscordUsername, requestDiscordID, requestDiscordClientClose, closePdabSocketServer, setDiscordClientPrsense, startPdabSocketServer } from './pdabHandler.mjs';
import { openOP25, closeOP25 } from '../op25Handler/op25Handler.mjs'; import { openOP25, closeOP25 } from '../op25Handler/op25Handler.mjs';
let activeDiscordClient = undefined; let activeDiscordClient = undefined;
@@ -8,16 +8,26 @@ let activeDiscordClient = undefined;
* @param {object} joinData The object containing all the information to join the server * @param {object} joinData The object containing all the information to join the server
*/ */
export const joinDiscordVC = async (joinData) => { export const joinDiscordVC = async (joinData) => {
console.log("Join requested: ", joinData) console.log("Join requested: ", joinData);
const connection = await new Promise(async (res) => { const connection = await new Promise(async (res) => {
// Check if a client already exists // Check if a client already exists
console.log("Checking if there is a client open");
if (!await checkIfClientIsOpen()) { if (!await checkIfClientIsOpen()) {
console.log("There is no open client, starting it now");
await startPdabSocketServer();
// Open an instance of OP25
console.log("Starting OP25")
openOP25(joinData.system);
// Open a new client and join the requested channel with the requested ID // Open a new client and join the requested channel with the requested ID
initDiscordBotClient(joinData.clientID, () => { initDiscordBotClient(joinData.clientID, () => {
// Open an instance of OP25 console.log("Started PDAB");
openOP25(joinData.system);
console.log("Setting the presense of the bot");
setDiscordClientPrsense(joinData.system);
// Add the client object to the IO instance // Add the client object to the IO instance
console.log("Connecting to channel")
connectToChannel(joinData.channelID, (connectionStatus) => { connectToChannel(joinData.channelID, (connectionStatus) => {
console.log("Bot Connected to VC:", connectionStatus); console.log("Bot Connected to VC:", connectionStatus);
res(connectionStatus); res(connectionStatus);
@@ -25,7 +35,9 @@ export const joinDiscordVC = async (joinData) => {
}); });
} else { } else {
// Join the requested channel with the requested ID // Join the requested channel with the requested ID
// Add the client object to the IO instance console.log("There is an open client");
console.log("Connecting to channel")
const connection = connectToChannel(joinData.channelID); const connection = connectToChannel(joinData.channelID);
console.log("Bot Connected to VC::"); console.log("Bot Connected to VC::");
res(connection); res(connection);

View File

@@ -1,4 +1,6 @@
import { spawn } from "child_process"; import { spawn } from "child_process";
import dotenv from 'dotenv';
dotenv.config()
/** /**
* Object to store references to spawned processes. * Object to store references to spawned processes.
@@ -12,11 +14,11 @@ const runningProcesses = {};
* @param {string[]} args - The arguments to pass to the process. * @param {string[]} args - The arguments to pass to the process.
* @param {boolean} waitForClose - Set this to wait to return until the process exits * @param {boolean} waitForClose - Set this to wait to return until the process exits
*/ */
export const launchProcess = (processName, args, waitForClose=false, pcwd=undefined) => { export const launchProcess = (processName, args, waitForClose = false, pcwd = undefined) => {
if (!runningProcesses[processName]) { if (!runningProcesses[processName]) {
let childProcess; let childProcess;
if (pcwd) { if (pcwd) {
childProcess = spawn(processName, args, {cwd: pcwd}); childProcess = spawn(processName, args, { cwd: pcwd });
} }
else { else {
childProcess = spawn(processName, args); childProcess = spawn(processName, args);
@@ -25,11 +27,29 @@ export const launchProcess = (processName, args, waitForClose=false, pcwd=undefi
// Store reference to the spawned process // Store reference to the spawned process
runningProcesses[processName] = childProcess; runningProcesses[processName] = childProcess;
// Output the process output in development
var scriptOutput = "";
// Get the stdout from the child process
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', (data) => {
if (process.env.NODE_ENV === "development") console.log(`Data from ${processName}:`, data);
scriptOutput += data.toString();
});
// Get the stderr from the child process
childProcess.stderr.setEncoding('utf8');
childProcess.stderr.on('data', (data) => {
if (process.env.NODE_ENV === "development") console.log(`Data from ${processName}:`, data);
scriptOutput += data.toString();
})
let code = new Promise(res => { let code = new Promise(res => {
childProcess.on('exit', (code, signal) => { childProcess.on('exit', (code, signal) => {
// Remove reference to the process when it exits // Remove reference to the process when it exits
delete runningProcesses[processName]; delete runningProcesses[processName];
console.log(`${processName} process exited with code ${code} and signal ${signal}`); console.log(`${processName} process exited with code ${code} and signal ${signal}`);
console.log("Child process console output: ", scriptOutput);
res(code); res(code);
}) })
}); });

232
client/package-lock.json generated
View File

@@ -10,6 +10,7 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@discordjs/voice": "^0.16.1", "@discordjs/voice": "^0.16.1",
"chai-http": "^4.4.0",
"convert-units": "^2.3.4", "convert-units": "^2.3.4",
"discord.js": "^14.14.1", "discord.js": "^14.14.1",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
@@ -236,11 +237,21 @@
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
}, },
"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=="
},
"node_modules/@types/cookie": { "node_modules/@types/cookie": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
}, },
"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=="
},
"node_modules/@types/cors": { "node_modules/@types/cors": {
"version": "2.8.17", "version": "2.8.17",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
@@ -257,6 +268,15 @@
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
}, },
"node_modules/@types/superagent": {
"version": "4.1.13",
"resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.13.tgz",
"integrity": "sha512-YIGelp3ZyMiH0/A09PMAORO0EBGlF5xIKfDpK74wdYvWUs2o96b5CItJcWPdH409b7SAXIIG6p8NdU/4U2Maww==",
"dependencies": {
"@types/cookiejar": "*",
"@types/node": "*"
}
},
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.5.10", "version": "8.5.10",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
@@ -341,6 +361,11 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
}, },
"node_modules/asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
},
"node_modules/assertion-error": { "node_modules/assertion-error": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
@@ -350,6 +375,11 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -491,6 +521,38 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/chai-http": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/chai-http/-/chai-http-4.4.0.tgz",
"integrity": "sha512-uswN3rZpawlRaa5NiDUHcDZ3v2dw5QgLyAwnQ2tnVNuP7CwIsOFuYJ0xR1WiR7ymD4roBnJIzOUep7w9jQMFJA==",
"dependencies": {
"@types/chai": "4",
"@types/superagent": "4.1.13",
"charset": "^1.0.1",
"cookiejar": "^2.1.4",
"is-ip": "^2.0.0",
"methods": "^1.1.2",
"qs": "^6.11.2",
"superagent": "^8.0.9"
},
"engines": {
"node": ">=10"
}
},
"node_modules/chai-http/node_modules/qs": {
"version": "6.12.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
"integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==",
"dependencies": {
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/chalk": { "node_modules/chalk": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -506,6 +568,14 @@
"url": "https://github.com/chalk/chalk?sponsor=1" "url": "https://github.com/chalk/chalk?sponsor=1"
} }
}, },
"node_modules/charset": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz",
"integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/check-error": { "node_modules/check-error": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.0.0.tgz", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.0.0.tgz",
@@ -571,6 +641,25 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}, },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/component-emitter": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
"integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/content-disposition": { "node_modules/content-disposition": {
"version": "0.5.4", "version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -612,6 +701,11 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
}, },
"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=="
},
"node_modules/cors": { "node_modules/cors": {
"version": "2.8.5", "version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
@@ -677,6 +771,14 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/depd": { "node_modules/depd": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -694,6 +796,15 @@
"npm": "1.2.8000 || >= 1.4.16" "npm": "1.2.8000 || >= 1.4.16"
} }
}, },
"node_modules/dezalgo": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
"dependencies": {
"asap": "^2.0.0",
"wrappy": "1"
}
},
"node_modules/diff": { "node_modules/diff": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
@@ -948,6 +1059,11 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
}, },
"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=="
},
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -1015,6 +1131,33 @@
"flat": "cli.js" "flat": "cli.js"
} }
}, },
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/formidable": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz",
"integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==",
"dependencies": {
"dezalgo": "^1.0.4",
"hexoid": "^1.0.0",
"once": "^1.4.0",
"qs": "^6.11.0"
},
"funding": {
"url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
"node_modules/forwarded": { "node_modules/forwarded": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -1195,6 +1338,14 @@
"he": "bin/he" "he": "bin/he"
} }
}, },
"node_modules/hexoid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
"integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==",
"engines": {
"node": ">=8"
}
},
"node_modules/http-errors": { "node_modules/http-errors": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@@ -1235,6 +1386,14 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
}, },
"node_modules/ip-regex": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
"integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==",
"engines": {
"node": ">=4"
}
},
"node_modules/ipaddr.js": { "node_modules/ipaddr.js": {
"version": "1.9.1", "version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -1284,6 +1443,17 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/is-ip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-ip/-/is-ip-2.0.0.tgz",
"integrity": "sha512-9MTn0dteHETtyUx8pxqMwg5hMBi3pvlyglJ+b79KOCca0po23337LbVV2Hl4xmMvfw++ljnO0/+5G6G+0Szh6g==",
"dependencies": {
"ip-regex": "^2.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/is-number": { "node_modules/is-number": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -1543,6 +1713,17 @@
"get-func-name": "^2.0.1" "get-func-name": "^2.0.1"
} }
}, },
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/magic-bytes.js": { "node_modules/magic-bytes.js": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.7.0.tgz", "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.7.0.tgz",
@@ -1988,6 +2169,20 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"node_modules/semver": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/send": { "node_modules/send": {
"version": "0.18.0", "version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
@@ -2200,6 +2395,38 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/superagent": {
"version": "8.1.2",
"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",
"dependencies": {
"component-emitter": "^1.3.0",
"cookiejar": "^2.1.4",
"debug": "^4.3.4",
"fast-safe-stringify": "^2.1.1",
"form-data": "^4.0.0",
"formidable": "^2.1.2",
"methods": "^1.1.2",
"mime": "2.6.0",
"qs": "^6.11.0",
"semver": "^7.3.8"
},
"engines": {
"node": ">=6.4.0 <13 || >=14"
}
},
"node_modules/superagent/node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -2369,6 +2596,11 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/yargs": { "node_modules/yargs": {
"version": "17.7.2", "version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",

View File

@@ -24,8 +24,9 @@
"socket.io-client": "^4.7.2" "socket.io-client": "^4.7.2"
}, },
"devDependencies": { "devDependencies": {
"chai-http": "^4.4.0",
"chai": "^5.1.0", "chai": "^5.1.0",
"mocha": "^10.4.0", "mocha": "^10.4.0",
"typescript": "^5.3.3" "typescript": "^5.3.3"
} }
} }

View File

@@ -4,8 +4,8 @@
npm install npm install
# Install OP25 Updates # Install OP25 Updates
cd ./op25 #cd ./op25
bash rebuild.sh #bash rebuild.sh
# Check for PDAB updates # Check for PDAB updates
cd ../discordAudioBot/pdab cd ../discordAudioBot/pdab

View File

@@ -16,6 +16,12 @@ if [[ ! -f "$(pwd)/package.json" ]]; then
exit 1 exit 1
fi fi
# Check to make sure the pi user exists
if ! id "pi" &>/dev/null; then
echo "Error: User pi does not exist."
exit 1
fi
####------------------- Functions ####------------------- Functions
# Function to prompt user for input with a specific message and store the result in a variable # Function to prompt user for input with a specific message and store the result in a variable
prompt_user() { prompt_user() {
@@ -147,7 +153,8 @@ echo "Installing npm dependencies..."
npm install npm install
# Get rid of PEP 668 # Get rid of PEP 668
rm -rf /usr/lib/python3.11/EMTERNALL-MANAGED rm -rf /usr/lib/python3.11/EMTERNALL-MANAGED # Not sure if this was an attrocious fat finger or if this is needed, doesn't throw an error, so...
rm -rf /usr/lib/python3.11/EXTERNALLY-MANAGED
# Getting the Python DAB # Getting the Python DAB
echo "Installing PDAB and Dependencies" echo "Installing PDAB and Dependencies"
@@ -181,7 +188,7 @@ echo "OP25_FULL_PATH=$op25_full_path" >> .env
echo "" >> .env echo "" >> .env
echo "# Core config, DO NOT TOUCH UNLESS YOU KNOW WHAT YOU ARE DOING" >> .env echo "# Core config, DO NOT TOUCH UNLESS YOU KNOW WHAT YOU ARE DOING" >> .env
echo "CONFIG_PATH=./config/radioPresets.json" >> .env echo "CONFIG_PATH=./config/radioPresets.json" >> .env
python3 ./discordAudioBot/pdab/getDevices.py runuser -l pi -c 'python3 ./discordAudioBot/pdab/getDevices.py'
audio_device_id=$(prompt_user "Enter the ID of the 'input' audio device you would like to use (most often 'default')") audio_device_id=$(prompt_user "Enter the ID of the 'input' audio device you would like to use (most often 'default')")
echo "AUDIO_DEVICE_ID=$audio_device_id" >> .env echo "AUDIO_DEVICE_ID=$audio_device_id" >> .env
echo "PDAB_PORT=3110" >> .env echo "PDAB_PORT=3110" >> .env
@@ -297,7 +304,7 @@ confirm="${confirm,,}"
#echo "To configure the app, please go to http://$nodeIP:$nodePort" # TODO - uncomment when webapp is built #echo "To configure the app, please go to http://$nodeIP:$nodePort" # TODO - uncomment when webapp is built
echo "Thank you for joining the network!" echo "Thank you for joining the network!"
if [[ "$confirm" != "y" && "$confirm" != "yes" ]]; then if [[ "$confirm" == "y" && "$confirm" == "yes" ]]; then
# Prompt user to press any key before rebooting # Prompt user to press any key before rebooting
read -rsp $'System will now reboot, press any key to continue or Ctrl+C to cancel...\n' -n1 key read -rsp $'System will now reboot, press any key to continue or Ctrl+C to cancel...\n' -n1 key
echo "Rebooting..." echo "Rebooting..."

View File

@@ -1,6 +1,7 @@
// Import necessary modules for testing // Import necessary modules for testing
import { expect } from 'chai'; import { expect } from 'chai'
import io from 'socket.io-client'; import io from 'socket.io-client';
const ioClient = io;
import dotenv from 'dotenv'; import dotenv from 'dotenv';
dotenv.config() dotenv.config()
@@ -15,32 +16,31 @@ before(async done => {
}); });
after(async () => { after(async () => {
// Any teardown needed after tests
try{
await socket.close();
}
catch {
console.log("Socket already closed");
}
console.log('Closing PDAB Socker Server');
await closePdabSocketServer(); await closePdabSocketServer();
}); })
describe('Socket Server Tests', done => {
after(async () => {
// Any teardown needed after tests
try {
await socket.close();
}
catch {
console.log("Socket already closed");
}
console.log('Closing PDAB Socker Server');
});
describe('Python Discord Bot Socket IPC Tests', done => {
it('Should open a socket server and callback when the client is connected and ready', done => { it('Should open a socket server and callback when the client is connected and ready', done => {
let clientConnected = false; const clientId = process.env.TEST_CLIENT_TOKEN;
const clientId = process.env.DISCORD_CLIENT_ID;
const callback = () => { const callback = () => {
clientConnected = true;
expect(clientConnected).to.be.true;
done(); done();
}; };
initDiscordBotClient(clientId, callback); initDiscordBotClient(clientId, callback, false);
socket = io.connect(`http://localhost:${process.env.PDAB_PORT}`); socket = ioClient.connect(`http://localhost:${process.env.PDAB_PORT}`);
socket.on('connect', () => { socket.on('connect', () => {
socket.emit('discord_ready') socket.emit('discord_ready')
@@ -69,7 +69,7 @@ describe('Python Discord Bot Socket IPC Tests', done => {
expect(data).to.deep.equal({ guildId: process.env.TEST_GUILD_ID }); expect(data).to.deep.equal({ guildId: process.env.TEST_GUILD_ID });
callback(false, false); callback(false, false);
}); });
// Simulate emitting 'leave_server' event // Simulate emitting 'leave_server' event
const openStatus = await leaveVoiceChannel(process.env.TEST_GUILD_ID); const openStatus = await leaveVoiceChannel(process.env.TEST_GUILD_ID);
@@ -95,19 +95,19 @@ describe('Python Discord Bot Socket IPC Tests', done => {
socket.on('request_discord_username', (data, callback) => { socket.on('request_discord_username', (data, callback) => {
console.log('Username Check data:', data); console.log('Username Check data:', data);
expect(data).to.deep.equal({ guildId: process.env.TEST_GUILD_ID }); expect(data).to.deep.equal({ guildId: process.env.TEST_GUILD_ID });
callback('!bot-username'); callback(process.env.EXPECTED_USERNAME);
}); });
// Simulate emitting 'request_discord_username' event // Simulate emitting 'request_discord_username' event
const username = await requestDiscordUsername(process.env.TEST_GUILD_ID); const username = await requestDiscordUsername(process.env.TEST_GUILD_ID);
// Assert the username returned from the server // Assert the username returned from the server
expect(username).to.equal("!bot-username"); expect(username).to.equal(process.env.EXPECTED_USERNAME);
}); });
it('Should emit command for and return discord client ID', async () => { it('Should emit command for and return discord client ID', async () => {
socket.on('request_discord_id', (callback) => { socket.on('request_discord_id', (callback) => {
callback(process.env.EXPECTED_CLIENT_ID); callback(process.env.EXPECTED_CLIENT_ID);
}); });
// Simulate emitting 'request_discord_id' event // Simulate emitting 'request_discord_id' event
const clientId = await requestDiscordID(); const clientId = await requestDiscordID();
@@ -124,4 +124,71 @@ describe('Python Discord Bot Socket IPC Tests', done => {
requestDiscordClientClose(); requestDiscordClientClose();
}); });
});
describe('Socket Client & Python IPC Tests', done => {
it('Should open a socket server and callback when the client is connected and ready', done => {
let clientConnected = false;
const clientId = process.env.TEST_CLIENT_TOKEN;
const callback = () => {
clientConnected = true;
expect(clientConnected).to.be.true;
done();
};
initDiscordBotClient(clientId, callback);
});
it('Should emit command for and return status from join server', async () => {
// Simulate emitting 'join_server' event
const status = await connectToChannel(process.env.TEST_CHANNEL_ID);
// Check the server sent the expected info
// Assert the status returned from the server
expect(status).to.be.true;
});
it('Should emit command for and return status if connected to voice channel', async () => {
// Simulate emitting 'check_discord_vc_connected' event
const isConnected = await checkIfConnectedToVC(process.env.TEST_GUILD_ID);
// Assert the connection status returned from the server
expect(isConnected).to.be.true;
});
it('Should emit command for and return username for request discord username', async () => {
// Simulate emitting 'request_discord_username' event
const username = await requestDiscordUsername(process.env.TEST_GUILD_ID);
// Assert the username returned from the server
expect(username).to.equal(process.env.EXPECTED_USERNAME);
});
it('Should emit command for and return discord client ID', async () => {
// Simulate emitting 'request_discord_id' event
const clientId = await requestDiscordID();
console.log("type of client id", typeof clientId, typeof process.env.EXPECTED_CLIENT_ID);
// Assert the client ID returned from the server
expect(clientId).to.equal(Number(process.env.EXPECTED_CLIENT_ID));
});
it('Should emit command for and return open status for leave server', async () => {
// Simulate emitting 'leave_server' event
const openStatus = await leaveVoiceChannel(process.env.TEST_GUILD_ID);
// Assert the open status returned from the server
expect(openStatus).to.be.false;
});
it('Should emit command for discord client to close', async () => {
// Simulate emitting 'request_client_close' event
await requestDiscordClientClose();
});
}); });

View File

@@ -0,0 +1,40 @@
import { use } from 'chai';
import chaiHttp from 'chai-http';
const chai = use(chaiHttp)
chai.should();
import dotenv from 'dotenv';
dotenv.config()
import { joinDiscordVC, leaveDiscordVC } from '../discordAudioBot/pdabWrappers.mjs'
before(async () => {
// Any setup needed before tests
});
after(async () => {
// Any teardown needed after tests
});
describe('PDAB Wrapper Tests', () => {
it('Should open the discord bot, and join the first server when requested', async () => {
// Test case
const joinData = {
channelID: process.env.TEST_CHANNEL_ID,
clientID: process.env.TEST_CLIENT_TOKEN,
system: process.env.TEST_SYSTEM,
};
const connection = await joinDiscordVC(joinData);
console.log("Connection:", connection);
});
it('Should open OP25', async () => {
const res = await chai.request('http://localhost:8081').get('/');
expect(res).to.have.status(200); // Assuming 200 is the expected status code
// Add more assertions if needed
})
it("Should disconnect from the discord server", async () => {
await leaveDiscordVC(process.env.TEST_GUILD_ID);
})
});

21
server/Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
# Use the official Node.js image as the base image
FROM node:20
# Set the working directory inside the container
WORKDIR /server
# Copy package.json and package-lock.json (if available) to the working directory
COPY package*.json ./
# Install dependencies
RUN npm install -g node-gyp
RUN npm install
# Copy the rest of the application code to the working directory
COPY . .
# Expose the port on which your Node.js application will run
EXPOSE 3000
# Command to run the Node.js application
CMD ["node", "."]

View File

@@ -41,9 +41,10 @@ export async function autocomplete(nodeIo, interaction) {
*/ */
export async function execute(nodeIo, interaction) { export async function execute(nodeIo, interaction) {
// Check if the user is in a VC // Check if the user is in a VC
if (!interaction.member.voice.channel) { return await interaction.editReply({ content: `<@${interaction.member.id}>, you need to enter a voice channel before use the command`, ephemeral: true }) } if (!interaction.member.voice.channel) { return await interaction.editReply({ content: `<@${interaction.member.id}>, you need to enter a voice channel before you use this command`, ephemeral: true }) }
// Grab the channel if the user is connected to VC // Grab the channel if the user is connected to VC
const channelToJoin = interaction.member.voice.channel; const channelToJoin = interaction.member.voice.channel;
console.log(`The user '${interaction.member.id}' is in the voice channel '${channelToJoin}'`);
// Get the selected system option from the command interaction // Get the selected system option from the command interaction
const selectedSystem = interaction.options.getString('system'); const selectedSystem = interaction.options.getString('system');
@@ -56,13 +57,19 @@ export async function execute(nodeIo, interaction) {
const joinSelectedNode = async (selectedNodeSocketId) => { const joinSelectedNode = async (selectedNodeSocketId) => {
const openSocket = await nodeIo.sockets.sockets.get(selectedNodeSocketId); const openSocket = await nodeIo.sockets.sockets.get(selectedNodeSocketId);
// Get the open ID for this connection\ // Get the open ID for this connection\
const discordToken = await getAvailableTokensInGuild(nodeIo, interaction.guild.id); const ss = await getAvailableTokensInGuild(nodeIo, interaction.guild.id);
// TODO - Implement a method to have preferred tokens (bot users) for specific systems console.log("Available discord tokens: ", discordTokens);
console.log("Joining selected open socket:", selectedNodeSocketId, system.name, channelToJoin.id, openSocket.node.name, discordToken);
// Ask the node to join the selected channel and system if (discordTokens.length >= 1) {
await requestNodeJoinSystem(openSocket, system.name, channelToJoin.id, discordToken[0].token); // TODO - Implement a method to have preferred tokens (bot users) for specific systems
console.log("Joining selected open socket:", selectedNodeSocketId, system.name, channelToJoin.id, openSocket.node.name, discordTokens[0].token);
// Ask the node to join the selected channel and system
await requestNodeJoinSystem(openSocket, system.name, channelToJoin.id, discordTokens[0].token);
}
else {
return await interaction.editReply({ content: `<@${interaction.member.id}>, there are no free bots. Free up or create a new bot ID (discord app) to listen to this system.`, ephemeral: true })
}
} }
// Get all open socket nodes // Get all open socket nodes

View File

@@ -74,7 +74,7 @@ export function addEnabledEventListeners(serverClient, _eventsPath = "./events")
} }
// The discord client // The discord client
export const serverClient = new Client({ intents: [GatewayIntentBits.Guilds] }); export const serverClient = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates] });
// Run when the bot is ready // Run when the bot is ready
serverClient.on('ready', async () => { serverClient.on('ready', async () => {

View File

@@ -37,10 +37,7 @@ export const checkOnlineBotsInGuild = async (nodeIo, guildId) => {
console.log("Online bots in the guild:", onlineBots); console.log("Online bots in the guild:", onlineBots);
// Filter any discordIDs that are not active // Filter any discordIDs that are not active
var availableDiscordIDs = discordIDs.filter(discordID => discordID.active == true); const availableDiscordIDs = discordIDs.filter(discordID => discordID.active == true).filter(discordID => !onlineBots.some(bot => Number(bot.discord_id) == discordID.discord_id));
// Filter out discordIDs that are not found in onlineBots
availableDiscordIDs = availableDiscordIDs.filter(discordID => !onlineBots.some(bot => bot.discord_id === discordID.discord_id));
// Return the unavailable discordIDs // Return the unavailable discordIDs
return availableDiscordIDs; return availableDiscordIDs;

25
server/makefile Normal file
View File

@@ -0,0 +1,25 @@
# Define variables
DOCKER_IMAGE_NAME := drb-server
# Define targets and rules
.PHONY: clean build run
clean:
@echo "Cleaning existing Docker images, containers, and builds..."
docker stop drb || true
docker rm drb || true
docker rmi $(DOCKER_IMAGE_NAME) || true
build:
@echo "Building Docker image..."
docker build -t $(DOCKER_IMAGE_NAME) .
run:
@echo "Running Docker container..."
docker run -d -e NODE_ENV=${NODE_ENV} \
-e SERVER_PORT=${SERVER_PORT} \
-e MONGO_URL=${MONGO_URL} \
-e DISCORD_TOKEN=${DISCORD_TOKEN} \
-p ${SERVER_PORT}:${SERVER_PORT} \
--name=drb \
$(DOCKER_IMAGE_NAME)