Compare commits
42 Commits
feature/#1
...
ffe9c413ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffe9c413ba | ||
|
|
851a9c55fa | ||
|
|
fb9df3230e | ||
|
|
7163df21e9 | ||
|
|
47d18c494d | ||
|
|
ea2dbd9fb0 | ||
|
|
9ce77a5be0 | ||
|
|
57881a7e17 | ||
|
|
e350cd6030 | ||
|
|
fba0a2a2b2 | ||
|
|
83cef63109 | ||
|
|
2390bdc2c6 | ||
|
|
93be4ca9dc | ||
|
|
d96e6ad519 | ||
|
|
b180f90973 | ||
|
|
fd7435c7bc | ||
|
|
e062cf5794 | ||
|
|
597546b73d | ||
|
|
333e7420f4 | ||
|
|
37a03c5cc6 | ||
|
|
d2e9f286e2 | ||
|
|
255b1282ec | ||
|
|
878e64fa42 | ||
|
|
7a040a8e97 | ||
|
|
8dffeccf83 | ||
|
|
2108a3b92b | ||
|
|
960b801dd2 | ||
|
|
dd5b442377 | ||
|
|
c5a7131063 | ||
|
|
5d54f07af4 | ||
|
|
24faa5279d | ||
|
|
79d2ca1887 | ||
|
|
c2b4b4bfa1 | ||
|
|
d8a697e583 | ||
|
|
44caa11f7c | ||
|
|
dc92b07426 | ||
|
|
92f4caad0c | ||
|
|
b888a9233d | ||
|
|
b4e27162aa | ||
|
|
bfda15866e | ||
|
|
f4475dc9d7 | ||
|
|
c4650a9e99 |
@@ -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], { cwd: resolve(__dirname, "../pdab/").toString() });
|
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('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 ], { cwd: resolve(__dirname, "../pdab/") });
|
pythonProcess = await spawn('python3', [resolve(__dirname, "../pdab/main.py"), deviceId, channelId, clientId,'-n', NGThreshold, '-p', presetName ], { cwd: resolve(__dirname, "../pdab/") });
|
||||||
}
|
}
|
||||||
|
|
||||||
log.VERBOSE("Python Process: ", pythonProcess);
|
log.VERBOSE("Python Process: ", pythonProcess);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const log = new DebugBuilder("client", "clientController");
|
|||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
const modes = require("../config/modes");
|
const modes = require("../config/modes");
|
||||||
// Modules
|
// Modules
|
||||||
const { executeAsyncConsoleCommand, nodeObject } = require("../utilities/utilities");
|
const { executeAsyncConsoleCommand, nodeObject, BufferToJson } = require("../utilities/utilities");
|
||||||
// Utilities
|
// Utilities
|
||||||
const { updateId, updateConfig } = require("../utilities/updateConfig");
|
const { updateId, updateConfig } = require("../utilities/updateConfig");
|
||||||
const { updatePreset, addNewPreset, getPresets, removePreset } = require("../utilities/updatePresets");
|
const { updatePreset, addNewPreset, getPresets, removePreset } = require("../utilities/updatePresets");
|
||||||
@@ -67,22 +67,27 @@ 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') {
|
||||||
|
await updateId(0);
|
||||||
|
runningClientConfig.id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!runningClientConfig.ip) {
|
if (!runningClientConfig.ip) {
|
||||||
const ipAddr = await checkLocalIP();
|
const ipAddr = await checkLocalIP();
|
||||||
updateConfig('ip', ipAddr);
|
await updateConfig('CLIENT_IP', ipAddr);
|
||||||
runningClientConfig.ip = ipAddr;
|
runningClientConfig.ip = ipAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!runningClientConfig.name) {
|
if(!runningClientConfig.name) {
|
||||||
const lastOctet = await String(checkLocalIP()).spit('.')[-1];
|
const lastOctet = await String(checkLocalIP()).spit('.')[-1];
|
||||||
const name = `Radio-Node-${lastOctet}`;
|
const name = `Radio-Node-${lastOctet}`;
|
||||||
updateConfig('name', name);
|
await updateConfig('CLIENT_NAME', name);
|
||||||
runningClientConfig.name = name;
|
runningClientConfig.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!runningClientConfig.port) {
|
if(!runningClientConfig.port) {
|
||||||
const port = 3010;
|
const port = 3010;
|
||||||
updateConfig('port', port);
|
await updateConfig('CLIENT_PORT', port);
|
||||||
runningClientConfig.port = port;
|
runningClientConfig.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,21 +100,34 @@ exports.checkConfig = async function checkConfig() {
|
|||||||
exports.checkIn = async () => {
|
exports.checkIn = async () => {
|
||||||
let reqOptions;
|
let reqOptions;
|
||||||
await this.checkConfig();
|
await this.checkConfig();
|
||||||
|
runningClientConfig.online = true;
|
||||||
// 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 === 0) {
|
if (!runningClientConfig?.id || 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(runningClientConfig), async (responseObject) => {
|
||||||
// Update the client's ID if the server accepted it
|
// Check if the server responded
|
||||||
|
if (!responseObject) {
|
||||||
|
log.WARN("Server did not respond to checkIn. Will wait 60 seconds then try again");
|
||||||
|
setTimeout(() => {
|
||||||
|
// Run itself again to see if the server is up now
|
||||||
|
this.checkIn();
|
||||||
|
}, 60000);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the client's ID if the server accepted its
|
||||||
if (responseObject.statusCode === 202) {
|
if (responseObject.statusCode === 202) {
|
||||||
runningClientConfig.id = responseObject.body.nodeId;
|
runningClientConfig.id = responseObject.body.nodeId;
|
||||||
updateId(responseObject.body.nodeId);
|
log.DEBUG("Response object from new node: ", responseObject, runningClientConfig);
|
||||||
|
await updateId(runningClientConfig.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseObject.statusCode >= 300) {
|
if (responseObject.statusCode >= 300) {
|
||||||
// Server threw an error
|
// Server threw an error
|
||||||
onHttpError(responseObject.statusCode);
|
log.DEBUG("HTTP Error: ", responseObject, await BufferToJson(responseObject.body));
|
||||||
|
await onHttpError(responseObject.statusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -118,7 +136,19 @@ 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);
|
||||||
|
// Check if the server responded
|
||||||
|
if (!responseObject) {
|
||||||
|
log.WARN("Server did not respond to checkIn. Will wait 60 seconds then try again");
|
||||||
|
setTimeout(() => {
|
||||||
|
// Run itself again to see if the server is up now
|
||||||
|
this.checkIn();
|
||||||
|
}, 60000);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (responseObject.statusCode === 202) {
|
if (responseObject.statusCode === 202) {
|
||||||
|
log.DEBUG("Updated keys: ", responseObject.body.updatedKeys)
|
||||||
// Server accepted an update
|
// Server accepted an update
|
||||||
}
|
}
|
||||||
if (responseObject.statusCode === 200) {
|
if (responseObject.statusCode === 200) {
|
||||||
|
|||||||
1992
Client/package-lock.json
generated
1992
Client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
|||||||
"express": "~4.16.1",
|
"express": "~4.16.1",
|
||||||
"http-errors": "~1.6.3",
|
"http-errors": "~1.6.3",
|
||||||
"morgan": "~1.9.1",
|
"morgan": "~1.9.1",
|
||||||
"replace-in-file": "~6.3.5",
|
"replace-in-file": "~7.0.1",
|
||||||
"@discordjs/builders": "^1.4.0",
|
"@discordjs/builders": "^1.4.0",
|
||||||
"@discordjs/rest": "^1.4.0",
|
"@discordjs/rest": "^1.4.0",
|
||||||
"discord.js": "^14.7.1"
|
"discord.js": "^14.7.1"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import argparse, platform, os
|
import argparse, platform, os
|
||||||
from discord import Intents, Client, Member, opus
|
from discord import Intents, Client, Member, opus, Activity, ActivityType
|
||||||
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):
|
def main(clientId='OTQzNzQyMDQwMjU1MTE1MzA0.Yg3eRA.ZxEbRr55xahjfaUmPY8pmS-RHTY', channelId=367396189529833476, NGThreshold=50, deviceId=1, presence="the radio"):
|
||||||
intents = Intents.default()
|
intents = Intents.default()
|
||||||
|
|
||||||
client = commands.Bot(command_prefix='!', intents=intents)
|
client = commands.Bot(command_prefix='!', intents=intents)
|
||||||
@@ -33,6 +33,8 @@ 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)
|
||||||
@@ -55,21 +57,24 @@ def main(clientId='OTQzNzQyMDQwMjU1MTE1MzA0.Yg3eRA.ZxEbRr55xahjfaUmPY8pmS-RHTY',
|
|||||||
|
|
||||||
client.run(clientId)
|
client.run(clientId)
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
if __name__ == "__main__":
|
||||||
parser.add_argument("deviceId", type=int, help="The ID of the audio device to use")
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("channelId", type=int, help="The ID of the voice channel to use")
|
parser.add_argument("deviceId", type=int, help="The ID of the audio device to use")
|
||||||
parser.add_argument("clientId", type=str, help="The discord client ID")
|
parser.add_argument("channelId", type=int, help="The ID of the voice channel to use")
|
||||||
parser.add_argument("-n", "--NGThreshold", type=int, help="Change the noisegate threshold. This defaults to 50")
|
parser.add_argument("clientId", type=str, help="The discord client ID")
|
||||||
args = parser.parse_args()
|
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()
|
||||||
|
|
||||||
if (not args.NGThreshold):
|
if (not args.NGThreshold):
|
||||||
args.NGThreshold = 50
|
args.NGThreshold = 50
|
||||||
|
|
||||||
print("Arguments:", args)
|
print("Arguments:", args)
|
||||||
|
|
||||||
main(
|
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
|
||||||
|
)
|
||||||
@@ -9,6 +9,19 @@ Explanation here
|
|||||||
---
|
---
|
||||||
|
|
||||||
Requirements here (not modules, that will be installed with npm)
|
Requirements here (not modules, that will be installed with npm)
|
||||||
|
### Hardware
|
||||||
|
|
||||||
|
- SBC
|
||||||
|
- [Orange Pi](https://www.amazon.com/dp/B0BN16ZLXB/r)
|
||||||
|
- [Raspberry Pi](https://www.canakit.com/raspberry-pi-4-4gb.html)
|
||||||
|
- [Rock Pi](https://www.okdo.com/us/p/okdo-rock-4-model-c-4gb-single-board-computer-rockchip-rk3399-t-arm-cortex-a72-cortex-a53/)
|
||||||
|
- SDR
|
||||||
|
- [Nooelec RTL-SDR v5 Bundle ](https://www.amazon.com/dp/B01GDN1T4S)
|
||||||
|
- [RTL-SDR Blog V3](https://www.amazon.com/dp/B0BMKB3L47)
|
||||||
|
- [Nooelec NESDR Mini](https://www.amazon.com/dp/B009U7WZCA)
|
||||||
|
- Proper Power Adapter (Sometimes comes in SBC Packs)
|
||||||
|
- SD Card (Sometimes comes in SBC Packs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,6 @@ 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
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ 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;
|
||||||
|
|
||||||
@@ -34,31 +35,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(`${appName}:${fileName}:INFO\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:INFO\t-\t${messageParts.map((messagePart, index, array) => {return inspect(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(`${appName}:${fileName}:DEBUG\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:DEBUG\t-\t${messageParts.map((messagePart, index, array) => {return inspect(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(`${appName}:${fileName}:VERBOSE\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:VERBOSE\t-\t${messageParts.map((messagePart, index, array) => {return inspect(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(`${appName}:${fileName}:WARNING\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:WARNING\t-\t${messageParts.map((messagePart, index, array) => {return inspect(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(`${appName}:${fileName}:ERROR\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:ERROR\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName);
|
||||||
if (process.env.EXIT_ON_ERROR && process.env.EXIT_ON_ERROR > 0) {
|
if (process.env.EXIT_ON_ERROR && process.env.EXIT_ON_ERROR > 0) {
|
||||||
writeToLog("!--- EXITING ---!", appName);
|
writeToLog("!--- EXITING ---!", appName);
|
||||||
setTimeout(process.exit, process.env.EXIT_ON_ERROR_DELAY ?? 0);
|
setTimeout(process.exit, process.env.EXIT_ON_ERROR_DELAY ?? 0);
|
||||||
|
|||||||
@@ -5,11 +5,16 @@ const log = new DebugBuilder("client", "httpRequests");
|
|||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
// Modules
|
// Modules
|
||||||
const http = require("http");
|
const http = require("http");
|
||||||
|
const { isJsonString } = require("./utilities.js");
|
||||||
|
|
||||||
exports.requestOptions = class requestOptions {
|
exports.requestOptions = class requestOptions {
|
||||||
constructor(path, method, hostname = undefined, headers = undefined, port = undefined) {
|
constructor(path, method, hostname = undefined, headers = undefined, port = undefined) {
|
||||||
if (method === "POST"){
|
if (method === "POST"){
|
||||||
this.hostname = hostname ?? process.env.SERVER_HOSTNAME ?? process.env.SERVER_IP;
|
log.VERBOSE("Hostname Vars: ", hostname, process.env.SERVER_HOSTNAME, process.env.SERVER_IP);
|
||||||
|
if (hostname) this.hostname = hostname;
|
||||||
|
if (process.env.SERVER_HOSTNAME) this.hostname = process.env.SERVER_HOSTNAME;
|
||||||
|
if (process.env.SERVER_IP) this.hostname = process.env.SERVER_IP;
|
||||||
|
if (!this.hostname) throw new Error("No server hostname / IP was given when creating a request");
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.port = port ?? process.env.SERVER_PORT;
|
this.port = port ?? process.env.SERVER_PORT;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
@@ -31,31 +36,26 @@ exports.sendHttpRequest = function sendHttpRequest(requestOptions, data, callbac
|
|||||||
// Create the request
|
// Create the request
|
||||||
const req = http.request(requestOptions, res => {
|
const req = http.request(requestOptions, res => {
|
||||||
res.on('data', (data) => {
|
res.on('data', (data) => {
|
||||||
if (res.statusCode >= 200 && res.statusCode <= 299) {
|
|
||||||
const responseObject = {
|
const responseObject = {
|
||||||
"statusCode": res.statusCode,
|
"statusCode": res.statusCode,
|
||||||
"body": JSON.parse(data)
|
"body": (isJsonString(data.toString())) ? JSON.parse(data.toString()) : data.toString()
|
||||||
};
|
};
|
||||||
log.DEBUG("Response Object: ", responseObject);
|
log.VERBOSE("Response Object: ", responseObject);
|
||||||
callback(responseObject);
|
callback(responseObject);
|
||||||
}
|
|
||||||
if (res.statusCode >= 300) {
|
|
||||||
const responseObject = {
|
|
||||||
"statusCode": res.statusCode,
|
|
||||||
"body": data
|
|
||||||
};
|
|
||||||
log.DEBUG("Response Object: ", responseObject);
|
|
||||||
callback(responseObject);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}).on('error', err => {
|
}).on('error', err => {
|
||||||
log.ERROR('Error: ', err.message)
|
if (err.code === "ECONNREFUSED"){
|
||||||
|
// Bot refused connection, assumed offline
|
||||||
|
log.WARN("Connection Refused");
|
||||||
|
}
|
||||||
|
else log.ERROR('Error: ', err.message, err);
|
||||||
|
callback(undefined);
|
||||||
// TODO need to handle if the server is down
|
// TODO need to handle if the server is down
|
||||||
})
|
})
|
||||||
|
|
||||||
// Write the data to the request and send it
|
// Write the data to the request and send it
|
||||||
req.write(data)
|
req.write(data);
|
||||||
req.end()
|
req.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.onHttpError = function onHttpError(httpStatusCode) {
|
exports.onHttpError = function onHttpError(httpStatusCode) {
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ class Options {
|
|||||||
constructor(key, updatedValue) {
|
constructor(key, updatedValue) {
|
||||||
this.files = "./.env";
|
this.files = "./.env";
|
||||||
// A regex of the line containing the key in the config file
|
// A regex of the line containing the key in the config file
|
||||||
this.from = new RegExp(`${key}="(.+)",`, "g");
|
this.from = new RegExp(`${key}="?(.+)"?`, "g");
|
||||||
// Check to see if the value is a string and needs to be wrapped in double quotes
|
// Check to see if the value is a string and needs to be wrapped in double quotes
|
||||||
if (Array(["string", "number"]).includes(typeof updatedValue)) this.to = `${key}="${updatedValue}",`;
|
if (Array(["string", "number"]).includes(typeof updatedValue)) this.to = `${key}="${updatedValue}",`;
|
||||||
else this.to = `${key}=${updatedValue},`;
|
else this.to = `${key}=${updatedValue}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ class Options {
|
|||||||
* @param updatedId The updated ID assigned to the bot
|
* @param updatedId The updated ID assigned to the bot
|
||||||
*/
|
*/
|
||||||
exports.updateId = (updatedId) => {
|
exports.updateId = (updatedId) => {
|
||||||
this.updateConfig('id', updatedId);
|
this.updateConfig('CLIENT_ID', updatedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,7 +46,7 @@ exports.updateConfig = function updateConfig(key, value) {
|
|||||||
function updateConfigFile(options, callback){
|
function updateConfigFile(options, callback){
|
||||||
replace(options, (error, changedFiles) => {
|
replace(options, (error, changedFiles) => {
|
||||||
if (error) return console.error('Error occurred:', error);
|
if (error) return console.error('Error occurred:', error);
|
||||||
log.DEBUG('Modified files:', changedFiles);
|
log.VERBOSE('Modified files:', changedFiles);
|
||||||
callback(changedFiles);
|
callback(changedFiles);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -262,3 +262,23 @@ function convertRadioPresetsToOP25Config(presetName){
|
|||||||
log.DEBUG(updatedOP25Config);
|
log.DEBUG(updatedOP25Config);
|
||||||
return updatedOP25Config;
|
return updatedOP25Config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert a buffer from the DB to JSON object
|
||||||
|
exports.BufferToJson = (buffer) => {
|
||||||
|
return JSON.parse(buffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see if the input is a valid JSON string
|
||||||
|
*
|
||||||
|
* @param {*} str The string to check for valud JSON
|
||||||
|
* @returns {true|false}
|
||||||
|
*/
|
||||||
|
exports.isJsonString = (str) => {
|
||||||
|
try {
|
||||||
|
JSON.parse(str);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
52
Server/commands/giveRole.js
Normal file
52
Server/commands/giveRole.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
// Modules
|
// Modules
|
||||||
const { customSlashCommandBuilder } = require('../utilities/customSlashCommandBuilder');
|
const { SlashCommandBuilder } = require('discord.js');
|
||||||
const { DebugBuilder } = require("../utilities/debugBuilder");
|
const { DebugBuilder } = require("../utilities/debugBuilder");
|
||||||
const { getMembersInRole, getAllClientIds } = require("../utilities/utils");
|
const { getMembersInRole, getAllClientIds, filterAutocompleteValues } = require("../utilities/utils");
|
||||||
const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests");
|
const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests");
|
||||||
const { getOnlineNodes, updateNodeInfo, addNodeConnection, getConnectionByNodeId } = require("../utilities/mysqlHandler");
|
const { getOnlineNodes, updateNodeInfo, addNodeConnection, getConnectionByNodeId, getAllConnections } = 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 {*} 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
|
* @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
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async function joinServerWrapper(presetName, channelId, clientIdsUsed) {
|
async function joinServerWrapper(presetName, channelId, connections) {
|
||||||
// Get nodes online
|
// Get nodes online
|
||||||
var onlineNodes = await new Promise((recordResolve, recordReject) => {
|
var onlineNodes = await new Promise((recordResolve, recordReject) => {
|
||||||
getOnlineNodes((nodeRows) => {
|
getOnlineNodes((nodeRows) => {
|
||||||
@@ -25,7 +25,7 @@ async function joinServerWrapper(presetName, channelId, clientIdsUsed) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check which nodes have the selected preset
|
// Check which nodes have the selected preset
|
||||||
onlineNodes = onlineNodes.filter(node => node.nearbySystems.includes(presetName));
|
onlineNodes = onlineNodes.filter(node => node.presets.includes(presetName));
|
||||||
log.DEBUG("Filtered Online Nodes: ", onlineNodes);
|
log.DEBUG("Filtered Online Nodes: ", onlineNodes);
|
||||||
|
|
||||||
// Check if any nodes with this preset are available
|
// Check if any nodes with this preset are available
|
||||||
@@ -45,16 +45,16 @@ async function joinServerWrapper(presetName, channelId, clientIdsUsed) {
|
|||||||
log.DEBUG("All clients: ", Object.keys(availableClientIds));
|
log.DEBUG("All clients: ", Object.keys(availableClientIds));
|
||||||
|
|
||||||
var selectedClientId;
|
var selectedClientId;
|
||||||
if (typeof clientIdsUsed === 'string') {
|
if (typeof connections === 'string') {
|
||||||
for (const availableClientId of availableClientIds) {
|
for (const availableClientId of availableClientIds) {
|
||||||
if (availableClientId.discordId != clientIdsUsed ) selectedClientId = availableClientId;
|
if (availableClientId.discordId != connections ) selectedClientId = availableClientId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.DEBUG("Client IDs Used: ", clientIdsUsed.keys());
|
log.DEBUG("Open connections: ", connections);
|
||||||
for (const usedClientId of clientIdsUsed.keys()) {
|
for (const connection of connections) {
|
||||||
log.DEBUG("Used Client ID: ", usedClientId);
|
log.DEBUG("Used Client ID: ", connection);
|
||||||
availableClientIds = availableClientIds.filter(cid => cid.discordId != usedClientId);
|
availableClientIds = availableClientIds.filter(cid => cid.discordId != connection.clientObject.discordId);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.DEBUG("Available Client IDs: ", availableClientIds);
|
log.DEBUG("Available Client IDs: ", availableClientIds);
|
||||||
@@ -84,33 +84,63 @@ async function joinServerWrapper(presetName, channelId, clientIdsUsed) {
|
|||||||
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 customSlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
.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')
|
||||||
.addAllSystemPresetOptions(),
|
.addStringOption(option =>
|
||||||
|
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);
|
||||||
|
presetsAvailable.push.apply(presetsAvailable, nodeObject.presets);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
const presetName = interaction.options.getString('preset');
|
const presetName = interaction.options.getString('preset');
|
||||||
if (!interaction.member.voice.channel.id) return interaction.editReply(`You need to be in a voice channel, ${interaction.user}`)
|
if (!interaction.member.voice.channel) return interaction.editReply(`You need to be in a voice channel, ${interaction.user}`)
|
||||||
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 onlineBots = await getMembersInRole(interaction);
|
const connections = await getAllConnections();
|
||||||
|
|
||||||
log.DEBUG("Online Bots: ", onlineBots);
|
log.DEBUG("Current Connections: ", connections);
|
||||||
|
|
||||||
await joinServerWrapper(presetName, channelId, onlineBots.online);
|
const selectedClientId = await joinServerWrapper(presetName, channelId, connections);
|
||||||
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)
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
// Modules
|
// Modules
|
||||||
const { customSlashCommandBuilder } = require('../utilities/customSlashCommandBuilder');
|
const { SlashCommandBuilder } = require('discord.js');
|
||||||
const { DebugBuilder } = require("../utilities/debugBuilder");
|
const { DebugBuilder } = require("../utilities/debugBuilder");
|
||||||
const { getAllClientIds, getKeyByArrayValue } = require("../utilities/utils");
|
const { getAllClientIds, getKeyByArrayValue, filterAutocompleteValues } = require("../utilities/utils");
|
||||||
const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests");
|
const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests");
|
||||||
const { checkNodeConnectionByClientId, removeNodeConnectionByNodeId, updateNodeInfo, getConnectedNodes, getAllConnections } = require('../utilities/mysqlHandler');
|
const { checkNodeConnectionByClientId, removeNodeConnectionByNodeId, 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");
|
||||||
@@ -34,30 +33,26 @@ async function leaveServerWrapper(clientIdObject) {
|
|||||||
exports.leaveServerWrapper = leaveServerWrapper;
|
exports.leaveServerWrapper = leaveServerWrapper;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new customSlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
.setName('leave')
|
.setName('leave')
|
||||||
.setDescription('Disconnect a bot from the server')
|
.setDescription('Disconnect a bot from the server')
|
||||||
.addStringOption(option =>
|
.addStringOption(option =>
|
||||||
option.setName("bot")
|
option.setName("bot")
|
||||||
.setDescription("The bot to disconnect from the server")
|
.setDescription("The bot to disconnect from the server")
|
||||||
.setAutocomplete(true)),
|
.setAutocomplete(true)
|
||||||
|
.setRequired(true)),
|
||||||
example: "leave",
|
example: "leave",
|
||||||
isPrivileged: false,
|
isPrivileged: false,
|
||||||
requiresTokens: false,
|
requiresTokens: false,
|
||||||
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 filtered = connections.filter(conn => String(conn.clientObject.name).startsWith(focusedValue)).map(conn => conn.clientObject.name);
|
const options = connections.map(conn => conn.clientObject.name);
|
||||||
logAC.DEBUG("Focused Value: ", focusedValue, connections, filtered);
|
await filterAutocompleteValues(interaction, options);
|
||||||
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();
|
||||||
|
|||||||
@@ -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\' title')
|
.setDescription('Remove an RSS source by it\'s 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')
|
||||||
|
|||||||
@@ -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.send(400)
|
if (!req.body.name) return res.status(400).json("No name specified for new node");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Try to add the new user with defaults if missing options
|
// Try to add the new user with defaults if missing options
|
||||||
@@ -35,12 +35,12 @@ exports.newNode = async (req, res) => {
|
|||||||
_port: req.body.port ?? null,
|
_port: req.body.port ?? null,
|
||||||
_location: req.body.location ?? null,
|
_location: req.body.location ?? null,
|
||||||
_nearbySystems: req.body.nearbySystems ?? null,
|
_nearbySystems: req.body.nearbySystems ?? null,
|
||||||
_online: req.body.online ?? 0
|
_online: (req.body.online == "true" || req.body.online == "True") ? true : false
|
||||||
});
|
});
|
||||||
|
|
||||||
addNewNode(newNode, (queryResults) => {
|
addNewNode(newNode, (newNodeObject) => {
|
||||||
// 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": queryResults.insertId});
|
res.status(202).json({"nodeId": newNodeObject.id});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
@@ -65,30 +65,62 @@ exports.getNodeInfo = async (req, res) => {
|
|||||||
exports.nodeCheckIn = async (req, res) => {
|
exports.nodeCheckIn = async (req, res) => {
|
||||||
if (!req.body.id) return res.status(400).json("No id specified");
|
if (!req.body.id) return res.status(400).json("No id specified");
|
||||||
getNodeInfoFromId(req.body.id, (nodeInfo) => {
|
getNodeInfoFromId(req.body.id, (nodeInfo) => {
|
||||||
let checkInObject = new nodeObject();
|
let checkInObject = {};
|
||||||
// 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
|
// Convert the online status to a boolean to be worked with
|
||||||
nodeInfo.online = nodeInfo.online !== 0;
|
log.DEBUG("REQ Body: ", req.body);
|
||||||
|
|
||||||
if (req.body.name && req.body.name !== nodeInfo.name) checkInObject.name = req.body.name
|
var isObjectUpdated = false;
|
||||||
if (req.body.ip && req.body.ip !== nodeInfo.ip) checkInObject.ip = req.body.ip
|
|
||||||
if (req.body.port && req.body.port !== nodeInfo.port) checkInObject.port = req.body.port
|
if (req.body.name && req.body.name != nodeInfo.name) {
|
||||||
if (req.body.location && req.body.location !== nodeInfo.location) checkInObject.location = req.body.location
|
checkInObject._name = req.body.name;
|
||||||
if (req.body.nearbySystems && JSON.stringify(req.body.nearbySystems) !== JSON.stringify(nodeInfo.nearbySystems)) checkInObject.nearbySystems = req.body.nearbySystems
|
isObjectUpdated = true;
|
||||||
if (req.body.online && req.body.online !== nodeInfo.online) checkInObject.online = req.body.online
|
}
|
||||||
|
|
||||||
|
if (req.body.ip && req.body.ip != nodeInfo.ip) {
|
||||||
|
checkInObject._ip = req.body.ip;
|
||||||
|
isObjectUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.body.port && req.body.port != nodeInfo.port) {
|
||||||
|
checkInObject._port = req.body.port;
|
||||||
|
isObjectUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.body.location && req.body.location != nodeInfo.location) {
|
||||||
|
checkInObject._location = req.body.location;
|
||||||
|
isObjectUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.body.nearbySystems && JSON.stringify(req.body.nearbySystems) !== JSON.stringify(nodeInfo.nearbySystems)) {
|
||||||
|
checkInObject._nearbySystems = req.body.nearbySystems;
|
||||||
|
isObjectUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.body.online != nodeInfo.online || req.body.online && (req.body.online === "true") != nodeInfo.online) {
|
||||||
|
checkInObject._online = req.body.online;
|
||||||
|
isObjectUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
// If no changes are made tell the client
|
// If no changes are made tell the client
|
||||||
if (Object.keys(checkInObject).length === 0) return res.status(200).json("No keys updated");
|
if (!isObjectUpdated) return res.status(200).json("No keys updated");
|
||||||
|
|
||||||
log.INFO("Updating the following keys for ID: ", req.body.id, checkInObject);
|
log.INFO("Updating the following keys for ID: ", req.body.id, checkInObject);
|
||||||
// Adding the ID key to the body so that the client can double-check their ID
|
|
||||||
checkInObject.id = req.body.id;
|
checkInObject._id = req.body.id;
|
||||||
|
checkInObject = new nodeObject(checkInObject);
|
||||||
|
|
||||||
|
if (!nodeInfo) {
|
||||||
|
log.WARN("No existing node found with this ID, adding node: ", checkInObject);
|
||||||
|
addNewNode(checkInObject, (newNode) => {
|
||||||
|
return res.status(201).json({"updatedKeys": newNode});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
updateNodeInfo(checkInObject, () => {
|
updateNodeInfo(checkInObject, () => {
|
||||||
return res.status(202).json({"updatedKeys": checkInObject});
|
return res.status(202).json({"updatedKeys": checkInObject});
|
||||||
})
|
});
|
||||||
})
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,7 +132,7 @@ exports.nodeCheckIn = async (req, res) => {
|
|||||||
*/
|
*/
|
||||||
exports.requestNodeJoinServer = async (req, res) => {
|
exports.requestNodeJoinServer = async (req, res) => {
|
||||||
if (!req.body.clientId || !req.body.channelId || !req.body.presetName) return res.status(400).json("Missing information in request, requires clientId, channelId, presetName");
|
if (!req.body.clientId || !req.body.channelId || !req.body.presetName) return res.status(400).json("Missing information in request, requires clientId, channelId, presetName");
|
||||||
await joinServerWrapper(req.body.presetName, req.body.channelId, req.body.clientId)
|
await joinServerWrapper(req.body.presetName, req.body.channelId, req.body.clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,6 +140,7 @@ 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(){
|
||||||
@@ -130,21 +163,21 @@ exports.nodeMonitorService = class nodeMonitorService {
|
|||||||
|
|
||||||
async checkInWithOnlineNodes(){
|
async checkInWithOnlineNodes(){
|
||||||
getOnlineNodes((nodes) => {
|
getOnlineNodes((nodes) => {
|
||||||
log.DEBUG("Online Nodes: ", nodes);
|
this.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)
|
||||||
const request = sendHttpRequest(reqOptions, "", (responseObj) => {
|
sendHttpRequest(reqOptions, "", (responseObj) => {
|
||||||
if (responseObj) {
|
if (responseObj) {
|
||||||
log.DEBUG("Response from: ", node.name, responseObj);
|
this.log.DEBUG("Response from: ", node.name, responseObj);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.DEBUG("No response from node, assuming it's offline");
|
this.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 });
|
||||||
log.DEBUG("Offline node update object: ", offlineNode);
|
this.log.DEBUG("Offline node update object: ", offlineNode);
|
||||||
updateNodeInfo(offlineNode, (sqlResponse) => {
|
updateNodeInfo(offlineNode, (sqlResponse) => {
|
||||||
if (!sqlResponse) log.ERROR("No response from SQL object");
|
if (!sqlResponse) this.log.ERROR("No response from SQL object");
|
||||||
|
|
||||||
log.DEBUG("Updated node: ", sqlResponse);
|
this.log.DEBUG("Updated offline node: ", sqlResponse);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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("mysql");
|
const mysql = require("mysql2");
|
||||||
|
|
||||||
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();
|
||||||
@@ -32,17 +32,38 @@ var runningPostsToRemove = [{
|
|||||||
}]
|
}]
|
||||||
*/
|
*/
|
||||||
var runningPostsToRemove = {};
|
var runningPostsToRemove = {};
|
||||||
const sourceFailureLimit = process.env.SOURCE_FAILURE_LIMIT ?? 3;
|
const sourceFailureLimit = process.env.SOURCE_FAILURE_LIMIT ?? 15;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Wrapper for feeds that cause errors. By default it will wait over a day for the source to come back online before deleting it.
|
||||||
*
|
*
|
||||||
* @param {*} sourceURL
|
* @param {string} sourceURL The URL of the feed source causing issues
|
||||||
*/
|
*/
|
||||||
exports.removeSource = function removeSource(sourceURL) {
|
exports.removeSource = function removeSource(sourceURL) {
|
||||||
log.INFO("Removing source URL: ", sourceURL);
|
log.INFO("Removing source URL: ", sourceURL);
|
||||||
if (!sourceURL in runningPostsToRemove) {runningPostsToRemove[sourceURL] = 1; return;}
|
// Check to see if this is the first time this source has been attempted
|
||||||
|
if (!Object.keys(runningPostsToRemove).includes(sourceURL)) {
|
||||||
|
runningPostsToRemove[sourceURL] = { count: 1, timestamp: Date.now(), ignoredAttempts: 0 };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (runningPostsToRemove[sourceURL] < sourceFailureLimit) {runningPostsToRemove[sourceURL] += 1; return;}
|
const backoffDateTimeDifference = (Date.now() - new Date(runningPostsToRemove[sourceURL].timestamp));
|
||||||
|
const backoffWaitTime = (runningPostsToRemove[sourceURL].count * 30000);
|
||||||
|
|
||||||
|
log.DEBUG("Datetime", runningPostsToRemove[sourceURL], backoffDateTimeDifference, backoffWaitTime);
|
||||||
|
|
||||||
|
// Check to see if the last error occurred within the backoff period or if we should try again
|
||||||
|
if (backoffDateTimeDifference <= backoffWaitTime) {
|
||||||
|
runningPostsToRemove[sourceURL].ignoredAttempts +=1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increase the retry counter
|
||||||
|
if (runningPostsToRemove[sourceURL].count < sourceFailureLimit) {
|
||||||
|
runningPostsToRemove[sourceURL].count += 1;
|
||||||
|
runningPostsToRemove[sourceURL].timestamp = Date.now();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
feedStorage.getRecordBy('link', sourceURL, (err, record) => {
|
feedStorage.getRecordBy('link', sourceURL, (err, record) => {
|
||||||
if (err) log.ERROR("Error getting record from feedStorage", err);
|
if (err) log.ERROR("Error getting record from feedStorage", err);
|
||||||
@@ -62,13 +83,14 @@ exports.removeSource = function removeSource(sourceURL) {
|
|||||||
/**
|
/**
|
||||||
* Unset a source URL from deletion if the source has not already been deleted
|
* Unset a source URL from deletion if the source has not already been deleted
|
||||||
* @param {*} sourceURL The source URL to be unset from deletion
|
* @param {*} sourceURL The source URL to be unset from deletion
|
||||||
* @returns {*}
|
|
||||||
*/
|
*/
|
||||||
exports.unsetRemoveSource = function unsetRemoveSource(sourceURL) {
|
exports.unsetRemoveSource = function unsetRemoveSource(sourceURL) {
|
||||||
log.INFO("Unsetting source URL from deletion (if not already deleted): ", sourceURL);
|
log.INFO("Unsetting source URL from deletion (if not already deleted): ", sourceURL);
|
||||||
if (!sourceURL in runningPostsToRemove) return;
|
if (!Object.keys(runningPostsToRemove).includes(sourceURL)) return;
|
||||||
|
|
||||||
if (runningPostsToRemove[sourceURL] > sourceFailureLimit) return delete runningPostsToRemove[sourceURL];
|
delete runningPostsToRemove[sourceURL];
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const { RSSSourceRecord, RSSPostRecord } = require("./utilities/recordHelper");
|
|||||||
|
|
||||||
// Storage Specific Modules
|
// Storage Specific Modules
|
||||||
// MySQL
|
// MySQL
|
||||||
const mysql = require("mysql");
|
const mysql = require("mysql2");
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|||||||
@@ -1,189 +0,0 @@
|
|||||||
import re
|
|
||||||
import json
|
|
||||||
import pandas as pd
|
|
||||||
import requests
|
|
||||||
import os
|
|
||||||
import random
|
|
||||||
from fake_useragent import UserAgent
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
from urllib.parse import urlparse, unquote, parse_qs
|
|
||||||
from time import sleep
|
|
||||||
ua = UserAgent()
|
|
||||||
|
|
||||||
|
|
||||||
#simply scrape
|
|
||||||
def scrape(url,**kwargs):
|
|
||||||
|
|
||||||
session=requests.Session()
|
|
||||||
session.headers.update({
|
|
||||||
'User-Agent': ua.random,
|
|
||||||
"authority": "www.zillow.com",
|
|
||||||
"accept": "*/*",
|
|
||||||
"accept-language": "en-US,en;q=0.9",
|
|
||||||
"cache-control": "no-cache",
|
|
||||||
"sec-ch-ua-mobile": "?0",
|
|
||||||
"sec-ch-ua-platform": '^\^"Windows^\^"',
|
|
||||||
"sec-fetch-dest": "empty",
|
|
||||||
"sec-fetch-mode": "cors",
|
|
||||||
"sec-fetch-site": "same-origin",
|
|
||||||
})
|
|
||||||
|
|
||||||
response=session.get(url,**kwargs)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
# Return all sections with key and attributes
|
|
||||||
def slurp(html, tag, attributes):
|
|
||||||
return BeautifulSoup(html, features="html.parser").findAll(tag, attributes)
|
|
||||||
|
|
||||||
# Returns the first number group from a given string
|
|
||||||
def return_numbers(string):
|
|
||||||
return int(re.findall(r'\d+', string)[0])
|
|
||||||
|
|
||||||
|
|
||||||
class Listing:
|
|
||||||
def __init__(self, address, bedrooms, bathrooms, sqft, price, link):
|
|
||||||
self.address = address
|
|
||||||
self.bedrooms = bedrooms
|
|
||||||
self.bathrooms = bathrooms
|
|
||||||
self.sqft = sqft
|
|
||||||
self.price = price
|
|
||||||
self.link = link
|
|
||||||
|
|
||||||
|
|
||||||
class ScrapeZillowListings:
|
|
||||||
def __init__(self, url):
|
|
||||||
self.parsed_original_url = self.init_check_url(urlparse(url))
|
|
||||||
self.html = scrape(url).text
|
|
||||||
self.listings = []
|
|
||||||
|
|
||||||
def init_check_url(self, parsed_url):
|
|
||||||
# Check to see if we are requesting listResults
|
|
||||||
print(parsed_url)
|
|
||||||
print(unquote(parsed_url.query))
|
|
||||||
print(parse_qs(parsed_url.query)['wants'])
|
|
||||||
for want in parse_qs(parsed_url.query)['wants']:
|
|
||||||
print(unquote(unquote(want)))
|
|
||||||
|
|
||||||
return parsed_url
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.listings.extend(self.scrape_listings(self.html))
|
|
||||||
pages = []
|
|
||||||
for page_nav in slurp(self.html, "nav", {"role":"navigation", "aria-label":"Pagination"}):
|
|
||||||
page_nav = f"<html><head><head/><body>{page_nav}<body/><html/>"
|
|
||||||
pages_list = slurp(page_nav, "li", {})
|
|
||||||
for page in pages_list:
|
|
||||||
if re.match("\d{1,2}", page.text) and not page.text == "1":
|
|
||||||
parsed_url = self.setup_url(page.find('a').get('href'))
|
|
||||||
sleep(random.randint(0,15))
|
|
||||||
temp_html = scrape(parsed_url.geturl()).text
|
|
||||||
self.listings.extend(self.scrape_listings(temp_html))
|
|
||||||
|
|
||||||
return self.listings
|
|
||||||
|
|
||||||
def print_listings(self):
|
|
||||||
index = 0
|
|
||||||
for temp_listing in self.listings:
|
|
||||||
print("--------")
|
|
||||||
print(f"Listing #{index}")
|
|
||||||
print(temp_listing.address)
|
|
||||||
print(temp_listing.price)
|
|
||||||
print(temp_listing.bedrooms)
|
|
||||||
print(temp_listing.bathrooms)
|
|
||||||
print(temp_listing.sqft)
|
|
||||||
print(temp_listing.link)
|
|
||||||
print("--------")
|
|
||||||
index += 1
|
|
||||||
|
|
||||||
def scrape_listings(self, html):
|
|
||||||
temp_listings = []
|
|
||||||
for listing in slurp(html, "article", {"data-test":"property-card"}):
|
|
||||||
listing = f"<html><head><head/><body>{listing}<body/><html/>"
|
|
||||||
|
|
||||||
uls = slurp(listing, "li", {})
|
|
||||||
beds = 0
|
|
||||||
baths = 0
|
|
||||||
sqft = 0
|
|
||||||
for ul in uls:
|
|
||||||
ul = ul.get_text()
|
|
||||||
if ("bds" in str(ul)):
|
|
||||||
beds = return_numbers(ul)
|
|
||||||
if ("ba" in str(ul)):
|
|
||||||
baths = return_numbers(ul)
|
|
||||||
if ("sqft" in str(ul)):
|
|
||||||
sqft = return_numbers(ul)
|
|
||||||
|
|
||||||
temp_listings.append(Listing(
|
|
||||||
address=slurp(listing, "address", {"data-test":"property-card-addr"})[0].get_text(),
|
|
||||||
bedrooms=beds,
|
|
||||||
bathrooms=baths,
|
|
||||||
sqft=sqft,
|
|
||||||
price=slurp(listing, "span", {"data-test":"property-card-price"})[0].get_text(),
|
|
||||||
link=slurp(listing, "a", {"data-test":"property-card-link"})[0].get('href'),
|
|
||||||
))
|
|
||||||
|
|
||||||
return temp_listings
|
|
||||||
|
|
||||||
def setup_url(self, url):
|
|
||||||
parsed_url = urlparse(url)
|
|
||||||
print(parsed_url)
|
|
||||||
if not parsed_url.netloc:
|
|
||||||
return urlparse(f"{self.parsed_original_url.scheme}://{self.parsed_original_url.netloc}{parsed_url.path}{self.parsed_original_url.query}{self.parsed_original_url.params}")
|
|
||||||
|
|
||||||
#create dataframe
|
|
||||||
def etl(response):
|
|
||||||
|
|
||||||
#regex to find the data
|
|
||||||
|
|
||||||
for listing in listings:
|
|
||||||
print("--------")
|
|
||||||
print(listing)
|
|
||||||
print("--------")
|
|
||||||
|
|
||||||
print("FORCE STOP")
|
|
||||||
exit()
|
|
||||||
|
|
||||||
#convert text to dict via json
|
|
||||||
dicts=[json.loads('{'+i+'}') for i in num]
|
|
||||||
|
|
||||||
#create dataframe
|
|
||||||
df=pd.DataFrame()
|
|
||||||
for ind,val in enumerate(text):
|
|
||||||
df[val]=dicts[ind].values()
|
|
||||||
df.index=dicts[ind].keys()
|
|
||||||
|
|
||||||
return df
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
#scrapper = ScrapeZillowListings('https://www.zillow.com/westchester-county-ny/?searchQueryState=%7B%22usersSearchTerm%22%3A%22Yorktown%20Heights%2C%20NY%22%2C%22mapBounds%22%3A%7B%22north%22%3A41.69948153143324%2C%22east%22%3A-72.68804025585938%2C%22south%22%3A40.83865274682678%2C%22west%22%3A-74.29479074414063%7D%2C%22isMapVisible%22%3Atrue%2C%22filterState%22%3A%7B%22price%22%3A%7B%22max%22%3A250000%7D%2C%22ah%22%3A%7B%22value%22%3Atrue%7D%2C%22sort%22%3A%7B%22value%22%3A%22days%22%7D%2C%22land%22%3A%7B%22value%22%3Afalse%7D%2C%22cmsn%22%3A%7B%22value%22%3Afalse%7D%2C%22sche%22%3A%7B%22value%22%3Afalse%7D%2C%22schm%22%3A%7B%22value%22%3Afalse%7D%2C%22schh%22%3A%7B%22value%22%3Afalse%7D%2C%22schp%22%3A%7B%22value%22%3Afalse%7D%2C%22schr%22%3A%7B%22value%22%3Afalse%7D%2C%22schc%22%3A%7B%22value%22%3Afalse%7D%2C%22schu%22%3A%7B%22value%22%3Afalse%7D%7D%2C%22isListVisible%22%3Atrue%2C%22regionSelection%22%3A%5B%7B%22regionId%22%3A3148%2C%22regionType%22%3A4%7D%2C%7B%22regionId%22%3A2694%2C%22regionType%22%3A4%7D%5D%2C%22pagination%22%3A%7B%7D%7D')
|
|
||||||
scrapper = ScrapeZillowListings("https://www.zillow.com/search/GetSearchPageState.htm?searchQueryState=^%^7B^%^22pagination^%^22^%^3A^%^7B^%^7D^%^2C^%^22usersSearchTerm^%^22^%^3A^%^22Yorktown^%^20Heights^%^2C^%^20NY^%^22^%^2C^%^22mapBounds^%^22^%^3A^%^7B^%^22north^%^22^%^3A42.99146217894271^%^2C^%^22east^%^22^%^3A-70.80209903627659^%^2C^%^22south^%^22^%^3A39.549453943310084^%^2C^%^22west^%^22^%^3A-77.00937442690159^%^7D^%^2C^%^22mapZoom^%^22^%^3A8^%^2C^%^22regionSelection^%^22^%^3A^%^5B^%^7B^%^22regionId^%^22^%^3A3148^%^2C^%^22regionType^%^22^%^3A4^%^7D^%^2C^%^7B^%^22regionId^%^22^%^3A2694^%^2C^%^22regionType^%^22^%^3A4^%^7D^%^5D^%^2C^%^22isMapVisible^%^22^%^3Atrue^%^2C^%^22filterState^%^22^%^3A^%^7B^%^22price^%^22^%^3A^%^7B^%^22max^%^22^%^3A250000^%^7D^%^2C^%^22isAllHomes^%^22^%^3A^%^7B^%^22value^%^22^%^3Atrue^%^7D^%^2C^%^22sortSelection^%^22^%^3A^%^7B^%^22value^%^22^%^3A^%^22days^%^22^%^7D^%^2C^%^22isLotLand^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isMiddleSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isHighSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22includeUnratedSchools^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isComingSoon^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isPublicSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isPrivateSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isElementarySchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isCharterSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^7D^%^2C^%^22isListVisible^%^22^%^3Atrue^%^7D&wants=^\{^%^22cat1^%^22:^\[^%^22mapResults^%^22^\]^\}&requestId=3")
|
|
||||||
listings = scrapper.run()
|
|
||||||
scrapper.print_listings()
|
|
||||||
|
|
||||||
#df=etl(response)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|
||||||
|
|
||||||
#curl "https://www.zillow.com/search/GetSearchPageState.htm?searchQueryState=^%^7B^%^22pagination^%^22^%^3A^%^7B^%^7D^%^2C^%^22usersSearchTerm^%^22^%^3A^%^22Yorktown^%^20Heights^%^2C^%^20NY^%^22^%^2C^%^22mapBounds^%^22^%^3A^%^7B^%^22north^%^22^%^3A42.99146217894271^%^2C^%^22east^%^22^%^3A-70.80209903627659^%^2C^%^22south^%^22^%^3A39.549453943310084^%^2C^%^22west^%^22^%^3A-77.00937442690159^%^7D^%^2C^%^22mapZoom^%^22^%^3A8^%^2C^%^22regionSelection^%^22^%^3A^%^5B^%^7B^%^22regionId^%^22^%^3A3148^%^2C^%^22regionType^%^22^%^3A4^%^7D^%^2C^%^7B^%^22regionId^%^22^%^3A2694^%^2C^%^22regionType^%^22^%^3A4^%^7D^%^5D^%^2C^%^22isMapVisible^%^22^%^3Atrue^%^2C^%^22filterState^%^22^%^3A^%^7B^%^22price^%^22^%^3A^%^7B^%^22max^%^22^%^3A250000^%^7D^%^2C^%^22isAllHomes^%^22^%^3A^%^7B^%^22value^%^22^%^3Atrue^%^7D^%^2C^%^22sortSelection^%^22^%^3A^%^7B^%^22value^%^22^%^3A^%^22days^%^22^%^7D^%^2C^%^22isLotLand^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isMiddleSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isHighSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22includeUnratedSchools^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isComingSoon^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isPublicSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isPrivateSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isElementarySchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^2C^%^22isCharterSchool^%^22^%^3A^%^7B^%^22value^%^22^%^3Afalse^%^7D^%^7D^%^2C^%^22isListVisible^%^22^%^3Atrue^%^7D&wants=^\{^%^22cat1^%^22:^\[^%^22mapResults^%^22^\]^\}&requestId=3",
|
|
||||||
# "authority: www.zillow.com",
|
|
||||||
# "accept: */*",
|
|
||||||
# "accept-language: en-US,en;q=0.9",
|
|
||||||
# "cache-control: no-cache",
|
|
||||||
# "cookie: JSESSIONID=97FD1EB701E102B7353E8EA4528843CE; zguid=24^|^%^24825bd6e9-4f90-46df-a475-4a9910b5847c; zgsession=1^|a6a5b7ca-c651-45a2-93c8-c5b66fea68d3; AWSALB=oQ3DGTMPgyQOTPA6zLmQ0liqJ1oax2QoQ5rUSCsORkWP52C7k6G8H1gZnlxOtgU/zzO503UHUnQ7tUeivhOnupv7aYI6+E5LxUZl4TeE0JyhvT3pZ6LYeC9iFbTw; AWSALBCORS=oQ3DGTMPgyQOTPA6zLmQ0liqJ1oax2QoQ5rUSCsORkWP52C7k6G8H1gZnlxOtgU/zzO503UHUnQ7tUeivhOnupv7aYI6+E5LxUZl4TeE0JyhvT3pZ6LYeC9iFbTw; search=6^|1689549806090^%^7Crect^%^3D42.92311815473404^%^252C-70.80209903627659^%^252C39.62142250427077^%^252C-77.00937442690159^%^26rid^%^3D2694^%^26disp^%^3Dmap^%^26mdm^%^3Dauto^%^26p^%^3D1^%^26sort^%^3Ddays^%^26z^%^3D1^%^26listPriceActive^%^3D1^%^26type^%^3Dhouse^%^252Ccondo^%^252Capartment_duplex^%^252Cmobile^%^252Ctownhouse^%^26lt^%^3Dfsba^%^252Cfsbo^%^252Cfore^%^252Cnew^%^252Cauction^%^26price^%^3D0-250000^%^26fs^%^3D1^%^26fr^%^3D0^%^26mmm^%^3D0^%^26rs^%^3D0^%^26ah^%^3D0^%^26singlestory^%^3D0^%^26housing-connector^%^3D0^%^26abo^%^3D0^%^26garage^%^3D0^%^26pool^%^3D0^%^26ac^%^3D0^%^26waterfront^%^3D0^%^26finished^%^3D0^%^26unfinished^%^3D0^%^26cityview^%^3D0^%^26mountainview^%^3D0^%^26parkview^%^3D0^%^26waterview^%^3D0^%^26hoadata^%^3D1^%^26zillow-owned^%^3D0^%^263dhome^%^3D0^%^26featuredMultiFamilyBuilding^%^3D0^%^26commuteMode^%^3Ddriving^%^26commuteTimeOfDay^%^3Dnow^%^09^%^092694^%^09^%^09^%^09^%^09^%^09^%^09",
|
|
||||||
# "pragma: no-cache",
|
|
||||||
# "sec-ch-ua: ^\^"Not.A/Brand^\^";v=^\^"8^\^", ^\^"Chromium^\^";v=^\^"114^\^", ^\^"Google Chrome^\^";v=^\^"114^\^"",
|
|
||||||
# "sec-ch-ua-mobile: ?0",
|
|
||||||
# "sec-ch-ua-platform: ^\^"Windows^\^"",
|
|
||||||
# "sec-fetch-dest: empty",
|
|
||||||
# "sec-fetch-mode: cors",
|
|
||||||
# "sec-fetch-site: same-origin",
|
|
||||||
# "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
|
|
||||||
# "x-kl-ajax-request: Ajax_Request",
|
|
||||||
# --compressed
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
pandas
|
|
||||||
requests
|
|
||||||
fake-useragent
|
|
||||||
beautifulsoup4
|
|
||||||
150
Server/package-lock.json
generated
150
Server/package-lock.json
generated
@@ -26,7 +26,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",
|
||||||
"mysql": "^2.18.1",
|
"mysql2": "^3.3.5",
|
||||||
"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",
|
||||||
@@ -489,14 +489,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
},
|
},
|
||||||
"node_modules/bignumber.js": {
|
|
||||||
"version": "9.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
|
|
||||||
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/bluebird": {
|
"node_modules/bluebird": {
|
||||||
"version": "3.7.2",
|
"version": "3.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||||
@@ -736,11 +728,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",
|
||||||
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
|
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
|
||||||
},
|
},
|
||||||
"node_modules/core-util-is": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
|
||||||
},
|
|
||||||
"node_modules/css-select": {
|
"node_modules/css-select": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
||||||
@@ -805,6 +792,14 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/denque": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
@@ -1284,6 +1279,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/generate-function": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-property": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
|
||||||
@@ -1510,10 +1513,10 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/isarray": {
|
"node_modules/is-property": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
|
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
|
||||||
},
|
},
|
||||||
"node_modules/jake": {
|
"node_modules/jake": {
|
||||||
"version": "10.8.7",
|
"version": "10.8.7",
|
||||||
@@ -1662,6 +1665,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
|
||||||
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
|
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/long": {
|
||||||
|
"version": "5.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
||||||
|
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
@@ -1846,24 +1854,69 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
},
|
},
|
||||||
"node_modules/mysql": {
|
"node_modules/mysql2": {
|
||||||
"version": "2.18.1",
|
"version": "3.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
|
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.3.5.tgz",
|
||||||
"integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
|
"integrity": "sha512-ZTQGAzxGeaX1PyeSiZFCgQ34uiXguaEpn3aTFN9Enm9JDnbwWo+4/CJnDdQZ3n0NaMeysi8vwtW/jNUb9VqVDw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bignumber.js": "9.0.0",
|
"denque": "^2.1.0",
|
||||||
"readable-stream": "2.3.7",
|
"generate-function": "^2.3.1",
|
||||||
"safe-buffer": "5.1.2",
|
"iconv-lite": "^0.6.3",
|
||||||
"sqlstring": "2.3.1"
|
"long": "^5.2.1",
|
||||||
|
"lru-cache": "^8.0.0",
|
||||||
|
"named-placeholders": "^1.1.3",
|
||||||
|
"seq-queue": "^0.0.5",
|
||||||
|
"sqlstring": "^2.3.2"
|
||||||
},
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mysql2/node_modules/iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mysql2/node_modules/lru-cache": {
|
||||||
|
"version": "8.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
|
||||||
|
"integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mysql2/node_modules/sqlstring": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mysql/node_modules/safe-buffer": {
|
"node_modules/named-placeholders": {
|
||||||
"version": "5.1.2",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "^7.14.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders/node_modules/lru-cache": {
|
||||||
|
"version": "7.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||||
|
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/negotiator": {
|
"node_modules/negotiator": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
@@ -2209,11 +2262,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/process-nextick-args": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
|
||||||
},
|
|
||||||
"node_modules/proxy-addr": {
|
"node_modules/proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
@@ -2319,25 +2367,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/readable-stream": {
|
|
||||||
"version": "2.3.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
|
||||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
|
||||||
"dependencies": {
|
|
||||||
"core-util-is": "~1.0.0",
|
|
||||||
"inherits": "~2.0.3",
|
|
||||||
"isarray": "~1.0.0",
|
|
||||||
"process-nextick-args": "~2.0.0",
|
|
||||||
"safe-buffer": "~5.1.1",
|
|
||||||
"string_decoder": "~1.1.1",
|
|
||||||
"util-deprecate": "~1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/readable-stream/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/readable-web-to-node-stream": {
|
"node_modules/readable-web-to-node-stream": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
|
||||||
@@ -2475,6 +2504,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/seq-queue": {
|
||||||
|
"version": "0.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||||
|
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
|
||||||
|
},
|
||||||
"node_modules/serve-static": {
|
"node_modules/serve-static": {
|
||||||
"version": "1.15.0",
|
"version": "1.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
|
||||||
@@ -2546,14 +2580,6 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sqlstring": {
|
|
||||||
"version": "2.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
|
|
||||||
"integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/statuses": {
|
"node_modules/statuses": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||||
|
|||||||
@@ -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",
|
||||||
"mysql": "^2.18.1",
|
"mysql2": "^3.3.5",
|
||||||
"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",
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -4,6 +4,7 @@ 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;
|
||||||
|
|
||||||
@@ -34,31 +35,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(`${appName}:${fileName}:INFO\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:INFO\t-\t${messageParts.map((messagePart, index, array) => {return inspect(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(`${appName}:${fileName}:DEBUG\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:DEBUG\t-\t${messageParts.map((messagePart, index, array) => {return inspect(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(`${appName}:${fileName}:VERBOSE\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:VERBOSE\t-\t${messageParts.map((messagePart, index, array) => {return inspect(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(`${appName}:${fileName}:WARNING\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:WARNING\t-\t${messageParts.map((messagePart, index, array) => {return inspect(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(`${appName}:${fileName}:ERROR\t-\t${messageParts.map((messagePart, index, array) => {return JSON.stringify(messagePart)})}`, appName);
|
writeToLog(`${Date.now().toLocaleString('en-US', { timeZone: 'America/New_York' })} - ${appName}:${fileName}:ERROR\t-\t${messageParts.map((messagePart, index, array) => {return inspect(messagePart)})}`, appName);
|
||||||
if (process.env.EXIT_ON_ERROR && process.env.EXIT_ON_ERROR > 0) {
|
if (process.env.EXIT_ON_ERROR && process.env.EXIT_ON_ERROR > 0) {
|
||||||
writeToLog("!--- EXITING ---!", appName);
|
writeToLog("!--- EXITING ---!", appName);
|
||||||
setTimeout(process.exit, process.env.EXIT_ON_ERROR_DELAY ?? 0);
|
setTimeout(process.exit, process.env.EXIT_ON_ERROR_DELAY ?? 0);
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|
||||||
const commands = [];
|
var 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,3 +48,35 @@ 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);
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ exports.sendHttpRequest = function sendHttpRequest(requestOptions, data, callbac
|
|||||||
res.on('data', (data) => {
|
res.on('data', (data) => {
|
||||||
const responseObject = {
|
const responseObject = {
|
||||||
"statusCode": res.statusCode,
|
"statusCode": res.statusCode,
|
||||||
"body": (isJsonString(data.toString)) ? JSON.parse(data) : data.toString()
|
"body": (isJsonString(data.toString())) ? JSON.parse(data.toString()) : data.toString()
|
||||||
};
|
};
|
||||||
log.DEBUG("Response Object: ", responseObject);
|
log.DEBUG("Response Object: ", responseObject);
|
||||||
callback(responseObject);
|
callback(responseObject);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
const mysql = require('mysql');
|
const mysql = require('mysql2');
|
||||||
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");
|
||||||
@@ -24,6 +24,8 @@ const nodeConnectionsTable = `${process.env.NODE_DB_NAME}.node_connections`;
|
|||||||
* @returns {nodeObject} The converted node object to be used downstream
|
* @returns {nodeObject} The converted node object to be used downstream
|
||||||
*/
|
*/
|
||||||
function returnNodeObjectFromRow(row) {
|
function returnNodeObjectFromRow(row) {
|
||||||
|
if (!isNaN(row.online)) row.online = Boolean(row.online);
|
||||||
|
else if (row.online == "true" || row.online == "false") row.online = (row.online == "true");
|
||||||
return new nodeObject({
|
return new nodeObject({
|
||||||
_id: row.id,
|
_id: row.id,
|
||||||
_name: row.name,
|
_name: row.name,
|
||||||
@@ -31,7 +33,7 @@ function returnNodeObjectFromRow(row) {
|
|||||||
_port: row.port,
|
_port: row.port,
|
||||||
_location: row.location,
|
_location: row.location,
|
||||||
_nearbySystems: BufferToJson(row.nearbySystems),
|
_nearbySystems: BufferToJson(row.nearbySystems),
|
||||||
_online: (row.online === 1) ? true : false,
|
_online: row.online,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +94,7 @@ exports.getAllNodesSync = async () => {
|
|||||||
|
|
||||||
console.log("Rows: ", rows);
|
console.log("Rows: ", rows);
|
||||||
|
|
||||||
return returnNodeObjectFromRows(rows);
|
return await 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 +112,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) throw new Error("No node ID given when trying to fetch node");
|
if (!nodeId || nodeId == '0' || nodeId == 0 ) 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 +124,8 @@ 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(returnNodeObjectFromRow(sqlResponse[0])) : returnNodeObjectFromRow(sqlResponse[0]);
|
if (!sqlResponse.length > 0) return (callback) ? callback(false) : false;
|
||||||
|
return (callback) ? callback(await returnNodeObjectFromRow(sqlResponse[0])) : await returnNodeObjectFromRow(sqlResponse[0]);
|
||||||
}
|
}
|
||||||
exports.getNodeInfoFromId = getNodeInfoFromId
|
exports.getNodeInfoFromId = getNodeInfoFromId
|
||||||
|
|
||||||
@@ -136,10 +139,15 @@ 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,
|
|
||||||
connected = 0;
|
var online = nodeObject.online;
|
||||||
const sqlQuery = `INSERT INTO ${nodesTable} (name, ip, port, location, nearbySystems, online, connected) VALUES ('${name}', '${ip}', ${port}, '${location}', '${nearbySystems}', ${online}, ${connected})`;
|
if (typeof online === "boolean" || typeof online === "number") {
|
||||||
|
if (online) online = 1;
|
||||||
|
else online = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sqlQuery = `INSERT INTO ${nodesTable} (name, ip, port, location, nearbySystems, online) VALUES ('${name}', '${ip}', ${port}, '${location}', '${nearbySystems}', ${online})`;
|
||||||
|
|
||||||
const sqlResponse = await new Promise((recordResolve, recordReject) => {
|
const sqlResponse = await new Promise((recordResolve, recordReject) => {
|
||||||
runSQL(sqlQuery, (rows) => {
|
runSQL(sqlQuery, (rows) => {
|
||||||
@@ -149,7 +157,9 @@ 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
|
||||||
return (callback) ? callback(returnNodeObjectFromRow(sqlResponse)) : returnNodeObjectFromRow(sqlResponse);
|
const newNode = await this.getNodeInfoFromId(sqlResponse.insertId);
|
||||||
|
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
|
||||||
@@ -206,7 +216,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(returnNodeObjectFromRows(sqlResponse)) : returnNodeObjectFromRows(sqlResponse);
|
else return (callback) ? callback(await returnNodeObjectFromRows(sqlResponse)) : await returnNodeObjectFromRows(sqlResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -353,12 +363,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) => {
|
||||||
console.log(err);
|
log.ERROR(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);
|
||||||
//console.log('The rows are:', rows);
|
log.VERBOSE('Response for query: ', sqlQuery, rows);
|
||||||
return (callback) ? callback(rows) : rows
|
return (callback) ? callback(rows) : rows
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,17 +110,16 @@ 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 = undefined, _name = undefined, _ip = undefined, _port = undefined, _location = undefined, _nearbySystems = undefined, _online = undefined }) {
|
||||||
this.id = _id;
|
this.id = _id;
|
||||||
this.name = _name;
|
this.name = _name;
|
||||||
this.ip = _ip;
|
this.ip = _ip;
|
||||||
this.port = _port;
|
this.port = _port;
|
||||||
this.location = _location;
|
this.location = _location;
|
||||||
this.nearbySystems = _nearbySystems;
|
this.nearbySystems = _nearbySystems;
|
||||||
|
if (this.nearbySystems) this.presets = Object.keys(_nearbySystems);
|
||||||
this.online = _online;
|
this.online = _online;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +136,7 @@ class clientObject {
|
|||||||
* @param {*} param0._name The name of the bot associated with the IDs
|
* @param {*} param0._name The name of the bot associated with the IDs
|
||||||
* @param {*} param0._client_id The client ID of the bot needed to connect to Discord
|
* @param {*} param0._client_id The client ID of the bot needed to connect to Discord
|
||||||
*/
|
*/
|
||||||
constructor({_discord_id = null, _name = null, _client_id = null,}) {
|
constructor({_discord_id = undefined, _name = undefined, _client_id = undefined,}) {
|
||||||
this.discordId = _discord_id;
|
this.discordId = _discord_id;
|
||||||
this.name = _name;
|
this.name = _name;
|
||||||
this.clientId = _client_id;
|
this.clientId = _client_id;
|
||||||
@@ -156,7 +155,7 @@ class connectionObject {
|
|||||||
* @param {*} param0._node The node associated with the connection
|
* @param {*} param0._node The node associated with the connection
|
||||||
* @param {*} param0._client_object The client object associated with the connection
|
* @param {*} param0._client_object The client object associated with the connection
|
||||||
*/
|
*/
|
||||||
constructor({_connection_id = null, _node = null, _client_object}) {
|
constructor({_connection_id = undefined, _node = undefined, _client_object}) {
|
||||||
this.connectionId = _connection_id;
|
this.connectionId = _connection_id;
|
||||||
this.node = _node;
|
this.node = _node;
|
||||||
this.clientObject = _client_object;
|
this.clientObject = _client_object;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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
|
||||||
@@ -117,3 +118,19 @@ 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 })),
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user