mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-07-31 01:09:18 +02:00
change some stuff
This commit is contained in:
+2
-2
@@ -8,7 +8,7 @@ function heartbeat() { // WebSocket heartbeat helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createChatServer(storage) {
|
function createChatServer(storage) {
|
||||||
if (!serverConfig.webserver.chatEnabled) return null;
|
if (!serverConfig.webserver.chatEnabled) return;
|
||||||
|
|
||||||
const chatWss = new WebSocket.Server({ noServer: true });
|
const chatWss = new WebSocket.Server({ noServer: true });
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ function createChatServer(storage) {
|
|||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
});
|
});
|
||||||
|
|
||||||
return chatWss;
|
storage.websocket_delegation.set("/chat", chatWss);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { createChatServer };
|
module.exports = { createChatServer };
|
||||||
+25
-18
@@ -21,15 +21,14 @@ const allPluginConfigs = require('./plugins');
|
|||||||
router.get('/', (req, res) => {
|
router.get('/', (req, res) => {
|
||||||
let requestIp = helpers.getIpAddress(req);
|
let requestIp = helpers.getIpAddress(req);
|
||||||
|
|
||||||
const normalizedIp = requestIp?.replace(/^::ffff:/, '');
|
const ipList = (requestIp || '').split(',').map(ip => ip.trim()).filter(Boolean); // in case there are multiple IPs (proxy), we need to check all of them (No we don't)
|
||||||
const ipList = (normalizedIp || '').split(',').map(ip => ip.trim()).filter(Boolean); // in case there are multiple IPs (proxy), we need to check all of them (No we don't)
|
|
||||||
|
|
||||||
const banEntry = serverConfig.webserver.banlist.find(banEntry => ipList.includes(banEntry[0]));
|
const banEntry = serverConfig.webserver.banlist.find(banEntry => ipList.includes(banEntry[0]));
|
||||||
|
|
||||||
if (banEntry) {
|
if (banEntry) {
|
||||||
const reason = banEntry[3];
|
const reason = banEntry[3];
|
||||||
res.render('403', { reason });
|
res.render('403', { reason });
|
||||||
logInfo(`Web client (${normalizedIp}) is banned`);
|
logInfo(`Web client (${requestIp}) is banned`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@ router.get('/', (req, res) => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
parseAudioDevice((result) => {
|
parseAudioDevice((result) => {
|
||||||
res.render('wizard', {
|
res.render('wizard', { // Magical utility wizard
|
||||||
isAdminAuthenticated: true,
|
isAdminAuthenticated: true,
|
||||||
videoDevices: result.audioDevices,
|
videoDevices: result.audioDevices,
|
||||||
audioDevices: result.videoDevices,
|
audioDevices: result.videoDevices,
|
||||||
@@ -123,7 +122,7 @@ router.get('/wizard', (req, res) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get('/setup', (req, res) => {
|
router.get('/setup', (req, res) => {
|
||||||
let serialPorts;
|
let serialPorts;
|
||||||
function loadConfig() {
|
function loadConfig() {
|
||||||
if (fs.existsSync(configPath)) {
|
if (fs.existsSync(configPath)) {
|
||||||
@@ -173,7 +172,7 @@ router.get('/wizard', (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
router.get('/rds', (req, res) => {
|
router.get('/rds', (req, res) => {
|
||||||
@@ -197,11 +196,11 @@ router.get('/api', (req, res) => {
|
|||||||
|
|
||||||
|
|
||||||
const loginAttempts = {}; // Format: { 'ip': { count: 1, lastAttempt: 1234567890 } }
|
const loginAttempts = {}; // Format: { 'ip': { count: 1, lastAttempt: 1234567890 } }
|
||||||
const MAX_ATTEMPTS = 15;
|
const MAX_ATTEMPTS = 10;
|
||||||
const WINDOW_MS = 15 * 60 * 1000;
|
const WINDOW_MS = 15 * 60 * 1000;
|
||||||
|
|
||||||
const authenticate = (req, res, next) => {
|
const authenticate = (req, res, next) => {
|
||||||
const ip = req.ip || req.connection.remoteAddress;
|
const ip = helpers.getIpAddress(req);
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
if (!loginAttempts[ip]) loginAttempts[ip] = { count: 0, lastAttempt: now };
|
if (!loginAttempts[ip]) loginAttempts[ip] = { count: 0, lastAttempt: now };
|
||||||
@@ -226,6 +225,8 @@ const authenticate = (req, res, next) => {
|
|||||||
loginAttempts[ip].count = 0;
|
loginAttempts[ip].count = 0;
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
|
req.session.isAdminAuthenticated = false;
|
||||||
|
req.session.isTuneAuthenticated = false;
|
||||||
loginAttempts[ip].count += 1;
|
loginAttempts[ip].count += 1;
|
||||||
res.status(403).json({ message: 'Login failed. Wrong password?' });
|
res.status(403).json({ message: 'Login failed. Wrong password?' });
|
||||||
}
|
}
|
||||||
@@ -245,16 +246,23 @@ router.get('/logout', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/kick', (req, res) => {
|
router.get('/kick', (req, res) => {
|
||||||
const ipAddress = req.query.ip;
|
|
||||||
// Terminate the WebSocket connection for the specified IP address
|
// Terminate the WebSocket connection for the specified IP address
|
||||||
if(req.session.isAdminAuthenticated) helpers.kickClient(ipAddress);
|
if(req.session.isAdminAuthenticated) helpers.kickClient(req.query.ip);
|
||||||
|
else {
|
||||||
|
res.status(403);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
res.redirect('/setup');
|
res.redirect('/setup');
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/addToBanlist', (req, res) => {
|
router.get('/addToBanlist', (req, res) => {
|
||||||
if (!req.session.isAdminAuthenticated) return;
|
if (!req.session.isAdminAuthenticated) {
|
||||||
|
res.status(403);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const ipAddress = req.query.ip;
|
const ipAddress = req.query.ip;
|
||||||
const location = 'Unknown';
|
const location = 'Unknown';
|
||||||
const date = Date.now();
|
const date = Date.now();
|
||||||
@@ -271,7 +279,10 @@ router.get('/addToBanlist', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/removeFromBanlist', (req, res) => {
|
router.get('/removeFromBanlist', (req, res) => {
|
||||||
if (!req.session.isAdminAuthenticated) return;
|
if (!req.session.isAdminAuthenticated) {
|
||||||
|
res.status(403);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const ipAddress = req.query.ip;
|
const ipAddress = req.query.ip;
|
||||||
|
|
||||||
@@ -303,9 +314,7 @@ router.post('/saveData', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/getData', (req, res) => {
|
router.get('/getData', (req, res) => {
|
||||||
if (configExists() === false) {
|
if (configExists() === false) res.json(serverConfig);
|
||||||
res.json(serverConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(req.session.isAdminAuthenticated) {
|
if(req.session.isAdminAuthenticated) {
|
||||||
// Check if the file exists
|
// Check if the file exists
|
||||||
@@ -346,9 +355,7 @@ router.get('/static_data', (req, res) => {
|
|||||||
router.get('/server_time', (req, res) => {
|
router.get('/server_time', (req, res) => {
|
||||||
const serverTime = new Date(); // Get current server time
|
const serverTime = new Date(); // Get current server time
|
||||||
const serverTimeUTC = new Date(serverTime.getTime() - (serverTime.getTimezoneOffset() * 60000)); // Adjust server time to UTC
|
const serverTimeUTC = new Date(serverTime.getTime() - (serverTime.getTimezoneOffset() * 60000)); // Adjust server time to UTC
|
||||||
res.json({
|
res.json({ serverTime: serverTimeUTC });
|
||||||
serverTime: serverTimeUTC,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/ping', (req, res) => {
|
router.get('/ping', (req, res) => {
|
||||||
|
|||||||
+10
-15
@@ -30,6 +30,12 @@ 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 });
|
||||||
|
|
||||||
|
storage.websocket_delegation.set("/text", wss);
|
||||||
|
storage.websocket_delegation.set("/audio", audioWss);
|
||||||
|
storage.websocket_delegation.set("/rds", rdsWss);
|
||||||
|
storage.websocket_delegation.set("/rdsspy", rdsWss);
|
||||||
|
storage.websocket_delegation.set("/data_plugins", pluginsWss);
|
||||||
|
|
||||||
// Get all plugins from config and find corresponding server files
|
// Get all plugins from config and find corresponding server files
|
||||||
const plugins = findServerFiles(serverConfig.plugins);
|
const plugins = findServerFiles(serverConfig.plugins);
|
||||||
|
|
||||||
@@ -40,10 +46,7 @@ if (plugins.length > 0) {
|
|||||||
}, 3000); // Initial delay of 3 seconds for the first plugin
|
}, 3000); // Initial delay of 3 seconds for the first plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
const terminalWidth = readline.createInterface({
|
const terminalWidth = readline.createInterface({input: process.stdin, output: process.stdout}).output.columns;
|
||||||
input: process.stdin,
|
|
||||||
output: process.stdout
|
|
||||||
}).output.columns;
|
|
||||||
|
|
||||||
console.log('\x1b[32m' + figlet.textSync("FM-DX Webserver"));
|
console.log('\x1b[32m' + figlet.textSync("FM-DX Webserver"));
|
||||||
console.log('\x1b[32m\x1b[2mby Noobish @ \x1b[4mFMDX.org + KubaPro010\x1b[0m');
|
console.log('\x1b[32m\x1b[2mby Noobish @ \x1b[4mFMDX.org + KubaPro010\x1b[0m');
|
||||||
@@ -66,7 +69,7 @@ const sessionMiddleware = session({
|
|||||||
});
|
});
|
||||||
app.use(sessionMiddleware);
|
app.use(sessionMiddleware);
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
const chatWss = createChatServer(storage);
|
createChatServer(storage);
|
||||||
|
|
||||||
connectToXdrd();
|
connectToXdrd();
|
||||||
connectToSerial();
|
connectToSerial();
|
||||||
@@ -276,7 +279,7 @@ client.on('error', (err) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.set('view engine', 'ejs');
|
app.set('view engine', 'ejs');
|
||||||
app.set('views', path.join(__dirname, '../web'));
|
app.set('views', path.join(__dirname, '../views'));
|
||||||
app.use('/', endpoints);
|
app.use('/', endpoints);
|
||||||
|
|
||||||
const tunerLockTracker = new WeakMap();
|
const tunerLockTracker = new WeakMap();
|
||||||
@@ -530,15 +533,7 @@ httpServer.on('upgrade', (request, socket, head) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var upgradeWss = undefined;
|
const upgradeWss = storage.websocket_delegation.get(request.url);
|
||||||
|
|
||||||
// TODO: make it a map, so plugins can register their url if needed
|
|
||||||
if (request.url === '/text') upgradeWss = wss;
|
|
||||||
else if (request.url === '/audio') upgradeWss = audioWss;
|
|
||||||
else if (request.url === '/chat' && serverConfig.webserver.chatEnabled === true) upgradeWss = chatWss;
|
|
||||||
else if (request.url === '/rds' || request.url === '/rdsspy') upgradeWss = rdsWss;
|
|
||||||
else if (request.url === '/data_plugins') upgradeWss = pluginsWss;
|
|
||||||
|
|
||||||
if(upgradeWss) {
|
if(upgradeWss) {
|
||||||
sessionMiddleware(request, {}, () => {
|
sessionMiddleware(request, {}, () => {
|
||||||
upgradeWss.handleUpgrade(request, socket, head, (ws) => {
|
upgradeWss.handleUpgrade(request, socket, head, (ws) => {
|
||||||
|
|||||||
@@ -232,7 +232,6 @@ class RDSDecoder {
|
|||||||
|
|
||||||
if(d_error > 2) return; // Don't risk it
|
if(d_error > 2) return; // Don't risk it
|
||||||
|
|
||||||
|
|
||||||
const idx = blockB & 0x3;
|
const idx = blockB & 0x3;
|
||||||
|
|
||||||
const last_err = this.ps_errors[idx * 2];
|
const last_err = this.ps_errors[idx * 2];
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
let connectedUsers = [];
|
let connectedUsers = [];
|
||||||
let chatHistory = [];
|
let chatHistory = [];
|
||||||
|
let websocket_delegation = new Map();
|
||||||
|
|
||||||
module.exports = { connectedUsers, chatHistory };
|
module.exports = { connectedUsers, chatHistory, websocket_delegation };
|
||||||
+4
-6
@@ -26,6 +26,7 @@ const WebSocket = require('ws');
|
|||||||
// Get weighting values based on algorithm setting.
|
// Get weighting values based on algorithm setting.
|
||||||
// Defaults = algorithm 1
|
// Defaults = algorithm 1
|
||||||
let weightedErp = 10;
|
let weightedErp = 10;
|
||||||
|
let weightedDist = 400;
|
||||||
const algorithms = [
|
const algorithms = [
|
||||||
[10, 400],
|
[10, 400],
|
||||||
[30, 500],
|
[30, 500],
|
||||||
@@ -287,9 +288,7 @@ async function fetchTx(freq, piCode, rdsPs) {
|
|||||||
|
|
||||||
if (filteredLocations.length > 1) {
|
if (filteredLocations.length > 1) {
|
||||||
// Check for any 10kW+ stations within 700km, and don't Es weight if any found.
|
// Check for any 10kW+ stations within 700km, and don't Es weight if any found.
|
||||||
const tropoPriority = filteredLocations.some(
|
const tropoPriority = filteredLocations.some(loc => loc.distanceKm < 700 && loc.erp >= 10);
|
||||||
loc => loc.distanceKm < 700 && loc.erp >= 10
|
|
||||||
);
|
|
||||||
let esMode = false;
|
let esMode = false;
|
||||||
if (!tropoPriority) esMode = checkEs();
|
if (!tropoPriority) esMode = checkEs();
|
||||||
for (let loc of filteredLocations) loc.score = evaluateStation(loc, esMode);
|
for (let loc of filteredLocations) loc.score = evaluateStation(loc, esMode);
|
||||||
@@ -297,15 +296,14 @@ async function fetchTx(freq, piCode, rdsPs) {
|
|||||||
filteredLocations.sort((a, b) => b.score - a.score);
|
filteredLocations.sort((a, b) => b.score - a.score);
|
||||||
match = filteredLocations[0];
|
match = filteredLocations[0];
|
||||||
// Have a maximum of 10 extra matches and remove any with less than 1/10 of the winning score
|
// Have a maximum of 10 extra matches and remove any with less than 1/10 of the winning score
|
||||||
multiMatches = filteredLocations.slice(1, 11)
|
multiMatches = filteredLocations.slice(1, 11).filter(obj => obj.score >= (match.score / 10));
|
||||||
.filter(obj => obj.score >= (match.score / 10));
|
|
||||||
} else if (filteredLocations.length === 1) {
|
} else if (filteredLocations.length === 1) {
|
||||||
match = filteredLocations[0];
|
match = filteredLocations[0];
|
||||||
match.score = 1;
|
match.score = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
if (match.itu == 'USA') { // Also known as Dumbfuckinstan. they should not go to hell, but hell+ (it is NOT better)
|
if (match.itu == 'USA') { // Also known as Dumbfuckinstan. they should not go to hell, but hell+ (it is NOT better). Jews have anti-semitism, but what do americans have?
|
||||||
const state = getStateForCoordinates(match.lat, match.lon);
|
const state = getStateForCoordinates(match.lat, match.lon);
|
||||||
if (state) match.state = state; // Add state to matchingCity
|
if (state) match.state = state; // Add state to matchingCity
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user