Compare commits
7 Commits
4831bb817c
...
automated-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57aaf04119 | ||
| dc988a41c1 | |||
|
|
43dfa7b5ad | ||
|
|
8f56fd9b92 | ||
|
|
702e291fcb | ||
|
|
2ab5a181bd | ||
|
|
81a215f048 |
56
.gitea/workflows/DRBv3_server_build.yaml
Normal file
56
.gitea/workflows/DRBv3_server_build.yaml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
name: release-tag
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
env:
|
||||||
|
DOCKER_ORG: teacup
|
||||||
|
DOCKER_LATEST: nightly
|
||||||
|
RUNNER_TOOL_CACHE: /toolcache
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Set up Docker BuildX
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
with: # replace it with your local IP
|
||||||
|
config-inline: |
|
||||||
|
[registry."${{ secrets.LOCAL_GITEA_IP}}:3000"]
|
||||||
|
http = true
|
||||||
|
insecure = true
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ${{ secrets.LOCAL_GITEA_IP}}:3000 # replace it with your local IP
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Get Meta
|
||||||
|
id: meta
|
||||||
|
run: |
|
||||||
|
echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}') >> $GITHUB_OUTPUT
|
||||||
|
echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: |
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: | # replace it with your local IP and tags
|
||||||
|
${{ secrets.LOCAL_GITEA_IP}}:3000/${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}
|
||||||
|
${{ secrets.LOCAL_GITEA_IP}}:3000/${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
// addons/addon1/index.js
|
// addons/addon1/index.js
|
||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "server");
|
||||||
|
|
||||||
// Function called by the main application to initialize the addon
|
// Function called by the main application to initialize the addon
|
||||||
export function initialize(nodeIo, config) {
|
export function initialize(nodeIo, config) {
|
||||||
console.log(`Initializing ${config.name}`);
|
log.INFO(`Initializing ${config.name}`);
|
||||||
|
|
||||||
// Call other functions within the addon module
|
// Call other functions within the addon module
|
||||||
registerSocketEvents(nodeIo, config);
|
registerSocketEvents(nodeIo, config);
|
||||||
@@ -12,6 +14,6 @@ export function initialize(nodeIo, config) {
|
|||||||
// Function to register Socket.IO event handlers
|
// Function to register Socket.IO event handlers
|
||||||
function registerSocketEvents(nodeIo, config) {
|
function registerSocketEvents(nodeIo, config) {
|
||||||
nodeIo.on(config.options.eventName, (data) => {
|
nodeIo.on(config.options.eventName, (data) => {
|
||||||
console.log(`Received event "${config.options.eventName}" from client:`, data);
|
log.DEBUG(`Received event "${config.options.eventName}" from client:`, data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "discordBot.command.join");
|
||||||
import { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js';
|
import { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js';
|
||||||
import { requestNodeJoinSystem, checkIfNodeIsConnectedToVC, checkIfNodeHasOpenDiscordClient, getNodeCurrentListeningSystem } from '../../modules/socketServerWrappers.mjs';
|
import { requestNodeJoinSystem, checkIfNodeIsConnectedToVC, checkIfNodeHasOpenDiscordClient, getNodeCurrentListeningSystem } from '../../modules/socketServerWrappers.mjs';
|
||||||
import { getSystemsByNuid, getAllSystems, getSystemByName } from '../../modules/mongo-wrappers/mongoSystemsWrappers.mjs';
|
import { getSystemsByNuid, getAllSystems, getSystemByName } from '../../modules/mongo-wrappers/mongoSystemsWrappers.mjs';
|
||||||
@@ -27,7 +29,7 @@ export async function autocomplete(nodeIo, interaction) {
|
|||||||
const choices = await getAllSystems();
|
const choices = await getAllSystems();
|
||||||
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue));
|
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue));
|
||||||
|
|
||||||
console.log(focusedValue, choices, filtered);
|
log.DEBUG(focusedValue, choices, filtered);
|
||||||
|
|
||||||
await interaction.respond(
|
await interaction.respond(
|
||||||
filtered.map(choice => ({ name: choice.name, value: choice.name })),
|
filtered.map(choice => ({ name: choice.name, value: choice.name })),
|
||||||
@@ -44,7 +46,7 @@ export async function execute(nodeIo, interaction) {
|
|||||||
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 }) }
|
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}'`);
|
log.INFO(`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');
|
||||||
@@ -58,11 +60,11 @@ export async function execute(nodeIo, interaction) {
|
|||||||
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 discordTokens = await getAvailableTokensInGuild(nodeIo, interaction.guild.id);
|
const discordTokens = await getAvailableTokensInGuild(nodeIo, interaction.guild.id);
|
||||||
console.log("Available discord tokens: ", discordTokens);
|
log.DEBUG("Available discord tokens: ", discordTokens);
|
||||||
|
|
||||||
if (discordTokens.length >= 1) {
|
if (discordTokens.length >= 1) {
|
||||||
// TODO - Implement a method to have preferred tokens (bot users) for specific systems
|
// 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);
|
log.INFO("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
|
// Ask the node to join the selected channel and system
|
||||||
await requestNodeJoinSystem(openSocket, system.name, channelToJoin.id, discordTokens[0].token);
|
await requestNodeJoinSystem(openSocket, system.name, channelToJoin.id, discordTokens[0].token);
|
||||||
@@ -74,7 +76,7 @@ export async function execute(nodeIo, interaction) {
|
|||||||
|
|
||||||
// Get all open socket nodes
|
// Get all open socket nodes
|
||||||
const openSockets = [...await nodeIo.allSockets()]; // TODO - Filter the returned nodes to only nodes that have the radio capability
|
const openSockets = [...await nodeIo.allSockets()]; // TODO - Filter the returned nodes to only nodes that have the radio capability
|
||||||
console.log("All open sockets: ", openSockets);
|
log.DEBUG("All open sockets: ", openSockets);
|
||||||
|
|
||||||
var availableNodes = [];
|
var availableNodes = [];
|
||||||
// Check each open socket to see if the node has the requested system
|
// Check each open socket to see if the node has the requested system
|
||||||
@@ -85,14 +87,14 @@ export async function execute(nodeIo, interaction) {
|
|||||||
if (hasOpenClient) {
|
if (hasOpenClient) {
|
||||||
let currentSystem = await getNodeCurrentListeningSystem(openSocket);
|
let currentSystem = await getNodeCurrentListeningSystem(openSocket);
|
||||||
if (currentSystem != system.name) {
|
if (currentSystem != system.name) {
|
||||||
console.log("Node is listening to a different system than requested", openSocket.node.name);
|
log.INFO("Node is listening to a different system than requested", openSocket.node.name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the bot has an open voice connection in the requested server already
|
// Check if the bot has an open voice connection in the requested server already
|
||||||
const connected = await checkIfNodeIsConnectedToVC(nodeIo, interaction.guild.id, openSocket.node.nuid);
|
const connected = await checkIfNodeIsConnectedToVC(nodeIo, interaction.guild.id, openSocket.node.nuid);
|
||||||
console.log("Connected:", connected);
|
log.INFO("Connected:", connected);
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
// Check if this node has the requested system, if so add it to the availble array
|
// Check if this node has the requested system, if so add it to the availble array
|
||||||
if (system.nodes.includes(openSocket.node.nuid)) {
|
if (system.nodes.includes(openSocket.node.nuid)) {
|
||||||
@@ -102,7 +104,7 @@ export async function execute(nodeIo, interaction) {
|
|||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
console.log("Availble nodes:", availableNodes.map(socket => socket.node.name));
|
log.DEBUG("Availble nodes:", availableNodes.map(socket => socket.node.name));
|
||||||
|
|
||||||
// If there are no available nodes, let the user know there are none available
|
// If there are no available nodes, let the user know there are none available
|
||||||
if (availableNodes.length == 0) {
|
if (availableNodes.length == 0) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "discordBot.command.leave");
|
||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import { requestBotLeaveServer, getSocketIdByNuid } from '../../modules/socketServerWrappers.mjs';
|
import { requestBotLeaveServer, getSocketIdByNuid } from '../../modules/socketServerWrappers.mjs';
|
||||||
import { checkOnlineBotsInGuild } from '../modules/wrappers.mjs'
|
import { checkOnlineBotsInGuild } from '../modules/wrappers.mjs'
|
||||||
@@ -25,11 +27,11 @@ export async function autocomplete(nodeIo, interaction) {
|
|||||||
const focusedValue = interaction.options.getFocused();
|
const focusedValue = interaction.options.getFocused();
|
||||||
const choices = (await checkOnlineBotsInGuild(nodeIo, interaction.guild.id));
|
const choices = (await checkOnlineBotsInGuild(nodeIo, interaction.guild.id));
|
||||||
|
|
||||||
console.log(choices);
|
log.DEBUG(choices);
|
||||||
|
|
||||||
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue)).map(choice => choice = {name: choice.name, value: choice.nuid});
|
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue)).map(choice => choice = {name: choice.name, value: choice.nuid});
|
||||||
|
|
||||||
console.log(focusedValue, choices, filtered);
|
log.DEBUG(focusedValue, choices, filtered);
|
||||||
|
|
||||||
await interaction.respond(filtered);
|
await interaction.respond(filtered);
|
||||||
}
|
}
|
||||||
@@ -44,7 +46,7 @@ export async function execute(nodeIo, interaction) {
|
|||||||
// Get the requested bot
|
// Get the requested bot
|
||||||
const selectedNode = interaction.options.getString('bot');
|
const selectedNode = interaction.options.getString('bot');
|
||||||
const socket = await getSocketIdByNuid(nodeIo, selectedNode);
|
const socket = await getSocketIdByNuid(nodeIo, selectedNode);
|
||||||
console.log("All open sockets:", socket, selectedNode);
|
log.DEBUG("All open sockets:", socket, selectedNode);
|
||||||
await requestBotLeaveServer(socket, interaction.guild.id);
|
await requestBotLeaveServer(socket, interaction.guild.id);
|
||||||
//await interaction.reply(`**Online Sockets: '${sockets}'**`);
|
//await interaction.reply(`**Online Sockets: '${sockets}'**`);
|
||||||
await interaction.editReply(`Ok <@${interaction.member.id}>, the bot is leaving shortly`);
|
await interaction.editReply(`Ok <@${interaction.member.id}>, the bot is leaving shortly`);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "discordBot.command.ping");
|
||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
|
|
||||||
// Exporting data property that contains the command structure for discord including any params
|
// Exporting data property that contains the command structure for discord including any params
|
||||||
@@ -17,10 +19,10 @@ export const deferInitialReply = false; // If we the initial reply in discord sh
|
|||||||
/*
|
/*
|
||||||
export async function autocomplete(nodeIo, interaction) {
|
export async function autocomplete(nodeIo, interaction) {
|
||||||
const focusedValue = interaction.options.getFocused();
|
const focusedValue = interaction.options.getFocused();
|
||||||
const choices = [];
|
const choices = []; // The array to be filled with the autocorrect values
|
||||||
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue));
|
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue));
|
||||||
console.log(focusedValue, choices, filtered);
|
log.INFO(focusedValue, choices, filtered);
|
||||||
await interaction.respond(filtered);
|
await interaction.respond(filtered.map(choice => ({name: choice.name, value: choice.name})));
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -32,7 +34,7 @@ export async function autocomplete(nodeIo, interaction) {
|
|||||||
export const execute = async (nodeIo, interaction) => {
|
export const execute = async (nodeIo, interaction) => {
|
||||||
try {
|
try {
|
||||||
const sockets = await nodeIo.allSockets();
|
const sockets = await nodeIo.allSockets();
|
||||||
console.log("All open sockets: ",sockets);
|
log.DEBUG("All open sockets: ",sockets);
|
||||||
//await interaction.reply(`**Online Sockets: '${sockets}'**`);
|
//await interaction.reply(`**Online Sockets: '${sockets}'**`);
|
||||||
await interaction.reply('**Pong.**');
|
await interaction.reply('**Pong.**');
|
||||||
//await interaction.channel.send('**Pong.**');
|
//await interaction.channel.send('**Pong.**');
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import { DebugBuilder } from "../../modules/debugger.mjs";
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
import { addSource } from '../../rss-manager/feedHandler.mjs'
|
import { addSource } from '../../rss-manager/sourceManager.mjs'
|
||||||
const log = new DebugBuilder("server", "add");
|
const log = new DebugBuilder("server", "discordBot.command.rssAdd");
|
||||||
|
|
||||||
// Exporting data property that contains the command structure for discord including any params
|
// Exporting data property that contains the command structure for discord including any params
|
||||||
export const data = new SlashCommandBuilder()
|
export const data = new SlashCommandBuilder()
|
||||||
.setName('add')
|
.setName('rss-add')
|
||||||
.setDescription('Add RSS Source')
|
.setDescription('Add RSS Source')
|
||||||
.addStringOption(option =>
|
.addStringOption(option =>
|
||||||
option.setName('title')
|
option.setName('title')
|
||||||
@@ -22,7 +22,7 @@ export const data = new SlashCommandBuilder()
|
|||||||
.setRequired(false))
|
.setRequired(false))
|
||||||
|
|
||||||
// Exporting other properties
|
// Exporting other properties
|
||||||
export const example = "/add [title] [https://domain.com/feed.xml] [category]"; // An example of how the command would be run in discord chat, this will be used for the help command
|
export const example = "/rss-add [title] [https://domain.com/feed.xml] [category]"; // An example of how the command would be run in discord chat, this will be used for the help command
|
||||||
export const deferInitialReply = false; // If we the initial reply in discord should be deferred. This gives extra time to respond, however the method of replying is different.
|
export const deferInitialReply = false; // If we the initial reply in discord should be deferred. This gives extra time to respond, however the method of replying is different.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,7 +37,7 @@ export async function autocomplete(nodeIo, interaction) {
|
|||||||
const focusedValue = interaction.options.getFocused();
|
const focusedValue = interaction.options.getFocused();
|
||||||
const choices = [];
|
const choices = [];
|
||||||
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue));
|
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue));
|
||||||
console.log(focusedValue, choices, filtered);
|
log.DEBUG(focusedValue, choices, filtered);
|
||||||
await interaction.respond(filtered);
|
await interaction.respond(filtered);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@@ -59,7 +59,7 @@ export const execute = async (nodeIo, interaction) => {
|
|||||||
log.DEBUG("Result from adding entry", result);
|
log.DEBUG("Result from adding entry", result);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
interaction.reply(`Adding ${title} to the list of RSS sources`);
|
interaction.reply(`Successfully added ${title} to the list of RSS sources`);
|
||||||
} else {
|
} else {
|
||||||
interaction.reply(`${title} already exists in the list of RSS sources`);
|
interaction.reply(`${title} already exists in the list of RSS sources`);
|
||||||
}
|
}
|
||||||
58
discordBot/commands/rssRemove.mjs
Normal file
58
discordBot/commands/rssRemove.mjs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
|
||||||
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
import { removeSource } from '../../rss-manager/sourceManager.mjs'
|
||||||
|
import { getAllFeeds, deleteFeedByTitle } from '../../modules/mongo-wrappers/mongoFeedsWrappers.mjs'
|
||||||
|
const log = new DebugBuilder("server", "discordBot.command.rssRemove");
|
||||||
|
|
||||||
|
// Exporting data property that contains the command structure for discord including any params
|
||||||
|
export const data = new SlashCommandBuilder()
|
||||||
|
.setName('rss-remove')
|
||||||
|
.setDescription('Add RSS Source')
|
||||||
|
.addStringOption(option =>
|
||||||
|
option.setName('title')
|
||||||
|
.setDescription('The title of the RSS feed')
|
||||||
|
.setRequired(true)
|
||||||
|
.setAutocomplete(true))
|
||||||
|
|
||||||
|
// Exporting other properties
|
||||||
|
export const example = "/rss-remove [title]"; // An example of how the command would be run in discord chat, this will be used for the help command
|
||||||
|
export const deferInitialReply = false; // If we the initial reply in discord should be deferred. This gives extra time to respond, however the method of replying is different.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to give the user auto-reply suggestions
|
||||||
|
* @param {any} nodeIo The nodeIO server for manipulation of sockets
|
||||||
|
* @param {any} interaction The interaction object
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function autocomplete(nodeIo, interaction) {
|
||||||
|
const focusedValue = interaction.options.getFocused();
|
||||||
|
const choices = await getAllFeeds() ?? [];
|
||||||
|
log.INFO("RSS Remove Choices:", choices);
|
||||||
|
const filtered = choices.filter(choice => choice.title.startsWith(focusedValue));
|
||||||
|
log.DEBUG(focusedValue, choices, filtered);
|
||||||
|
await interaction.respond(filtered.map(choice => ({ name: choice.title, value: choice.title })));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function to run when the command is called by a discord user
|
||||||
|
* @param {any} nodeIo The nodeIO server for manipulation of sockets
|
||||||
|
* @param {any} interaction The interaction object
|
||||||
|
*/
|
||||||
|
export const execute = async (nodeIo, interaction) => {
|
||||||
|
try {
|
||||||
|
var title = interaction.options.getString('title');
|
||||||
|
interaction.reply(`Removing ${title} from the list of RSS sources, please wait...`);
|
||||||
|
|
||||||
|
const results = await deleteFeedByTitle(title);
|
||||||
|
if (!results) {
|
||||||
|
log.WARN(`Failed to remove source: ${title}`);
|
||||||
|
interaction.editReply(`Failed to remove source: '${title}'`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
interaction.editReply(`${title} was successfully removed from the RSS sources.`)
|
||||||
|
} catch (err) {
|
||||||
|
log.ERROR(err)
|
||||||
|
interaction.editReply(err.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "discordBot.command.rssTrigger");
|
||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import { updateFeeds } from '../../rss-manager/feedHandler.mjs'
|
import { updateFeeds } from '../../rss-manager/feedHandler.mjs'
|
||||||
|
|
||||||
// Exporting data property that contains the command structure for discord including any params
|
// Exporting data property that contains the command structure for discord including any params
|
||||||
export const data = new SlashCommandBuilder()
|
export const data = new SlashCommandBuilder()
|
||||||
.setName('trigger-rss')
|
.setName('rss-trigger')
|
||||||
.setDescription('Manually triggers an RSS feed update');
|
.setDescription('Manually triggers an RSS feed update');
|
||||||
|
|
||||||
// Exporting other properties
|
// Exporting other properties
|
||||||
export const example = "/trigger-rss"; // An example of how the command would be run in discord chat, this will be used for the help command
|
export const example = "/rss-trigger"; // An example of how the command would be run in discord chat, this will be used for the help command
|
||||||
export const deferInitialReply = false; // If we the initial reply in discord should be deferred. This gives extra time to respond, however the method of replying is different.
|
export const deferInitialReply = false; // If we the initial reply in discord should be deferred. This gives extra time to respond, however the method of replying is different.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,7 +22,7 @@ export async function autocomplete(nodeIo, interaction) {
|
|||||||
const focusedValue = interaction.options.getFocused();
|
const focusedValue = interaction.options.getFocused();
|
||||||
const choices = [];
|
const choices = [];
|
||||||
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue));
|
const filtered = choices.filter(choice => choice.name.startsWith(focusedValue));
|
||||||
console.log(focusedValue, choices, filtered);
|
log.INFO(focusedValue, choices, filtered);
|
||||||
await interaction.respond(filtered);
|
await interaction.respond(filtered);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@@ -33,7 +35,6 @@ export async function autocomplete(nodeIo, interaction) {
|
|||||||
export const execute = async (nodeIo, interaction) => {
|
export const execute = async (nodeIo, interaction) => {
|
||||||
try {
|
try {
|
||||||
//const sockets = await nodeIo.allSockets();
|
//const sockets = await nodeIo.allSockets();
|
||||||
//console.log("All open sockets: ", sockets);
|
|
||||||
//await interaction.reply(`**Online Sockets: '${sockets}'**`);
|
//await interaction.reply(`**Online Sockets: '${sockets}'**`);
|
||||||
await interaction.reply('Triggering RSS update');
|
await interaction.reply('Triggering RSS update');
|
||||||
await updateFeeds(interaction.client);
|
await updateFeeds(interaction.client);
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "discordBot.command.update");
|
||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import { requestNodeUpdate } from '../../modules/socketServerWrappers.mjs';
|
import { requestNodeUpdate } from '../../modules/socketServerWrappers.mjs';
|
||||||
|
|
||||||
@@ -18,7 +20,7 @@ export const deferInitialReply = false; // If we the initial reply in discord sh
|
|||||||
export const execute = async (nodeIo, interaction) => {
|
export const execute = async (nodeIo, interaction) => {
|
||||||
try {
|
try {
|
||||||
const openSockets = [...await nodeIo.allSockets()]; // TODO - Filter the returned nodes to only nodes that have the radio capability
|
const openSockets = [...await nodeIo.allSockets()]; // TODO - Filter the returned nodes to only nodes that have the radio capability
|
||||||
console.log("All open sockets: ", openSockets);
|
log.DEBUG("All open sockets: ", openSockets);
|
||||||
|
|
||||||
// Check each open socket to see if the node has the requested system
|
// Check each open socket to see if the node has the requested system
|
||||||
await Promise.all(openSockets.map(openSocket => {
|
await Promise.all(openSockets.map(openSocket => {
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
|
import { DebugBuilder } from "../modules/debugger.mjs";
|
||||||
import { Client, GatewayIntentBits, Collection } from 'discord.js';
|
import { Client, GatewayIntentBits, Collection } from 'discord.js';
|
||||||
import { registerActiveCommands, unregisterAllCommands } from './modules/registerCommands.mjs'
|
import { registerActiveCommands, unregisterAllCommands } from './modules/registerCommands.mjs'
|
||||||
|
import { RSSController } from '../rss-manager/rssController.mjs'
|
||||||
import { join, dirname } from 'path';
|
import { join, dirname } from 'path';
|
||||||
import { readdirSync } from 'fs';
|
import { readdirSync } from 'fs';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
dotenv.config()
|
||||||
|
|
||||||
|
const log = new DebugBuilder("server", "discordBot");
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
import dotenv from 'dotenv';
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the enabled commands to the bot to be used by users in discord
|
* Add the enabled commands to the bot to be used by users in discord
|
||||||
@@ -25,18 +30,18 @@ export const addEnabledCommands = async (serverClient, _commandsPath = "./comman
|
|||||||
|
|
||||||
for (const file of commandFiles) {
|
for (const file of commandFiles) {
|
||||||
const filePath = await join(commandsPath, file);
|
const filePath = await join(commandsPath, file);
|
||||||
console.log(`Adding enabled command: ${filePath}`);
|
log.INFO(`Adding enabled command: ${filePath}`);
|
||||||
await import(`file://${filePath}`).then(command => {
|
await import(`file://${filePath}`).then(command => {
|
||||||
if (command.data instanceof Promise) {
|
if (command.data instanceof Promise) {
|
||||||
command.data.then(async (builder) => {
|
command.data.then(async (builder) => {
|
||||||
command.data = builder;
|
command.data = builder;
|
||||||
console.log("Importing command: ", command.data.name, command);
|
log.DEBUG("Importing command: ", command.data.name, command);
|
||||||
// Set a new item in the Collection
|
// Set a new item in the Collection
|
||||||
// With the key as the command name and the value as the exported module
|
// With the key as the command name and the value as the exported module
|
||||||
serverClient.commands.set(command.data.name, command);
|
serverClient.commands.set(command.data.name, command);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log("Importing command: ", command.data.name, command);
|
log.DEBUG("Importing command: ", command.data.name, command);
|
||||||
// Set a new item in the Collection
|
// Set a new item in the Collection
|
||||||
// With the key as the command name and the value as the exported module
|
// With the key as the command name and the value as the exported module
|
||||||
serverClient.commands.set(command.data.name, command);
|
serverClient.commands.set(command.data.name, command);
|
||||||
@@ -61,9 +66,9 @@ export function addEnabledEventListeners(serverClient, _eventsPath = "./events")
|
|||||||
|
|
||||||
for (const file of eventFiles) {
|
for (const file of eventFiles) {
|
||||||
const filePath = join(eventsPath, file);
|
const filePath = join(eventsPath, file);
|
||||||
console.log(`Adding enabled event listener: ${filePath}`);
|
log.INFO(`Adding enabled event listener: ${filePath}`);
|
||||||
import(`file://${filePath}`).then(event => {
|
import(`file://${filePath}`).then(event => {
|
||||||
console.log("Adding event: ", event);
|
log.DEBUG("Adding event: ", event);
|
||||||
if (event.once) {
|
if (event.once) {
|
||||||
serverClient.once(event.name, (...args) => event.execute(serverClient.nodeIo, ...args));
|
serverClient.once(event.name, (...args) => event.execute(serverClient.nodeIo, ...args));
|
||||||
} else {
|
} else {
|
||||||
@@ -78,15 +83,21 @@ export const serverClient = new Client({ intents: [GatewayIntentBits.Guilds, Gat
|
|||||||
|
|
||||||
// Run when the bot is ready
|
// Run when the bot is ready
|
||||||
serverClient.on('ready', async () => {
|
serverClient.on('ready', async () => {
|
||||||
console.log(`Logged in as ${serverClient.user.tag}!`);
|
log.INFO(`Logged in as ${serverClient.user.tag}!`);
|
||||||
|
|
||||||
// Add and register commands
|
// Add and register commands
|
||||||
await addEnabledCommands(serverClient);
|
await addEnabledCommands(serverClient);
|
||||||
|
|
||||||
// Config the discord bot with events
|
// Config the discord bot with events
|
||||||
await addEnabledEventListeners(serverClient);
|
await addEnabledEventListeners(serverClient);
|
||||||
|
|
||||||
|
// Start the RSS Controller
|
||||||
|
serverClient.RSSController = await new RSSController(serverClient);
|
||||||
|
serverClient.RSSController.start();
|
||||||
|
|
||||||
|
log.INFO("RSS Controller:", serverClient.RSSController);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Startup the discord bot
|
// Startup the discord bot
|
||||||
console.log(`Logging into discord with ID: ${process.env.DISCORD_TOKEN}`);
|
log.INFO(`Logging into discord with ID: ${process.env.DISCORD_TOKEN}`);
|
||||||
serverClient.login(process.env.DISCORD_TOKEN);
|
serverClient.login(process.env.DISCORD_TOKEN);
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "discordBot.events.interactionCreate");
|
||||||
import { Events } from 'discord.js';
|
import { Events } from 'discord.js';
|
||||||
|
|
||||||
export const name = Events.InteractionCreate;
|
export const name = Events.InteractionCreate;
|
||||||
|
|
||||||
export async function execute(nodeIo, interaction) {
|
export async function execute(nodeIo, interaction) {
|
||||||
const command = interaction.client.commands.get(interaction.commandName);
|
const command = interaction.client.commands.get(interaction.commandName);
|
||||||
console.log("Interaction created for command: ", command);
|
log.INFO("Interaction created for command: ", command);
|
||||||
|
|
||||||
// Execute autocomplete if the user is checking autocomplete
|
// Execute autocomplete if the user is checking autocomplete
|
||||||
if (interaction.isAutocomplete()) {
|
if (interaction.isAutocomplete()) {
|
||||||
console.log("Running autocomplete for command: ", command.data.name);
|
log.INFO("Running autocomplete for command: ", command.data.name);
|
||||||
return await command.autocomplete(nodeIo, interaction);
|
return await command.autocomplete(nodeIo, interaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +22,7 @@ export async function execute(nodeIo, interaction) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`${interaction.member.user} is running '${interaction.commandName}'`);
|
log.INFO(`${interaction.member.user} is running '${interaction.commandName}'`);
|
||||||
|
|
||||||
// Defer the initial reply if the command has the parameter set
|
// Defer the initial reply if the command has the parameter set
|
||||||
if (command.deferInitialReply) {
|
if (command.deferInitialReply) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "discordBot.modules.registerCommands");
|
||||||
import { REST, Routes } from 'discord.js';
|
import { REST, Routes } from 'discord.js';
|
||||||
|
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
@@ -15,21 +17,21 @@ export const registerActiveCommands = async (serverClient) => {
|
|||||||
|
|
||||||
// and deploy your commands!
|
// and deploy your commands!
|
||||||
guildIDs.forEach(guild => {
|
guildIDs.forEach(guild => {
|
||||||
console.log("Deploying commands for: ", guild.id);
|
log.INFO("Deploying commands for: ", guild.id);
|
||||||
console.log("Commands", commands);
|
log.DEBUG("Commands", commands);
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
console.log(`Started refreshing application (/) commands for guild ID: ${guild.id}.`);
|
log.DEBUG(`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
|
// The put method is used to fully refresh all commands in the guild with the current set
|
||||||
const data = await rest.put(
|
const data = await rest.put(
|
||||||
Routes.applicationGuildCommands(clientId, guild.id),
|
Routes.applicationGuildCommands(clientId, guild.id),
|
||||||
{ body: commands },
|
{ body: commands },
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Successfully reloaded ${data.length} application (/) commands for guild ID: ${guild.id}.`);
|
log.DEBUG(`Successfully reloaded ${data.length} application (/) commands for guild ID: ${guild.id}.`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// And of course, make sure you catch and log any errors!
|
// And of course, make sure you catch and log any errors!
|
||||||
console.log("ERROR Deploying commands: ", error, "Body from error: ", commands);
|
log.ERROR("ERROR Deploying commands: ", error, "Body from error: ", commands);
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
})
|
})
|
||||||
@@ -47,20 +49,20 @@ export const unregisterAllCommands = async (serverClient) => {
|
|||||||
|
|
||||||
const rest = new REST({ version: '10' }).setToken(discordToken);
|
const rest = new REST({ version: '10' }).setToken(discordToken);
|
||||||
guildIDs.forEach(guild => {
|
guildIDs.forEach(guild => {
|
||||||
console.log("Removing commands for: ", clientId, guild.id);
|
log.INFO("Removing commands for: ", clientId, guild.id);
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
console.log(`Started removal of ${commands.length} application (/) commands for guild ID: ${guild.id}.`);
|
log.DEBUG(`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
|
// The put method is used to fully refresh all commands in the guild with the current set
|
||||||
const data = await rest.put(
|
const data = await rest.put(
|
||||||
Routes.applicationGuildCommands(clientId, guild.id),
|
Routes.applicationGuildCommands(clientId, guild.id),
|
||||||
{ body: commands },
|
{ body: commands },
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Successfully removed ${data.length} application (/) commands for guild ID: ${guild.id}.`);
|
log.DEBUG(`Successfully removed ${data.length} application (/) commands for guild ID: ${guild.id}.`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// And of course, make sure you catch and log any errors!
|
// And of course, make sure you catch and log any errors!
|
||||||
console.log("ERROR removing commands: ", error, "Body from error: ", commands);
|
log.ERROR("ERROR removing commands: ", error, "Body from error: ", commands);
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
})
|
})
|
||||||
@@ -74,10 +76,10 @@ export const unregisterAllCommands = async (serverClient) => {
|
|||||||
*/
|
*/
|
||||||
export const refreshActiveCommandsWrapper = async (serverClient) => {
|
export const refreshActiveCommandsWrapper = async (serverClient) => {
|
||||||
// Remove all commands
|
// Remove all commands
|
||||||
console.log("Removing/Unregistering all commands from all connected servers/guilds");
|
log.INFO("Removing/Unregistering all commands from all connected servers/guilds");
|
||||||
await unregisterAllCommands(serverClient);
|
await unregisterAllCommands(serverClient);
|
||||||
// Deploy the active commands
|
// Deploy the active commands
|
||||||
console.log("Adding commands to all connected servers/guilds");
|
log.INFO("Adding commands to all connected servers/guilds");
|
||||||
await registerActiveCommands(serverClient);
|
await registerActiveCommands(serverClient);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -7,12 +7,12 @@ import { config } from 'dotenv';
|
|||||||
// Load environment variables
|
// Load environment variables
|
||||||
config();
|
config();
|
||||||
|
|
||||||
const log = new DebugBuilder("server", "libUtils");
|
const log = new DebugBuilder("server", "discordBot.modules.rssWrappers");
|
||||||
|
|
||||||
const imageRegex = /(http(s?):)([/|.|\w|\s|-])*((\.(?:jpg|gif|png|webm))|(\/gallery\/(?:[/|.|\w|\s|-])*))/g;
|
const imageRegex = /(http(s?):)([/|.|\w|\s|-])*((\.(?:jpg|gif|png|webm))|(\/gallery\/(?:[/|.|\w|\s|-])*))/g;
|
||||||
const youtubeVideoRegex = /((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube(-nocookie)?\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)/g;
|
const youtubeVideoRegex = /((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube(-nocookie)?\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)/g;
|
||||||
|
|
||||||
export class EmmeliaEmbedBuilder extends EmbedBuilder {
|
export class DRBEmbedBuilder extends EmbedBuilder {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.setTimestamp();
|
this.setTimestamp();
|
||||||
@@ -66,7 +66,7 @@ export const sendPost = (post, source, channel) => {
|
|||||||
log.DEBUG("Post content: ", postContent);
|
log.DEBUG("Post content: ", postContent);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const rssMessage = new EmmeliaEmbedBuilder()
|
const rssMessage = new DRBEmbedBuilder()
|
||||||
.setColor(0x0099FF)
|
.setColor(0x0099FF)
|
||||||
.setTitle(postTitle)
|
.setTitle(postTitle)
|
||||||
.setURL(postLink)
|
.setURL(postLink)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "discordBot.modules.wrappers");
|
||||||
import { checkIfNodeIsConnectedToVC, getNodeDiscordID, getNodeDiscordUsername } from '../../modules/socketServerWrappers.mjs';
|
import { checkIfNodeIsConnectedToVC, getNodeDiscordID, getNodeDiscordUsername } from '../../modules/socketServerWrappers.mjs';
|
||||||
import { getAllDiscordIDs } from '../../modules/mongo-wrappers/mongoDiscordIDWrappers.mjs'
|
import { getAllDiscordIDs } from '../../modules/mongo-wrappers/mongoDiscordIDWrappers.mjs'
|
||||||
|
|
||||||
@@ -8,7 +10,7 @@ export const checkOnlineBotsInGuild = async (nodeIo, guildId) => {
|
|||||||
await Promise.all(openSockets.map(async openSocket => {
|
await Promise.all(openSockets.map(async openSocket => {
|
||||||
openSocket = await nodeIo.sockets.sockets.get(openSocket);
|
openSocket = await nodeIo.sockets.sockets.get(openSocket);
|
||||||
const connected = await checkIfNodeIsConnectedToVC(nodeIo, guildId, openSocket.node.nuid);
|
const connected = await checkIfNodeIsConnectedToVC(nodeIo, guildId, openSocket.node.nuid);
|
||||||
console.log("Connected:", connected);
|
log.INFO("Connected:", connected);
|
||||||
if (connected) {
|
if (connected) {
|
||||||
const username = await getNodeDiscordUsername(openSocket, guildId);
|
const username = await getNodeDiscordUsername(openSocket, guildId);
|
||||||
const discordID = await getNodeDiscordID(openSocket);
|
const discordID = await getNodeDiscordID(openSocket);
|
||||||
@@ -33,8 +35,8 @@ export const checkOnlineBotsInGuild = async (nodeIo, guildId) => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// Use the results of both promises here
|
// Use the results of both promises here
|
||||||
console.log("Available Discord IDs:", discordIDs);
|
log.INFO("Available Discord IDs:", discordIDs);
|
||||||
console.log("Online bots in the guild:", onlineBots);
|
log.INFO("Online bots in the guild:", onlineBots);
|
||||||
|
|
||||||
// Filter any discordIDs that are not active
|
// Filter any discordIDs that are not active
|
||||||
const availableDiscordIDs = discordIDs.filter(discordID => discordID.active == true).filter(discordID => !onlineBots.some(bot => Number(bot.discord_id) == discordID.discord_id));
|
const availableDiscordIDs = discordIDs.filter(discordID => discordID.active == true).filter(discordID => !onlineBots.some(bot => Number(bot.discord_id) == discordID.discord_id));
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "addonManager");
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
@@ -20,9 +22,9 @@ export const loadAddons = async (nodeIo) => {
|
|||||||
if (addonConfig.enabled) {
|
if (addonConfig.enabled) {
|
||||||
const addonIndexPath = path.join(addonsDir, addonDir.name, 'index.js');
|
const addonIndexPath = path.join(addonsDir, addonDir.name, 'index.js');
|
||||||
import(`file://${addonIndexPath}`).then(addonModule => {
|
import(`file://${addonIndexPath}`).then(addonModule => {
|
||||||
console.log("Loading addon: ", addonModule);
|
log.DEBUG("Loading addon: ", addonModule);
|
||||||
addonModule.initialize(nodeIo, addonConfig);
|
addonModule.initialize(nodeIo, addonConfig);
|
||||||
console.log(`Addon ${addonConfig.name} loaded.`);
|
log.DEBUG(`Addon ${addonConfig.name} loaded.`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,35 @@
|
|||||||
// Import necessary modules
|
// Import necessary modules
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import { config } from 'dotenv';
|
import { config } from 'dotenv';
|
||||||
import { writeFile } from 'fs';
|
config();
|
||||||
|
import { promises as fs } from 'fs';
|
||||||
|
import { join, dirname } from 'path';
|
||||||
import { inspect } from 'util';
|
import { inspect } from 'util';
|
||||||
|
|
||||||
// Load environment variables
|
/**
|
||||||
config();
|
* Write a given message to the log file
|
||||||
|
* @param {any} logMessage The message to write to the log file
|
||||||
const logLocation = process.env.LOG_LOCATION;
|
* @param {string} appName The app name that created the log entry
|
||||||
|
*/
|
||||||
const writeToLog = async (logMessage, appName) => {
|
const writeToLog = async (logMessage, appName) => {
|
||||||
|
const logLocation = join(process.env.LOG_LOCATION ?? `./logs/${appName}.log`);
|
||||||
|
|
||||||
|
// Ensure the log directory exists
|
||||||
|
try {
|
||||||
|
await fs.mkdir(dirname(logLocation), { recursive: true });
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the message is a string
|
||||||
logMessage = `${String(logMessage)}\n`;
|
logMessage = `${String(logMessage)}\n`;
|
||||||
|
|
||||||
writeFile(
|
// Write to the file
|
||||||
logLocation ?? `./${appName}.log`,
|
try {
|
||||||
logMessage,
|
await fs.writeFile(logLocation, logMessage, { encoding: 'utf-8', flag: 'a+' });
|
||||||
{ encoding: "utf-8", flag: 'a+' },
|
} catch (err) {
|
||||||
(err) => {
|
console.error(err);
|
||||||
if (err) console.error(err);
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,37 +40,31 @@ const writeToLog = async (logMessage, appName) => {
|
|||||||
*/
|
*/
|
||||||
export class DebugBuilder {
|
export class DebugBuilder {
|
||||||
constructor(appName, fileName) {
|
constructor(appName, fileName) {
|
||||||
this.INFO = (...messageParts) => {
|
const buildLogger = (level) => (...messageParts) => {
|
||||||
const _info = debug(`${appName}:${fileName}:INFO`);
|
const logger = debug(`${appName}:${fileName}:${level}`);
|
||||||
_info(messageParts);
|
logger(messageParts);
|
||||||
writeToLog(`${new Date().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:INFO\t-\t${messageParts.map(messagePart => inspect(messagePart))}`, appName);
|
|
||||||
};
|
const timeStamp = new Date().toLocaleString('en-US', { timeZone: 'America/New_York' });
|
||||||
|
const message = `${timeStamp} - ${appName}:${fileName}:${level}\t-\t${messageParts.map(part => inspect(part)).join(' ')}`;
|
||||||
this.DEBUG = (...messageParts) => {
|
|
||||||
const _debug = debug(`${appName}:${fileName}:DEBUG`);
|
// Write to console
|
||||||
_debug(messageParts);
|
console.log(message);
|
||||||
writeToLog(`${new Date().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:DEBUG\t-\t${messageParts.map(messagePart => inspect(messagePart))}`, appName);
|
|
||||||
};
|
// Write to logfile
|
||||||
|
writeToLog(message, appName);
|
||||||
this.VERBOSE = (...messageParts) => {
|
|
||||||
const _verbose = debug(`${appName}:${fileName}:VERBOSE`);
|
|
||||||
_verbose(messageParts);
|
|
||||||
writeToLog(`${new Date().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:VERBOSE\t-\t${messageParts.map(messagePart => inspect(messagePart))}`, appName);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.WARN = (...messageParts) => {
|
|
||||||
const _warn = debug(`${appName}:${fileName}:WARNING`);
|
|
||||||
_warn(messageParts);
|
|
||||||
writeToLog(`${new Date().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:WARNING\t-\t${messageParts.map(messagePart => inspect(messagePart))}`, appName);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.INFO = buildLogger('INFO');
|
||||||
|
this.DEBUG = buildLogger('DEBUG');
|
||||||
|
this.VERBOSE = buildLogger('VERBOSE');
|
||||||
|
this.WARN = buildLogger('WARNING');
|
||||||
this.ERROR = (...messageParts) => {
|
this.ERROR = (...messageParts) => {
|
||||||
const _error = debug(`${appName}:${fileName}:ERROR`);
|
buildLogger('ERROR')(...messageParts);
|
||||||
_error(messageParts);
|
|
||||||
writeToLog(`${new Date().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:ERROR\t-\t${messageParts.map(messagePart => inspect(messagePart))}`, appName);
|
|
||||||
if (process.env.EXIT_ON_ERROR && process.env.EXIT_ON_ERROR > 0) {
|
if (process.env.EXIT_ON_ERROR && process.env.EXIT_ON_ERROR > 0) {
|
||||||
writeToLog("!--- EXITING ---!", appName);
|
writeToLog("!--- EXITING ---!", appName);
|
||||||
setTimeout(() => process.exit(), process.env.EXIT_ON_ERROR_DELAY ?? 0);
|
const exitDelay = parseInt(process.env.EXIT_ON_ERROR_DELAY, 10) || 0;
|
||||||
|
setTimeout(() => process.exit(1), exitDelay);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "mongoDiscordIDWrappers");
|
||||||
import { insertDocument, getDocuments, connectToDatabase } from "./mongoHandler.mjs";
|
import { insertDocument, getDocuments, connectToDatabase } from "./mongoHandler.mjs";
|
||||||
|
|
||||||
const collectionName = 'discord-ids';
|
const collectionName = 'discord-ids';
|
||||||
@@ -8,7 +10,7 @@ export const createDiscordID = async (discordID) => {
|
|||||||
const insertedId = await insertDocument(collectionName, discordID);
|
const insertedId = await insertDocument(collectionName, discordID);
|
||||||
return insertedId;
|
return insertedId;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating Discord ID:', error);
|
log.ERROR('Error creating Discord ID:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -19,7 +21,7 @@ export const getAllDiscordIDs = async () => {
|
|||||||
const discordIDs = await getDocuments(collectionName);
|
const discordIDs = await getDocuments(collectionName);
|
||||||
return discordIDs;
|
return discordIDs;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting all Discord IDs:', error);
|
log.ERROR('Error getting all Discord IDs:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -37,7 +39,7 @@ export const getDiscordID = async (identifier) => {
|
|||||||
});
|
});
|
||||||
return discordID;
|
return discordID;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting Discord ID:', error);
|
log.ERROR('Error getting Discord ID:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
@@ -56,10 +58,10 @@ export const updateDiscordID = async (identifier, updatedFields) => {
|
|||||||
{ discord_id: identifier }
|
{ discord_id: identifier }
|
||||||
]
|
]
|
||||||
}, { $set: updatedFields });
|
}, { $set: updatedFields });
|
||||||
console.log('Discord ID updated:', result.modifiedCount);
|
log.INFO('Discord ID updated:', result.modifiedCount);
|
||||||
return result.modifiedCount;
|
return result.modifiedCount;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating Discord ID:', error);
|
log.ERROR('Error updating Discord ID:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
@@ -78,10 +80,10 @@ export const deleteDiscordID = async (identifier) => {
|
|||||||
{ discord_id: identifier }
|
{ discord_id: identifier }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
console.log('Discord ID deleted:', result.deletedCount);
|
log.INFO('Discord ID deleted:', result.deletedCount);
|
||||||
return result.deletedCount;
|
return result.deletedCount;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting Discord ID:', error);
|
log.ERROR('Error deleting Discord ID:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "mongoFeedsWrappers");
|
||||||
import {
|
import {
|
||||||
insertDocument,
|
insertDocument,
|
||||||
getDocuments,
|
getDocuments,
|
||||||
@@ -15,7 +17,7 @@ import {
|
|||||||
const insertedId = await insertDocument(feedCollectionName, feed);
|
const insertedId = await insertDocument(feedCollectionName, feed);
|
||||||
return insertedId;
|
return insertedId;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating feed:', error);
|
log.ERROR('Error creating feed:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -26,7 +28,7 @@ import {
|
|||||||
const feeds = await getDocuments(feedCollectionName);
|
const feeds = await getDocuments(feedCollectionName);
|
||||||
return feeds;
|
return feeds;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting all feeds:', error);
|
log.ERROR('Error getting all feeds:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -37,7 +39,18 @@ import {
|
|||||||
const feed = await getDocumentByField(feedCollectionName, 'link', link);
|
const feed = await getDocumentByField(feedCollectionName, 'link', link);
|
||||||
return feed;
|
return feed;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting feed by link:', error);
|
log.ERROR('Error getting feed by link:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wrapper for retrieving a feed by the title
|
||||||
|
export const getFeedByTitle = async (title) => {
|
||||||
|
try {
|
||||||
|
const feed = await getDocumentByField(feedCollectionName, 'title', title);
|
||||||
|
return feed;
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR('Error getting feed by link:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -48,7 +61,7 @@ import {
|
|||||||
const modifiedCount = await updateDocumentByField(feedCollectionName, 'link', link, updatedFields);
|
const modifiedCount = await updateDocumentByField(feedCollectionName, 'link', link, updatedFields);
|
||||||
return modifiedCount;
|
return modifiedCount;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating feed by link:', error);
|
log.ERROR('Error updating feed by link:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -59,7 +72,18 @@ import {
|
|||||||
const deletedCount = await deleteDocumentByField(feedCollectionName, 'link', link);
|
const deletedCount = await deleteDocumentByField(feedCollectionName, 'link', link);
|
||||||
return deletedCount;
|
return deletedCount;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting feed by link:', error);
|
log.ERROR('Error deleting feed by link:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wrapper for deleting a feed by title
|
||||||
|
export const deleteFeedByTitle = async (title) => {
|
||||||
|
try {
|
||||||
|
const deletedCount = await deleteDocumentByField(feedCollectionName, 'title', title);
|
||||||
|
return deletedCount;
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR('Error deleting feed by link:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -70,7 +94,7 @@ import {
|
|||||||
const insertedId = await insertDocument(postCollectionName, post);
|
const insertedId = await insertDocument(postCollectionName, post);
|
||||||
return insertedId;
|
return insertedId;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating post:', error);
|
log.ERROR('Error creating post:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -81,7 +105,7 @@ import {
|
|||||||
const post = await getDocumentByField(postCollectionName, 'postId', postId);
|
const post = await getDocumentByField(postCollectionName, 'postId', postId);
|
||||||
return post;
|
return post;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting post by postId:', error);
|
log.ERROR('Error getting post by postId:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "mongoNodesWrappers");
|
||||||
import { insertDocument, getDocuments, connectToDatabase } from "./mongoHandler.mjs";
|
import { insertDocument, getDocuments, connectToDatabase } from "./mongoHandler.mjs";
|
||||||
|
|
||||||
const collectionName = 'nodes';
|
const collectionName = 'nodes';
|
||||||
@@ -8,7 +10,7 @@ export const createNode = async (node) => {
|
|||||||
const insertedId = await insertDocument(collectionName, node);
|
const insertedId = await insertDocument(collectionName, node);
|
||||||
return insertedId;
|
return insertedId;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating node:', error);
|
log.ERROR('Error creating node:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -19,7 +21,7 @@ export const getAllNodes = async () => {
|
|||||||
const nodes = await getDocuments(collectionName);
|
const nodes = await getDocuments(collectionName);
|
||||||
return nodes;
|
return nodes;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting all nodes:', error);
|
log.ERROR('Error getting all nodes:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -32,7 +34,7 @@ export const getNodeByNuid = async (nuid) => {
|
|||||||
const node = await collection.findOne({ nuid });
|
const node = await collection.findOne({ nuid });
|
||||||
return node;
|
return node;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting node by NUID:', error);
|
log.ERROR('Error getting node by NUID:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
@@ -46,10 +48,10 @@ export const updateNodeByNuid = async (nuid, updatedFields) => {
|
|||||||
try {
|
try {
|
||||||
const collection = db.db().collection(collectionName);
|
const collection = db.db().collection(collectionName);
|
||||||
const result = await collection.updateOne({ nuid }, { $set: updatedFields });
|
const result = await collection.updateOne({ nuid }, { $set: updatedFields });
|
||||||
console.log('Node updated:', result.modifiedCount);
|
log.INFO('Node updated:', result.modifiedCount);
|
||||||
return result.modifiedCount;
|
return result.modifiedCount;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating node by NUID:', error);
|
log.ERROR('Error updating node by NUID:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
@@ -63,10 +65,10 @@ export const deleteNodeByNuid = async (nuid) => {
|
|||||||
try {
|
try {
|
||||||
const collection = db.db().collection(collectionName);
|
const collection = db.db().collection(collectionName);
|
||||||
const result = await collection.deleteOne({ nuid });
|
const result = await collection.deleteOne({ nuid });
|
||||||
console.log('Node deleted:', result.deletedCount);
|
log.INFO('Node deleted:', result.deletedCount);
|
||||||
return result.deletedCount;
|
return result.deletedCount;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting node by NUID:', error);
|
log.ERROR('Error deleting node by NUID:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "mongoSystemsWrappers");
|
||||||
import { insertDocument, getDocuments, connectToDatabase } from "./mongoHandler.mjs";
|
import { insertDocument, getDocuments, connectToDatabase } from "./mongoHandler.mjs";
|
||||||
|
|
||||||
const collectionName = 'radio-systems';
|
const collectionName = 'radio-systems';
|
||||||
@@ -21,7 +23,7 @@ export const createSystem = async (name, system, nuid) => {
|
|||||||
const insertedId = await insertDocument(collectionName, system);
|
const insertedId = await insertDocument(collectionName, system);
|
||||||
return insertedId;
|
return insertedId;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating system:', error);
|
log.ERROR('Error creating system:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -32,7 +34,7 @@ export const getAllSystems = async () => {
|
|||||||
const systems = await getDocuments(collectionName);
|
const systems = await getDocuments(collectionName);
|
||||||
return systems;
|
return systems;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting all systems:', error);
|
log.ERROR('Error getting all systems:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -45,7 +47,7 @@ export const getSystemByName = async (name) => {
|
|||||||
const system = await collection.findOne({ name });
|
const system = await collection.findOne({ name });
|
||||||
return system;
|
return system;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting system by name:', error);
|
log.ERROR('Error getting system by name:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
@@ -65,7 +67,7 @@ export const getSystemsByNuid = async (nuid) => {
|
|||||||
|
|
||||||
return systems;
|
return systems;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error finding entries:', error);
|
log.ERROR('Error finding entries:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
@@ -82,10 +84,10 @@ export const updateSystemByName = async (name, updatedSystem) => {
|
|||||||
try {
|
try {
|
||||||
const collection = db.db().collection(collectionName);
|
const collection = db.db().collection(collectionName);
|
||||||
const result = await collection.updateOne({ name }, { $set: updatedSystem });
|
const result = await collection.updateOne({ name }, { $set: updatedSystem });
|
||||||
console.log('System updated:', result.modifiedCount);
|
log.INFO('System updated:', result.modifiedCount);
|
||||||
return result.modifiedCount;
|
return result.modifiedCount;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating system by name:', error);
|
log.ERROR('Error updating system by name:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
@@ -99,10 +101,10 @@ export const deleteSystemByName = async (name) => {
|
|||||||
try {
|
try {
|
||||||
const collection = db.db().collection(collectionName);
|
const collection = db.db().collection(collectionName);
|
||||||
const result = await collection.deleteOne({ name });
|
const result = await collection.deleteOne({ name });
|
||||||
console.log('System deleted:', result.deletedCount);
|
log.INFO('System deleted:', result.deletedCount);
|
||||||
return result.deletedCount;
|
return result.deletedCount;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting system by name:', error);
|
log.ERROR('Error deleting system by name:', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
// Close the connection
|
// Close the connection
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "socketServer");
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { createServer } from 'node:http';
|
import { createServer } from 'node:http';
|
||||||
import { Server } from 'socket.io';
|
import { Server } from 'socket.io';
|
||||||
@@ -15,7 +17,7 @@ app.get('/', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
nodeIo.on('connection', (socket) => {
|
nodeIo.on('connection', (socket) => {
|
||||||
console.log('a user connected', socket.id);
|
log.INFO('a user connected', socket.id);
|
||||||
|
|
||||||
socket.on('node-login', async (data) => {
|
socket.on('node-login', async (data) => {
|
||||||
await nodeLoginWrapper(data, socket);
|
await nodeLoginWrapper(data, socket);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "socketServerWrappers");
|
||||||
import { createNode, getNodeByNuid, updateNodeByNuid } from "./mongo-wrappers/mongoNodesWrappers.mjs"
|
import { createNode, getNodeByNuid, updateNodeByNuid } from "./mongo-wrappers/mongoNodesWrappers.mjs"
|
||||||
import { createSystem, getSystemByName, updateSystemByName, getSystemsByNuid, deleteSystemByName } from "./mongo-wrappers/mongoSystemsWrappers.mjs"
|
import { createSystem, getSystemByName, updateSystemByName, getSystemsByNuid, deleteSystemByName } from "./mongo-wrappers/mongoSystemsWrappers.mjs"
|
||||||
|
|
||||||
@@ -22,17 +24,16 @@ const sendNodeCommand = async (socket, command, data) => {
|
|||||||
* @returns {any}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
export const nodeLoginWrapper = async (data, socket) => {
|
export const nodeLoginWrapper = async (data, socket) => {
|
||||||
console.log(`Login requested from node: ${data.nuid}`, data);
|
log.INFO(`Login requested from node: ${data.nuid}`, data);
|
||||||
// Check to see if node exists
|
// Check to see if node exists
|
||||||
var node = await getNodeByNuid(data.nuid);
|
var node = await getNodeByNuid(data.nuid);
|
||||||
console.log("After grabbing", node);
|
|
||||||
if (!node) {
|
if (!node) {
|
||||||
const insertedId = await createNode(data);
|
const insertedId = await createNode(data);
|
||||||
console.log("Added new node to the database:", insertedId);
|
log.DEBUG("Added new node to the database:", insertedId);
|
||||||
} else {
|
} else {
|
||||||
// Check for updates
|
// Check for updates
|
||||||
const updatedNode = await updateNodeByNuid(data.nuid, data)
|
const updatedNode = await updateNodeByNuid(data.nuid, data)
|
||||||
console.log("Updated node:", updatedNode);
|
log.DEBUG("Updated node:", updatedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
node = await getNodeByNuid(data.nuid);
|
node = await getNodeByNuid(data.nuid);
|
||||||
@@ -59,7 +60,7 @@ export const nodeDisconnectWrapper = async (socketId) => {
|
|||||||
* @returns {any}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
export const nodeUpdateWrapper = async (nodeData) => {
|
export const nodeUpdateWrapper = async (nodeData) => {
|
||||||
console.log("Data update sent by node: ", nodeData);
|
log.DEBUG("Data update sent by node: ", nodeData);
|
||||||
const updateResults = await updateNodeByNuid(nodeData.nuid, nodeData);
|
const updateResults = await updateNodeByNuid(nodeData.nuid, nodeData);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -70,10 +71,10 @@ export const nodeUpdateWrapper = async (nodeData) => {
|
|||||||
* @param {object} nearbySystems The nearby systems object passed from the node to be updated
|
* @param {object} nearbySystems The nearby systems object passed from the node to be updated
|
||||||
*/
|
*/
|
||||||
export const nearbySystemsUpdateWraper = async (nuid, nearbySystems) => {
|
export const nearbySystemsUpdateWraper = async (nuid, nearbySystems) => {
|
||||||
console.log("System updates sent by node: ", nuid, nearbySystems);
|
log.DEBUG("System updates sent by node: ", nuid, nearbySystems);
|
||||||
// Check to see if the node removed any systems
|
// Check to see if the node removed any systems
|
||||||
const existingSystems = await getSystemsByNuid(nuid);
|
const existingSystems = await getSystemsByNuid(nuid);
|
||||||
console.log("Existing systems:", existingSystems);
|
log.DEBUG("Existing systems:", existingSystems);
|
||||||
if (existingSystems !== nearbySystems) {
|
if (existingSystems !== nearbySystems) {
|
||||||
for (const existingSystem of existingSystems) {
|
for (const existingSystem of existingSystems) {
|
||||||
if (existingSystem.name in nearbySystems) {
|
if (existingSystem.name in nearbySystems) {
|
||||||
@@ -81,17 +82,17 @@ export const nearbySystemsUpdateWraper = async (nuid, nearbySystems) => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("System exists that was not given by node", existingSystem);
|
log.DEBUG("System exists that was not given by node", existingSystem);
|
||||||
// Check if this node was the only node on this system
|
// Check if this node was the only node on this system
|
||||||
if (existingSystem.nodes.filter(node => node !== nuid).length === 0) {
|
if (existingSystem.nodes.filter(node => node !== nuid).length === 0) {
|
||||||
// Remove the system if so
|
// Remove the system if so
|
||||||
console.log("Given node was the only node on this system, removing the system...");
|
log.INFO("Given node was the only node on this system, removing the system...");
|
||||||
await deleteSystemByName(existingSystem.name);
|
await deleteSystemByName(existingSystem.name);
|
||||||
} else {
|
} else {
|
||||||
// Remove the node from the array if there are other nodes with this system
|
// 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");
|
log.INFO("Other nodes found on this system, removing the given NUID");
|
||||||
existingSystem.nodes = existingSystem.nodes.filter(node => node !== nuid);
|
existingSystem.nodes = existingSystem.nodes.filter(node => node !== nuid);
|
||||||
console.log(existingSystem);
|
log.DEBUG(existingSystem);
|
||||||
await updateSystemByName(existingSystem.name, existingSystem);
|
await updateSystemByName(existingSystem.name, existingSystem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,7 +112,7 @@ export const nearbySystemsUpdateWraper = async (nuid, nearbySystems) => {
|
|||||||
existingSystem.nodes.push(nuid);
|
existingSystem.nodes.push(nuid);
|
||||||
// Update the system with the added node
|
// Update the system with the added node
|
||||||
const updateResults = await updateSystemByName(nearbySystem, existingSystem);
|
const updateResults = await updateSystemByName(nearbySystem, existingSystem);
|
||||||
if (updateResults) console.log("System updated", nearbySystem);
|
if (updateResults) log.INFO("System updated", nearbySystem);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The systems are not the same
|
// The systems are not the same
|
||||||
@@ -125,13 +126,13 @@ export const nearbySystemsUpdateWraper = async (nuid, nearbySystems) => {
|
|||||||
|
|
||||||
// Update the system with the added node
|
// Update the system with the added node
|
||||||
const updateResults = await updateSystemByName(nearbySystem, nearbySystems[nearbySystem]);
|
const updateResults = await updateSystemByName(nearbySystem, nearbySystems[nearbySystem]);
|
||||||
if (updateResults) console.log("System updated", nearbySystem);
|
if (updateResults) log.INFO("System updated", nearbySystem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Create a new system
|
// Create a new system
|
||||||
const newSystem = await createSystem(nearbySystem, nearbySystems[nearbySystem], nuid);
|
const newSystem = await createSystem(nearbySystem, nearbySystems[nearbySystem], nuid);
|
||||||
console.log("New system created", nearbySystem, newSystem);
|
log.INFO("New system created", nearbySystem, newSystem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -146,7 +147,7 @@ export const nearbySystemsUpdateWraper = async (nuid, nearbySystems) => {
|
|||||||
export const getSocketIdByNuid = async (nodeIo, nuid) => {
|
export const getSocketIdByNuid = async (nodeIo, nuid) => {
|
||||||
const openSockets = await nodeIo.allSockets();
|
const openSockets = await nodeIo.allSockets();
|
||||||
for (const openSocketId of openSockets) {
|
for (const openSocketId of openSockets) {
|
||||||
console.log(openSockets)
|
log.DEBUG(openSockets)
|
||||||
const openSocket = await nodeIo.sockets.sockets.get(openSocketId);
|
const openSocket = await nodeIo.sockets.sockets.get(openSocketId);
|
||||||
if (openSocket.node.nuid == nuid)
|
if (openSocket.node.nuid == nuid)
|
||||||
return openSocket;
|
return openSocket;
|
||||||
@@ -171,10 +172,10 @@ export const getAllSocketsConnectedToVC = async (nodeIo, guildId) => {
|
|||||||
await new Promise((res) => {
|
await new Promise((res) => {
|
||||||
openSocket.emit('node-check-connected-status', guildId, (status) => {
|
openSocket.emit('node-check-connected-status', guildId, (status) => {
|
||||||
if (status) {
|
if (status) {
|
||||||
console.log("Socket is connected to VC:", openSocket.node.name, status);
|
log.INFO("Socket is connected to VC:", openSocket.node.name, status);
|
||||||
socketsConnectedToVC.push(openSocket);
|
socketsConnectedToVC.push(openSocket);
|
||||||
} else {
|
} else {
|
||||||
console.log("Socket is NOT connected to VC:", openSocket.node.name);
|
log.INFO("Socket is NOT connected to VC:", openSocket.node.name);
|
||||||
}
|
}
|
||||||
res();
|
res();
|
||||||
})
|
})
|
||||||
@@ -196,10 +197,10 @@ export const checkIfNodeHasOpenDiscordClient = async (openSocket) => {
|
|||||||
await new Promise((res) => {
|
await new Promise((res) => {
|
||||||
openSocket.emit('node-check-discord-open-client', (status) => {
|
openSocket.emit('node-check-discord-open-client', (status) => {
|
||||||
if (status) {
|
if (status) {
|
||||||
console.log("Socket has an open discord client:", openSocket.node.name, status);
|
log.INFO("Socket has an open discord client:", openSocket.node.name, status);
|
||||||
hasOpenDiscordClient = true;
|
hasOpenDiscordClient = true;
|
||||||
} else {
|
} else {
|
||||||
console.log("Socket does NOT have an open discord client:", openSocket.node.name);
|
log.INFO("Socket does NOT have an open discord client:", openSocket.node.name);
|
||||||
}
|
}
|
||||||
res();
|
res();
|
||||||
})
|
})
|
||||||
@@ -217,10 +218,10 @@ export const getNodeCurrentListeningSystem = async (openSocket) => {
|
|||||||
await new Promise((res) => {
|
await new Promise((res) => {
|
||||||
openSocket.emit('node-check-current-system', (system) => {
|
openSocket.emit('node-check-current-system', (system) => {
|
||||||
if (system) {
|
if (system) {
|
||||||
console.log("Socket is listening to system:", openSocket.node.name, system);
|
log.INFO("Socket is listening to system:", openSocket.node.name, system);
|
||||||
currentSystem = system;
|
currentSystem = system;
|
||||||
} else {
|
} else {
|
||||||
console.log("Socket is not currently listening to a system:", openSocket.node.name);
|
log.INFO("Socket is not currently listening to a system:", openSocket.node.name);
|
||||||
}
|
}
|
||||||
res();
|
res();
|
||||||
})
|
})
|
||||||
@@ -307,9 +308,9 @@ export const requestBotLeaveServer = async (socket, guildId) => {
|
|||||||
export const requestNodeUpdate = async (socket) => {
|
export const requestNodeUpdate = async (socket) => {
|
||||||
await sendNodeCommand(socket, 'node-update', (status) => {
|
await sendNodeCommand(socket, 'node-update', (status) => {
|
||||||
if (status) {
|
if (status) {
|
||||||
console.log("Node is out of date, updating now", socket.node.name);
|
log.INFO("Node is out of date, updating now", socket.node.name);
|
||||||
} else {
|
} else {
|
||||||
console.log("Node is up to date", socket.node.name);
|
log.INFO("Node is up to date", socket.node.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha --timeout 5000",
|
"test": "jasmine",
|
||||||
"start": "node server.js"
|
"start": "node server.js"
|
||||||
},
|
},
|
||||||
"author": "Logan Cusano",
|
"author": "Logan Cusano",
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { createFeed, getAllFeeds, getFeedByLink, updateFeedByLink, deleteFeedByLink, createPost, getPostByPostId } from '../modules/mongo-wrappers/mongoFeedsWrappers.mjs';
|
import { getAllFeeds, deleteFeedByLink, createPost, getPostByPostId } from '../modules/mongo-wrappers/mongoFeedsWrappers.mjs';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { sendPost } from '../discordBot/modules/rssWrappers.mjs';
|
import { sendPost } from '../discordBot/modules/rssWrappers.mjs';
|
||||||
import { DebugBuilder } from "../modules/debugger.mjs";
|
import { DebugBuilder } from "../modules/debugger.mjs";
|
||||||
|
import { removeSource } from './sourceManager.mjs'
|
||||||
import UserAgent from "user-agents";
|
import UserAgent from "user-agents";
|
||||||
import Parser from 'rss-parser';
|
import Parser from 'rss-parser';
|
||||||
|
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
dotenv.config()
|
||||||
|
|
||||||
// Initialize the User-Agent string
|
// Initialize the User-Agent string
|
||||||
process.env.USER_AGENT_STRING = new UserAgent({ platform: 'Win32' }).toString();
|
process.env.USER_AGENT_STRING = new UserAgent({ platform: 'Win32' }).toString();
|
||||||
|
|
||||||
@@ -16,13 +20,16 @@ const parser = new Parser({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const log = new DebugBuilder("server", "feedHandler");
|
const log = new DebugBuilder("server", "feedHandler");
|
||||||
const runningPostsToRemove = {};
|
|
||||||
const sourceFailureLimit = 5;
|
|
||||||
|
|
||||||
export const returnHash = (...stringsIncluded) => {
|
export const returnHash = (...stringsIncluded) => {
|
||||||
return crypto.createHash('sha1').update(stringsIncluded.join("-<<??//\\\\??>>-")).digest("base64");
|
return crypto.createHash('sha1').update(stringsIncluded.join("-<<??//\\\\??>>-")).digest("base64");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the active RSS feeds and send any new posts to their discord channels
|
||||||
|
* @param {any} client The discord client to send posts with
|
||||||
|
* @returns {any}
|
||||||
|
*/
|
||||||
export const updateFeeds = async (client) => {
|
export const updateFeeds = async (client) => {
|
||||||
if (!client) throw new Error("Client object not passed");
|
if (!client) throw new Error("Client object not passed");
|
||||||
|
|
||||||
@@ -84,56 +91,3 @@ export const updateFeeds = async (client) => {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addSource = async (title, link, category, guildId, channelId, callback) => {
|
|
||||||
try {
|
|
||||||
const feed = { title, link, category, guild_id: guildId, channel_id: channelId };
|
|
||||||
const record = await createFeed(feed);
|
|
||||||
log.DEBUG("Source added:", record);
|
|
||||||
callback(null, record);
|
|
||||||
} catch (err) {
|
|
||||||
log.ERROR("Error adding source:", err);
|
|
||||||
callback(err, null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const removeSource = async (sourceURL) => {
|
|
||||||
log.INFO("Removing source:", sourceURL);
|
|
||||||
|
|
||||||
if (!runningPostsToRemove[sourceURL]) {
|
|
||||||
runningPostsToRemove[sourceURL] = { count: 1, timestamp: Date.now(), ignoredAttempts: 0 };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const elapsedTime = Date.now() - runningPostsToRemove[sourceURL].timestamp;
|
|
||||||
const waitTime = runningPostsToRemove[sourceURL].count * 30000;
|
|
||||||
|
|
||||||
if (elapsedTime <= waitTime) {
|
|
||||||
runningPostsToRemove[sourceURL].ignoredAttempts += 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runningPostsToRemove[sourceURL].count < sourceFailureLimit) {
|
|
||||||
runningPostsToRemove[sourceURL].count += 1;
|
|
||||||
runningPostsToRemove[sourceURL].timestamp = Date.now();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const record = await getFeedByLink(sourceURL);
|
|
||||||
if (!record) {
|
|
||||||
log.ERROR("Source not found in storage");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await deleteFeedByLink(sourceURL);
|
|
||||||
if (!results) {
|
|
||||||
log.WARN("Failed to remove source");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log.DEBUG("Source removed after exceeding failure limit:", sourceURL);
|
|
||||||
} catch (err) {
|
|
||||||
log.ERROR("Error removing source from storage:", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,37 +1,49 @@
|
|||||||
//Will handle updating feeds in all channels
|
// Will handle updating feeds in all channels
|
||||||
|
|
||||||
import { DebugBuilder } from "../modules/debugger.mjs";
|
import { DebugBuilder } from "../modules/debugger.mjs";
|
||||||
import { updateFeeds } from "./feedHandler.mjs";
|
import { updateFeeds } from "./feedHandler.mjs";
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
dotenv.config()
|
dotenv.config();
|
||||||
|
|
||||||
const log = new DebugBuilder("server", "rssController");
|
const log = new DebugBuilder("server", "rssController");
|
||||||
|
|
||||||
const refreshInterval = process.env.RSS_REFRESH_INTERVAL ?? 300000;
|
const refreshInterval = parseInt(process.env.RSS_REFRESH_INTERVAL) || 300000;
|
||||||
|
|
||||||
export class RSSController {
|
export class RSSController {
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
this.intervalId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
// Wait for the refresh period before starting RSS feeds, so the rest of the bot can start
|
try {
|
||||||
await new Promise(resolve => setTimeout(resolve, refreshInterval));
|
log.INFO("Starting RSS Controller");
|
||||||
|
// Get initial feeds before starting the interval loop
|
||||||
log.INFO("Starting RSS Controller");
|
|
||||||
// Get initial feeds before starting the infinite loop
|
|
||||||
await updateFeeds(this.client);
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
// Wait for the refresh interval, then wait for the posts to return, then wait a quarter of the refresh interval to make sure everything is cleared up
|
|
||||||
await new Promise(resolve => setTimeout(resolve, refreshInterval));
|
|
||||||
await this.collectLatestPosts();
|
await this.collectLatestPosts();
|
||||||
await new Promise(resolve => setTimeout(resolve, refreshInterval / 4));
|
|
||||||
|
// Start the interval loop for updating feeds
|
||||||
|
this.intervalId = setInterval(async () => {
|
||||||
|
await this.collectLatestPosts();
|
||||||
|
}, refreshInterval);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR(`Failed to start RSS Controller: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async stop() {
|
||||||
|
if (this.intervalId) {
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
log.INFO("RSS Controller stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async collectLatestPosts() {
|
async collectLatestPosts() {
|
||||||
log.INFO("Updating sources");
|
try {
|
||||||
await updateFeeds(this.client);
|
log.INFO("Updating sources");
|
||||||
|
await updateFeeds(this.client);
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR(`Error updating feeds: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
75
rss-manager/sourceManager.mjs
Normal file
75
rss-manager/sourceManager.mjs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import { createFeed, getFeedByLink, deleteFeedByLink } from '../modules/mongo-wrappers/mongoFeedsWrappers.mjs';
|
||||||
|
|
||||||
|
class SourceManager {
|
||||||
|
constructor(sourceFailureLimit) {
|
||||||
|
this.sourceFailureLimit = sourceFailureLimit;
|
||||||
|
this.runningSourcesToRemove = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeSource(sourceURL) {
|
||||||
|
log.INFO(`Removing source: ${sourceURL}`);
|
||||||
|
|
||||||
|
const currentTime = Date.now();
|
||||||
|
const sourceData = this.runningSourcesToRemove[sourceURL];
|
||||||
|
|
||||||
|
if (!sourceData) {
|
||||||
|
this.runningSourcesToRemove[sourceURL] = { count: 1, timestamp: currentTime, ignoredAttempts: 0 };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const elapsedTimeSinceLastAttempt = currentTime - sourceData.timestamp;
|
||||||
|
const waitTime = sourceData.count * 30000;
|
||||||
|
|
||||||
|
if (elapsedTimeSinceLastAttempt <= waitTime) {
|
||||||
|
sourceData.ignoredAttempts += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceData.count < this.sourceFailureLimit) {
|
||||||
|
sourceData.count += 1;
|
||||||
|
sourceData.timestamp = currentTime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const record = await getFeedByLink(sourceURL);
|
||||||
|
if (!record) {
|
||||||
|
log.ERROR(`Source not found in storage: ${sourceURL}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = await deleteFeedByLink(sourceURL);
|
||||||
|
if (!results) {
|
||||||
|
log.WARN(`Failed to remove source: ${sourceURL}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.DEBUG(`Source removed after exceeding failure limit: ${sourceURL}`);
|
||||||
|
// Optionally, clean up the entry from runningSourcesToRemove
|
||||||
|
delete this.runningSourcesToRemove[sourceURL];
|
||||||
|
} catch (err) {
|
||||||
|
log.ERROR(`Error removing source from storage: ${sourceURL}`, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async addSource(title, link, category, guildId, channelId, callback) {
|
||||||
|
try {
|
||||||
|
const feed = { title, link, category, guild_id: guildId, channel_id: channelId };
|
||||||
|
const record = await createFeed(feed);
|
||||||
|
log.DEBUG("Source added:", record);
|
||||||
|
if (callback) callback(null, record);
|
||||||
|
} catch (err) {
|
||||||
|
log.ERROR("Error adding source:", err);
|
||||||
|
if (callback) callback(err, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create a default instance of SourceManager
|
||||||
|
const defaultSourceManager = new SourceManager();
|
||||||
|
|
||||||
|
// Export the class and default instance methods
|
||||||
|
export { SourceManager };
|
||||||
|
export const addSource = defaultSourceManager.addSource.bind(defaultSourceManager);
|
||||||
|
export const removeSource = defaultSourceManager.removeSource.bind(defaultSourceManager);
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DebugBuilder } from "./modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "server");
|
||||||
import { nodeIo, app, server } from './modules/socketServer.mjs';
|
import { nodeIo, app, server } from './modules/socketServer.mjs';
|
||||||
import { loadAddons } from './modules/addonManager.mjs';
|
import { loadAddons } from './modules/addonManager.mjs';
|
||||||
import { serverClient, addEnabledEventListeners } from './discordBot/discordBot.mjs';
|
import { serverClient, addEnabledEventListeners } from './discordBot/discordBot.mjs';
|
||||||
@@ -7,7 +9,7 @@ dotenv.config()
|
|||||||
|
|
||||||
// Startup the node server
|
// Startup the node server
|
||||||
server.listen(process.env.SERVER_PORT || 3000, () => {
|
server.listen(process.env.SERVER_PORT || 3000, () => {
|
||||||
console.log(`server running at http://localhost:${process.env.SERVER_PORT}`);
|
log.INFO(`server running at http://localhost:${process.env.SERVER_PORT}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add objects to the others
|
// Add objects to the others
|
||||||
|
|||||||
13
spec/support/jasmine.json
Normal file
13
spec/support/jasmine.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"spec_dir": "spec",
|
||||||
|
"spec_files": [
|
||||||
|
"**/*[sS]pec.?(m)js"
|
||||||
|
],
|
||||||
|
"helpers": [
|
||||||
|
"helpers/**/*.?(m)js"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"stopSpecOnExpectationFailure": false,
|
||||||
|
"random": true
|
||||||
|
}
|
||||||
|
}
|
||||||
29
spec/test/rssManager.spec.js.b
Normal file
29
spec/test/rssManager.spec.js.b
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import * as feedHandler from '../../rss-manager/feedHandler.mjs';
|
||||||
|
import * as mw from '../../modules/mongo-wrappers/mongoFeedsWrappers.mjs';
|
||||||
|
import * as drw from '../../discordBot/modules/rssWrappers.mjs';
|
||||||
|
|
||||||
|
describe('feedHandler', () => {
|
||||||
|
it('should call updateFeeds', async () => {
|
||||||
|
// Spy on the updateFeeds function
|
||||||
|
const feedsSpy = spyOn(mw, 'getAllFeeds').and.stub();
|
||||||
|
const sendPostSpy = spyOn(drw, 'sendPost').and.stub();
|
||||||
|
|
||||||
|
// Call the function that triggers updateFeeds
|
||||||
|
// For example:
|
||||||
|
// someFunctionThatCallsUpdateFeeds();
|
||||||
|
console.log(await spyOn(feedHandler, 'updateFeeds').and.callThrough({
|
||||||
|
channels: {
|
||||||
|
cache: {
|
||||||
|
get: () => ([{
|
||||||
|
// Stub methods or properties of the channel object as needed for testing
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Add your expectations here to ensure updateFeeds was called
|
||||||
|
expect(feedsSpy).toHaveBeenCalled();
|
||||||
|
expect(sendPostSpy).toHaveBeenCalled();
|
||||||
|
// Add more specific expectations if needed
|
||||||
|
});
|
||||||
|
});
|
||||||
494
spec/test/socketServerWrappers.spec.js
Normal file
494
spec/test/socketServerWrappers.spec.js
Normal file
@@ -0,0 +1,494 @@
|
|||||||
|
// Import necessary modules for testing
|
||||||
|
import ioClient from 'socket.io-client';
|
||||||
|
import { deleteNodeByNuid, getNodeByNuid } from '../../modules/mongo-wrappers/mongoNodesWrappers.mjs';
|
||||||
|
import { deleteSystemByName, getSystemByName } from '../../modules/mongo-wrappers/mongoSystemsWrappers.mjs';
|
||||||
|
import { nodeDisconnectWrapper, checkIfNodeHasOpenDiscordClient, getNodeCurrentListeningSystem, checkIfNodeIsConnectedToVC, getNodeDiscordUsername, getNodeDiscordID, requestBotLeaveServer, requestNodeJoinSystem, requestNodeUpdate } from '../../modules/socketServerWrappers.mjs';
|
||||||
|
import { nodeIo } from '../../modules/socketServer.mjs';
|
||||||
|
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
dotenv.config()
|
||||||
|
|
||||||
|
process.env.SERVER_PORT = 6000
|
||||||
|
|
||||||
|
// Define necessary variables for testing, such as mocked database connections or socket instances
|
||||||
|
const localNodeConfig = {
|
||||||
|
serverIp: 'localhost',
|
||||||
|
serverPort: process.env.SERVER_PORT,
|
||||||
|
node: {
|
||||||
|
nuid: "4f29a6340901a12affc87047c0ac16b01b92496c460c880a2459abe8c7928374",
|
||||||
|
name: "testyv7",
|
||||||
|
location: "china",
|
||||||
|
capabilities: ["radio"]
|
||||||
|
},
|
||||||
|
nearbySystems: {
|
||||||
|
"Testing P25 System Name": {
|
||||||
|
"frequencies": [
|
||||||
|
155344000,
|
||||||
|
155444000,
|
||||||
|
155555000,
|
||||||
|
155588550
|
||||||
|
],
|
||||||
|
"mode": "p25",
|
||||||
|
"trunkFile": "trunk.tsv",
|
||||||
|
"whitelistFile": "whitelist.tsv"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updatedLocalNodeConfig = {
|
||||||
|
node: {
|
||||||
|
nuid: localNodeConfig.node.nuid,
|
||||||
|
name: "updatedName",
|
||||||
|
location: "updatedLocation",
|
||||||
|
capabilities: ["radio", "weather"] // Updated capabilities
|
||||||
|
},
|
||||||
|
nearbySystems: {
|
||||||
|
"Testing P25 System Name": {
|
||||||
|
"frequencies": [
|
||||||
|
155444000,
|
||||||
|
155555000,
|
||||||
|
155500000
|
||||||
|
],
|
||||||
|
"mode": "p25",
|
||||||
|
"trunkFile": "trunk2.tsv",
|
||||||
|
"whitelistFile": "whitelist2.tsv"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Socket Server - Core Tests', () => {
|
||||||
|
// Start the Socket.IO server before running tests
|
||||||
|
let clientSocket; // The socket client
|
||||||
|
let serverClientSocket // The open client socket on the server
|
||||||
|
beforeAll(done => {
|
||||||
|
// Startup the node server
|
||||||
|
nodeIo.listen(process.env.SERVER_PORT || 3000, () => {
|
||||||
|
console.log(`server running at http://localhost:${process.env.SERVER_PORT}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Connect a client socket to the server
|
||||||
|
clientSocket = ioClient.connect(`http://localhost:${process.env.SERVER_PORT}`);
|
||||||
|
|
||||||
|
nodeIo.on('connection', (socket) => {
|
||||||
|
serverClientSocket = socket;
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close the Socket.IO server after running tests
|
||||||
|
afterAll(async () => {
|
||||||
|
// Disconnect client socket
|
||||||
|
clientSocket.disconnect();
|
||||||
|
|
||||||
|
// Close the server
|
||||||
|
nodeIo.close();
|
||||||
|
|
||||||
|
// Remove the test data
|
||||||
|
deleteNodeByNuid(localNodeConfig.node.nuid); // Delete the user
|
||||||
|
deleteSystemByName(Object.keys(localNodeConfig.nearbySystems)[0])
|
||||||
|
});
|
||||||
|
// Test Node Login functionality
|
||||||
|
describe('Node Login', () => {
|
||||||
|
it('Should add a new node if it does not exist', async () => {
|
||||||
|
// Simulate a node login request
|
||||||
|
// Use the getNodeByNuid mock function to simulate checking if node exists
|
||||||
|
const existingNode = await getNodeByNuid(localNodeConfig.node.nuid);
|
||||||
|
|
||||||
|
// Assert that existingNode is null before node login
|
||||||
|
expect(existingNode).toEqual(null);
|
||||||
|
|
||||||
|
// Wait for the update
|
||||||
|
const node_login = new Promise(res => {
|
||||||
|
clientSocket.on('node-login-successful', async () => {
|
||||||
|
res();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Emit the login command
|
||||||
|
clientSocket.emit("node-login", localNodeConfig.node);
|
||||||
|
|
||||||
|
// Wait for the successful login event
|
||||||
|
await node_login;
|
||||||
|
|
||||||
|
// Now we need to check if the node is added to the database
|
||||||
|
// We can use getNodeByNuid again to verify if the node was added correctly
|
||||||
|
const addedNode = await getNodeByNuid(localNodeConfig.node.nuid);
|
||||||
|
|
||||||
|
console.log("Added Node:", addedNode);
|
||||||
|
|
||||||
|
// Assert that the node is added correctly
|
||||||
|
expect(addedNode['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(addedNode['nuid']).toEqual(localNodeConfig.node.nuid);
|
||||||
|
expect(addedNode['name']).toEqual(localNodeConfig.node.name);
|
||||||
|
expect(addedNode['location']).toEqual(localNodeConfig.node.location);
|
||||||
|
expect(addedNode['capabilities']).toEqual(localNodeConfig.node.capabilities);
|
||||||
|
})
|
||||||
|
it('Should update a node if it exists', async () => {
|
||||||
|
// Simulate a node login request
|
||||||
|
// Use the getNodeByNuid mock function to simulate checking if node exists
|
||||||
|
const existingNode = await getNodeByNuid(localNodeConfig.node.nuid);
|
||||||
|
|
||||||
|
// Assert that existingNode is matches the existing data before logging in
|
||||||
|
expect(existingNode['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(existingNode['nuid']).toEqual(localNodeConfig.node.nuid);
|
||||||
|
expect(existingNode['name']).toEqual(localNodeConfig.node.name);
|
||||||
|
expect(existingNode['location']).toEqual(localNodeConfig.node.location);
|
||||||
|
expect(existingNode['capabilities']).toEqual(localNodeConfig.node.capabilities);
|
||||||
|
|
||||||
|
// Wait for the update
|
||||||
|
const node_login = new Promise(res => {
|
||||||
|
clientSocket.on('node-login-successful', async () => {
|
||||||
|
res();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Emit the login command
|
||||||
|
clientSocket.emit("node-login", updatedLocalNodeConfig.node);
|
||||||
|
|
||||||
|
// Wait for the successful login event
|
||||||
|
await node_login;
|
||||||
|
|
||||||
|
// Now we need to check if the node is added to the database
|
||||||
|
// We can use getNodeByNuid again to verify if the node was added correctly
|
||||||
|
const updatedNode = await getNodeByNuid(localNodeConfig.node.nuid);
|
||||||
|
|
||||||
|
console.log("Updated Node:", updatedNode);
|
||||||
|
|
||||||
|
// Assert that the node is added correctly
|
||||||
|
expect(updatedNode['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(updatedNode['nuid']).toEqual(updatedLocalNodeConfig.node.nuid);
|
||||||
|
expect(updatedNode['name']).toEqual(updatedLocalNodeConfig.node.name);
|
||||||
|
expect(updatedNode['location']).toEqual(updatedLocalNodeConfig.node.location);
|
||||||
|
expect(updatedNode['capabilities']).toEqual(updatedLocalNodeConfig.node.capabilities);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test Node Update functionality
|
||||||
|
describe('Node Update', () => {
|
||||||
|
it('Should add a node\'s nearby systems', async () => {
|
||||||
|
// Simulate an update request sent from the client to the server
|
||||||
|
|
||||||
|
// Get the existing node in the database
|
||||||
|
const existingNode = await getNodeByNuid(localNodeConfig.node.nuid);
|
||||||
|
|
||||||
|
// Assert that existingNode matches the updatedLocalNodeConfig
|
||||||
|
expect(existingNode['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(existingNode['nuid']).toEqual(updatedLocalNodeConfig.node.nuid);
|
||||||
|
expect(existingNode['name']).toEqual(updatedLocalNodeConfig.node.name);
|
||||||
|
expect(existingNode['location']).toEqual(updatedLocalNodeConfig.node.location);
|
||||||
|
expect(existingNode['capabilities']).toEqual(updatedLocalNodeConfig.node.capabilities);
|
||||||
|
|
||||||
|
// Get the system from the DB
|
||||||
|
const existsingSystem = await getSystemByName("Testing P25 System Name");
|
||||||
|
|
||||||
|
// Assert that there is no existing system in the DB
|
||||||
|
expect(existsingSystem).toEqual(null);
|
||||||
|
|
||||||
|
// Wait for the update
|
||||||
|
const node_system_update = new Promise(res => {
|
||||||
|
clientSocket.on('node-update-successful', async () => {
|
||||||
|
res();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Emit the update command
|
||||||
|
clientSocket.emit("node-update", updatedLocalNodeConfig);
|
||||||
|
|
||||||
|
// Wait for the successful update event
|
||||||
|
await node_system_update;
|
||||||
|
|
||||||
|
// Now we need to check if the system is added to the database
|
||||||
|
// We can use getNodeByNuid again to verify if the node was added correctly
|
||||||
|
const updatedNode = await getNodeByNuid(localNodeConfig.node.nuid);
|
||||||
|
|
||||||
|
console.log("Updated Node:", updatedNode);
|
||||||
|
|
||||||
|
// Assert that the node is added correctly
|
||||||
|
expect(updatedNode['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(updatedNode['nuid']).toEqual(updatedLocalNodeConfig.node.nuid);
|
||||||
|
expect(updatedNode['name']).toEqual(updatedLocalNodeConfig.node.name);
|
||||||
|
expect(updatedNode['location']).toEqual(updatedLocalNodeConfig.node.location);
|
||||||
|
expect(updatedNode['capabilities']).toEqual(updatedLocalNodeConfig.node.capabilities);
|
||||||
|
|
||||||
|
// Get the updated system
|
||||||
|
const addedSystem = await getSystemByName("Testing P25 System Name");
|
||||||
|
|
||||||
|
console.log("Added system:", addedSystem);
|
||||||
|
|
||||||
|
expect(addedSystem['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(addedSystem['nodes']).toBeDefined(); // Check if nodes property exists
|
||||||
|
expect(addedSystem.nodes).toEqual(updatedLocalNodeConfig.node.nuid) // Check if this node ID is in the nodes array
|
||||||
|
expect(addedSystem['frequencies']).toEqual(updatedLocalNodeConfig.nearbySystems['Testing P25 System Name'].frequencies);
|
||||||
|
expect(addedSystem['mode']).toEqual(updatedLocalNodeConfig.nearbySystems['Testing P25 System Name'].mode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update a node and its nearby systems', async () => {
|
||||||
|
// Get the existing node in the database
|
||||||
|
const existingNode = await getNodeByNuid(localNodeConfig.node.nuid);
|
||||||
|
|
||||||
|
// Assert that existingNode matches the updatedLocalNodeConfig
|
||||||
|
expect(existingNode['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(existingNode['nuid']).toEqual(updatedLocalNodeConfig.node.nuid);
|
||||||
|
expect(existingNode['name']).toEqual(updatedLocalNodeConfig.node.name);
|
||||||
|
expect(existingNode['location']).toEqual(updatedLocalNodeConfig.node.location);
|
||||||
|
expect(existingNode['capabilities']).toEqual(updatedLocalNodeConfig.node.capabilities);
|
||||||
|
|
||||||
|
// Get the updated system
|
||||||
|
const existingSystem = await getSystemByName("Testing P25 System Name");
|
||||||
|
expect(existingSystem['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(existingSystem['nodes']).toBeDefined(); // Check if nodes property exists
|
||||||
|
expect(existingSystem.nodes).toContain(updatedLocalNodeConfig.node.nuid); // Check if this node ID is in the nodes array
|
||||||
|
expect(existingSystem['frequencies']).toEqual(updatedLocalNodeConfig.nearbySystems['Testing P25 System Name'].frequencies);
|
||||||
|
expect(existingSystem['mode']).toEqual(updatedLocalNodeConfig.nearbySystems['Testing P25 System Name'].mode);
|
||||||
|
|
||||||
|
// Wait for the update
|
||||||
|
const node_update = new Promise(res => {
|
||||||
|
clientSocket.on('node-update-successful', async () => {
|
||||||
|
res();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Emit the update command
|
||||||
|
clientSocket.emit("node-update", localNodeConfig);
|
||||||
|
|
||||||
|
// Wait for the successful update event
|
||||||
|
await node_update;
|
||||||
|
|
||||||
|
const updatedNode = await getNodeByNuid(localNodeConfig.node.nuid);
|
||||||
|
|
||||||
|
console.log("Updated Node:", updatedNode);
|
||||||
|
|
||||||
|
// Assert that the node is added correctly
|
||||||
|
expect(updatedNode['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(updatedNode['nuid']).toEqual(localNodeConfig.node.nuid);
|
||||||
|
expect(updatedNode['name']).toEqual(localNodeConfig.node.name);
|
||||||
|
expect(updatedNode['location']).toEqual(localNodeConfig.node.location);
|
||||||
|
expect(updatedNode['capabilities']).toEqual(localNodeConfig.node.capabilities);
|
||||||
|
|
||||||
|
// Get the updated system
|
||||||
|
const updatedSystem = await getSystemByName("Testing P25 System Name");
|
||||||
|
|
||||||
|
console.log("Updated system:", updatedSystem);
|
||||||
|
|
||||||
|
expect(updatedSystem['_id']).toBeDefined(); // Check if _id property exists
|
||||||
|
expect(updatedSystem['nodes']).toBeDefined(); // Check if nodes property exists
|
||||||
|
expect(updatedSystem.nodes).toContain(localNodeConfig.node.nuid); // Check if this node ID is in the nodes array
|
||||||
|
expect(updatedSystem['frequencies']).toEqual(localNodeConfig.nearbySystems['Testing P25 System Name'].frequencies);
|
||||||
|
expect(updatedSystem['mode']).toEqual(localNodeConfig.nearbySystems['Testing P25 System Name'].mode);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test getNodeCurrentListeningSystem
|
||||||
|
describe('Get Node Current Listening System', () => {
|
||||||
|
it('should correctly determine if the node is connected to a voice channel', async () => {
|
||||||
|
// Simulate that the client socket is listening to a system
|
||||||
|
const isConnectedToVC = true;
|
||||||
|
const guildId = 'mockGuildId';
|
||||||
|
|
||||||
|
// Emit the event to the server and wait for the response
|
||||||
|
const nodeReply = new Promise((resolve) => {
|
||||||
|
clientSocket.once('node-check-connected-status', (passedGuildId, callback) => {
|
||||||
|
// Check if the passed guild ID matches the expected guild ID
|
||||||
|
expect(passedGuildId).toEqual(guildId);
|
||||||
|
// Simulate receiving the connection status from the client
|
||||||
|
callback(isConnectedToVC);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the function to check if the node is connected to a voice channel
|
||||||
|
const response = checkIfNodeIsConnectedToVC(nodeIo, guildId, localNodeConfig.node.nuid);
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for the promise to resolve
|
||||||
|
const response = await nodeReply;
|
||||||
|
|
||||||
|
// Assert that the response matches the expected connection status
|
||||||
|
expect(response).toEqual(isConnectedToVC);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test checkIfNodeIsConnectedToVC
|
||||||
|
describe('Check if Node is Connected to VC', () => {
|
||||||
|
it('Should correctly determine if the node is connected to a voice channel', async () => {
|
||||||
|
// Simulate that the client socket is listening to a system
|
||||||
|
const isConnectedToVC = true;
|
||||||
|
const guildId = 'mockGuildId';
|
||||||
|
|
||||||
|
// Emit the event to the server and wait for the response
|
||||||
|
const nodeReply = new Promise((resolve) => {
|
||||||
|
clientSocket.once('node-check-connected-status', (passedGuildId, callback) => {
|
||||||
|
// Check if the passed guild ID matches the expected guild ID
|
||||||
|
expect(passedGuildId).to.equal(guildId);
|
||||||
|
// Simulate receiving the connection status from the client
|
||||||
|
callback(isConnectedToVC);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the function to check if the node is connected to a voice channel
|
||||||
|
const response = checkIfNodeIsConnectedToVC(nodeIo, guildId, localNodeConfig.node.nuid);
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for the promise to resolve
|
||||||
|
const response = await nodeReply;
|
||||||
|
|
||||||
|
// Assert that the response matches the expected connection status
|
||||||
|
expect(response).to.equal(isConnectedToVC);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test checkIfNodeHasOpenDiscordClient
|
||||||
|
describe('Check if Node has an open discord client', () => {
|
||||||
|
it('should correctly determine if the node has an open Discord client', async () => {
|
||||||
|
const isDiscordOpen = true;
|
||||||
|
|
||||||
|
// Emit the event to the server and wait for the response
|
||||||
|
const nodeReply = new Promise((resolve) => {
|
||||||
|
clientSocket.once('node-check-discord-open-client', (callback) => {
|
||||||
|
// Simulate receiving the client status from the client
|
||||||
|
callback(isDiscordOpen);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the function to check if the node has an open Discord client
|
||||||
|
const response = checkIfNodeHasOpenDiscordClient(serverClientSocket);
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for the promise to resolve
|
||||||
|
const response = await nodeReply;
|
||||||
|
|
||||||
|
// Assert that the response matches the expected client status
|
||||||
|
expect(response).toEqual(isDiscordOpen);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test getNodeDiscordUsername
|
||||||
|
describe('Get the discord username from the client', () => {
|
||||||
|
it('should request the username from a specific client', async () => {
|
||||||
|
const discordUsername = "Test Discord Username";
|
||||||
|
const guildId = 'mockGuildId';
|
||||||
|
|
||||||
|
// Emit the event to the server and wait for the response
|
||||||
|
const nodeReply = new Promise((resolve) => {
|
||||||
|
clientSocket.once('node-get-discord-username', (passedGuildId, callback) => {
|
||||||
|
// Check if the passed guild ID matches the expected guild ID
|
||||||
|
expect(passedGuildId).toEqual(guildId);
|
||||||
|
// Simulate receiving the username from the client
|
||||||
|
callback(discordUsername);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the function to get the Discord username
|
||||||
|
const username = getNodeDiscordUsername(nodeIo, guildId, localNodeConfig.node.nuid);
|
||||||
|
resolve(username);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for the promise to resolve
|
||||||
|
const username = await nodeReply;
|
||||||
|
|
||||||
|
// Assert that the username matches the expected username
|
||||||
|
expect(username).toEqual(discordUsername);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test getNodeDiscordID
|
||||||
|
describe('Get the discord ID from the client', () => {
|
||||||
|
it('Should get the ID from the client', async () => {
|
||||||
|
// Mocked Discord ID
|
||||||
|
const discordId = "mockDiscordID";
|
||||||
|
|
||||||
|
// Emit the event to the server and wait for the response
|
||||||
|
const nodeReply = new Promise((resolve) => {
|
||||||
|
// Listen for the 'node-get-discord-id' event from the server
|
||||||
|
clientSocket.once('node-get-discord-id', (callback) => {
|
||||||
|
// Simulate receiving the Discord ID from the client
|
||||||
|
callback(discordId);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the function to get the Discord ID
|
||||||
|
const response = getNodeDiscordID(serverClientSocket);
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for the promise to resolve
|
||||||
|
const response = await nodeReply;
|
||||||
|
|
||||||
|
// Assert that the response matches the expected Discord ID
|
||||||
|
expect(response).toEqual(discordId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test requestNodeJoinSystem
|
||||||
|
describe('Request Node Join System', () => {
|
||||||
|
it('Should send a request to the node to join a system', async () => {
|
||||||
|
const systemName = 'mockSystemName';
|
||||||
|
const channelId = 'mockChannelId';
|
||||||
|
const token = 'mockToken';
|
||||||
|
|
||||||
|
// Emit the event to the server and wait for the response
|
||||||
|
await new Promise(async (resolve) => {
|
||||||
|
clientSocket.once('node-join', (joinData) => {
|
||||||
|
// Check if the passed system ID matches the expected system ID
|
||||||
|
expect(joinData.clientID).toEqual(token);
|
||||||
|
expect(joinData.channelID).toEqual(channelId);
|
||||||
|
expect(joinData.system).toEqual(systemName);
|
||||||
|
// Simulate receiving a success callback from the client
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the function to request joining a system
|
||||||
|
requestNodeJoinSystem(serverClientSocket, systemName, channelId, token);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test requestNodeLeaveSystem
|
||||||
|
describe('Request Node Leave System', () => {
|
||||||
|
it('Should send a request to the node to leave a given server', async () => {
|
||||||
|
const guildId = 'mockGuildId';
|
||||||
|
|
||||||
|
// Emit the event to the server and wait for the response
|
||||||
|
await new Promise(async (resolve) => {
|
||||||
|
clientSocket.once('node-leave', (passedGuildId) => {
|
||||||
|
// Check if the passed system ID matches the expected system ID
|
||||||
|
expect(passedGuildId).toEqual(guildId);
|
||||||
|
// Simulate receiving a success callback from the client
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the function to request joining a system
|
||||||
|
requestBotLeaveServer(serverClientSocket, guildId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test requestNodeUpdate
|
||||||
|
describe('Request Node Update', () => {
|
||||||
|
it('Should send the node a request to check for an update', async () => {
|
||||||
|
// Emit the event to the server and wait for the response
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
clientSocket.once('node-request-update', (callback) => {
|
||||||
|
// Simulate an out of date request
|
||||||
|
expect(callback).toBeDefined();
|
||||||
|
callback(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the function to request updating node information
|
||||||
|
const response = requestNodeUpdate(serverClientSocket);
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test nodeDisconnectWrapper
|
||||||
|
describe('Node Disconnect Wrapper', () => {
|
||||||
|
it('Should disconnect the node and trigger cleanup actions', async () => {
|
||||||
|
// Mock the socket ID
|
||||||
|
const socketId = 'mockSocketId';
|
||||||
|
|
||||||
|
// Call the nodeDisconnectWrapper function
|
||||||
|
const result = await nodeDisconnectWrapper(socketId);
|
||||||
|
|
||||||
|
// Assert that the result is as expected (if any)
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user