From 9ef820d69914c84f47ee454c341d1ebb5d0f16b0 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Mon, 6 Apr 2026 20:22:56 +0200 Subject: [PATCH] better plugin configs (add backend path) --- package.json | 2 +- server/console.js | 7 +- server/device.js | 198 +++++++++++++++++++++ server/endpoints.js | 10 +- server/helpers.js | 8 +- server/index.js | 227 ++---------------------- server/plugins.js | 32 ++-- server/{fmdx_list.js => server_list.js} | 4 +- server/xdr_server.js | 15 +- views/setup.ejs | 6 +- web/js/audio.js | 2 +- web/js/main.js | 3 +- 12 files changed, 256 insertions(+), 258 deletions(-) create mode 100644 server/device.js rename server/{fmdx_list.js => server_list.js} (97%) diff --git a/package.json b/package.json index 580141c..aef165d 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "webserver": "node index.js" }, "author": "", - "license": "ISC", + "license": "GPL-3.0-only", "dependencies": { "@mapbox/node-pre-gyp": "2.0.3", "body-parser": "2.2.2", diff --git a/server/console.js b/server/console.js index 7646e46..e4a98d8 100644 --- a/server/console.js +++ b/server/console.js @@ -7,10 +7,10 @@ const LOG_FILE = process.argv.includes('--config') && process.argv[process.argv. ? `serverlog_${process.argv[process.argv.indexOf('--config') + 1]}.txt` : 'serverlog.txt'; const ANSI_ESCAPE_CODE_PATTERN = /\x1b\[[0-9;]*m/g; -const MAX_LOG_LINES = 3500; +const MAX_LOG_LINES = 2500; const FLUSH_INTERVAL = 60000; const logs = []; -const maxConsoleLogLines = 250; +const maxConsoleLogLines = 230; let logBuffer = []; // Message prefixes with ANSI codes @@ -27,7 +27,7 @@ const MESSAGE_PREFIX = { const getCurrentTime = () => { const currentTime = new Date(); const date = currentTime.toLocaleDateString().replace(/\ /g, ''); - const time = currentTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + const time = currentTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false }); return `\x1b[90m[${date} ${time}]\x1b[0m`; }; @@ -57,6 +57,7 @@ function appendLogToBuffer(logMessage) { const cleanLogMessage = removeANSIEscapeCodes(logMessage); logBuffer.push(cleanLogMessage + '\n'); } +appendLogToBuffer("Server started."); async function flushLogBuffer() { if (logBuffer.length === 0) return; diff --git a/server/device.js b/server/device.js new file mode 100644 index 0000000..1384a61 --- /dev/null +++ b/server/device.js @@ -0,0 +1,198 @@ +const { SerialPort } = require('serialport'); +const { serverConfig, configExists } = require('./server_config'); +const { logError, logInfo, logWarn } = require('./console'); +const pluginsApi = require('./plugins_api'); +const dataHandler = require('./datahandler'); +const client = new (require('net')).Socket(); +const helpers = require('./helpers'); + +let serialport; + +connectToXdrd(); +connectToSerial(); + +dataHandler.state.isSerialportRetrying = false; + +setInterval(() => { + if (!dataHandler.state.isSerialportAlive && serverConfig.xdrd.wirelessConnection === false) { + dataHandler.state.isSerialportAlive = true; + dataHandler.state.isSerialportRetrying = true; + if (serialport && serialport.isOpen) { + logWarn('Communication lost from ' + serverConfig.xdrd.comPort + ', force closing serialport.'); + setTimeout(() => { + serialport.close((err) => { + if (err) logError('Error closing serialport: ', err.message); + }); + }, 1000); + } else logWarn('Communication lost from ' + serverConfig.xdrd.comPort + '.'); + } +}, 2000); + +// Serial Connection +function connectToSerial() { + if (serverConfig.xdrd.wirelessConnection === true) return; + + serialport = new SerialPort({ + path: serverConfig.xdrd.comPort, + baudRate: 115200, + autoOpen: false, + dtr: false, rts: false + }); + + serialport.open((err) => { + if (err) { + logError('Error opening port: ' + err.message); + setTimeout(() => { + connectToSerial(); + }, 5000); + return; + } + + logInfo('Using serial port: ' + serverConfig.xdrd.comPort); + dataHandler.state.isSerialportAlive = true; + pluginsApi.setOutput(serialport); + setTimeout(() => { + serialport.write('x\n'); + }, 1000); + + setTimeout(() => { + serialport.write('Q0\n'); + serialport.write('M0\n'); + serialport.write(`Z${serverConfig.antennaStartup}\n`); // Antenna on startup + + if (serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true) { + serialport.write('T' + Math.round(serverConfig.defaultFreq * 1000) + '\n'); + dataHandler.initialData.freq = Number(serverConfig.defaultFreq).toFixed(3); + dataHandler.dataToSend.freq = Number(serverConfig.defaultFreq).toFixed(3); + } else if (dataHandler.state.lastFrequencyAlive && dataHandler.state.isSerialportRetrying) { // Serialport retry code when port is open but communication is lost + serialport.write('T' + (dataHandler.state.lastFrequencyAlive * 1000) + '\n'); + } else serialport.write('T87500\n'); + dataHandler.state.isSerialportRetrying = false; + + if (serverConfig.device === 'si47xx') serialport.write('A0\n'); + serialport.write('F-1\n'); + serialport.write('W0\n'); + serverConfig.webserver.rdsMode ? serialport.write('D1\n') : serialport.write('D0\n'); + serialport.write(`G${serverConfig.ceqStartup}${serverConfig.imsStartup}\n`); + serialport.write(`B${serverConfig.stereoStartup}\n`); + serverConfig.audio.startupVolume + ? serialport.write('Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n') + : serialport.write('Y100\n'); + }, 6000); + + serialport.on('data', helpers.resolveDataBuffer); + serialport.on('error', (error) => logError(error.message)); + }); + + // Handle port closure + serialport.on('close', () => { + pluginsApi.setOutput(null); + logWarn('Disconnected from ' + serverConfig.xdrd.comPort + '. Attempting to reconnect.'); + setTimeout(() => { + dataHandler.state.isSerialportRetrying = true; + connectToSerial(); + }, 5000); + }); + return serialport; +} + +// xdrd connection +let authFlags = {}; + +function connectToXdrd() { + const { xdrd } = serverConfig; + + if (xdrd.wirelessConnection && configExists()) { + client.connect(xdrd.xdrdPort, xdrd.xdrdIp, () => { + logInfo('Connection to xdrd established successfully.'); + pluginsApi.setOutput(client); + + authFlags = { + authMsg: false, + firstClient: false, + receivedSalt: '', + receivedPassword: false, + messageCount: 0, + }; + }); + } +} + +client.on('data', (data) => { + const { xdrd } = serverConfig; + + helpers.resolveDataBuffer(data); + if (authFlags.authMsg == true && authFlags.messageCount > 1) return; + + authFlags.messageCount++; + const receivedData = data.toString(); + const lines = receivedData.split('\n'); + + for (const line of lines) { + if (authFlags.receivedPassword === false) { + authFlags.receivedSalt = line.trim(); + authFlags.receivedPassword = true; + helpers.authenticateWithXdrd(client, authFlags.receivedSalt, xdrd.xdrdPassword); + } else { + if (line.startsWith('a')) { + authFlags.authMsg = true; + logWarn('Authentication with xdrd failed. Is your password set correctly?'); + } else if (line.startsWith('o1,')) authFlags.firstClient = true; + else if (line.startsWith('T') && line.length <= 7) { + const freq = line.slice(1) / 1000; + dataHandler.dataToSend.freq = freq.toFixed(3); + } else if (line.startsWith('OK')) { + authFlags.authMsg = true; + logInfo('Authentication with xdrd successful.'); + } else if (line.startsWith('G')) { + dataHandler.initialData.eq = line.charAt(1); + dataHandler.dataToSend.eq = line.charAt(1); + dataHandler.initialData.ims = line.charAt(2); + dataHandler.dataToSend.ims = line.charAt(2); + } else if (line.startsWith('Z')) { + let modifiedLine = line.slice(1); + dataHandler.initialData.ant = modifiedLine; + dataHandler.dataToSend.ant = modifiedLine; + } + + if (authFlags.authMsg === true && authFlags.firstClient === true) { + client.write('x\n'); + client.write(serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? 'T' + Math.round(serverConfig.defaultFreq * 1000) + '\n' : 'T87500\n'); + dataHandler.initialData.freq = serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? Number(serverConfig.defaultFreq).toFixed(3) : (87.5).toFixed(3); + dataHandler.dataToSend.freq = serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? Number(serverConfig.defaultFreq).toFixed(3) : (87.5).toFixed(3); + if (serverConfig.device === 'si47xx') serialport.write('A0\n'); + client.write(serverConfig.audio.startupVolume ? 'Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n' : 'Y100\n'); + serverConfig.webserver.rdsMode ? client.write('D1\n') : client.write('D0\n'); + return; + } + } + } +}); + +client.on('close', () => { + pluginsApi.setOutput(null); + if(serverConfig.autoShutdown === false) { + logWarn('Disconnected from xdrd. Attempting to reconnect.'); + setTimeout(connectToXdrd, 2000); + } else logWarn('Disconnected from xdrd.'); +}); + +client.on('error', (err) => { + switch (true) { + case err.message.includes("ECONNRESET"): + logError("Connection to xdrd lost. Reconnecting..."); + break; + case err.message.includes("ETIMEDOUT"): + logError("Connection to xdrd @ " + serverConfig.xdrd.xdrdIp + ":" + serverConfig.xdrd.xdrdPort + " timed out."); + break; + case err.message.includes("ECONNREFUSED"): + logError("Connection to xdrd @ " + serverConfig.xdrd.xdrdIp + ":" + serverConfig.xdrd.xdrdPort + " failed. Is xdrd running?"); + break; + case err.message.includes("EINVAL"): + logError("Attempts to reconnect are failing repeatedly. Consider checking your settings or restarting xdrd."); + break; + default: + logError("Unhandled error: ", err.message); + break; + } +}); diff --git a/server/endpoints.js b/server/endpoints.js index ca7521d..edec546 100644 --- a/server/endpoints.js +++ b/server/endpoints.js @@ -14,8 +14,7 @@ const storage = require('./storage'); const tunerProfiles = require('./tuner_profiles'); const { logInfo, logs } = require('./console'); const dataHandler = require('./datahandler'); -const fmdxList = require('./fmdx_list'); -const allPluginConfigs = require('./plugins'); +const serverList = require('./server_list'); // Endpoints router.get('/', (req, res) => { @@ -141,8 +140,7 @@ router.get('/setup', (req, res) => { return; } - SerialPort.list() - .then((deviceList) => { + SerialPort.list().then((deviceList) => { serialPorts = deviceList.map(port => ({ path: port.path, friendlyName: port.friendlyName, @@ -162,7 +160,7 @@ router.get('/setup', (req, res) => { memoryHeap: (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(1) + ' MB', processUptime: formattedProcessUptime, consoleOutput: logs, - plugins: allPluginConfigs, + plugins: require('./plugins'), enabledPlugins: updatedConfig.plugins, onlineUsers: dataHandler.dataToSend.users, connectedUsers: storage.connectedUsers, @@ -308,7 +306,7 @@ router.post('/saveData', (req, res) => { let firstSetup; if(req.session.isAdminAuthenticated || !configExists()) { configUpdate(data); - fmdxList.update(); + serverList.update(); if(!configExists()) firstSetup = true; logInfo('Server config changed successfully.'); diff --git a/server/helpers.js b/server/helpers.js index 21637a2..e2a36d7 100644 --- a/server/helpers.js +++ b/server/helpers.js @@ -400,12 +400,18 @@ function startPluginsWithDelay(plugins, delay) { function findServerFiles(plugins) { let results = []; plugins.forEach(plugin => { - // Remove .js extension if present if (plugin.endsWith('.js')) plugin = plugin.slice(0, -3); const pluginPath = path.join(__dirname, '..', 'plugins', `${plugin}_server.js`); if (fs.existsSync(pluginPath) && fs.statSync(pluginPath).isFile()) results.push(pluginPath); }); + + require("./plugins").forEach(config => { + if(config.backEndPath) { + const pluginPath = config.backEndPath; + if (fs.existsSync(pluginPath) && fs.statSync(pluginPath).isFile()) results.push(pluginPath); + } + }); return results; } diff --git a/server/index.js b/server/index.js index b62dfee..9f4a104 100644 --- a/server/index.js +++ b/server/index.js @@ -1,229 +1,26 @@ -const { SerialPort } = require('serialport'); -const tunnel = require('./tunnel'); -const helpers = require('./helpers'); -const dataHandler = require('./datahandler'); -const { logError, logInfo, logWarn } = require('./console'); -const { serverConfig, configExists } = require('./server_config'); -const pluginsApi = require('./plugins_api'); -const startServer = require("./web"); - -const client = new (require('net')).Socket(); - -// Get all plugins from config and find corresponding server files -const plugins = helpers.findServerFiles(serverConfig.plugins); - -// Start the first plugin after 3 seconds, then the rest with 3 seconds delay -if (plugins.length > 0) { - setTimeout(() => { - helpers.startPluginsWithDelay(plugins, 3000); // Start plugins with 3 seconds interval - }, 4000); // Initial delay of 4 seconds for the first plugin -} - const terminalWidth = require('readline').createInterface({input: process.stdin, output: process.stdout}).output.columns; console.log('\x1b[32m' + require('figlet').textSync("FM-DX Webserver")); -console.log('\x1b[32m\x1b[2mby Noobish @ \x1b[4mFMDX.org + KubaPro010\x1b[0m'); +console.log('\x1b[2mby (Noobish @ \x1b[4mFMDX.org\x1b[0m\x1b[32m\x1b[2m) + KubaPro010\x1b[0m'); console.log("v" + require('../package.json').version) console.log('\x1b[90m' + '─'.repeat(terminalWidth - 1) + '\x1b[0m'); -require('./plugins'); - -let serialport; - +const { serverConfig } = require('./server_config'); +const tunnel = require('./tunnel'); tunnel.download(); -connectToXdrd(); -connectToSerial(); -// Serialport retry code when port is open but communication is lost (additional code in datahandler.js) -dataHandler.state.isSerialportRetrying = false; +require("./device"); -setInterval(() => { - if (!dataHandler.state.isSerialportAlive && serverConfig.xdrd.wirelessConnection === false) { - dataHandler.state.isSerialportAlive = true; - dataHandler.state.isSerialportRetrying = true; - if (serialport && serialport.isOpen) { - logWarn('Communication lost from ' + serverConfig.xdrd.comPort + ', force closing serialport.'); - setTimeout(() => { - serialport.close((err) => { - if (err) logError('Error closing serialport: ', err.message); - }); - }, 1000); - } else logWarn('Communication lost from ' + serverConfig.xdrd.comPort + '.'); - } -}, 2000); - -// Serial Connection -function connectToSerial() { - if (serverConfig.xdrd.wirelessConnection === true) return; - - serialport = new SerialPort({ - path: serverConfig.xdrd.comPort, - baudRate: 115200, - autoOpen: false, - dtr: false, rts: false - }); - - serialport.open((err) => { - if (err) { - logError('Error opening port: ' + err.message); - setTimeout(() => { - connectToSerial(); - }, 5000); - return; - } - - logInfo('Using serial port: ' + serverConfig.xdrd.comPort); - dataHandler.state.isSerialportAlive = true; - pluginsApi.setOutput(serialport); - setTimeout(() => { - serialport.write('x\n'); - }, 1000); - - setTimeout(() => { - serialport.write('Q0\n'); - serialport.write('M0\n'); - serialport.write(`Z${serverConfig.antennaStartup}\n`); // Antenna on startup - - if (serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true) { - serialport.write('T' + Math.round(serverConfig.defaultFreq * 1000) + '\n'); - dataHandler.initialData.freq = Number(serverConfig.defaultFreq).toFixed(3); - dataHandler.dataToSend.freq = Number(serverConfig.defaultFreq).toFixed(3); - } else if (dataHandler.state.lastFrequencyAlive && dataHandler.state.isSerialportRetrying) { // Serialport retry code when port is open but communication is lost - serialport.write('T' + (dataHandler.state.lastFrequencyAlive * 1000) + '\n'); - } else serialport.write('T87500\n'); - dataHandler.state.isSerialportRetrying = false; - - if (serverConfig.device === 'si47xx') serialport.write('A0\n'); - serialport.write('F-1\n'); - serialport.write('W0\n'); - serverConfig.webserver.rdsMode ? serialport.write('D1\n') : serialport.write('D0\n'); - serialport.write(`G${serverConfig.ceqStartup}${serverConfig.imsStartup}\n`); - serialport.write(`B${serverConfig.stereoStartup}\n`); // Mono - serverConfig.audio.startupVolume - ? serialport.write('Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n') - : serialport.write('Y100\n'); - }, 6000); - - serialport.on('data', (data) => helpers.resolveDataBuffer(data)); - serialport.on('error', (error) => logError(error.message)); - }); - - // Handle port closure - serialport.on('close', () => { - pluginsApi.setOutput(null); - logWarn('Disconnected from ' + serverConfig.xdrd.comPort + '. Attempting to reconnect.'); - setTimeout(() => { - dataHandler.state.isSerialportRetrying = true; - connectToSerial(); - }, 5000); - }); - return serialport; +{ + const helpers = require('./helpers'); + const plugins = helpers.findServerFiles(serverConfig.plugins); + if (plugins.length > 0) setTimeout(helpers.startPluginsWithDelay, 4000, plugins, 3000); } -// xdrd connection -let authFlags = {}; - -function connectToXdrd() { - const { xdrd } = serverConfig; - - if (xdrd.wirelessConnection && configExists()) { - client.connect(xdrd.xdrdPort, xdrd.xdrdIp, () => { - logInfo('Connection to xdrd established successfully.'); - pluginsApi.setOutput(client); - - authFlags = { - authMsg: false, - firstClient: false, - receivedSalt: '', - receivedPassword: false, - messageCount: 0, - }; - }); - } -} - -client.on('data', (data) => { - const { xdrd } = serverConfig; - - helpers.resolveDataBuffer(data); - if (authFlags.authMsg == true && authFlags.messageCount > 1) return; - - authFlags.messageCount++; - const receivedData = data.toString(); - const lines = receivedData.split('\n'); - - for (const line of lines) { - if (authFlags.receivedPassword === false) { - authFlags.receivedSalt = line.trim(); - authFlags.receivedPassword = true; - helpers.authenticateWithXdrd(client, authFlags.receivedSalt, xdrd.xdrdPassword); - } else { - if (line.startsWith('a')) { - authFlags.authMsg = true; - logWarn('Authentication with xdrd failed. Is your password set correctly?'); - } else if (line.startsWith('o1,')) authFlags.firstClient = true; - else if (line.startsWith('T') && line.length <= 7) { - const freq = line.slice(1) / 1000; - dataHandler.dataToSend.freq = freq.toFixed(3); - } else if (line.startsWith('OK')) { - authFlags.authMsg = true; - logInfo('Authentication with xdrd successful.'); - } else if (line.startsWith('G')) { - dataHandler.initialData.eq = line.charAt(1); - dataHandler.dataToSend.eq = line.charAt(1); - dataHandler.initialData.ims = line.charAt(2); - dataHandler.dataToSend.ims = line.charAt(2); - } else if (line.startsWith('Z')) { - let modifiedLine = line.slice(1); - dataHandler.initialData.ant = modifiedLine; - dataHandler.dataToSend.ant = modifiedLine; - } - - if (authFlags.authMsg === true && authFlags.firstClient === true) { - client.write('x\n'); - client.write(serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? 'T' + Math.round(serverConfig.defaultFreq * 1000) + '\n' : 'T87500\n'); - dataHandler.initialData.freq = serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? Number(serverConfig.defaultFreq).toFixed(3) : (87.5).toFixed(3); - dataHandler.dataToSend.freq = serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? Number(serverConfig.defaultFreq).toFixed(3) : (87.5).toFixed(3); - if (serverConfig.device === 'si47xx') serialport.write('A0\n'); - client.write(serverConfig.audio.startupVolume ? 'Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n' : 'Y100\n'); - serverConfig.webserver.rdsMode ? client.write('D1\n') : client.write('D0\n'); - return; - } - } - } -}); - -client.on('close', () => { - pluginsApi.setOutput(null); - if(serverConfig.autoShutdown === false) { - logWarn('Disconnected from xdrd. Attempting to reconnect.'); - setTimeout(function () { - connectToXdrd(); - }, 2000) - } else logWarn('Disconnected from xdrd.'); -}); - -client.on('error', (err) => { - switch (true) { - case err.message.includes("ECONNRESET"): - logError("Connection to xdrd lost. Reconnecting..."); - break; - case err.message.includes("ETIMEDOUT"): - logError("Connection to xdrd @ " + serverConfig.xdrd.xdrdIp + ":" + serverConfig.xdrd.xdrdPort + " timed out."); - break; - case err.message.includes("ECONNREFUSED"): - logError("Connection to xdrd @ " + serverConfig.xdrd.xdrdIp + ":" + serverConfig.xdrd.xdrdPort + " failed. Is xdrd running?"); - break; - case err.message.includes("EINVAL"): - logError("Attempts to reconnect are failing repeatedly. Consider checking your settings or restarting xdrd."); - break; - default: - logError("Unhandled error: ", err.message); - break; - } -}); - require('./stream/index'); +const startServer = require("./web"); + startServer(serverConfig.webserver.webserverIp === '0.0.0.0' ? 'localhost' : serverConfig.webserver.webserverIp); + tunnel.connect(); -require('./fmdx_list').update(); \ No newline at end of file +require('./server_list').update(); \ No newline at end of file diff --git a/server/plugins.js b/server/plugins.js index b412d36..ebfdd48 100644 --- a/server/plugins.js +++ b/server/plugins.js @@ -3,8 +3,7 @@ const path = require('path'); const consoleCmd = require('./console'); function readJSFiles(dir) { - const files = fs.readdirSync(dir); - return files.filter(file => file.endsWith('.js')); + return fs.readdirSync(dir).filter(file => file.endsWith('.js')); } function parsePluginConfig(filePath) { @@ -44,7 +43,7 @@ function parsePluginConfig(filePath) { console.error(`Error creating symlink at ${destinationFile}: ${err.message}`); } } - } else console.error(`Error: frontEndPath is not defined in ${filePath}`); + } } catch (err) { console.error(`Error parsing plugin config from ${filePath}: ${err.message}`); } @@ -52,27 +51,13 @@ function parsePluginConfig(filePath) { return pluginConfig; } -// Main function to collect plugin configs from all .js files in the 'plugins' directory -function collectPluginConfigs() { - const pluginsDir = path.join(__dirname, '../plugins'); - const jsFiles = readJSFiles(pluginsDir); - - const pluginConfigs = []; - jsFiles.forEach(file => { - const filePath = path.join(pluginsDir, file); - const config = parsePluginConfig(filePath); - if (Object.keys(config).length > 0) pluginConfigs.push(config); - }); - - return pluginConfigs; -} - // Ensure the web/js/plugins directory exists const webJsPluginsDir = path.join(__dirname, '../web/js/plugins'); if (!fs.existsSync(webJsPluginsDir)) fs.mkdirSync(webJsPluginsDir, { recursive: true }); +const pluginsDir = path.join(__dirname, '../plugins'); + if (process.platform === 'win32') { - const pluginsDir = path.join(__dirname, '../plugins'); const destinationPluginsDir = path.join(__dirname, '../web/js/plugins'); // On Windows, create a junction @@ -84,4 +69,11 @@ if (process.platform === 'win32') { } } -module.exports = collectPluginConfigs(); +const pluginConfigs = []; +readJSFiles(pluginsDir).forEach(file => { + const filePath = path.join(pluginsDir, file); + const config = parsePluginConfig(filePath); + if (Object.keys(config).length > 0) pluginConfigs.push(config); +}); + +module.exports = pluginConfigs; diff --git a/server/fmdx_list.js b/server/server_list.js similarity index 97% rename from server/fmdx_list.js rename to server/server_list.js index 1d29310..ea8d7bf 100644 --- a/server/fmdx_list.js +++ b/server/server_list.js @@ -8,8 +8,6 @@ var os = require('os'); let timeoutID = null; function send(request) { - const url = "https://servers.fmdx.org/api/"; - const options = { method: 'POST', headers: { @@ -19,7 +17,7 @@ function send(request) { body: JSON.stringify(request) }; - fetch(url, options) + fetch("https://servers.fmdx.org/api/", options) .then(response => response.json()) .then(data => { if (data.success && data.token) { diff --git a/server/xdr_server.js b/server/xdr_server.js index 4b32047..1688cc4 100644 --- a/server/xdr_server.js +++ b/server/xdr_server.js @@ -44,7 +44,7 @@ function xdr_auth(ws, salt) { }); } -xdr.on('connection', async (ws, request) => { +xdr.on('connection', async (ws) => { const { initialData } = require('./datahandler'); const salt = randomString(16); @@ -79,12 +79,19 @@ xdr.on('connection', async (ws, request) => { case "wL1": serverConfig.lockToAdmin = true; send_to_xdr("wL1\n") - break; + return; case "wL0": serverConfig.lockToAdmin = false; send_to_xdr("wL0\n") - break; - // TODO: Do the wT, but not rn because i don't feel like doing the tunerlockTracker + return; + case "wT1": + serverConfig.publicTuner = false; + send_to_xdr("wT1\n") + return; + case "wT0": + serverConfig.publicTuner = true; + send_to_xdr("wT0\n") + return; } } diff --git a/views/setup.ejs b/views/setup.ejs index 27e386d..59ae878 100644 --- a/views/setup.ejs +++ b/views/setup.ejs @@ -420,11 +420,13 @@

Any compatible .js plugin, which is in the "plugins" folder, will be listed here.
Click on the individual plugins to enable/disable them.



Download new plugins here! diff --git a/web/js/audio.js b/web/js/audio.js index 8bfdc1e..267aa35 100644 --- a/web/js/audio.js +++ b/web/js/audio.js @@ -21,7 +21,7 @@ class WebSocketAudioPlayer { const liveEdge = buffered.end(buffered.length - 1); const lag = liveEdge - this.audio.currentTime; - if (lag > .9) this.audio.currentTime = liveEdge - 0.15; // snap to near live edge + if (lag > .9) this.audio.currentTime = liveEdge - 0.2; // snap to near live edge } Start() { diff --git a/web/js/main.js b/web/js/main.js index cb903bf..7412fd4 100644 --- a/web/js/main.js +++ b/web/js/main.js @@ -815,8 +815,7 @@ function findOnMaps() { frequency > 74 ? frequency = frequency.toFixed(1) : null; - var url = `https://maps.fmdx.org/#qth=${longitude},${latitude}&freq=${frequency}&findPi=${pi}`; - window.open(url, "_blank"); + window.open(`https://maps.fmdx.org/#qth=${longitude},${latitude}&freq=${frequency}&findPi=${pi}`, "_blank"); } function updateSignalUnits(parsedData, averageSignal) {