Implement Discord CnC Server into Emmelia
This commit is contained in:
8
config/databaseConfig.js
Normal file
8
config/databaseConfig.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
const databaseConfig = {
|
||||||
|
database_host: '100.20.1.45',
|
||||||
|
database_user: 'DRB_CNC',
|
||||||
|
database_password: 'baMbC6IAl$Rn7$h0PS',
|
||||||
|
database_database: 'DRB_CNC'
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = databaseConfig;
|
||||||
5
config/discordConfig.js
Normal file
5
config/discordConfig.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
const discordConfig = {
|
||||||
|
channelID: '367396189529833476'
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = discordConfig;
|
||||||
129
controllers/adminController.js
Normal file
129
controllers/adminController.js
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
// Config
|
||||||
|
const discordConfig = require("../config/discordConfig");
|
||||||
|
// Debug
|
||||||
|
const { DebugBuilder } = require("../utilities/debugBuilder.js");
|
||||||
|
const log = new DebugBuilder("server", "adminController");
|
||||||
|
// Utilities
|
||||||
|
const mysqlHandler = require("../utilities/mysqlHandler");
|
||||||
|
const utils = require("../utilities/utils");
|
||||||
|
const requests = require("../utilities/httpRequests");
|
||||||
|
|
||||||
|
/** Get the presets of all online nodes, can be used for functions
|
||||||
|
*
|
||||||
|
* @param callback Callback function
|
||||||
|
* @returns {*} A list of the systems online
|
||||||
|
*/
|
||||||
|
async function getPresetsOfOnlineNodes(callback) {
|
||||||
|
mysqlHandler.getOnlineNodes((onlineNodes) => {
|
||||||
|
let systems = {};
|
||||||
|
onlineNodes.forEach(onlineNode => {
|
||||||
|
systems[onlineNode.id] = utils.BufferToJson(onlineNode.nearbySystems);
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(systems);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function requestNodeListenToPreset(preset, nodeId, callback) {
|
||||||
|
mysqlHandler.getNodeInfoFromId(nodeId, (nodeObject) =>{
|
||||||
|
reqOptions = new requests.requestOptions("/bot/join", "POST", nodeObject.ip, nodeObject.port);
|
||||||
|
requests.sendHttpRequest(reqOptions, JSON.stringify({
|
||||||
|
"channelID": discordConfig.channelID,
|
||||||
|
"presetName": preset
|
||||||
|
}), (responseObject) => {
|
||||||
|
callback(responseObject)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getNodeBotStatus(nodeId, callback) {
|
||||||
|
mysqlHandler.getNodeInfoFromId(nodeId, (nodeObject) =>{
|
||||||
|
reqOptions = new requests.requestOptions("/bot/status", "GET", nodeObject.ip, nodeObject.port, undefined, 5);
|
||||||
|
requests.sendHttpRequest(reqOptions, JSON.stringify({}), (responseObject) => {
|
||||||
|
if (responseObject === false) {
|
||||||
|
// Bot is joined
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Bot is free
|
||||||
|
}
|
||||||
|
callback(responseObject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function requestNodeLeaveServer(nodeId, callback) {
|
||||||
|
getNodeBotStatus(nodeId, (responseObject) => {
|
||||||
|
if (responseObject === false) {
|
||||||
|
// Bot is joined
|
||||||
|
mysqlHandler.getNodeInfoFromId(nodeId, (nodeObject) =>{
|
||||||
|
reqOptions = new requests.requestOptions("/bot/leave", "POST", nodeObject.ip, nodeObject.port);
|
||||||
|
requests.sendHttpRequest(reqOptions, JSON.stringify({}), (responseObject) => {
|
||||||
|
callback(responseObject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Bot is free
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Return to requests for the presets of all online nodes, cannot be used in functions
|
||||||
|
*
|
||||||
|
* @param {*} req Express request parameter
|
||||||
|
* @param {*} res Express response parameter
|
||||||
|
*/
|
||||||
|
exports.getAvailablePresets = async (req, res) => {
|
||||||
|
await getPresetsOfOnlineNodes((systems) => {
|
||||||
|
res.status(200).json({
|
||||||
|
"systemsOnline": systems
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Request a node to join the server listening to a specific preset
|
||||||
|
*
|
||||||
|
* @param {*} req Express request parameter
|
||||||
|
* @var {*} req.body.preset The preset to join (REQ)
|
||||||
|
* @var {*} req.body.nodeId The specific node to join (OPT/REQ if more than one node has the preset)
|
||||||
|
* @param {*} res Express response parameter
|
||||||
|
*/
|
||||||
|
exports.joinPreset = async (req, res) => {
|
||||||
|
if (!req.body.preset) return res.status(400).json("No preset specified");
|
||||||
|
await getPresetsOfOnlineNodes((systems) => {
|
||||||
|
const systemsWithSelectedPreset = Object.values(systems).filter(nodePresets => nodePresets.includes(req.body.preset)).length
|
||||||
|
if (!systemsWithSelectedPreset) return res.status(400).json("No system online with that preset");
|
||||||
|
if (systemsWithSelectedPreset > 1) {
|
||||||
|
if (!req.body.nodeId) return res.status(175).json("Multiple locations with the selected channel, please specify a nodeID (nodeId)")
|
||||||
|
requestNodeListenToPreset(req.body.preset, req.body.nodeId, (responseObject) => {
|
||||||
|
if (responseObject === false) return res.status(400).json("Timeout reached");
|
||||||
|
return res.sendStatus(responseObject.statusCode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let nodeId;
|
||||||
|
if (!req.body.nodeId) nodeId = utils.getKeyByArrayValue(systems, req.body.preset);
|
||||||
|
else nodeId = req.body.nodeId;
|
||||||
|
requestNodeListenToPreset(req.body.preset, nodeId, (responseObject) => {
|
||||||
|
if (responseObject === false) return res.status(400).json("Timeout reached");
|
||||||
|
return res.sendStatus(responseObject.statusCode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Request a node to join the server listening to a specific preset
|
||||||
|
*
|
||||||
|
* @param {*} req Express request parameter
|
||||||
|
* @param {*} res Express response parameter
|
||||||
|
*/
|
||||||
|
exports.leaveServer = async (req, res) => {
|
||||||
|
if (!req.body.nodeId) return res.status(400).json("No nodeID specified");
|
||||||
|
|
||||||
|
requestNodeLeaveServer(req.body.nodeId, (responseObject) => {
|
||||||
|
if (responseObject === false) return res.status(400).json("Bot not joined to server");
|
||||||
|
return res.sendStatus(responseObject.statusCode);
|
||||||
|
});
|
||||||
|
}
|
||||||
80
controllers/nodesController.js
Normal file
80
controllers/nodesController.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// Debug
|
||||||
|
const { DebugBuilder } = require("../utilities/debugBuilder.js");
|
||||||
|
const log = new DebugBuilder("server", "nodesController");
|
||||||
|
// Utilities
|
||||||
|
const mysqlHander = require("../utilities/mysqlHandler");
|
||||||
|
const utils = require("../utilities/utils");
|
||||||
|
|
||||||
|
exports.listAllNodes = async (req, res) => {
|
||||||
|
mysqlHander.getAllNodes((allNodes) => {
|
||||||
|
res.status(200).json({
|
||||||
|
"nodes_online": allNodes
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new node to the
|
||||||
|
exports.newNode = async (req, res) => {
|
||||||
|
if (!req.body.name) return res.send(400)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try to add the new user with defaults if missing options
|
||||||
|
mysqlHander.addNewNode({
|
||||||
|
'name': req.body.name,
|
||||||
|
'ip': req.body.ip ?? null,
|
||||||
|
'port': req.body.port ?? null,
|
||||||
|
'location': req.body.location ?? null,
|
||||||
|
'nearbySystems': req.body.nearbySystems ?? null,
|
||||||
|
'online': req.body.online ?? 0
|
||||||
|
}, (queryResults) => {
|
||||||
|
// 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": queryResults.insertId});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// Catch any errors
|
||||||
|
if (err === "No name provided") {
|
||||||
|
return res.sendStatus(400);
|
||||||
|
}
|
||||||
|
else log.ERROR(err)
|
||||||
|
return res.sendStatus(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the known info for the node specified
|
||||||
|
exports.getNodeInfo = async (req, res) => {
|
||||||
|
if (!req.query.id) return res.status(400).json("No id specified");
|
||||||
|
mysqlHander.getNodeInfoFromId(req.query.id, (nodeInfo) => {
|
||||||
|
res.status(200).json(nodeInfo);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates the information received from the client based on ID
|
||||||
|
exports.nodeCheckIn = async (req, res) => {
|
||||||
|
if (!req.body.id) return res.status(400).json("No id specified");
|
||||||
|
mysqlHander.getNodeInfoFromId(req.body.id, (nodeInfo) => {
|
||||||
|
let nodeObject = {};
|
||||||
|
// Convert the DB systems buffer to a JSON object to be worked with
|
||||||
|
nodeInfo.nearbySystems = utils.BufferToJson(nodeInfo.nearbySystems)
|
||||||
|
// Convert the online status to a boolean to be worked with
|
||||||
|
nodeInfo.online = nodeInfo.online !== 0;
|
||||||
|
|
||||||
|
if (req.body.name && req.body.name !== nodeInfo.name) nodeObject.name = req.body.name
|
||||||
|
if (req.body.ip && req.body.ip !== nodeInfo.ip) nodeObject.ip = req.body.ip
|
||||||
|
if (req.body.port && req.body.port !== nodeInfo.port) nodeObject.port = req.body.port
|
||||||
|
if (req.body.location && req.body.location !== nodeInfo.location) nodeObject.location = req.body.location
|
||||||
|
if (req.body.nearbySystems && JSON.stringify(req.body.nearbySystems) !== JSON.stringify(nodeInfo.nearbySystems)) nodeObject.nearbySystems = req.body.nearbySystems
|
||||||
|
if (req.body.online && req.body.online !== nodeInfo.online) nodeObject.online = req.body.online
|
||||||
|
|
||||||
|
// If no changes are made tell the client
|
||||||
|
if (Object.keys(nodeObject).length === 0) return res.status(200).json("No keys updated");
|
||||||
|
|
||||||
|
log.INFO("Updating the following keys for ID: ", req.body.id, nodeObject);
|
||||||
|
// Adding the ID key to the body so that the client can double-check their ID
|
||||||
|
nodeObject.id = req.body.id;
|
||||||
|
mysqlHander.updateNodeInfo(nodeObject, () => {
|
||||||
|
return res.status(202).json({"updatedKeys": nodeObject});
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
123
index.js
123
index.js
@@ -1,14 +1,22 @@
|
|||||||
|
var createError = require('http-errors');
|
||||||
|
var express = require('express');
|
||||||
|
var path = require('path');
|
||||||
|
var cookieParser = require('cookie-parser');
|
||||||
|
var logger = require('morgan');
|
||||||
|
var http = require('http');
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('node:path');
|
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
prefix = process.env.PREFIX
|
const libCore = require("./libCore");
|
||||||
token = process.env.TOKEN;
|
const libUtils = require("./libUtils");
|
||||||
|
|
||||||
|
const { DebugBuilder } = require("./utilities/debugBuilder");
|
||||||
|
const log = new DebugBuilder("server", "index");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Routes
|
Routes
|
||||||
} = require('discord-api-types/v9');
|
} = require('discord-api-types/v9');
|
||||||
const {
|
|
||||||
quotes
|
|
||||||
} = require('./quotes.json');
|
|
||||||
//const Discord = require('discord.js');Client, Collection, Intents
|
//const Discord = require('discord.js');Client, Collection, Intents
|
||||||
const {
|
const {
|
||||||
Client,
|
Client,
|
||||||
@@ -18,54 +26,81 @@ const {
|
|||||||
MessageButton
|
MessageButton
|
||||||
} = require('discord.js');
|
} = require('discord.js');
|
||||||
//const client = new Discord.Client();
|
//const client = new Discord.Client();
|
||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
intents: [Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILDS]
|
intents: [Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILDS]
|
||||||
});
|
});
|
||||||
const PORT = process.env.PORT || 3000;
|
|
||||||
const express = require("express");
|
|
||||||
const server = express();
|
|
||||||
var libCore = require("./libCore.js");
|
|
||||||
|
|
||||||
let linkFlayerMap = [];
|
prefix = process.env.PREFIX
|
||||||
|
discordToken = process.env.TOKEN;
|
||||||
|
|
||||||
server.all("/", (req, res) => {
|
var indexRouter = require('./routes/index');
|
||||||
var htmlOutput = "LinkFlayer Bot is Ready - Sources loading <br />";
|
var nodesRouter = require('./routes/nodes');
|
||||||
|
var adminRouter = require('./routes/admin');
|
||||||
|
|
||||||
var sources = libCore.getSources();
|
// HTTP Server Config
|
||||||
sources.forEach(source => {
|
var app = express();
|
||||||
htmlOutput += `
|
|
||||||
<div style='margin-bottom:15px;'>
|
|
||||||
|
|
||||||
<div> Title: ${source.title} </div>
|
// view engine setup
|
||||||
<div> Link: ${source.link} </div>
|
app.set('views', path.join(__dirname, 'views'));
|
||||||
<div> category: ${source.category} </div>
|
app.set('view engine', 'ejs');
|
||||||
|
|
||||||
</div>
|
app.use(logger('dev'));
|
||||||
<div>
|
app.use(express.json());
|
||||||
<hr />
|
app.use(express.urlencoded({ extended: false }));
|
||||||
|
app.use(cookieParser());
|
||||||
|
app.use(express.static(path.join(__dirname, 'public')));
|
||||||
|
|
||||||
</div>
|
// Web Interface
|
||||||
|
app.use('/', indexRouter);
|
||||||
|
|
||||||
`
|
// Nodes API
|
||||||
});
|
app.use('/nodes', nodesRouter);
|
||||||
res.send(htmlOutput);
|
|
||||||
|
|
||||||
|
// Admin API
|
||||||
|
app.use('/admin', adminRouter);
|
||||||
|
|
||||||
|
// catch 404 and forward to error handler
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
next(createError(404));
|
||||||
});
|
});
|
||||||
|
|
||||||
function keepAlive() {
|
var port = libUtils.normalizePort(process.env.HTTP_PORT || '3000');
|
||||||
server.listen(PORT, () => {
|
app.set('port', port);
|
||||||
console.log("Keep Alive Server Running");
|
|
||||||
|
// error handler
|
||||||
|
app.use((err, req, res, next) => {
|
||||||
|
// set locals, only providing error in development
|
||||||
|
res.locals.message = err.message;
|
||||||
|
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||||
|
|
||||||
|
// render the error page
|
||||||
|
res.status(err.status || 500);
|
||||||
|
res.render('error');
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the HTTP background server
|
||||||
|
*/
|
||||||
|
function runHTTPServer() {
|
||||||
|
var server = http.createServer(app);
|
||||||
|
server.listen(port);
|
||||||
|
|
||||||
|
server.on('error', libUtils.onError);
|
||||||
|
|
||||||
|
server.on('listening', () => {
|
||||||
|
log.INFO("Local HTTP Server Running");
|
||||||
try {
|
try {
|
||||||
libCore.loadFeeds();
|
|
||||||
libCore.feedArray = libCore.getFeeds();
|
libCore.feedArray = libCore.getFeeds();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
log.ERROR(error);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Discord bot config
|
||||||
|
|
||||||
|
// Setup commands for the Discord bot
|
||||||
client.commands = new Collection();
|
client.commands = new Collection();
|
||||||
const commandsPath = path.join(__dirname, 'commands');
|
const commandsPath = path.join(__dirname, 'commands');
|
||||||
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
|
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
|
||||||
@@ -78,8 +113,13 @@ for (const file of commandFiles) {
|
|||||||
client.commands.set(command.name, command);
|
client.commands.set(command.name, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
client.on('ready', () => {
|
client.on('ready', () => {
|
||||||
console.log(`Logged in as ${client.user.tag}!`);
|
log.DEBUG(`Discord server up and running with client: ${client.user.tag}`);
|
||||||
|
log.DEBUG(`Starting HTTP Server`);
|
||||||
|
runHTTPServer();
|
||||||
|
|
||||||
|
log.INFO(`Logged in as ${client.user.tag}!`);
|
||||||
|
log.INFO("HTTP server started!");
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('interactionCreate', async interaction => {
|
client.on('interactionCreate', async interaction => {
|
||||||
@@ -95,6 +135,7 @@ client.on('interactionCreate', async interaction => {
|
|||||||
try {
|
try {
|
||||||
//await command.execute(interaction);
|
//await command.execute(interaction);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
log.ERROR(error);
|
||||||
//console.error(error);
|
//console.error(error);
|
||||||
//await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
|
//await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
|
||||||
}
|
}
|
||||||
@@ -111,17 +152,15 @@ client.on('messageCreate', message => {
|
|||||||
try {
|
try {
|
||||||
client.commands.get(command).execute(message, args);
|
client.commands.get(command).execute(message, args);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
log.ERROR(error);
|
||||||
//message.reply('there was an error trying to execute that command!');
|
//message.reply('there was an error trying to execute that command!');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Link Flayer Bot Activating");
|
client.login(discordToken); //Load Client Discord Token
|
||||||
keepAlive();
|
|
||||||
client.login(token); //Load Client Discord Token
|
|
||||||
try {
|
try {
|
||||||
console.log("Loading initial startup feeds");
|
log.INFO("Loading initial startup feeds");
|
||||||
libCore.loadFeeds();
|
libCore.loadFeeds();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
log.ERROR(error);
|
||||||
}
|
}
|
||||||
55
libCore.js
55
libCore.js
@@ -4,6 +4,9 @@ const axios = require('axios');
|
|||||||
let parser = new Parser();
|
let parser = new Parser();
|
||||||
const storageHandler = require("./libStorage");
|
const storageHandler = require("./libStorage");
|
||||||
|
|
||||||
|
const { DebugBuilder } = require("./utilities/debugBuilder");
|
||||||
|
const log = new DebugBuilder("server", "libCore");
|
||||||
|
|
||||||
/* OpenAI config
|
/* OpenAI config
|
||||||
const { Configuration, OpenAIApi } = require('openai');
|
const { Configuration, OpenAIApi } = require('openai');
|
||||||
const configuration = new Configuration({
|
const configuration = new Configuration({
|
||||||
@@ -48,11 +51,11 @@ exports.addSource = function (title, link, category, callback) {
|
|||||||
}
|
}
|
||||||
}], function (err, record) {
|
}], function (err, record) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error("Error in create:", err);
|
log.ERROR("Error in create:", err);
|
||||||
callback(err, undefined);
|
callback(err, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Record ID:", record.getId());
|
log.DEBUG("Record ID:", record.getId());
|
||||||
|
|
||||||
var linkData = {
|
var linkData = {
|
||||||
title: `${title}`,
|
title: `${title}`,
|
||||||
@@ -61,11 +64,11 @@ exports.addSource = function (title, link, category, callback) {
|
|||||||
id: record.getId()
|
id: record.getId()
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Link Data:", linkData);
|
log.DEBUG("Link Data:", linkData);
|
||||||
|
|
||||||
feeds.push(linkData);
|
feeds.push(linkData);
|
||||||
|
|
||||||
console.log("pushed item to feeds");
|
log.DEBUG("pushed item to feeds");
|
||||||
callback(undefined, true);
|
callback(undefined, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -85,10 +88,10 @@ exports.deleteSource = function (title, callback) {
|
|||||||
}
|
}
|
||||||
storageSource.destroy(deleteRecord, function (err, deletedRecord) {
|
storageSource.destroy(deleteRecord, function (err, deletedRecord) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
log.ERROR(err);
|
||||||
callback(err, undefined);
|
callback(err, undefined);
|
||||||
}
|
}
|
||||||
console.log(deletedRecord.id);
|
log.DEBUG(deletedRecord.id);
|
||||||
callback(undefined, deletedRecord);
|
callback(undefined, deletedRecord);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -124,9 +127,9 @@ exports.loadFeeds = function () {
|
|||||||
storageSource.getAllRecords(function (err, records) {
|
storageSource.getAllRecords(function (err, records) {
|
||||||
records.forEach(function (record) {
|
records.forEach(function (record) {
|
||||||
try {
|
try {
|
||||||
console.log('Retrieved title: ', record.get('title'));
|
log.DEBUG('Retrieved title: ', record.get('title'));
|
||||||
console.log('Retrieved link:', record.get('link'));
|
log.DEBUG('Retrieved link:', record.get('link'));
|
||||||
console.log('Retrieved category:', record.get('category'));
|
log.DEBUG('Retrieved category:', record.get('category'));
|
||||||
|
|
||||||
var feedData = {
|
var feedData = {
|
||||||
title: `${unescape(record.get('title'))}`,
|
title: `${unescape(record.get('title'))}`,
|
||||||
@@ -158,7 +161,7 @@ exports.loadFeeds = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
log.DEBUG(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -167,7 +170,7 @@ exports.loadFeeds = function () {
|
|||||||
try {
|
try {
|
||||||
const feed = parser.parseURL(feedBlock.link, function (err, feed) {
|
const feed = parser.parseURL(feedBlock.link, function (err, feed) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(err + " " + feedBlock.link);
|
log.DEBUG(err + " " + feedBlock.link);
|
||||||
//return;
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,19 +194,19 @@ exports.loadFeeds = function () {
|
|||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('error parsing :' + feedBlock.link);
|
log.DEBUG('error parsing :' + feedBlock.link);
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
log.DEBUG(error);
|
||||||
}
|
}
|
||||||
})().then();
|
})().then();
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
//fetchNextPage();
|
//fetchNextPage();
|
||||||
}, function done(error) {
|
}, function done(error) {
|
||||||
console.log(error);
|
log.DEBUG(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +219,7 @@ exports.loadFeeds = function () {
|
|||||||
exports.weatherAlert = async function (state) {
|
exports.weatherAlert = async function (state) {
|
||||||
|
|
||||||
var answerURL = `https://api.weather.gov/alerts/active?area=${state}`;
|
var answerURL = `https://api.weather.gov/alerts/active?area=${state}`;
|
||||||
console.log(answerURL);
|
log.DEBUG(answerURL);
|
||||||
answerData = [];
|
answerData = [];
|
||||||
|
|
||||||
await axios.get(answerURL)
|
await axios.get(answerURL)
|
||||||
@@ -228,7 +231,7 @@ exports.weatherAlert = async function (state) {
|
|||||||
return answerData;
|
return answerData;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
log.DEBUG(error);
|
||||||
});
|
});
|
||||||
return answerData;
|
return answerData;
|
||||||
}
|
}
|
||||||
@@ -241,15 +244,15 @@ exports.weatherAlert = async function (state) {
|
|||||||
exports.getFood = async function () {
|
exports.getFood = async function () {
|
||||||
|
|
||||||
var answerURL = `https://www.themealdb.com/api/json/v1/1/random.php`;
|
var answerURL = `https://www.themealdb.com/api/json/v1/1/random.php`;
|
||||||
console.log(answerURL);
|
log.DEBUG(answerURL);
|
||||||
answerData = {
|
answerData = {
|
||||||
text: `No answer found try using a simpler search term`,
|
text: `No answer found try using a simpler search term`,
|
||||||
source: ``
|
source: ``
|
||||||
}
|
}
|
||||||
await axios.get(answerURL)
|
await axios.get(answerURL)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
//console.log(response.data.RelatedTopics[0].Text);
|
//log.DEBUG(response.data.RelatedTopics[0].Text);
|
||||||
//console.log(response.data.RelatedTopics[0].FirstURL);
|
//log.DEBUG(response.data.RelatedTopics[0].FirstURL);
|
||||||
|
|
||||||
// if (response.data.meals.length != 0) {
|
// if (response.data.meals.length != 0) {
|
||||||
|
|
||||||
@@ -274,7 +277,7 @@ exports.getFood = async function () {
|
|||||||
return answerData;
|
return answerData;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
log.DEBUG(error);
|
||||||
});
|
});
|
||||||
return answerData;
|
return answerData;
|
||||||
}
|
}
|
||||||
@@ -288,14 +291,14 @@ exports.getFood = async function () {
|
|||||||
exports.getSlang = async function (question) {
|
exports.getSlang = async function (question) {
|
||||||
|
|
||||||
var answerURL = `https://api.urbandictionary.com/v0/define?term=${question}`;
|
var answerURL = `https://api.urbandictionary.com/v0/define?term=${question}`;
|
||||||
console.log(answerURL);
|
log.DEBUG(answerURL);
|
||||||
slangData = {
|
slangData = {
|
||||||
definition: `No answer found try using a simpler search term`,
|
definition: `No answer found try using a simpler search term`,
|
||||||
example: ``
|
example: ``
|
||||||
}
|
}
|
||||||
await axios.get(answerURL)
|
await axios.get(answerURL)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
console.log(response.data.list[0]);
|
log.DEBUG(response.data.list[0]);
|
||||||
|
|
||||||
slangData = {
|
slangData = {
|
||||||
definition: `${unescape(response.data.list[0].definition) ? unescape(response.data.list[0].definition) : ''}`,
|
definition: `${unescape(response.data.list[0].definition) ? unescape(response.data.list[0].definition) : ''}`,
|
||||||
@@ -307,7 +310,7 @@ exports.getSlang = async function (question) {
|
|||||||
return slangData;
|
return slangData;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
log.DEBUG(error);
|
||||||
});
|
});
|
||||||
return slangData;
|
return slangData;
|
||||||
}
|
}
|
||||||
@@ -349,14 +352,14 @@ exports.getQuotes = async function (quote_url) {
|
|||||||
var data = [];
|
var data = [];
|
||||||
await axios.get(quote_url)
|
await axios.get(quote_url)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
console.log(response.data[0].q);
|
log.DEBUG(response.data[0].q);
|
||||||
console.log(response.data[0].a);
|
log.DEBUG(response.data[0].a);
|
||||||
data = response.data;
|
data = response.data;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
log.DEBUG(error);
|
||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
// Update the functions here to change the storage medium
|
// Update the functions here to change the storage medium
|
||||||
|
|
||||||
// Import modules
|
// Import modules
|
||||||
|
const { DebugBuilder } = require("./utilities/debugBuilder");
|
||||||
|
const log = new DebugBuilder("server", "libStorage");
|
||||||
|
|
||||||
// Storage Specific Modules
|
// Storage Specific Modules
|
||||||
// MySQL
|
// MySQL
|
||||||
@@ -11,17 +13,17 @@ const mysql = require("mysql");
|
|||||||
// Helper Functions
|
// Helper Functions
|
||||||
// Function to run and handle SQL errors
|
// Function to run and handle SQL errors
|
||||||
function runSQL(sqlQuery, connection, callback = (err, rows) => {
|
function runSQL(sqlQuery, connection, callback = (err, rows) => {
|
||||||
console.log(err);
|
log.ERROR(err);
|
||||||
throw err;
|
throw err;
|
||||||
}) {
|
}) {
|
||||||
// Start the MySQL Connection
|
// Start the MySQL Connection
|
||||||
//connection.connect();
|
//connection.connect();
|
||||||
connection.query(sqlQuery, (err, rows) => {
|
connection.query(sqlQuery, (err, rows) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log("SQL Error:", err)
|
log.ERROR("SQL Error:", err)
|
||||||
callback(err, undefined);
|
callback(err, undefined);
|
||||||
}
|
}
|
||||||
console.log("RunSQL Returned Rows:", rows);
|
log.DEBUG("RunSQL Returned Rows:", rows);
|
||||||
callback(undefined, rows);
|
callback(undefined, rows);
|
||||||
})
|
})
|
||||||
//connection.
|
//connection.
|
||||||
@@ -73,18 +75,18 @@ exports.Storage = class Storage {
|
|||||||
* @param {function} callback The callback function to be called with the record when saved
|
* @param {function} callback The callback function to be called with the record when saved
|
||||||
*/
|
*/
|
||||||
create(toBeSaved, callback) {
|
create(toBeSaved, callback) {
|
||||||
console.log("To be saved:", toBeSaved);
|
log.DEBUG("To be saved:", toBeSaved);
|
||||||
console.log("to be saved length:", toBeSaved.length);
|
log.DEBUG("to be saved length:", toBeSaved.length);
|
||||||
if (!toBeSaved[0].fields?.title) callback(Error("No title given"), undefined);
|
if (!toBeSaved[0].fields?.title) callback(Error("No title given"), undefined);
|
||||||
let newRecords = []
|
let newRecords = []
|
||||||
for (var entry of toBeSaved) {
|
for (var entry of toBeSaved) {
|
||||||
entry = entry.fields
|
entry = entry.fields
|
||||||
console.log("Entry:", entry);
|
log.DEBUG("Entry:", entry);
|
||||||
this.returnRecord(undefined, entry.title, entry.link, entry.category, (err, record) => {
|
this.returnRecord(undefined, entry.title, entry.link, entry.category, (err, record) => {
|
||||||
if (err) callback(err, undefined);
|
if (err) callback(err, undefined);
|
||||||
newRecords.push(record);
|
newRecords.push(record);
|
||||||
if (toBeSaved.length === 1) {
|
if (toBeSaved.length === 1) {
|
||||||
console.log("One record to callback with:", record);
|
log.DEBUG("One record to callback with:", record);
|
||||||
callback(undefined, record);
|
callback(undefined, record);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -150,14 +152,14 @@ exports.Storage = class Storage {
|
|||||||
* @param {function} callback The callback to be called with either an error or undefined if successful
|
* @param {function} callback The callback to be called with either an error or undefined if successful
|
||||||
*/
|
*/
|
||||||
saveEntry(entryObject, callback) {
|
saveEntry(entryObject, callback) {
|
||||||
console.log("Saving entry:", entryObject);
|
log.DEBUG("Saving entry:", entryObject);
|
||||||
if (!entryObject?.title || !entryObject?.link || !entryObject?.category) {
|
if (!entryObject?.title || !entryObject?.link || !entryObject?.category) {
|
||||||
callback(new Error("Entry object malformed, check the object before saving it"), undefined)
|
callback(new Error("Entry object malformed, check the object before saving it"), undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
const sqlQuery = `INSERT INTO ${this.dbTable} (title, link, category) VALUES ('${entryObject.title}', '${entryObject.link}', '${entryObject.category}');`;
|
const sqlQuery = `INSERT INTO ${this.dbTable} (title, link, category) VALUES ('${entryObject.title}', '${entryObject.link}', '${entryObject.category}');`;
|
||||||
|
|
||||||
console.log(`Adding new entry with SQL query: '${sqlQuery}'`)
|
log.DEBUG(`Adding new entry with SQL query: '${sqlQuery}'`)
|
||||||
|
|
||||||
runSQL(sqlQuery, this.connection, (err, rows) => {
|
runSQL(sqlQuery, this.connection, (err, rows) => {
|
||||||
if (err) callback(err, undefined);
|
if (err) callback(err, undefined);
|
||||||
@@ -194,7 +196,7 @@ exports.Storage = class Storage {
|
|||||||
|
|
||||||
sqlQuery = `${sqlQuery} WHERE title = '${entryObject.title}';`
|
sqlQuery = `${sqlQuery} WHERE title = '${entryObject.title}';`
|
||||||
|
|
||||||
console.log(`Updating entry with SQL query: '${sqlQuery}'`)
|
log.DEBUG(`Updating entry with SQL query: '${sqlQuery}'`)
|
||||||
|
|
||||||
runSQL(sqlQuery, this.connection, (err, rows) => {
|
runSQL(sqlQuery, this.connection, (err, rows) => {
|
||||||
if (err) callback(err, undefined);
|
if (err) callback(err, undefined);
|
||||||
@@ -229,7 +231,7 @@ exports.Storage = class Storage {
|
|||||||
* @param {*} callback Callback function to return an error or the record
|
* @param {*} callback Callback function to return an error or the record
|
||||||
*/
|
*/
|
||||||
returnRecord(_id, _title, _link, _category, callback) {
|
returnRecord(_id, _title, _link, _category, callback) {
|
||||||
console.log(`Return record for these values: ID: '${_id}', Title: '${_title}', Category: '${_category}', Link: '${_link}'`)
|
log.DEBUG(`Return record for these values: ID: '${_id}', Title: '${_title}', Category: '${_category}', Link: '${_link}'`)
|
||||||
if (!_link && !_title) callback(new Error("No link or title given when creating a record"), undefined);
|
if (!_link && !_title) callback(new Error("No link or title given when creating a record"), undefined);
|
||||||
let entryObject = {
|
let entryObject = {
|
||||||
"title": _title,
|
"title": _title,
|
||||||
@@ -250,7 +252,7 @@ exports.Storage = class Storage {
|
|||||||
else {
|
else {
|
||||||
this.checkForTitle(_title, (err, titleExists) => {
|
this.checkForTitle(_title, (err, titleExists) => {
|
||||||
if (!titleExists) {
|
if (!titleExists) {
|
||||||
console.log("Entry doesn't exist, making one now", entryObject);
|
log.DEBUG("Entry doesn't exist, making one now", entryObject);
|
||||||
this.saveEntry(entryObject, (err, rows) => {
|
this.saveEntry(entryObject, (err, rows) => {
|
||||||
if (err) callback(err, undefined);
|
if (err) callback(err, undefined);
|
||||||
this.getRecordBy("title", entryObject.title, (err, record) => {
|
this.getRecordBy("title", entryObject.title, (err, record) => {
|
||||||
@@ -277,7 +279,7 @@ exports.Storage = class Storage {
|
|||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
*/
|
*/
|
||||||
getAllRecords(callback) {
|
getAllRecords(callback) {
|
||||||
console.log("Getting all records");
|
log.INFO("Getting all records");
|
||||||
const sqlQuery = `SELECT * FROM ${this.dbTable}`
|
const sqlQuery = `SELECT * FROM ${this.dbTable}`
|
||||||
|
|
||||||
let rssRecords = [];
|
let rssRecords = [];
|
||||||
@@ -285,10 +287,10 @@ exports.Storage = class Storage {
|
|||||||
runSQL(sqlQuery, this.connection, (err, rows) => {
|
runSQL(sqlQuery, this.connection, (err, rows) => {
|
||||||
if (err) callback(err, undefined);
|
if (err) callback(err, undefined);
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
console.log("Row from SQL query:", row);
|
log.DEBUG("Row from SQL query:", row);
|
||||||
rssRecords.push(new RSSRecord(row.id, row.title, row.link, row.category));
|
rssRecords.push(new RSSRecord(row.id, row.title, row.link, row.category));
|
||||||
}
|
}
|
||||||
console.log("All records:", rssRecords);
|
log.DEBUG("All records:", rssRecords);
|
||||||
callback(undefined, rssRecords);
|
callback(undefined, rssRecords);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
54
libUtils.js
54
libUtils.js
@@ -1,7 +1,59 @@
|
|||||||
|
const { DebugBuilder } = require("./utilities/debugBuilder");
|
||||||
|
const log = new DebugBuilder("server", "libUtils");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sleep - sleep/wait
|
* sleep - sleep/wait
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
exports.sleep = (ms) => new Promise((resolve) => {
|
exports.sleep = (ms) => new Promise((resolve) => {
|
||||||
setTimeout(resolve, ms);
|
setTimeout(resolve, ms);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a port into a number, string, or false.
|
||||||
|
*
|
||||||
|
* @param {*} val Value to be normalized
|
||||||
|
* @returns Normalized value
|
||||||
|
*/
|
||||||
|
exports.normalizePort = (val) => {
|
||||||
|
var port = parseInt(val, 10);
|
||||||
|
|
||||||
|
if (isNaN(port)) {
|
||||||
|
// named pipe
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port >= 0) {
|
||||||
|
// port number
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event listener for HTTP server "error" event.
|
||||||
|
*/
|
||||||
|
exports.onError = (error) => {
|
||||||
|
if (error.syscall !== 'listen') {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bind = typeof port === 'string'
|
||||||
|
? 'Pipe ' + port
|
||||||
|
: 'Port ' + port;
|
||||||
|
|
||||||
|
// handle specific listen errors with friendly messages
|
||||||
|
switch (error.code) {
|
||||||
|
case 'EACCES':
|
||||||
|
log.ERROR(bind + ' requires elevated privileges');
|
||||||
|
process.exit(1);
|
||||||
|
break;
|
||||||
|
case 'EADDRINUSE':
|
||||||
|
log.ERROR(bind + ' is already in use');
|
||||||
|
process.exit(1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
234
package-lock.json
generated
234
package-lock.json
generated
@@ -11,17 +11,21 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/builders": "^0.15.0",
|
"@discordjs/builders": "^0.15.0",
|
||||||
"@discordjs/rest": "^0.5.0",
|
"@discordjs/rest": "^0.5.0",
|
||||||
"airtable": "^0.11.1",
|
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
"chatgpt": "^1.4.0",
|
"chatgpt": "^1.4.0",
|
||||||
|
"cookie-parser": "~1.4.4",
|
||||||
|
"debug": "~2.6.9",
|
||||||
"discord-api-types": "^0.35.0",
|
"discord-api-types": "^0.35.0",
|
||||||
"discord.js": "^13.8.1",
|
"discord.js": "^13.8.1",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
|
"ejs": "~2.6.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
|
"http-errors": "~1.6.3",
|
||||||
"js-doc": "^0.5.0",
|
"js-doc": "^0.5.0",
|
||||||
"jsonfile": "^6.1.0",
|
"jsonfile": "^6.1.0",
|
||||||
"mathjs": "^10.6.4",
|
"mathjs": "^10.6.4",
|
||||||
|
"morgan": "~1.9.1",
|
||||||
"mysql": "2.18.1",
|
"mysql": "2.18.1",
|
||||||
"openai": "^3.1.0",
|
"openai": "^3.1.0",
|
||||||
"parse-files": "^0.1.1",
|
"parse-files": "^0.1.1",
|
||||||
@@ -232,22 +236,6 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/abort-controller": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
|
||||||
"dependencies": {
|
|
||||||
"event-target-shim": "^5.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/abortcontroller-polyfill": {
|
|
||||||
"version": "1.7.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz",
|
|
||||||
"integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ=="
|
|
||||||
},
|
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
@@ -260,21 +248,6 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/airtable": {
|
|
||||||
"version": "0.11.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/airtable/-/airtable-0.11.6.tgz",
|
|
||||||
"integrity": "sha512-Na67L2TO1DflIJ1yOGhQG5ilMfL2beHpsR+NW/jhaYOa4QcoxZOtDFs08cpSd1tBMsLpz5/rrz/VMX/pGL/now==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": ">=8.0.0 <15",
|
|
||||||
"abort-controller": "^3.0.0",
|
|
||||||
"abortcontroller-polyfill": "^1.4.0",
|
|
||||||
"lodash": "^4.17.21",
|
|
||||||
"node-fetch": "^2.6.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ansi-regex": {
|
"node_modules/ansi-regex": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
|
||||||
@@ -376,6 +349,22 @@
|
|||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/basic-auth": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "5.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/basic-auth/node_modules/safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
},
|
||||||
"node_modules/bignumber.js": {
|
"node_modules/bignumber.js": {
|
||||||
"version": "9.0.0",
|
"version": "9.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
|
||||||
@@ -413,6 +402,21 @@
|
|||||||
"npm": "1.2.8000 || >= 1.4.16"
|
"npm": "1.2.8000 || >= 1.4.16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/body-parser/node_modules/http-errors": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"inherits": "2.0.4",
|
||||||
|
"setprototypeof": "1.2.0",
|
||||||
|
"statuses": "2.0.1",
|
||||||
|
"toidentifier": "1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
@@ -568,6 +572,26 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cookie-parser": {
|
||||||
|
"version": "1.4.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
|
||||||
|
"integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": "0.4.1",
|
||||||
|
"cookie-signature": "1.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cookie-parser/node_modules/cookie": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cookie-signature": {
|
"node_modules/cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
@@ -713,6 +737,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||||
},
|
},
|
||||||
|
"node_modules/ejs": {
|
||||||
|
"version": "2.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz",
|
||||||
|
"integrity": "sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/encodeurl": {
|
"node_modules/encodeurl": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
@@ -770,14 +802,6 @@
|
|||||||
"through": "^2.3.8"
|
"through": "^2.3.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/event-target-shim": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eventsource-parser": {
|
"node_modules/eventsource-parser": {
|
||||||
"version": "0.0.5",
|
"version": "0.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-0.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-0.0.5.tgz",
|
||||||
@@ -838,6 +862,21 @@
|
|||||||
"node": ">= 0.10.0"
|
"node": ">= 0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/express/node_modules/http-errors": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"inherits": "2.0.4",
|
||||||
|
"setprototypeof": "1.2.0",
|
||||||
|
"statuses": "2.0.1",
|
||||||
|
"toidentifier": "1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/extend": {
|
"node_modules/extend": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
@@ -1032,18 +1071,43 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/http-errors": {
|
"node_modules/http-errors": {
|
||||||
"version": "2.0.0",
|
"version": "1.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
||||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
"integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"depd": "2.0.0",
|
"depd": "~1.1.2",
|
||||||
"inherits": "2.0.4",
|
"inherits": "2.0.3",
|
||||||
"setprototypeof": "1.2.0",
|
"setprototypeof": "1.1.0",
|
||||||
"statuses": "2.0.1",
|
"statuses": ">= 1.4.0 < 2"
|
||||||
"toidentifier": "1.0.1"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-errors/node_modules/depd": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-errors/node_modules/inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="
|
||||||
|
},
|
||||||
|
"node_modules/http-errors/node_modules/setprototypeof": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
|
||||||
|
},
|
||||||
|
"node_modules/http-errors/node_modules/statuses": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
@@ -1890,6 +1954,40 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/morgan": {
|
||||||
|
"version": "1.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
|
||||||
|
"integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
|
||||||
|
"dependencies": {
|
||||||
|
"basic-auth": "~2.0.0",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"depd": "~1.1.2",
|
||||||
|
"on-finished": "~2.3.0",
|
||||||
|
"on-headers": "~1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/morgan/node_modules/depd": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/morgan/node_modules/on-finished": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
|
||||||
|
"dependencies": {
|
||||||
|
"ee-first": "1.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mri": {
|
"node_modules/mri": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||||
@@ -1968,6 +2066,14 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/on-headers": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/once": {
|
"node_modules/once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
@@ -2170,6 +2276,21 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/raw-body/node_modules/http-errors": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"inherits": "2.0.4",
|
||||||
|
"setprototypeof": "1.2.0",
|
||||||
|
"statuses": "2.0.1",
|
||||||
|
"toidentifier": "1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readable-stream": {
|
"node_modules/readable-stream": {
|
||||||
"version": "2.3.7",
|
"version": "2.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||||
@@ -2323,6 +2444,21 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/send/node_modules/http-errors": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"inherits": "2.0.4",
|
||||||
|
"setprototypeof": "1.2.0",
|
||||||
|
"statuses": "2.0.1",
|
||||||
|
"toidentifier": "1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/send/node_modules/ms": {
|
"node_modules/send/node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/builders": "^0.15.0",
|
"@discordjs/builders": "^0.15.0",
|
||||||
"@discordjs/rest": "^0.5.0",
|
"@discordjs/rest": "^0.5.0",
|
||||||
"airtable": "^0.11.1",
|
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
"chatgpt": "^1.4.0",
|
"chatgpt": "^1.4.0",
|
||||||
"discord-api-types": "^0.35.0",
|
"discord-api-types": "^0.35.0",
|
||||||
@@ -20,7 +19,12 @@
|
|||||||
"openai": "^3.1.0",
|
"openai": "^3.1.0",
|
||||||
"parse-files": "^0.1.1",
|
"parse-files": "^0.1.1",
|
||||||
"rss-parser": "^3.12.0",
|
"rss-parser": "^3.12.0",
|
||||||
"mysql": "2.18.1"
|
"mysql": "2.18.1",
|
||||||
|
"cookie-parser": "~1.4.4",
|
||||||
|
"debug": "~2.6.9",
|
||||||
|
"ejs": "~2.6.1",
|
||||||
|
"http-errors": "~1.6.3",
|
||||||
|
"morgan": "~1.9.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
|||||||
19
routes/admin.js
Normal file
19
routes/admin.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// Debug
|
||||||
|
const { DebugBuilder } = require("../utilities/debugBuilder.js");
|
||||||
|
const log = new DebugBuilder("server", "admin");
|
||||||
|
// Modules
|
||||||
|
var express = require('express');
|
||||||
|
var router = express.Router();
|
||||||
|
var adminController = require("../controllers/adminController");
|
||||||
|
|
||||||
|
/* GET */
|
||||||
|
router.get('/presets', adminController.getAvailablePresets);
|
||||||
|
|
||||||
|
/* POST */
|
||||||
|
router.post('/join', adminController.joinPreset);
|
||||||
|
|
||||||
|
/* POST */
|
||||||
|
router.post('/leave', adminController.leaveServer);
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
31
routes/index.js
Normal file
31
routes/index.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
const libCore = require("../libCore");
|
||||||
|
var express = require('express');
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
/* GET home page. */
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
var sources = libCore.getSources();
|
||||||
|
//res.render('index', { "sources": sources });
|
||||||
|
|
||||||
|
var htmlOutput = "";
|
||||||
|
|
||||||
|
sources.forEach(source => {
|
||||||
|
htmlOutput += `
|
||||||
|
<div style='margin-bottom:15px;'>
|
||||||
|
|
||||||
|
<div> Title: ${source.title} </div>
|
||||||
|
<div> Link: ${source.link} </div>
|
||||||
|
<div> category: ${source.category} </div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
`
|
||||||
|
});
|
||||||
|
res.send(htmlOutput);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
31
routes/nodes.js
Normal file
31
routes/nodes.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const nodesController = require('../controllers/nodesController');
|
||||||
|
|
||||||
|
/* GET nodes the server knows */
|
||||||
|
router.get('/', nodesController.listAllNodes);
|
||||||
|
|
||||||
|
// TODO Need to authenticate this request
|
||||||
|
/* POST a new node to the server
|
||||||
|
*
|
||||||
|
* Will create a new DB entry for the node for the server to reference later
|
||||||
|
* Req. body: {
|
||||||
|
* "serverInfo": {"ip": "x.x.x.x", port: 0000}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Will return a token for the client to reference when the bot is making requests
|
||||||
|
* Res. body {
|
||||||
|
* "serverToken": ""
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
router.post('/newNode', nodesController.newNode);
|
||||||
|
|
||||||
|
// TODO Need to authenticate this request
|
||||||
|
/* GET the information the server has on a particular node */
|
||||||
|
router.get('/nodeInfo', nodesController.getNodeInfo);
|
||||||
|
|
||||||
|
// TODO Need to authenticate this request
|
||||||
|
// Client checkin with the server to update information
|
||||||
|
router.post('/nodeCheckIn', nodesController.nodeCheckIn);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
17
utilities/debugBuilder.js
Normal file
17
utilities/debugBuilder.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// Debug
|
||||||
|
const debug = require('debug');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the different logging methods for a function
|
||||||
|
* Namespace template = ("[app]:[fileName]:['INFO', 'WARNING', 'DEBUG', 'ERROR']")
|
||||||
|
* @param {string} appName The name of the app to be used in the 'app' portion of the namespace
|
||||||
|
* @param {string} fileName The name of the file calling the builder to be used in the 'fileName' portion of the namespace
|
||||||
|
*/
|
||||||
|
exports.DebugBuilder = class DebugBuilder {
|
||||||
|
constructor(appName, fileName) {
|
||||||
|
this.INFO = debug(`${appName}:${fileName}:INFO`);
|
||||||
|
this.DEBUG = debug(`${appName}:${fileName}:DEBUG`);
|
||||||
|
this.WARN = debug(`${appName}:${fileName}:WARNING`);
|
||||||
|
this.ERROR = debug(`${appName}:${fileName}:ERROR`);
|
||||||
|
}
|
||||||
|
}
|
||||||
68
utilities/httpRequests.js
Normal file
68
utilities/httpRequests.js
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// Debug
|
||||||
|
const { DebugBuilder } = require("../utilities/debugBuilder.js");
|
||||||
|
const log = new DebugBuilder("server", "httpRequests");
|
||||||
|
// Modules
|
||||||
|
const http = require("http");
|
||||||
|
|
||||||
|
exports.requestOptions = class requestOptions {
|
||||||
|
/**
|
||||||
|
* Construct an HTTP request
|
||||||
|
* @param {*} method Method of request to use [GET, POST]
|
||||||
|
* @param {*} headers Headers of the request, not required but will get filled with default values if not set
|
||||||
|
* @param {*} hostname The destination of the request
|
||||||
|
* @param {*} port The port for the destination, will use 3001 by default
|
||||||
|
*/
|
||||||
|
constructor(path, method, hostname, port = 3001, headers = undefined, timeout = undefined) {
|
||||||
|
this.hostname = hostname;
|
||||||
|
this.path = path;
|
||||||
|
this.port = port;
|
||||||
|
this.method = method;
|
||||||
|
this.timeout = timeout;
|
||||||
|
if (method === "POST"){
|
||||||
|
this.headers = headers ?? {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the HTTP request to the server
|
||||||
|
* @param requestOptions
|
||||||
|
* @param data
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
exports.sendHttpRequest = function sendHttpRequest(requestOptions, data, callback){
|
||||||
|
log.DEBUG("Sending a request to: ", requestOptions.hostname, requestOptions.port)
|
||||||
|
// Create the request
|
||||||
|
const req = http.request(requestOptions, res => {
|
||||||
|
res.on('data', (data) => {
|
||||||
|
const responseObject = {
|
||||||
|
"statusCode": res.statusCode,
|
||||||
|
"body": data
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
responseObject.body = JSON.parse(responseObject.body)
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
}
|
||||||
|
|
||||||
|
log.DEBUG("Response Object: ", responseObject);
|
||||||
|
callback(responseObject);
|
||||||
|
})
|
||||||
|
}).on('error', err => {
|
||||||
|
log.ERROR('Error: ', err.message)
|
||||||
|
// TODO need to handle if the server is down
|
||||||
|
})
|
||||||
|
|
||||||
|
if (requestOptions.timeout) {
|
||||||
|
req.setTimeout(requestOptions.timeout, () => {
|
||||||
|
callback(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the data to the request and send it
|
||||||
|
req.write(data)
|
||||||
|
req.end()
|
||||||
|
}
|
||||||
134
utilities/mysqlHandler.js
Normal file
134
utilities/mysqlHandler.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
const mysql = require('mysql');
|
||||||
|
const databaseConfig = require('../config/databaseConfig');
|
||||||
|
const utils = require('./utils');
|
||||||
|
|
||||||
|
const connection = mysql.createConnection({
|
||||||
|
host: databaseConfig.database_host,
|
||||||
|
user: databaseConfig.database_user,
|
||||||
|
password: databaseConfig.database_password,
|
||||||
|
database: databaseConfig.database_database
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodesTable = `${databaseConfig.database_database}.nodes`;
|
||||||
|
|
||||||
|
connection.connect()
|
||||||
|
|
||||||
|
/** Get all nodes the server knows about regardless of status
|
||||||
|
* @param {*} callback Callback function
|
||||||
|
*/
|
||||||
|
exports.getAllNodes = (callback) => {
|
||||||
|
const sqlQuery = `SELECT * FROM ${nodesTable}`
|
||||||
|
runSQL(sqlQuery, (rows) => {
|
||||||
|
callback(rows);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get all nodes that have the online status set true (are online)
|
||||||
|
* @param callback Callback function
|
||||||
|
*/
|
||||||
|
exports.getOnlineNodes = (callback) => {
|
||||||
|
const sqlQuery = `SELECT * FROM ${nodesTable} WHERE online = 1;`
|
||||||
|
runSQL(sqlQuery, (rows) => {
|
||||||
|
callback(rows);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get info on a node based on ID
|
||||||
|
* @param nodeId The ID of the node
|
||||||
|
* @param callback Callback function
|
||||||
|
*/
|
||||||
|
exports.getNodeInfoFromId = (nodeId, callback) => {
|
||||||
|
const sqlQuery = `SELECT * FROM ${nodesTable} WHERE id = ${nodeId}`
|
||||||
|
runSQL(sqlQuery, (rows) => {
|
||||||
|
// Call back the first (and theoretically only) row
|
||||||
|
// Specify 0 so downstream functions don't have to worry about it
|
||||||
|
callback(rows[0]);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add a new node to the DB
|
||||||
|
* @param nodeObject Node information object
|
||||||
|
* @param callback Callback function
|
||||||
|
*/
|
||||||
|
exports.addNewNode = (nodeObject, callback) => {
|
||||||
|
if (!nodeObject.name) throw new Error("No name provided");
|
||||||
|
const name = nodeObject.name,
|
||||||
|
ip = nodeObject.ip,
|
||||||
|
port = nodeObject.port,
|
||||||
|
location = nodeObject.location,
|
||||||
|
nearbySystems = utils.JsonToBuffer(nodeObject.nearbySystems),
|
||||||
|
online = nodeObject.online;
|
||||||
|
const sqlQuery = `INSERT INTO ${nodesTable} (name, ip, port, location, nearbySystems, online) VALUES ('${name}', '${ip}', ${port}, '${location}', '${nearbySystems}', ${online})`;
|
||||||
|
|
||||||
|
runSQL(sqlQuery, (rows) => {
|
||||||
|
callback(rows);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update the known info on a node
|
||||||
|
* @param nodeObject Node information object
|
||||||
|
* @param callback Callback function
|
||||||
|
*/
|
||||||
|
exports.updateNodeInfo = (nodeObject, callback) => {
|
||||||
|
const name = nodeObject.name,
|
||||||
|
ip = nodeObject.ip,
|
||||||
|
port = nodeObject.port,
|
||||||
|
location = nodeObject.location,
|
||||||
|
online = nodeObject.online;
|
||||||
|
let queryParams = [],
|
||||||
|
nearbySystems = nodeObject.nearbySystems;
|
||||||
|
|
||||||
|
if (name) queryParams.push(`name = '${name}'`);
|
||||||
|
if (ip) queryParams.push(`ip = '${ip}'`);
|
||||||
|
if (port) queryParams.push(`port = ${port}`);
|
||||||
|
if (location) queryParams.push(`location = '${location}'`);
|
||||||
|
if (nearbySystems) {
|
||||||
|
nearbySystems = utils.JsonToBuffer(nearbySystems)
|
||||||
|
queryParams.push(`nearbySystems = '${nearbySystems}'`);
|
||||||
|
}
|
||||||
|
if (typeof online === "boolean") {
|
||||||
|
if (online) queryParams.push(`online = 1`);
|
||||||
|
else queryParams.push(`online = 0`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let sqlQuery = `UPDATE ${nodesTable} SET`
|
||||||
|
if (!queryParams || queryParams.length === 0) return callback(undefined);
|
||||||
|
if (queryParams.length === 1) {
|
||||||
|
sqlQuery = `${sqlQuery} ${queryParams[0]}`
|
||||||
|
} else {
|
||||||
|
let i = 0;
|
||||||
|
for (const param of queryParams) {
|
||||||
|
if (i === queryParams.length-1) {
|
||||||
|
sqlQuery = `${sqlQuery} ${param}`
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sqlQuery = `${sqlQuery} ${param},`
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlQuery = `${sqlQuery} WHERE id = ${nodeObject.id};`
|
||||||
|
|
||||||
|
runSQL(sqlQuery, (rows) => {
|
||||||
|
if (rows.affectedRows === 1) callback(true);
|
||||||
|
else callback(rows);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to run and handle SQL errors
|
||||||
|
function runSQL(sqlQuery, callback, error = (err) => {
|
||||||
|
console.log(err);
|
||||||
|
throw err;
|
||||||
|
}) {
|
||||||
|
connection.query(sqlQuery, (err, rows) => {
|
||||||
|
if (err) return error(err);
|
||||||
|
//console.log('The rows are:', rows);
|
||||||
|
return callback(rows);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.closeConnection = () => {
|
||||||
|
connection.end()
|
||||||
|
}
|
||||||
19
utilities/utils.js
Normal file
19
utilities/utils.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// Convert a JSON object to a buffer for the DB
|
||||||
|
exports.JsonToBuffer = (jsonObject) => {
|
||||||
|
return Buffer.from(JSON.stringify(jsonObject))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a buffer from the DB to JSON object
|
||||||
|
exports.BufferToJson = (buffer) => {
|
||||||
|
return JSON.parse(buffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Find a key in an object by its value
|
||||||
|
*
|
||||||
|
* @param {*} object The object to search
|
||||||
|
* @param {*} value The value to search the arrays in the object for
|
||||||
|
* @returns The key of the object that contains the value
|
||||||
|
*/
|
||||||
|
exports.getKeyByArrayValue = (object, value) => {
|
||||||
|
return Object.keys(object).find(key => object[key].includes(value));
|
||||||
|
}
|
||||||
3
views/error.ejs
Normal file
3
views/error.ejs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<h1><%= message %></h1>
|
||||||
|
<h2><%= error.status %></h2>
|
||||||
|
<pre><%= error.stack %></pre>
|
||||||
11
views/index.ejs
Normal file
11
views/index.ejs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title><%= title %></title>
|
||||||
|
<link rel='stylesheet' href='/stylesheets/style.css' />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1><%= title %></h1>
|
||||||
|
<p>Welcome to <%= title %></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user