1 Commits

Author SHA1 Message Date
Logan Cusano
77deb3ba2b Initial recording scraper 2023-06-17 17:33:24 -04:00
22 changed files with 188 additions and 235 deletions

View File

@@ -35,12 +35,12 @@ exports.joinServer = async (req, res) => {
log.INFO("Join requested to: ", deviceId, channelId, clientId, presetName, NGThreshold); log.INFO("Join requested to: ", deviceId, channelId, clientId, presetName, NGThreshold);
if (process.platform === "win32") { if (process.platform === "win32") {
log.DEBUG("Starting Windows Python"); log.DEBUG("Starting Windows Python");
pythonProcess = await spawn('python.exe', [resolve(__dirname, "../pdab/main.py"), deviceId, channelId, clientId, '-n', NGThreshold, '-p', presetName ], { cwd: resolve(__dirname, "../pdab/").toString() }); pythonProcess = await spawn('python.exe', [resolve(__dirname, "../pdab/main.py"), deviceId, channelId, clientId, '-n', NGThreshold], { cwd: resolve(__dirname, "../pdab/").toString() });
//pythonProcess = await spawn('C:\\Python310\\python.exe', [resolve(__dirname, "../PDAB/main.py"), deviceId, channelId, clientId, NGThreshold ]); //pythonProcess = await spawn('C:\\Python310\\python.exe', [resolve(__dirname, "../PDAB/main.py"), deviceId, channelId, clientId, NGThreshold ]);
} }
else { else {
log.DEBUG("Starting Linux Python"); log.DEBUG("Starting Linux Python");
pythonProcess = await spawn('python3', [resolve(__dirname, "../pdab/main.py"), deviceId, channelId, clientId,'-n', NGThreshold, '-p', presetName ], { cwd: resolve(__dirname, "../pdab/") }); pythonProcess = await spawn('python3', [resolve(__dirname, "../pdab/main.py"), deviceId, channelId, clientId,'-n', NGThreshold ], { cwd: resolve(__dirname, "../pdab/") });
} }
log.VERBOSE("Python Process: ", pythonProcess); log.VERBOSE("Python Process: ", pythonProcess);

View File

@@ -67,11 +67,6 @@ async function checkLocalIP() {
* Checks the config file for all required fields or gets and updates the required fields * Checks the config file for all required fields or gets and updates the required fields
*/ */
exports.checkConfig = async function checkConfig() { exports.checkConfig = async function checkConfig() {
if (!runningClientConfig.id || runningClientConfig.id == 0 || runningClientConfig.id == '0') {
updateConfig('id', "");
runningClientConfig.id = null;
}
if (!runningClientConfig.ip) { if (!runningClientConfig.ip) {
const ipAddr = await checkLocalIP(); const ipAddr = await checkLocalIP();
updateConfig('ip', ipAddr); updateConfig('ip', ipAddr);
@@ -102,10 +97,10 @@ exports.checkIn = async () => {
await this.checkConfig(); await this.checkConfig();
// Check if there is an ID found, if not add the node to the server. If there was an ID, check in with the server to make sure it has the correct information // Check if there is an ID found, if not add the node to the server. If there was an ID, check in with the server to make sure it has the correct information
try { try {
if (!runningClientConfig?.id || runningClientConfig.id == null) { if (runningClientConfig.id === 0) {
// ID was not found in the config, creating a new node // ID was not found in the config, creating a new node
reqOptions = new requestOptions("/nodes/newNode", "POST"); reqOptions = new requestOptions("/nodes/newNode", "POST");
sendHttpRequest(reqOptions, JSON.stringify({}), (responseObject) => { sendHttpRequest(reqOptions, JSON.stringify(), (responseObject) => {
// Update the client's ID if the server accepted it // Update the client's ID if the server accepted it
if (responseObject.statusCode === 202) { if (responseObject.statusCode === 202) {
runningClientConfig.id = responseObject.body.nodeId; runningClientConfig.id = responseObject.body.nodeId;
@@ -114,7 +109,6 @@ exports.checkIn = async () => {
if (responseObject.statusCode >= 300) { if (responseObject.statusCode >= 300) {
// Server threw an error // Server threw an error
log.DEBUG("HTTP Error: ", responseObject);
onHttpError(responseObject.statusCode); onHttpError(responseObject.statusCode);
} }
@@ -124,7 +118,6 @@ exports.checkIn = async () => {
// ID is in the config, checking in with the server // ID is in the config, checking in with the server
reqOptions = new requestOptions("/nodes/nodeCheckIn", "POST"); reqOptions = new requestOptions("/nodes/nodeCheckIn", "POST");
sendHttpRequest(reqOptions, JSON.stringify(runningClientConfig), (responseObject) => { sendHttpRequest(reqOptions, JSON.stringify(runningClientConfig), (responseObject) => {
log.DEBUG("Check In Respose: ", responseObject);
if (responseObject.statusCode === 202) { if (responseObject.statusCode === 202) {
// Server accepted an update // Server accepted an update
} }

View File

@@ -1,5 +1,5 @@
import argparse, platform, os import argparse, platform, os
from discord import Intents, Client, Member, opus, Activity, ActivityType from discord import Intents, Client, Member, opus
from discord.ext import commands from discord.ext import commands
from NoiseGatev2 import NoiseGate from NoiseGatev2 import NoiseGate
@@ -25,7 +25,7 @@ async def load_opus():
return "armv7l" return "armv7l"
def main(clientId='OTQzNzQyMDQwMjU1MTE1MzA0.Yg3eRA.ZxEbRr55xahjfaUmPY8pmS-RHTY', channelId=367396189529833476, NGThreshold=50, deviceId=1, presence="the radio"): def main(clientId='OTQzNzQyMDQwMjU1MTE1MzA0.Yg3eRA.ZxEbRr55xahjfaUmPY8pmS-RHTY', channelId=367396189529833476, NGThreshold=50, deviceId=1):
intents = Intents.default() intents = Intents.default()
client = commands.Bot(command_prefix='!', intents=intents) client = commands.Bot(command_prefix='!', intents=intents)
@@ -33,8 +33,6 @@ def main(clientId='OTQzNzQyMDQwMjU1MTE1MzA0.Yg3eRA.ZxEbRr55xahjfaUmPY8pmS-RHTY',
@client.event @client.event
async def on_ready(): async def on_ready():
print(f'We have logged in as {client.user}') print(f'We have logged in as {client.user}')
# Set the presence of the bot (what it's listening to)
await client.change_presence(activity=Activity(type=ActivityType.listening, name=presence))
channelIdToJoin = client.get_channel(channelId) channelIdToJoin = client.get_channel(channelId)
print("Channel", channelIdToJoin) print("Channel", channelIdToJoin)
@@ -57,13 +55,11 @@ def main(clientId='OTQzNzQyMDQwMjU1MTE1MzA0.Yg3eRA.ZxEbRr55xahjfaUmPY8pmS-RHTY',
client.run(clientId) client.run(clientId)
if __name__ == "__main__":
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("deviceId", type=int, help="The ID of the audio device to use") parser.add_argument("deviceId", type=int, help="The ID of the audio device to use")
parser.add_argument("channelId", type=int, help="The ID of the voice channel to use") parser.add_argument("channelId", type=int, help="The ID of the voice channel to use")
parser.add_argument("clientId", type=str, help="The discord client ID") parser.add_argument("clientId", type=str, help="The discord client ID")
parser.add_argument("-n", "--NGThreshold", type=int, help="Change the noisegate threshold. This defaults to 50") parser.add_argument("-n", "--NGThreshold", type=int, help="Change the noisegate threshold. This defaults to 50")
parser.add_argument("-p", "--presence", type=str, help="What the bot should be listening to")
args = parser.parse_args() args = parser.parse_args()
if (not args.NGThreshold): if (not args.NGThreshold):
@@ -75,6 +71,5 @@ if __name__ == "__main__":
clientId=args.clientId, clientId=args.clientId,
channelId=args.channelId, channelId=args.channelId,
NGThreshold=args.NGThreshold, NGThreshold=args.NGThreshold,
deviceId=args.deviceId, deviceId=args.deviceId
presence=args.presence
) )

View File

@@ -13,6 +13,9 @@ ls -ld $SCRIPT_DIR | awk '{print $3}' >> ./config/installerName
useradd -M RadioNode useradd -M RadioNode
usermod -s -L RadioNode usermod -s -L RadioNode
# Create the .env file from the example
cp $SCRIPT_DIR/.env.example $SCRIPT_DIR/.env
# Change the ownership of the directory to the service user # Change the ownership of the directory to the service user
chown RadioNode -R $SCRIPT_DIR chown RadioNode -R $SCRIPT_DIR

View File

@@ -4,7 +4,6 @@ const debug = require('debug');
require('dotenv').config(); require('dotenv').config();
// Modules // Modules
const { writeFile } = require('fs'); const { writeFile } = require('fs');
const { inspect } = require('util');
const logLocation = process.env.LOG_LOCATION; const logLocation = process.env.LOG_LOCATION;
@@ -35,31 +34,31 @@ exports.DebugBuilder = class DebugBuilder {
this.INFO = (...messageParts) => { this.INFO = (...messageParts) => {
const _info = debug(`${appName}:${fileName}:INFO`); const _info = debug(`${appName}:${fileName}:INFO`);
_info(messageParts); _info(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:INFO\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:INFO\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
} }
this.DEBUG = (...messageParts) => { this.DEBUG = (...messageParts) => {
const _debug = debug(`${appName}:${fileName}:DEBUG`); const _debug = debug(`${appName}:${fileName}:DEBUG`);
_debug(messageParts); _debug(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:DEBUG\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:DEBUG\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
} }
this.VERBOSE = (...messageParts) => { this.VERBOSE = (...messageParts) => {
const _verbose = debug(`${appName}:${fileName}:VERBOSE`); const _verbose = debug(`${appName}:${fileName}:VERBOSE`);
_verbose(messageParts); _verbose(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:VERBOSE\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:VERBOSE\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
} }
this.WARN = (...messageParts) => { this.WARN = (...messageParts) => {
const _warn = debug(`${appName}:${fileName}:WARNING`); const _warn = debug(`${appName}:${fileName}:WARNING`);
_warn(messageParts); _warn(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:WARNING\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:WARNING\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
} }
this.ERROR = (...messageParts) => { this.ERROR = (...messageParts) => {
const _error = debug(`${appName}:${fileName}:ERROR`); const _error = debug(`${appName}:${fileName}:ERROR`);
_error(messageParts); _error(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:ERROR\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:ERROR\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(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); setTimeout(process.exit, process.env.EXIT_ON_ERROR_DELAY ?? 0);

View File

@@ -1,52 +0,0 @@
const { SlashCommandBuilder } = require('discord.js');
const { DebugBuilder } = require("../utilities/debugBuilder");
const log = new DebugBuilder("server", "give-role");
module.exports = {
data: new SlashCommandBuilder()
.setName('give-role')
.setDescription('Use this command to give a role you have to another member.')
.addUserOption(option =>
option.setName('user')
.setDescription('The user you wish to give the role to ')
.setRequired(true))
.addRoleOption(option =>
option.setName('role')
.setDescription('The role you wish to give the selected user')
.setRequired(true)),
example: "give-role",
isPrivileged: false,
requiresTokens: false,
defaultTokenUsage: 0,
deferInitialReply: true,
/*async autocomplete(interaction) {
const focusedValue = interaction.options.getFocused();
},*/
async execute(interaction) {
try{
// The role to give to the user
const selectedRole = interaction.options.getRole('role');
// The user who should be given the role
var selectedUser = interaction.options.getUser("user");
selectedUser = interaction.guild.members.cache.get(selectedUser.id);
// The user who initiated the command
const initUser = interaction.member;
log.DEBUG("Give Role DEBUG: ", initUser, selectedRole, selectedUser);
// Check if the user has the role selected
if (!initUser.roles.cache.find(role => role.name === selectedRole.name)) return await interaction.editReply(`Sorry ${initUser}, you don't have the group ${selectedRole} and thus you cannot give it to ${selectedUser}`);
// Give the selected user the role and let both the user and the initiator know
await selectedUser.roles.add(selectedRole);
return await interaction.editReply(`Ok ${initUser}, ${selectedUser} has been given the ${selectedRole} role!`)
}catch(err){
log.ERROR(err)
//await interaction.reply(err.toString());
}
}
};

View File

@@ -1,9 +1,9 @@
// Modules // Modules
const { SlashCommandBuilder } = require('discord.js'); const { customSlashCommandBuilder } = require('../utilities/customSlashCommandBuilder');
const { DebugBuilder } = require("../utilities/debugBuilder"); const { DebugBuilder } = require("../utilities/debugBuilder");
const { getMembersInRole, getAllClientIds, filterAutocompleteValues } = require("../utilities/utils"); const { getMembersInRole, getAllClientIds } = require("../utilities/utils");
const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests"); const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests");
const { getOnlineNodes, updateNodeInfo, addNodeConnection, getConnectionByNodeId, getAllConnections } = require("../utilities/mysqlHandler"); const { getOnlineNodes, updateNodeInfo, addNodeConnection, getConnectionByNodeId } = require("../utilities/mysqlHandler");
// Global Vars // Global Vars
const log = new DebugBuilder("server", "join"); const log = new DebugBuilder("server", "join");
@@ -13,10 +13,10 @@ const log = new DebugBuilder("server", "join");
* *
* @param {*} presetName The preset name to listen to on the client * @param {*} presetName The preset name to listen to on the client
* @param {*} channelId The channel ID to join the bot to * @param {*} channelId The channel ID to join the bot to
* @param {*} connections EITHER A collection of clients that are currently connected OR a single discord client ID (NOT dev portal ID) that should be used to join the server with * @param {*} clientIdsUsed EITHER A collection of clients that are currently connected OR a single discord client ID (NOT dev portal ID) that should be used to join the server with
* @returns * @returns
*/ */
async function joinServerWrapper(presetName, channelId, connections) { async function joinServerWrapper(presetName, channelId, clientIdsUsed) {
// Get nodes online // Get nodes online
var onlineNodes = await new Promise((recordResolve, recordReject) => { var onlineNodes = await new Promise((recordResolve, recordReject) => {
getOnlineNodes((nodeRows) => { getOnlineNodes((nodeRows) => {
@@ -45,16 +45,16 @@ async function joinServerWrapper(presetName, channelId, connections) {
log.DEBUG("All clients: ", Object.keys(availableClientIds)); log.DEBUG("All clients: ", Object.keys(availableClientIds));
var selectedClientId; var selectedClientId;
if (typeof connections === 'string') { if (typeof clientIdsUsed === 'string') {
for (const availableClientId of availableClientIds) { for (const availableClientId of availableClientIds) {
if (availableClientId.discordId != connections ) selectedClientId = availableClientId; if (availableClientId.discordId != clientIdsUsed ) selectedClientId = availableClientId;
} }
} }
else { else {
log.DEBUG("Open connections: ", connections); log.DEBUG("Client IDs Used: ", clientIdsUsed.keys());
for (const connection of connections) { for (const usedClientId of clientIdsUsed.keys()) {
log.DEBUG("Used Client ID: ", connection); log.DEBUG("Used Client ID: ", usedClientId);
availableClientIds = availableClientIds.filter(cid => cid.discordId != connection.clientObject.discordId); availableClientIds = availableClientIds.filter(cid => cid.discordId != usedClientId);
} }
log.DEBUG("Available Client IDs: ", availableClientIds); log.DEBUG("Available Client IDs: ", availableClientIds);
@@ -84,48 +84,19 @@ async function joinServerWrapper(presetName, channelId, connections) {
const nodeConnection = await addNodeConnection(selectedNode, selectedClientId); const nodeConnection = await addNodeConnection(selectedNode, selectedClientId);
log.DEBUG("Node Connection: ", nodeConnection); log.DEBUG("Node Connection: ", nodeConnection);
}); });
return selectedClientId;
} }
exports.joinServerWrapper = joinServerWrapper; exports.joinServerWrapper = joinServerWrapper;
module.exports = { module.exports = {
data: new SlashCommandBuilder() data: new customSlashCommandBuilder()
.setName('join') .setName('join')
.setDescription('Join the channel you are in with the preset you choose') .setDescription('Join the channel you are in with the preset you choose')
.addStringOption(option => .addAllSystemPresetOptions(),
option.setName("preset")
.setDescription("The preset you would like to listen to")
.setAutocomplete(true)
.setRequired(true)),
example: "join", example: "join",
isPrivileged: false, isPrivileged: false,
requiresTokens: false, requiresTokens: false,
defaultTokenUsage: 0, defaultTokenUsage: 0,
deferInitialReply: true, deferInitialReply: true,
async autocomplete(interaction) {
const nodeObjects = await new Promise((recordResolve, recordReject) => {
getOnlineNodes((nodeRows) => {
recordResolve(nodeRows);
});
});
log.DEBUG("Node objects: ", nodeObjects);
var presetsAvailable = [];
for (const nodeObject of nodeObjects) {
log.DEBUG("Node object: ", nodeObject);
for (const presetName in nodeObject.nearbySystems) presetsAvailable.push(nodeObject.nearbySystems[presetName]);
}
log.DEBUG("All Presets available: ", presetsAvailable);
// Remove duplicates
options = [...new Set(presetsAvailable)];
log.DEBUG("DeDuped Presets available: ", options);
// Filter the results to what the user is entering
filterAutocompleteValues(interaction, options);
},
async execute(interaction) { async execute(interaction) {
try{ try{
const guildId = interaction.guild.id; const guildId = interaction.guild.id;
@@ -134,13 +105,12 @@ module.exports = {
const channelId = interaction.member.voice.channel.id; const channelId = interaction.member.voice.channel.id;
log.DEBUG(`Join requested by: ${interaction.user.username}, to: '${presetName}', in channel: ${channelId} / ${guildId}`); log.DEBUG(`Join requested by: ${interaction.user.username}, to: '${presetName}', in channel: ${channelId} / ${guildId}`);
const connections = await getAllConnections(); const onlineBots = await getMembersInRole(interaction);
log.DEBUG("Current Connections: ", connections); log.DEBUG("Online Bots: ", onlineBots);
const selectedClientId = await joinServerWrapper(presetName, channelId, connections); await joinServerWrapper(presetName, channelId, onlineBots.online);
await interaction.editReply('**Pong.**');
await interaction.editReply(`Ok, ${interaction.member}. **${selectedClientId.name}** is joining your channel.`);
//await interaction.channel.send('**Pong.**'); // This will send a message to the channel of the interaction outside of the initial reply //await interaction.channel.send('**Pong.**'); // This will send a message to the channel of the interaction outside of the initial reply
}catch(err){ }catch(err){
log.ERROR(err) log.ERROR(err)

View File

@@ -1,12 +1,13 @@
// Modules // Modules
const { SlashCommandBuilder } = require('discord.js'); const { customSlashCommandBuilder } = require('../utilities/customSlashCommandBuilder');
const { DebugBuilder } = require("../utilities/debugBuilder"); const { DebugBuilder } = require("../utilities/debugBuilder");
const { getAllClientIds, getKeyByArrayValue, filterAutocompleteValues } = require("../utilities/utils"); const { getAllClientIds, getKeyByArrayValue } = require("../utilities/utils");
const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests"); const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests");
const { checkNodeConnectionByClientId, removeNodeConnectionByNodeId, getAllConnections } = require('../utilities/mysqlHandler'); const { checkNodeConnectionByClientId, removeNodeConnectionByNodeId, updateNodeInfo, getConnectedNodes, getAllConnections } = require('../utilities/mysqlHandler');
// Global Vars // Global Vars
const log = new DebugBuilder("server", "leave"); const log = new DebugBuilder("server", "leave");
const logAC = new DebugBuilder("server", "leave_autocorrect");
async function leaveServerWrapper(clientIdObject) { async function leaveServerWrapper(clientIdObject) {
if (!clientIdObject.clientId || !clientIdObject.name) return log.ERROR("Tried to leave server without client ID and/or Name"); if (!clientIdObject.clientId || !clientIdObject.name) return log.ERROR("Tried to leave server without client ID and/or Name");
@@ -33,7 +34,7 @@ async function leaveServerWrapper(clientIdObject) {
exports.leaveServerWrapper = leaveServerWrapper; exports.leaveServerWrapper = leaveServerWrapper;
module.exports = { module.exports = {
data: new SlashCommandBuilder() data: new customSlashCommandBuilder()
.setName('leave') .setName('leave')
.setDescription('Disconnect a bot from the server') .setDescription('Disconnect a bot from the server')
.addStringOption(option => .addStringOption(option =>
@@ -47,12 +48,17 @@ module.exports = {
defaultTokenUsage: 0, defaultTokenUsage: 0,
deferInitialReply: true, deferInitialReply: true,
async autocomplete(interaction) { async autocomplete(interaction) {
const focusedValue = interaction.options.getFocused();
const connections = await getAllConnections(); const connections = await getAllConnections();
const options = connections.map(conn => conn.clientObject.name); const filtered = connections.filter(conn => String(conn.clientObject.name).startsWith(focusedValue)).map(conn => conn.clientObject.name);
await filterAutocompleteValues(interaction, options); logAC.DEBUG("Focused Value: ", focusedValue, connections, filtered);
await interaction.respond(
filtered.map(option => ({ name: option, value: option })),
);
}, },
async execute(interaction) { async execute(interaction) {
try{ try{
const guildId = interaction.guild.id;
const botName = interaction.options.getString('bot'); const botName = interaction.options.getString('bot');
log.DEBUG("Bot Name: ", botName) log.DEBUG("Bot Name: ", botName)
const clinetIds = await getAllClientIds(); const clinetIds = await getAllClientIds();

View File

@@ -7,7 +7,7 @@ const log = new DebugBuilder("server", "remove");
module.exports = { module.exports = {
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName('remove') .setName('remove')
.setDescription('Remove an RSS source by it\'s title') .setDescription('Remove an RSS source by it\' title')
.addStringOption(option => .addStringOption(option =>
option.setName('title') option.setName('title')
.setDescription('The title of the source to remove') .setDescription('The title of the source to remove')

View File

@@ -25,7 +25,7 @@ exports.listAllNodes = async (req, res) => {
// Add a new node to the storage // Add a new node to the storage
exports.newNode = async (req, res) => { exports.newNode = async (req, res) => {
if (!req.body.name) return res.status(400).json("No name specified for new node"); if (!req.body.name) return res.send(400)
try { try {
// Try to add the new user with defaults if missing options // Try to add the new user with defaults if missing options
@@ -38,9 +38,9 @@ exports.newNode = async (req, res) => {
_online: req.body.online ?? 0 _online: req.body.online ?? 0
}); });
addNewNode(newNode, (newNodeObject) => { addNewNode(newNode, (queryResults) => {
// Send back a success if the user has been added and the ID for the client to keep track of // Send back a success if the user has been added and the ID for the client to keep track of
res.status(202).json({"nodeId": newNodeObject.id}); res.status(202).json({"nodeId": queryResults.insertId});
}) })
} }
catch (err) { catch (err) {
@@ -108,7 +108,6 @@ exports.requestNodeJoinServer = async (req, res) => {
*/ */
exports.nodeMonitorService = class nodeMonitorService { exports.nodeMonitorService = class nodeMonitorService {
constructor() { constructor() {
this.log = new DebugBuilder("server", "nodeMonitorService");
} }
async start(){ async start(){
@@ -131,21 +130,21 @@ exports.nodeMonitorService = class nodeMonitorService {
async checkInWithOnlineNodes(){ async checkInWithOnlineNodes(){
getOnlineNodes((nodes) => { getOnlineNodes((nodes) => {
this.log.DEBUG("Online Nodes: ", nodes); log.DEBUG("Online Nodes: ", nodes);
for (const node of nodes) { for (const node of nodes) {
const reqOptions = new requestOptions("/client/requestCheckIn", "GET", node.ip, node.port) const reqOptions = new requestOptions("/client/requestCheckIn", "GET", node.ip, node.port)
sendHttpRequest(reqOptions, "", (responseObj) => { const request = sendHttpRequest(reqOptions, "", (responseObj) => {
if (responseObj) { if (responseObj) {
this.log.DEBUG("Response from: ", node.name, responseObj); log.DEBUG("Response from: ", node.name, responseObj);
} }
else { else {
this.log.DEBUG("No response from node, assuming it's offline"); log.DEBUG("No response from node, assuming it's offline");
const offlineNode = new nodeObject({ _online: 0, _id: node.id }); const offlineNode = new nodeObject({ _online: 0, _id: node.id });
this.log.DEBUG("Offline node update object: ", offlineNode); log.DEBUG("Offline node update object: ", offlineNode);
updateNodeInfo(offlineNode, (sqlResponse) => { updateNodeInfo(offlineNode, (sqlResponse) => {
if (!sqlResponse) this.log.ERROR("No response from SQL object"); if (!sqlResponse) log.ERROR("No response from SQL object");
this.log.DEBUG("Updated offline node: ", sqlResponse); log.DEBUG("Updated node: ", sqlResponse);
}) })
} }
}) })

View File

@@ -148,7 +148,7 @@ client.on('ready', () => {
runHTTPServer(); runHTTPServer();
log.DEBUG("Starting Node Monitoring Service"); log.DEBUG("Starting Node Monitoring Service");
runNodeMonitorService(); //runNodeMonitorService();
log.DEBUG("Starting RSS watcher"); log.DEBUG("Starting RSS watcher");
runRssService(); runRssService();

View File

@@ -5,7 +5,7 @@ const { FeedStorage, PostStorage } = require("./libStorage");
const libUtils = require("./libUtils"); const libUtils = require("./libUtils");
const { DebugBuilder } = require("./utilities/debugBuilder"); const { DebugBuilder } = require("./utilities/debugBuilder");
const log = new DebugBuilder("server", "libCore"); const log = new DebugBuilder("server", "libCore");
const mysql = require("mysql2"); const mysql = require("mysql");
const UserAgent = require("user-agents"); const UserAgent = require("user-agents");
process.env.USER_AGENT_STRING = new UserAgent({ platform: 'Win32' }).toString(); process.env.USER_AGENT_STRING = new UserAgent({ platform: 'Win32' }).toString();

View File

@@ -8,7 +8,7 @@ const { RSSSourceRecord, RSSPostRecord } = require("./utilities/recordHelper");
// Storage Specific Modules // Storage Specific Modules
// MySQL // MySQL
const mysql = require("mysql2"); const mysql = require("mysql");
const rssFeedsTable = process.env.DB_RSS_FEEDS_TABLE; const rssFeedsTable = process.env.DB_RSS_FEEDS_TABLE;
const rssPostsTable = process.env.DB_RSS_POSTS_TABLE; const rssPostsTable = process.env.DB_RSS_POSTS_TABLE;
@@ -481,10 +481,10 @@ exports.PostStorage = class PostStorage extends Storage {
savePost(_postObject, callback){ savePost(_postObject, callback){
const tempCreationDate = returnMysqlTime(); const tempCreationDate = returnMysqlTime();
log.DEBUG("Saving Post Object:", _postObject);
if (!_postObject?.postId || !_postObject?.link) { if (!_postObject?.postId || !_postObject?.link) {
return callback(new Error("Post object malformed, check the object before saving it", _postObject), undefined) return callback(new Error("Post object malformed, check the object before saving it", _postObject), undefined)
} }
log.DEBUG("Saving Post:", _postObject);
if (_postObject.link.length > 250) _postObject.link = _postObject.link.substring(0, 250); if (_postObject.link.length > 250) _postObject.link = _postObject.link.substring(0, 250);

View File

@@ -0,0 +1,40 @@
import scrapy
from scrapy.crawler import CrawlerProcess
class RecordingSpider(scrapy.Spider):
name = "recording-scraper"
start_urls = [
'https://radio.vpn.cusano.net/sdr/transmissions',
]
def parse(self, response):
print("ASDASDD")
print(response)
for row in response.css("tr"):
if row.css('td.py-1'):
links = row.css('a')
rows = row.css('td.py-1')
print(row)
yield {
'device': rows[0],
'date': rows[1],
'duration': rows[2],
"frequency": rows[3],
"link": links[0].attrib["href"],
}
next_page_url = response.css("a.page-link > a::attr(href)").extract_first()
if next_page_url is not None:
yield scrapy.Request(response.urljoin(next_page_url))
process = CrawlerProcess(
settings={
"FEEDS": {
"items.json": {"format": "json"},
},
}
)
process.crawl(RecordingSpider)
process.start() # the script will block here until the crawling is finished

View File

@@ -0,0 +1,3 @@
scrapy
fake-useragent
beautifulsoup4

View File

@@ -21,7 +21,7 @@
"jsdoc": "^4.0.2", "jsdoc": "^4.0.2",
"jsonfile": "^6.1.0", "jsonfile": "^6.1.0",
"morgan": "^1.10.0", "morgan": "^1.10.0",
"mysql2": "^3.3.5", "mysql": "^2.18.1",
"node-html-markdown": "^1.3.0", "node-html-markdown": "^1.3.0",
"node-html-parser": "^6.1.5", "node-html-parser": "^6.1.5",
"openai": "^3.2.1", "openai": "^3.2.1",

View File

@@ -0,0 +1,46 @@
const { SlashCommandBuilder, SlashCommandStringOption } = require('discord.js');
const { DebugBuilder } = require("../utilities/debugBuilder");
const { BufferToJson } = require("../utilities/utils");
const log = new DebugBuilder("server", "customSlashCommandBuilder");
const { getAllNodes, getAllNodesSync } = require("../utilities/mysqlHandler");
exports.customSlashCommandBuilder = class customSlashCommandBuilder extends SlashCommandBuilder {
constructor() {
super();
}
async addAllSystemPresetOptions() {
const nodeObjects = await new Promise((recordResolve, recordReject) => {
getAllNodes((nodeRows) => {
recordResolve(nodeRows);
});
});
log.DEBUG("Node objects: ", nodeObjects);
var presetsAvailable = [];
for (const nodeObject of nodeObjects) {
log.DEBUG("Node object: ", nodeObject);
for (const presetName in nodeObject.nearbySystems) presetsAvailable.push(nodeObject.nearbySystems[presetName]);
}
log.DEBUG("All Presets available: ", presetsAvailable);
// Remove duplicates
presetsAvailable = [...new Set(presetsAvailable)];
log.DEBUG("DeDuped Presets available: ", presetsAvailable);
this.addStringOption(option => option.setName("preset").setRequired(true).setDescription("The channels"));
for (const preset of presetsAvailable){
log.DEBUG("Preset: ", preset);
this.options[0].addChoices({
'name': String(preset),
'value': String(preset)
});
}
log.DEBUG("Preset Options: ", this);
return this;
}
}

View File

@@ -4,7 +4,6 @@ const debug = require('debug');
require('dotenv').config(); require('dotenv').config();
// Modules // Modules
const { writeFile } = require('fs'); const { writeFile } = require('fs');
const { inspect } = require('util');
const logLocation = process.env.LOG_LOCATION; const logLocation = process.env.LOG_LOCATION;
@@ -35,31 +34,31 @@ exports.DebugBuilder = class DebugBuilder {
this.INFO = (...messageParts) => { this.INFO = (...messageParts) => {
const _info = debug(`${appName}:${fileName}:INFO`); const _info = debug(`${appName}:${fileName}:INFO`);
_info(messageParts); _info(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:INFO\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:INFO\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
} }
this.DEBUG = (...messageParts) => { this.DEBUG = (...messageParts) => {
const _debug = debug(`${appName}:${fileName}:DEBUG`); const _debug = debug(`${appName}:${fileName}:DEBUG`);
_debug(messageParts); _debug(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:DEBUG\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:DEBUG\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
} }
this.VERBOSE = (...messageParts) => { this.VERBOSE = (...messageParts) => {
const _verbose = debug(`${appName}:${fileName}:VERBOSE`); const _verbose = debug(`${appName}:${fileName}:VERBOSE`);
_verbose(messageParts); _verbose(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:VERBOSE\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:VERBOSE\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
} }
this.WARN = (...messageParts) => { this.WARN = (...messageParts) => {
const _warn = debug(`${appName}:${fileName}:WARNING`); const _warn = debug(`${appName}:${fileName}:WARNING`);
_warn(messageParts); _warn(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:WARNING\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:WARNING\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
} }
this.ERROR = (...messageParts) => { this.ERROR = (...messageParts) => {
const _error = debug(`${appName}:${fileName}:ERROR`); const _error = debug(`${appName}:${fileName}:ERROR`);
_error(messageParts); _error(messageParts);
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:ERROR\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName); writeToLog(`${appName}:${fileName}:ERROR\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(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); setTimeout(process.exit, process.env.EXIT_ON_ERROR_DELAY ?? 0);

View File

@@ -11,14 +11,14 @@ const path = require('node:path');
const { DebugBuilder } = require("./debugBuilder"); const { DebugBuilder } = require("./debugBuilder");
const log = new DebugBuilder("server", "deployCommands"); const log = new DebugBuilder("server", "deployCommands");
var commands = []; const commands = [];
// Grab all the command files from the commands directory you created earlier // Grab all the command files from the commands directory you created earlier
const commandsPath = path.resolve(__dirname, '../commands'); const commandsPath = path.resolve(__dirname, '../commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
exports.deploy = (clientId, guildIDs) => { exports.deploy = (clientId, guildIDs) => {
log.DEBUG("Deploying commands for: ", guildIDs); log.DEBUG("Deploying commands for: ", guildIDs);
if (!Array.isArray(guildIDs)) guildIDs = [guildIDs]; if (Array.isArray(guildIDs)) guildIDs = [guildIDs];
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment // Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) { for (const file of commandFiles) {
const command = require(`${path.resolve(commandsPath, file)}`); const command = require(`${path.resolve(commandsPath, file)}`);
@@ -48,35 +48,3 @@ exports.deploy = (clientId, guildIDs) => {
})() })()
} }
}; };
/**
* Remove all commands for a given bot in a given guild
*
* @param {*} clientId The client ID of the bot to remove commands from
* @param {*} guildId The ID of the guild to remove the bot commands from
*/
exports.removeAll = (clientId, guildId) => {
if (!Array.isArray(guildId)) guildIDs = [guildId];
log.DEBUG("Removing commands for: ", clientId, guildIDs);
commands = [];
const rest = new REST({ version: '10' }).setToken(token);
for (const guildId of guildIDs){
(async () => {
try {
log.DEBUG(`Started refreshing ${commands.length} application (/) commands for guild ID: ${guildId}.`);
// The put method is used to fully refresh all commands in the guild with the current set
const data = await rest.put(
Routes.applicationGuildCommands(clientId, guildId),
{ body: commands },
);
log.DEBUG(`Successfully reloaded ${data.length} application (/) commands for guild ID: ${guildId}.`);
} catch (error) {
// And of course, make sure you catch and log any errors!
log.ERROR("ERROR Deploying commands: ", error, "Body from error: ", commands);
}
})()
}
}

View File

@@ -1,5 +1,5 @@
require('dotenv').config(); require('dotenv').config();
const mysql = require('mysql2'); const mysql = require('mysql');
const utils = require('./utils'); const utils = require('./utils');
const { nodeObject, clientObject, connectionObject } = require("./recordHelper"); const { nodeObject, clientObject, connectionObject } = require("./recordHelper");
const { DebugBuilder } = require("../utilities/debugBuilder"); const { DebugBuilder } = require("../utilities/debugBuilder");
@@ -92,7 +92,7 @@ exports.getAllNodesSync = async () => {
console.log("Rows: ", rows); console.log("Rows: ", rows);
return await returnNodeObjectFromRows(rows); return returnNodeObjectFromRows(rows);
} }
/** Get all nodes that have the online status set true (are online) /** Get all nodes that have the online status set true (are online)
@@ -110,7 +110,7 @@ exports.getOnlineNodes = (callback) => {
* @param callback Callback function * @param callback Callback function
*/ */
async function getNodeInfoFromId(nodeId, callback = undefined) { async function getNodeInfoFromId(nodeId, callback = undefined) {
if (!nodeId || nodeId == '0' || nodeId == 0 ) throw new Error("No node ID given when trying to fetch node"); if (!nodeId) throw new Error("No node ID given when trying to fetch node");
log.DEBUG("Getting node from ID: ", nodeId); log.DEBUG("Getting node from ID: ", nodeId);
const sqlQuery = `SELECT * FROM ${nodesTable} WHERE id = ${nodeId}` const sqlQuery = `SELECT * FROM ${nodesTable} WHERE id = ${nodeId}`
@@ -122,7 +122,7 @@ exports.getOnlineNodes = (callback) => {
// Call back the first (and theoretically only) row // Call back the first (and theoretically only) row
// Specify 0 so downstream functions don't have to worry about it // Specify 0 so downstream functions don't have to worry about it
return (callback) ? callback(await returnNodeObjectFromRow(sqlResponse[0])) : await returnNodeObjectFromRow(sqlResponse[0]); return (callback) ? callback(returnNodeObjectFromRow(sqlResponse[0])) : returnNodeObjectFromRow(sqlResponse[0]);
} }
exports.getNodeInfoFromId = getNodeInfoFromId exports.getNodeInfoFromId = getNodeInfoFromId
@@ -136,9 +136,10 @@ exports.addNewNode = async (nodeObject, callback) => {
ip = nodeObject.ip, ip = nodeObject.ip,
port = nodeObject.port, port = nodeObject.port,
location = nodeObject.location, location = nodeObject.location,
nearbySystems = utils.JsonToBuffer(nodeObject.nearbySystems ?? {}), nearbySystems = utils.JsonToBuffer(nodeObject.nearbySystems),
online = nodeObject.online online = nodeObject.online,
const sqlQuery = `INSERT INTO ${nodesTable} (name, ip, port, location, nearbySystems, online) VALUES ('${name}', '${ip}', ${port}, '${location}', '${nearbySystems}', ${online})`; connected = 0;
const sqlQuery = `INSERT INTO ${nodesTable} (name, ip, port, location, nearbySystems, online, connected) VALUES ('${name}', '${ip}', ${port}, '${location}', '${nearbySystems}', ${online}, ${connected})`;
const sqlResponse = await new Promise((recordResolve, recordReject) => { const sqlResponse = await new Promise((recordResolve, recordReject) => {
runSQL(sqlQuery, (rows) => { runSQL(sqlQuery, (rows) => {
@@ -148,9 +149,7 @@ exports.addNewNode = async (nodeObject, callback) => {
// Call back the first (and theoretically only) row // Call back the first (and theoretically only) row
// Specify 0 so downstream functions don't have to worry about it // Specify 0 so downstream functions don't have to worry about it
const newNode = await this.getNodeInfoFromId(sqlResponse.insertId); return (callback) ? callback(returnNodeObjectFromRow(sqlResponse)) : returnNodeObjectFromRow(sqlResponse);
log.DEBUG("Added new node: ", newNode)
return (callback) ? callback(newNode) : newNode;
} }
/** Update the known info on a node /** Update the known info on a node
@@ -207,7 +206,7 @@ exports.updateNodeInfo = async (nodeObject, callback = undefined) => {
}); });
if (sqlResponse.affectedRows === 1) return (callback) ? callback(true) : true; if (sqlResponse.affectedRows === 1) return (callback) ? callback(true) : true;
else return (callback) ? callback(await returnNodeObjectFromRows(sqlResponse)) : await returnNodeObjectFromRows(sqlResponse); else return (callback) ? callback(returnNodeObjectFromRows(sqlResponse)) : returnNodeObjectFromRows(sqlResponse);
} }
/** /**
@@ -354,12 +353,12 @@ exports.getAllConnections = async (callback = undefined) => {
// Function to run and handle SQL errors // Function to run and handle SQL errors
function runSQL(sqlQuery, callback = undefined, error = (err) => { function runSQL(sqlQuery, callback = undefined, error = (err) => {
log.ERROR(err); console.log(err);
throw err; throw err;
}) { }) {
connection.query(sqlQuery, (err, rows) => { connection.query(sqlQuery, (err, rows) => {
if (err) return error(err); if (err) return error(err);
log.VERBOSE('Response for query: ', sqlQuery, rows); //console.log('The rows are:', rows);
return (callback) ? callback(rows) : rows return (callback) ? callback(rows) : rows
}) })
} }

View File

@@ -110,6 +110,8 @@ class nodeObject {
* @param {*} param0._port The port that the client is listening on * @param {*} param0._port The port that the client is listening on
* @param {*} param0._location The physical location of the node * @param {*} param0._location The physical location of the node
* @param {*} param0._online True/False if the node is online or offline * @param {*} param0._online True/False if the node is online or offline
* @param {*} param0._connected True/False if the bot is connected to discord or not
* @param {*} param0._connection The connection Object associated with the node, null if not checked, undefined if none exists
* @param {*} param0._nearbySystems An object array of nearby systems * @param {*} param0._nearbySystems An object array of nearby systems
*/ */
constructor({ _id = null, _name = null, _ip = null, _port = null, _location = null, _nearbySystems = null, _online = null }) { constructor({ _id = null, _name = null, _ip = null, _port = null, _location = null, _nearbySystems = null, _online = null }) {

View File

@@ -3,7 +3,6 @@ const { DebugBuilder } = require("../utilities/debugBuilder");
const { clientObject } = require("./recordHelper"); const { clientObject } = require("./recordHelper");
const { readFileSync } = require('fs'); const { readFileSync } = require('fs');
const log = new DebugBuilder("server", "utils"); const log = new DebugBuilder("server", "utils");
const logAC = new DebugBuilder("server", "command-autocorrect");
const path = require('path'); const path = require('path');
// Convert a JSON object to a buffer for the DB // Convert a JSON object to a buffer for the DB
@@ -118,19 +117,3 @@ exports.getClientObjectByClientID = (clientId) => {
} }
return undefined return undefined
} }
exports.filterAutocompleteValues = async (interaction, options) => {
// Get the command used
const command = interaction.command;
// Find values that start with what the user is entering
const focusedValue = interaction.options.getFocused();
const filtered = options.filter(preset => preset.startsWith(focusedValue));
// Give the query response to the user
logAC.DEBUG("Focused Value: ", command, focusedValue, options, filtered);
await interaction.respond(
filtered.map(option => ({ name: option, value: option })),
);
}