mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-07-29 16:29:19 +02:00
some changes
This commit is contained in:
+11
-18
@@ -24,9 +24,7 @@ function parseMarkdown(parsed) {
|
||||
var linkRegex = /\[([^\]]+)]\(([^)]+)\)/g;
|
||||
parsed = parsed.replace(linkRegex, '<a href="$2" target="_blank">$1</a>');
|
||||
|
||||
parsed = parsed.replace(/\n/g, '<br>');
|
||||
|
||||
return parsed;
|
||||
return parsed.replace(/\n/g, '<br>');
|
||||
}
|
||||
|
||||
function removeMarkdown(parsed) {
|
||||
@@ -42,9 +40,8 @@ function removeMarkdown(parsed) {
|
||||
parsed = parsed.replace(italicRegex, '$1');
|
||||
|
||||
var linkRegex = /\[([^\]]+)]\(([^)]+)\)/g;
|
||||
parsed = parsed.replace(linkRegex, '$1');
|
||||
|
||||
return parsed;
|
||||
return parsed.replace(linkRegex, '$1');
|
||||
}
|
||||
|
||||
function authenticateWithXdrd(client, salt, password) {
|
||||
@@ -95,7 +92,7 @@ let bannedASCache = { data: null, timestamp: 0 };
|
||||
|
||||
function fetchBannedAS(callback) {
|
||||
const now = Date.now();
|
||||
if (bannedASCache.data && now - bannedASCache.timestamp < 10 * 60 * 1000) return callback(null, 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) => {
|
||||
let banData = "";
|
||||
@@ -108,10 +105,10 @@ function fetchBannedAS(callback) {
|
||||
try {
|
||||
const bannedAS = JSON.parse(banData).banned_as || [];
|
||||
bannedASCache = { data: bannedAS, timestamp: now };
|
||||
callback(null, bannedAS);
|
||||
callback(bannedAS);
|
||||
} catch (error) {
|
||||
console.error("Error parsing banned AS list:", error);
|
||||
callback(null, []); // Default to allowing user
|
||||
callback([]); // Default to allowing user
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -120,12 +117,12 @@ function fetchBannedAS(callback) {
|
||||
req.setTimeout(5000, () => {
|
||||
console.error("Error: Request timed out while fetching banned AS list.");
|
||||
req.abort();
|
||||
callback(null, []); // Default to allowing user
|
||||
callback([]); // Default to allowing user
|
||||
});
|
||||
|
||||
req.on("error", (err) => {
|
||||
console.error("Error fetching banned AS list:", err);
|
||||
callback(null, []); // Default to allowing user
|
||||
callback([]); // Default to allowing user
|
||||
});
|
||||
}
|
||||
|
||||
@@ -136,9 +133,7 @@ function processConnection(clientIp, locationInfo, currentUsers, ws, callback) {
|
||||
const connectionTime = new Date().toLocaleString([], options);
|
||||
const normalizedClientIp = clientIp?.replace(/^::ffff:/, '');
|
||||
|
||||
fetchBannedAS((error, bannedAS) => {
|
||||
if (error) console.error("Error fetching banned AS list:", error);
|
||||
|
||||
fetchBannedAS((bannedAS) => {
|
||||
if (bannedAS.some((as) => locationInfo.as?.includes(as))) {
|
||||
const now = Date.now();
|
||||
const lastSeen = recentBannedIps.get(normalizedClientIp) || 0;
|
||||
@@ -151,8 +146,7 @@ function processConnection(clientIp, locationInfo, currentUsers, ws, callback) {
|
||||
return callback("User banned");
|
||||
}
|
||||
|
||||
const userLocation =
|
||||
locationInfo.country === undefined ? "Unknown" : `${locationInfo.city}, ${locationInfo.regionName}, ${locationInfo.countryCode}`;
|
||||
const userLocation = locationInfo.country === undefined ? "Unknown" : `${locationInfo.city}, ${locationInfo.regionName}, ${locationInfo.countryCode}`;
|
||||
|
||||
storage.connectedUsers.push({
|
||||
ip: clientIp,
|
||||
@@ -168,13 +162,12 @@ function processConnection(clientIp, locationInfo, currentUsers, ws, callback) {
|
||||
}
|
||||
|
||||
function formatUptime(uptimeInSeconds) {
|
||||
const secondsInMinute = 60;
|
||||
const secondsInHour = secondsInMinute * 60;
|
||||
const secondsInHour = 60 ** 2;
|
||||
const secondsInDay = secondsInHour * 24;
|
||||
|
||||
const days = Math.floor(uptimeInSeconds / secondsInDay);
|
||||
const hours = Math.floor((uptimeInSeconds % secondsInDay) / secondsInHour);
|
||||
const minutes = Math.floor((uptimeInSeconds % secondsInHour) / secondsInMinute);
|
||||
const minutes = Math.floor((uptimeInSeconds % secondsInHour) / 60);
|
||||
|
||||
return `${days}d ${hours}h ${minutes}m`;
|
||||
}
|
||||
|
||||
+5
-3
@@ -10,7 +10,7 @@ const WebSocket = require('ws');
|
||||
const path = require('path');
|
||||
const net = require('net');
|
||||
const { SerialPort } = require('serialport');
|
||||
const tunnel = require('./tunnel');
|
||||
const tunnel_connect = require('./tunnel');
|
||||
const { createChatServer } = require('./chat');
|
||||
const figlet = require('figlet');
|
||||
|
||||
@@ -70,7 +70,7 @@ const chatWss = createChatServer(storage);
|
||||
|
||||
connectToXdrd();
|
||||
connectToSerial();
|
||||
tunnel.connect();
|
||||
tunnel_connect();
|
||||
|
||||
// Serialport retry code when port is open but communication is lost (additional code in datahandler.js)
|
||||
dataHandler.state.isSerialportRetrying = false;
|
||||
@@ -498,7 +498,7 @@ pluginsWss.on('connection', (ws, request) => {
|
||||
|
||||
ws.on('message', message => {
|
||||
// Anti-spam
|
||||
const command = helpers.antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, '10', 'data_plugins');
|
||||
helpers.antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, '10', 'data_plugins');
|
||||
|
||||
let messageData;
|
||||
|
||||
@@ -531,6 +531,8 @@ httpServer.on('upgrade', (request, socket, head) => {
|
||||
}
|
||||
|
||||
var upgradeWss = undefined;
|
||||
|
||||
// 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;
|
||||
|
||||
+148
-6
@@ -1,5 +1,147 @@
|
||||
const { rdsEccLookup, iso, countries } = require("./rds_country.js")
|
||||
|
||||
function decode_charset(input) {
|
||||
var character = input;
|
||||
switch (character) {
|
||||
case 0x0A: character = ' '; break;
|
||||
case 0x20: character = ' '; break;
|
||||
case 0x5E: character = '―'; break;
|
||||
case 0x5F: character = '_'; break;
|
||||
case 0x60: character = '`'; break;
|
||||
case 0x7E: character = '¯'; break;
|
||||
case 0x7F: character = ' '; break;
|
||||
case 0x80: character = 'á'; break;
|
||||
case 0x81: character = 'à'; break;
|
||||
case 0x82: character = 'é'; break;
|
||||
case 0x83: character = 'è'; break;
|
||||
case 0x84: character = 'í'; break;
|
||||
case 0x85: character = 'ì'; break;
|
||||
case 0x86: character = 'ó'; break;
|
||||
case 0x87: character = 'ò'; break;
|
||||
case 0x88: character = 'ú'; break;
|
||||
case 0x89: character = 'ù'; break;
|
||||
case 0x8A: character = 'Ñ'; break;
|
||||
case 0x8B: character = 'Ç'; break;
|
||||
case 0x8C: character = 'Ş'; break;
|
||||
case 0x8D: character = 'β'; break;
|
||||
case 0x8E: character = '¡'; break;
|
||||
case 0x8F: character = 'IJ'; break;
|
||||
case 0x90: character = 'â'; break;
|
||||
case 0x91: character = 'ä'; break;
|
||||
case 0x92: character = 'ê'; break;
|
||||
case 0x93: character = 'ë'; break;
|
||||
case 0x94: character = 'î'; break;
|
||||
case 0x95: character = 'ï'; break;
|
||||
case 0x96: character = 'ô'; break;
|
||||
case 0x97: character = 'ö'; break;
|
||||
case 0x98: character = 'û'; break;
|
||||
case 0x99: character = 'ü'; break;
|
||||
case 0x9A: character = 'ñ'; break;
|
||||
case 0x9B: character = 'ç'; break;
|
||||
case 0x9C: character = 'ş'; break;
|
||||
case 0x9D: character = 'ǧ'; break;
|
||||
case 0x9E: character = 'ı'; break;
|
||||
case 0x9F: character = 'ij'; break;
|
||||
case 0xA0: character = 'ª'; break;
|
||||
case 0xA1: character = 'α'; break;
|
||||
case 0xA2: character = '©'; break;
|
||||
case 0xA3: character = '‰'; break;
|
||||
case 0xA4: character = 'Ǧ'; break;
|
||||
case 0xA5: character = 'ě'; break;
|
||||
case 0xA6: character = 'ň'; break;
|
||||
case 0xA7: character = 'ő'; break;
|
||||
case 0xA8: character = 'π'; break;
|
||||
case 0xA9: character = '€'; break;
|
||||
case 0xAA: character = '£'; break;
|
||||
case 0xAB: character = '$'; break;
|
||||
case 0xAC: character = '←'; break;
|
||||
case 0xAD: character = '↑'; break;
|
||||
case 0xAE: character = '→'; break;
|
||||
case 0xAF: character = '↓'; break;
|
||||
case 0xB0: character = 'º'; break;
|
||||
case 0xB1: character = '¹'; break;
|
||||
case 0xB2: character = '²'; break;
|
||||
case 0xB3: character = '³'; break;
|
||||
case 0xB4: character = '±'; break;
|
||||
case 0xB5: character = 'İ'; break;
|
||||
case 0xB6: character = 'ń'; break;
|
||||
case 0xB7: character = 'ű'; break;
|
||||
case 0xB8: character = 'µ'; break;
|
||||
case 0xB9: character = '¿'; break;
|
||||
case 0xBA: character = '÷'; break;
|
||||
case 0xBB: character = '°'; break;
|
||||
case 0xBC: character = '¼'; break;
|
||||
case 0xBD: character = '½'; break;
|
||||
case 0xBE: character = '¾'; break;
|
||||
case 0xBF: character = '§'; break;
|
||||
case 0xC0: character = 'Á'; break;
|
||||
case 0xC1: character = 'À'; break;
|
||||
case 0xC2: character = 'É'; break;
|
||||
case 0xC3: character = 'È'; break;
|
||||
case 0xC4: character = 'Í'; break;
|
||||
case 0xC5: character = 'Ì'; break;
|
||||
case 0xC6: character = 'Ó'; break;
|
||||
case 0xC7: character = 'Ò'; break;
|
||||
case 0xC8: character = 'Ú'; break;
|
||||
case 0xC9: character = 'Ù'; break;
|
||||
case 0xCA: character = 'Ř'; break;
|
||||
case 0xCB: character = 'Č'; break;
|
||||
case 0xCC: character = 'Š'; break;
|
||||
case 0xCD: character = 'Ž'; break;
|
||||
case 0xCE: character = 'Ð'; break;
|
||||
case 0xCF: character = 'Ŀ'; break;
|
||||
case 0xD0: character = 'Â'; break;
|
||||
case 0xD1: character = 'Ä'; break;
|
||||
case 0xD2: character = 'Ê'; break;
|
||||
case 0xD3: character = 'Ë'; break;
|
||||
case 0xD4: character = 'Î'; break;
|
||||
case 0xD5: character = 'Ï'; break;
|
||||
case 0xD6: character = 'Ô'; break;
|
||||
case 0xD7: character = 'Ö'; break;
|
||||
case 0xD8: character = 'Û'; break;
|
||||
case 0xD9: character = 'Ü'; break;
|
||||
case 0xDA: character = 'ř'; break;
|
||||
case 0xDB: character = 'č'; break;
|
||||
case 0xDC: character = 'š'; break;
|
||||
case 0xDD: character = 'ž'; break;
|
||||
case 0xDE: character = 'đ'; break;
|
||||
case 0xDF: character = 'ŀ'; break;
|
||||
case 0xE0: character = 'Ã'; break;
|
||||
case 0xE1: character = 'Å'; break;
|
||||
case 0xE2: character = 'Æ'; break;
|
||||
case 0xE3: character = 'Œ'; break;
|
||||
case 0xE4: character = 'ŷ'; break;
|
||||
case 0xE5: character = 'Ý'; break;
|
||||
case 0xE6: character = 'Õ'; break;
|
||||
case 0xE7: character = 'Ø'; break;
|
||||
case 0xE8: character = 'Þ'; break;
|
||||
case 0xE9: character = 'Ŋ'; break;
|
||||
case 0xEA: character = 'Ŕ'; break;
|
||||
case 0xEB: character = 'Ć'; break;
|
||||
case 0xEC: character = 'Ś'; break;
|
||||
case 0xED: character = 'Ź'; break;
|
||||
case 0xEE: character = 'Ŧ'; break;
|
||||
case 0xEF: character = 'ð'; break;
|
||||
case 0xF0: character = 'ã'; break;
|
||||
case 0xF1: character = 'å'; break;
|
||||
case 0xF2: character = 'æ'; break;
|
||||
case 0xF3: character = 'œ'; break;
|
||||
case 0xF4: character = 'ŵ'; break;
|
||||
case 0xF5: character = 'ý'; break;
|
||||
case 0xF6: character = 'õ'; break;
|
||||
case 0xF7: character = 'ø'; break;
|
||||
case 0xF8: character = 'þ'; break;
|
||||
case 0xF9: character = 'ŋ'; break;
|
||||
case 0xFA: character = 'ŕ'; break;
|
||||
case 0xFB: character = 'ć'; break;
|
||||
case 0xFC: character = 'ś'; break;
|
||||
case 0xFD: character = 'ź'; break;
|
||||
case 0xFE: character = 'ŧ'; break;
|
||||
case 0xFF: character = ' '; break;
|
||||
}
|
||||
return character
|
||||
}
|
||||
|
||||
class RDSDecoder {
|
||||
constructor(data) {
|
||||
this.data = data;
|
||||
@@ -91,8 +233,8 @@ class RDSDecoder {
|
||||
|
||||
const idx = blockB & 0x3;
|
||||
|
||||
this.ps[idx * 2] = String.fromCharCode(blockD >> 8);
|
||||
this.ps[idx * 2 + 1] = String.fromCharCode(blockD & 0xFF);
|
||||
this.ps[idx * 2] = String.fromCharCode(decode_charset(blockD >> 8));
|
||||
this.ps[idx * 2 + 1] = String.fromCharCode(decode_charset(blockD & 0xFF));
|
||||
this.ps_errors[idx * 2] = Math.ceil(d_error * (10/3));
|
||||
this.ps_errors[idx * 2 + 1] = Math.ceil(d_error * (10/3));
|
||||
|
||||
@@ -122,15 +264,15 @@ class RDSDecoder {
|
||||
}
|
||||
|
||||
if(c_error < 2 && multiplier !== 2) {
|
||||
this.rt1[idx * multiplier] = String.fromCharCode(blockC >> 8);
|
||||
this.rt1[idx * multiplier + 1] = String.fromCharCode(blockC & 0xFF);
|
||||
this.rt1[idx * multiplier] = String.fromCharCode(decode_charset(blockC >> 8));
|
||||
this.rt1[idx * multiplier + 1] = String.fromCharCode(decode_charset(blockC & 0xFF));
|
||||
this.rt1_errors[idx * multiplier] = Math.ceil(c_error * (10/3));
|
||||
this.rt1_errors[idx * multiplier + 1] = Math.ceil(c_error * (10/3));
|
||||
}
|
||||
if(d_error < 2) {
|
||||
var offset = (multiplier == 2) ? 0 : 2;
|
||||
this.rt1[idx * multiplier + offset] = String.fromCharCode(blockD >> 8);
|
||||
this.rt1[idx * multiplier + offset + 1] = String.fromCharCode(blockD & 0xFF);
|
||||
this.rt1[idx * multiplier + offset] = String.fromCharCode(decode_charset(blockD >> 8));
|
||||
this.rt1[idx * multiplier + offset + 1] = String.fromCharCode(decode_charset(blockD & 0xFF));
|
||||
this.rt1_errors[idx * multiplier + offset] = Math.ceil(d_error * (10/3));
|
||||
this.rt1_errors[idx * multiplier + offset + 1] = Math.ceil(d_error * (10/3));
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ let serverConfig = {
|
||||
audioBitrate: "128k",
|
||||
audioBoost: false,
|
||||
softwareMode: false,
|
||||
startupVolume: "0.95",
|
||||
startupVolume: "1",
|
||||
ffmpeg: false,
|
||||
samplerateOffset: "0"
|
||||
},
|
||||
|
||||
@@ -41,14 +41,14 @@ checkFFmpeg().then((ffmpegPath) => {
|
||||
else inputArgs = ["-f", "alsa", "-i", device];
|
||||
|
||||
return [
|
||||
"-fflags", "+flush_packets",
|
||||
"-fflags", "+nobuffer",
|
||||
"-flags", "low_delay",
|
||||
"-rtbufsize", "4096",
|
||||
"-probesize", "128",
|
||||
"-rtbufsize", "6144",
|
||||
"-probesize", "256",
|
||||
|
||||
...inputArgs,
|
||||
|
||||
"-thread_queue_size", "1536",
|
||||
"-thread_queue_size", "2048",
|
||||
"-ar", String(sampleRate),
|
||||
"-ac", String(channels),
|
||||
|
||||
@@ -62,7 +62,7 @@ checkFFmpeg().then((ffmpegPath) => {
|
||||
"-id3v2_version", "0",
|
||||
|
||||
"-fflags", "+nobuffer",
|
||||
"-flush_packets", "1",
|
||||
// "-flush_packets", "1",
|
||||
|
||||
"pipe:1"
|
||||
];
|
||||
|
||||
+3
-7
@@ -53,10 +53,8 @@ async function connect() {
|
||||
});
|
||||
|
||||
rl.on('line', (line) => {
|
||||
if (line.includes('connect to server error')) {
|
||||
const reason = line.substring(line.indexOf(': ')+2);
|
||||
logError('Failed to connect to tunnel, reason: ' + reason);
|
||||
} else if (line.includes('invalid user or token')) logError('Failed to connect to tunnel, reason: invalid user or token');
|
||||
if (line.includes('connect to server error')) logError('Failed to connect to tunnel, reason: ' + line.substring(line.indexOf(': ')+2));
|
||||
else if (line.includes('invalid user or token')) logError('Failed to connect to tunnel, reason: invalid user or token');
|
||||
else if (line.includes('start proxy success')) logInfo('Tunnel established successfully');
|
||||
else if (line.includes('login to server success')) logInfo('Connection to tunnel server was successful');
|
||||
else logDebug('Tunnel log:', line);
|
||||
@@ -94,6 +92,4 @@ httpPassword = "<%= cfg.httpPassword %>"
|
||||
<% } %>
|
||||
`;
|
||||
|
||||
module.exports = {
|
||||
connect
|
||||
};
|
||||
module.exports = connect;
|
||||
+1
-2
@@ -294,8 +294,7 @@ async function fetchTx(freq, piCode, rdsPs) {
|
||||
filteredLocations.sort((a, b) => b.score - a.score);
|
||||
match = filteredLocations[0];
|
||||
// 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));
|
||||
} else if (filteredLocations.length === 1) {
|
||||
match = filteredLocations[0];
|
||||
|
||||
Reference in New Issue
Block a user