mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-07-30 08:49:16 +02:00
ugh! improvements AGAIN?
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/* Libraries / Imports */
|
/* Libraries / Imports */
|
||||||
const { send_xdr_online } = require('./xdr_server');
|
const { send_xdr_online, send_to_xdr } = require('./xdr_server');
|
||||||
const RDSDecoder = require("./rds.js");
|
const RDSDecoder = require("./rds.js");
|
||||||
const { serverConfig } = require('./server_config');
|
const { serverConfig } = require('./server_config');
|
||||||
|
|
||||||
@@ -85,6 +85,8 @@ function rdsReset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleData(wss, receivedData, rdsWss) {
|
function handleData(wss, receivedData, rdsWss) {
|
||||||
|
send_to_xdr(receivedData);
|
||||||
|
|
||||||
// Retrieve the last update time for this client
|
// Retrieve the last update time for this client
|
||||||
const currentTime = Date.now();
|
const currentTime = Date.now();
|
||||||
|
|
||||||
@@ -117,9 +119,7 @@ function handleData(wss, receivedData, rdsWss) {
|
|||||||
dataToSend.pi = '?';
|
dataToSend.pi = '?';
|
||||||
dataToSend.txInfo.reg = false;
|
dataToSend.txInfo.reg = false;
|
||||||
|
|
||||||
rdsWss.clients.forEach((client) => {
|
rdsWss.clients.forEach((client) => client.send("G:\r\nRESET-------\r\n\r\n"));
|
||||||
client.send("G:\r\nRESET-------\r\n\r\n");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case receivedLine.startsWith('Z'): // Antenna
|
case receivedLine.startsWith('Z'): // Antenna
|
||||||
@@ -228,9 +228,7 @@ function handleData(wss, receivedData, rdsWss) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => console.log("Error fetching Tx info:", error));
|
||||||
console.log("Error fetching Tx info:", error);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send the updated data to the client
|
// Send the updated data to the client
|
||||||
const dataToSendJSON = JSON.stringify(dataToSend);
|
const dataToSendJSON = JSON.stringify(dataToSend);
|
||||||
|
|||||||
+15
-25
@@ -7,7 +7,6 @@ const dataHandler = require('./datahandler');
|
|||||||
const storage = require('./storage');
|
const storage = require('./storage');
|
||||||
const consoleCmd = require('./console');
|
const consoleCmd = require('./console');
|
||||||
const { serverConfig, configSave } = require('./server_config');
|
const { serverConfig, configSave } = require('./server_config');
|
||||||
const { send_to_xdr } = require("./xdr_server")
|
|
||||||
|
|
||||||
let geoip = null;
|
let geoip = null;
|
||||||
try {
|
try {
|
||||||
@@ -139,9 +138,7 @@ function handleConnect(clientIp, currentUsers, ws, callback) {
|
|||||||
regionName: geo.region,
|
regionName: geo.region,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else if (!geoip) {
|
} else if (!geoip) consoleCmd.logWarn('geoip-lite is not installed; location will be Unknown.');
|
||||||
consoleCmd.logWarn('geoip-lite is not installed; location will be Unknown.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const inFlightPromise = fetchIpWhoisInfo(clientIp)
|
const inFlightPromise = fetchIpWhoisInfo(clientIp)
|
||||||
.then((whoisInfo) => {
|
.then((whoisInfo) => {
|
||||||
@@ -166,12 +163,10 @@ function fetchBannedAS(callback) {
|
|||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (bannedASCache.data && now - bannedASCache.timestamp < 10 * 60 * 1000) return callback(bannedASCache.data);
|
if (bannedASCache.data && now - bannedASCache.timestamp < 10 * 60 * 1000) return callback(bannedASCache.data);
|
||||||
|
|
||||||
const req = https.get("https://fmdx.org/banned_as.json", { family: 4 }, (banResponse) => {
|
const req = https.get("https://flerken.zapto.org:5000/banned_as.json", { family: 4 }, (banResponse) => {
|
||||||
let banData = "";
|
let banData = "";
|
||||||
|
|
||||||
banResponse.on("data", (chunk) => {
|
banResponse.on("data", (chunk) => banData += chunk);
|
||||||
banData += chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
banResponse.on("end", () => {
|
banResponse.on("end", () => {
|
||||||
try {
|
try {
|
||||||
@@ -185,8 +180,8 @@ function fetchBannedAS(callback) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set timeout for the request (5 seconds)
|
// Set timeout for the request (3 seconds)
|
||||||
req.setTimeout(5000, () => {
|
req.setTimeout(3000, () => {
|
||||||
console.error("Error: Request timed out while fetching banned AS list.");
|
console.error("Error: Request timed out while fetching banned AS list.");
|
||||||
req.abort();
|
req.abort();
|
||||||
callback([]); // Default to allowing user
|
callback([]); // Default to allowing user
|
||||||
@@ -232,12 +227,9 @@ function processConnection(clientIp, locationInfo, currentUsers, ws, callback) {
|
|||||||
const userLocationForLog = locationInfo?.isp ? `${userLocation} (${locationInfo.isp})` : userLocation;
|
const userLocationForLog = locationInfo?.isp ? `${userLocation} (${locationInfo.isp})` : userLocation;
|
||||||
|
|
||||||
storage.connectedUsers.push({
|
storage.connectedUsers.push({
|
||||||
ip: clientIp,
|
ip: clientIp, location: userLocation,
|
||||||
location: userLocation,
|
isp: locationInfo?.isp, as: locationInfo?.as,
|
||||||
isp: locationInfo?.isp,
|
time: connectionTime, instance: ws,
|
||||||
as: locationInfo?.as,
|
|
||||||
time: connectionTime,
|
|
||||||
instance: ws,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
consoleCmd.logInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m Location: ${userLocationForLog}`);
|
consoleCmd.logInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m Location: ${userLocationForLog}`);
|
||||||
@@ -259,7 +251,10 @@ function formatUptime(uptimeInSeconds) {
|
|||||||
|
|
||||||
let incompleteDataBuffer = '';
|
let incompleteDataBuffer = '';
|
||||||
|
|
||||||
function resolveDataBuffer(data, wss, rdsWss) {
|
function resolveDataBuffer(data) {
|
||||||
|
const wss = storage.websocket_delegation.get("/text"); // Genius
|
||||||
|
const rdsWss = storage.websocket_delegation.get("/rds");
|
||||||
|
|
||||||
var receivedData = incompleteDataBuffer + data.toString();
|
var receivedData = incompleteDataBuffer + data.toString();
|
||||||
const isIncomplete = (receivedData.slice(-1) != '\n');
|
const isIncomplete = (receivedData.slice(-1) != '\n');
|
||||||
|
|
||||||
@@ -274,10 +269,7 @@ function resolveDataBuffer(data, wss, rdsWss) {
|
|||||||
}
|
}
|
||||||
} else incompleteDataBuffer = '';
|
} else incompleteDataBuffer = '';
|
||||||
|
|
||||||
if (receivedData.length) {
|
if (receivedData.length) dataHandler.handleData(wss, receivedData, rdsWss);
|
||||||
dataHandler.handleData(wss, receivedData, rdsWss);
|
|
||||||
send_to_xdr(receivedData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function kickClient(ipAddress) {
|
function kickClient(ipAddress) {
|
||||||
@@ -311,12 +303,10 @@ function checkLatency(host, port = 80, timeout = 2000) {
|
|||||||
|
|
||||||
socket.on("timeout", () => {
|
socket.on("timeout", () => {
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
resolve(null); // timed out
|
resolve(null); // timed out (yeah thanks, didn't see that but that comment had changed how i look on the world)
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("error", () => {
|
socket.on("error", () => resolve(null));
|
||||||
resolve(null); // offline
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-9
@@ -5,7 +5,7 @@ const dataHandler = require('./datahandler');
|
|||||||
const { logError, logInfo, logWarn } = require('./console');
|
const { logError, logInfo, logWarn } = require('./console');
|
||||||
const { serverConfig, configExists } = require('./server_config');
|
const { serverConfig, configExists } = require('./server_config');
|
||||||
const pluginsApi = require('./plugins_api');
|
const pluginsApi = require('./plugins_api');
|
||||||
const { startServer, wss, rdsWss } = require("./web");
|
const startServer = require("./web");
|
||||||
|
|
||||||
const client = new (require('net')).Socket();
|
const client = new (require('net')).Socket();
|
||||||
|
|
||||||
@@ -104,13 +104,8 @@ function connectToSerial() {
|
|||||||
: serialport.write('Y100\n');
|
: serialport.write('Y100\n');
|
||||||
}, 6000);
|
}, 6000);
|
||||||
|
|
||||||
serialport.on('data', (data) => {
|
serialport.on('data', (data) => helpers.resolveDataBuffer(data));
|
||||||
helpers.resolveDataBuffer(data, wss, rdsWss);
|
serialport.on('error', (error) => logError(error.message));
|
||||||
});
|
|
||||||
|
|
||||||
serialport.on('error', (error) => {
|
|
||||||
logError(error.message);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle port closure
|
// Handle port closure
|
||||||
@@ -150,7 +145,7 @@ function connectToXdrd() {
|
|||||||
client.on('data', (data) => {
|
client.on('data', (data) => {
|
||||||
const { xdrd } = serverConfig;
|
const { xdrd } = serverConfig;
|
||||||
|
|
||||||
helpers.resolveDataBuffer(data, wss, rdsWss);
|
helpers.resolveDataBuffer(data);
|
||||||
if (authFlags.authMsg == true && authFlags.messageCount > 1) return;
|
if (authFlags.authMsg == true && authFlags.messageCount > 1) return;
|
||||||
|
|
||||||
authFlags.messageCount++;
|
authFlags.messageCount++;
|
||||||
|
|||||||
@@ -71,8 +71,6 @@ function collectPluginConfigs() {
|
|||||||
const webJsPluginsDir = path.join(__dirname, '../web/js/plugins');
|
const webJsPluginsDir = path.join(__dirname, '../web/js/plugins');
|
||||||
if (!fs.existsSync(webJsPluginsDir)) fs.mkdirSync(webJsPluginsDir, { recursive: true });
|
if (!fs.existsSync(webJsPluginsDir)) fs.mkdirSync(webJsPluginsDir, { recursive: true });
|
||||||
|
|
||||||
// Main function to create symlinks/junctions for plugins
|
|
||||||
function createLinks() {
|
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
const pluginsDir = path.join(__dirname, '../plugins');
|
const pluginsDir = path.join(__dirname, '../plugins');
|
||||||
const destinationPluginsDir = path.join(__dirname, '../web/js/plugins');
|
const destinationPluginsDir = path.join(__dirname, '../web/js/plugins');
|
||||||
@@ -85,8 +83,5 @@ function createLinks() {
|
|||||||
console.error(`Error creating junction at ${destinationPluginsDir}: ${err.message}`);
|
console.error(`Error creating junction at ${destinationPluginsDir}: ${err.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// the usage example comment that was here got me so laughing, that i don't know about all of this
|
|
||||||
createLinks();
|
|
||||||
module.exports = collectPluginConfigs();
|
module.exports = collectPluginConfigs();
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ async function sendPrivilegedCommand(command, isPluginInternal = false) {
|
|||||||
|
|
||||||
if (isPluginInternal) {
|
if (isPluginInternal) {
|
||||||
output.write(`${command}\n`);
|
output.write(`${command}\n`);
|
||||||
//logInfo(`[Privileged Plugin] Command sent: ${command}`); // Debug
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ var countries = [
|
|||||||
"Vietnam",
|
"Vietnam",
|
||||||
"Kiribati",
|
"Kiribati",
|
||||||
"North Korea",
|
"North Korea",
|
||||||
"Brazil/Equator"
|
"Brazil/Equador"
|
||||||
]
|
]
|
||||||
|
|
||||||
var iso = [
|
var iso = [
|
||||||
@@ -444,8 +444,6 @@ var iso = [
|
|||||||
"--"
|
"--"
|
||||||
]
|
]
|
||||||
|
|
||||||
// RDS ECC Lookup Tables - Converted from C to JavaScript
|
|
||||||
|
|
||||||
const rdsEccA0A6Lut = [
|
const rdsEccA0A6Lut = [
|
||||||
// A0
|
// A0
|
||||||
[
|
[
|
||||||
@@ -461,7 +459,7 @@ const rdsEccA0A6Lut = [
|
|||||||
],
|
],
|
||||||
// A2
|
// A2
|
||||||
[
|
[
|
||||||
"Anguilla", "Antigua and Barbuda", "Brazil/Equator", "Falkland Islands", "Barbados",
|
"Anguilla", "Antigua and Barbuda", "Brazil/Equador", "Falkland Islands", "Barbados",
|
||||||
"Belize", "Cayman Islands", "Costa Rica", "Cuba", "Argentina",
|
"Belize", "Cayman Islands", "Costa Rica", "Cuba", "Argentina",
|
||||||
"Brazil", "Brazil/Bermuda", "Brazil/AN", "Guadeloupe", "Bahamas"
|
"Brazil", "Brazil/Bermuda", "Brazil/AN", "Guadeloupe", "Bahamas"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ let serverConfig = {
|
|||||||
xdrdPassword: ""
|
xdrdPassword: ""
|
||||||
},
|
},
|
||||||
audio: {
|
audio: {
|
||||||
audioDevice: "Microphone (High Definition Audio Device)",
|
audioDevice: null,
|
||||||
audioChannels: 2,
|
audioChannels: 2,
|
||||||
audioBitrate: "128k",
|
audioBitrate: "128k",
|
||||||
startupVolume: "1"
|
startupVolume: "1"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const audio_pipe = new PassThrough();
|
|||||||
module.exports = audio_pipe; // Important
|
module.exports = audio_pipe; // Important
|
||||||
|
|
||||||
const { serverConfig, configExists } = require('../server_config');
|
const { serverConfig, configExists } = require('../server_config');
|
||||||
if (!configExists()) return;
|
if (!configExists() || !serverConfig.audio.audioDevice) return;
|
||||||
|
|
||||||
const { spawn } = require('child_process');
|
const { spawn } = require('child_process');
|
||||||
const { logDebug, logError, logInfo, logWarn, logFfmpeg } = require('../console');
|
const { logDebug, logError, logInfo, logWarn, logFfmpeg } = require('../console');
|
||||||
@@ -20,7 +20,6 @@ function connectMessage(message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
checkFFmpeg().then((ffmpegPath) => {
|
checkFFmpeg().then((ffmpegPath) => {
|
||||||
logInfo(`${consoleLogTitle} Using ${ffmpegPath === 'ffmpeg' ? 'system-installed FFmpeg' : 'ffmpeg-static'}`);
|
logInfo(`${consoleLogTitle} Using ${ffmpegPath === 'ffmpeg' ? 'system-installed FFmpeg' : 'ffmpeg-static'}`);
|
||||||
logInfo(`${consoleLogTitle} Starting audio stream on device: \x1b[35m${serverConfig.audio.audioDevice}\x1b[0m`);
|
logInfo(`${consoleLogTitle} Starting audio stream on device: \x1b[35m${serverConfig.audio.audioDevice}\x1b[0m`);
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ const tunerProfiles = [
|
|||||||
{ value: 254000, label: '254 kHz' },
|
{ value: 254000, label: '254 kHz' },
|
||||||
{ value: 287000, label: '287 kHz' },
|
{ value: 287000, label: '287 kHz' },
|
||||||
{ value: 311000, label: '311 kHz' }
|
{ value: 311000, label: '311 kHz' }
|
||||||
],
|
], details: ''
|
||||||
details: ''
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'xdr',
|
id: 'xdr',
|
||||||
@@ -43,12 +42,11 @@ const tunerProfiles = [
|
|||||||
{ value: 281000, value2: 13, label: '281 kHz' },
|
{ value: 281000, value2: 13, label: '281 kHz' },
|
||||||
{ value: 298000, value2: 14, label: '298 kHz' },
|
{ value: 298000, value2: 14, label: '298 kHz' },
|
||||||
{ value: 309000, value2: 15, label: '309 kHz' }
|
{ value: 309000, value2: 15, label: '309 kHz' }
|
||||||
],
|
], details: ''
|
||||||
details: ''
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'sdr',
|
id: 'sdr',
|
||||||
label: 'SDR (RTL-SDR / AirSpy)',
|
label: 'SDR',
|
||||||
fmBandwidths: [
|
fmBandwidths: [
|
||||||
{ value: 0, label: 'Auto' },
|
{ value: 0, label: 'Auto' },
|
||||||
{ value: 4000, label: '4 kHz' },
|
{ value: 4000, label: '4 kHz' },
|
||||||
@@ -64,20 +62,18 @@ const tunerProfiles = [
|
|||||||
{ value: 175000, label: '175 kHz' },
|
{ value: 175000, label: '175 kHz' },
|
||||||
{ value: 200000, label: '200 kHz' },
|
{ value: 200000, label: '200 kHz' },
|
||||||
{ value: 225000, label: '225 kHz' }
|
{ value: 225000, label: '225 kHz' }
|
||||||
],
|
], details: ''
|
||||||
details: ''
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'si47xx',
|
id: 'si47xx',
|
||||||
label: 'Si47XX (Si4735 / Si4732)',
|
label: 'Si47xx (Si4735 / Si4732)',
|
||||||
fmBandwidths: [
|
fmBandwidths: [
|
||||||
{ value: 0, label: 'Auto' },
|
{ value: 0, label: 'Auto' },
|
||||||
{ value: 40000, label: '40 kHz' },
|
{ value: 40000, label: '40 kHz' },
|
||||||
{ value: 60000, label: '60 kHz' },
|
{ value: 60000, label: '60 kHz' },
|
||||||
{ value: 84000, label: '84 kHz' },
|
{ value: 84000, label: '84 kHz' },
|
||||||
{ value: 110000, label: '110 kHz' }
|
{ value: 110000, label: '110 kHz' }
|
||||||
],
|
], details: ''
|
||||||
details: ''
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -51,9 +51,7 @@ async function connect() {
|
|||||||
const cfgPath = path.resolve(librariesDir, 'frpc.toml');
|
const cfgPath = path.resolve(librariesDir, 'frpc.toml');
|
||||||
await fs.writeFile(cfgPath, cfg);
|
await fs.writeFile(cfgPath, cfg);
|
||||||
const child = spawn(frpcPath, ['-c', cfgPath]);
|
const child = spawn(frpcPath, ['-c', cfgPath]);
|
||||||
process.on('exit', () => {
|
process.on('exit', () => child.kill());
|
||||||
child.kill();
|
|
||||||
});
|
|
||||||
|
|
||||||
const rl = readline.createInterface({
|
const rl = readline.createInterface({
|
||||||
input: child.stdout,
|
input: child.stdout,
|
||||||
|
|||||||
+8
-10
@@ -24,10 +24,16 @@ const sessionMiddleware = session({
|
|||||||
});
|
});
|
||||||
app.use(sessionMiddleware);
|
app.use(sessionMiddleware);
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
|
app.set('view engine', 'ejs');
|
||||||
|
app.set('views', path.join(__dirname, '../views'));
|
||||||
|
app.use('/', endpoints);
|
||||||
|
app.use(express.static(path.join(__dirname, '../web')));
|
||||||
|
|
||||||
const wss = new WebSocket.Server({ noServer: true });
|
const wss = new WebSocket.Server({ noServer: true });
|
||||||
const rdsWss = new WebSocket.Server({ noServer: true });
|
const rdsWss = new WebSocket.Server({ noServer: true });
|
||||||
const pluginsWss = new WebSocket.Server({ noServer: true, perMessageDeflate: true });
|
const pluginsWss = new WebSocket.Server({ noServer: true, perMessageDeflate: true });
|
||||||
|
pluginsApi.registerServerContext({ wss, pluginsWss, httpServer, serverConfig });
|
||||||
|
|
||||||
require('./chat');
|
require('./chat');
|
||||||
|
|
||||||
const tunerLockTracker = new WeakMap();
|
const tunerLockTracker = new WeakMap();
|
||||||
@@ -294,15 +300,7 @@ httpServer.on('upgrade', (request, socket, head) => {
|
|||||||
} else socket.destroy();
|
} else socket.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.set('view engine', 'ejs');
|
const logServerStart = (address) => logInfo(`Web server has started on address \x1b[34mhttp://${address}:${serverConfig.webserver.webserverPort}\x1b[0m.`);
|
||||||
app.set('views', path.join(__dirname, '../views'));
|
|
||||||
app.use('/', endpoints);
|
|
||||||
app.use(express.static(path.join(__dirname, '../web')));
|
|
||||||
pluginsApi.registerServerContext({ wss, pluginsWss, httpServer, serverConfig });
|
|
||||||
|
|
||||||
const logServerStart = (address) => {
|
|
||||||
logInfo(`Web server has started on address \x1b[34mhttp://${address}:${serverConfig.webserver.webserverPort}\x1b[0m.`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const startServer = (address) => {
|
const startServer = (address) => {
|
||||||
httpServer.listen(serverConfig.webserver.webserverPort, address, () => {
|
httpServer.listen(serverConfig.webserver.webserverPort, address, () => {
|
||||||
@@ -313,4 +311,4 @@ const startServer = (address) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = { startServer, wss, rdsWss };
|
module.exports = startServer;
|
||||||
@@ -66,9 +66,9 @@ xdr.on('connection', async (ws, request) => {
|
|||||||
ws.send(`A${initialData.agc}\n`);
|
ws.send(`A${initialData.agc}\n`);
|
||||||
ws.send(`F${initialData.bw}\n`);
|
ws.send(`F${initialData.bw}\n`);
|
||||||
ws.send(`W${initialData.bw}\n`);
|
ws.send(`W${initialData.bw}\n`);
|
||||||
ws.send(`wL${serverConfig.lockToAdmin ? "1" : "0"}\n`); // Don't know how XDR-GTK will handle this, but lets hope it will be fine
|
ws.send(`wL${serverConfig.lockToAdmin ? "1" : "0"}\n`);
|
||||||
ws.send(`wT${serverConfig.publicTuner ? "0" : "1"}\n`); // Again
|
ws.send(`wT${serverConfig.publicTuner ? "0" : "1"}\n`);
|
||||||
ws.send(`OK\n`); // Make sure dumbass clients don't need to wait long for the OK, does the comms really REQUIRE you to start the receiver for you to know you are in?
|
ws.send(`OK\n`); // Make sure dumbass clients don't need to wait long for the OK, does the protocol really REQUIRE you to start the receiver for you to know you are in?
|
||||||
clients.push(ws);
|
clients.push(ws);
|
||||||
|
|
||||||
ws.on('message', (message) => {
|
ws.on('message', (message) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user