Migra dal codice salvato in locale al codice condiviso

This commit is contained in:
Giuseppe Raffa
2026-01-06 17:36:58 +01:00
parent 8a88c31c75
commit ff1566d36b
30 changed files with 8985 additions and 0 deletions

935
plugin/bot/telegram.core.js Normal file
View File

@@ -0,0 +1,935 @@
/**
* telegram.core.js - Bot Telegram ottimizzato per MEB SignalK
* Gestione utenti, comandi e live updates
*/
const fs = require("fs");
const path = require("path");
const {
encrypt,
decrypt,
generateToken,
generateReadableToken,
encryptLog,
decryptLog,
loadSecureFile,
saveSecureFile
} = require("../tools/crypt");
const TelegramBot = require('node-telegram-bot-api');
function getSK(path) {
if (!app) return null;
const v = app.getSelfPath(path);
return v && v.value !== undefined && v.value !== null ? v.value : null;
}
// ==================== INIZIALIZZAZIONE BOT ====================
const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
let bot = null;
function initBot() {
if (!BOT_TOKEN) {
console.warn("[Telegram] BOT_TOKEN non impostato: bot disabilitato.");
return null;
}
// Riusa istanza esistente se disponibile
if (global.__meb_telegram_bot) {
bot = global.__meb_telegram_bot;
console.log("[Telegram] Riutilizzo istanza bot esistente");
} else {
bot = new TelegramBot(BOT_TOKEN, { polling: true });
global.__meb_telegram_bot = bot;
console.log("[Telegram] Nuova istanza bot creata");
}
// Registra handlers solo una volta
if (!global.__meb_telegram_handlers) {
global.__meb_telegram_handlers = true;
registerHandlers();
console.log("[Telegram] Handlers registrati");
}
return bot;
}
// Inizializza all'import
bot = initBot();
// ==================== CONFIGURAZIONE ====================
const CONFIG = {
filesPerPage: 8,
liveUpdateInterval: 3000,
fileExpirationTime: 10
};
const telegram_users_file = path.join(__dirname, "..", "telegram_users.json");
const logs_references_file = path.join(__dirname, "..", "datasetModels/logs_references.json");
const authorized_admins_file = path.join(__dirname, "..", "authorized_admins.txt");
let app = null;
// Maps per gestione timer e stati
const liveParamIntervals = new Map();
const keyExpirationTimers = new Map();
// ==================== GESTIONE FILE SENSIBILI ====================
function loadAuthorizedAdmins() {
try {
if (!fs.existsSync(authorized_admins_file)) {
return new Set();
}
const content = fs.readFileSync(authorized_admins_file, 'utf8');
const admins = content
.split('\n')
.map(line => line.trim())
.filter(line => line && !line.startsWith('#'));
return new Set(admins);
} catch (error) {
console.error('[Telegram] Errore caricamento admin:', error.message);
return new Set();
}
}
function saveAuthorizedAdmins(admins) {
try {
const adminArray = Array.from(admins);
const content = '# Authorized Admin ChatIDs (one per line)\n' + adminArray.join('\n');
fs.writeFileSync(authorized_admins_file, content, 'utf8');
return true;
} catch (error) {
console.error('[Telegram] Errore salvataggio admin:', error.message);
return false;
}
}
function isAdmin(chatID) {
const admins = loadAuthorizedAdmins();
return admins.has(String(chatID));
}
function loadUsers() {
return loadSecureFile(telegram_users_file, []);
}
function saveUsers(users) {
saveSecureFile(telegram_users_file, users);
}
function loadLogsReferences() {
return loadSecureFile(logs_references_file, { references: [] });
}
function saveLogsReferences(data) {
saveSecureFile(logs_references_file, data);
}
function isAuthenticated(chatID) {
const user = getUserByChatID(chatID);
return user && user.hasLoggedYet;
}
function createNewUser(permissions = ["basic"]) {
const users = loadUsers();
const newUser = {
token: generateReadableToken(24),
chatID: null,
isAuthorized: permissions,
hasLoggedYet: false
};
users.push(newUser);
saveUsers(users);
return newUser;
}
function login(token, chatID) {
const users = loadUsers();
const userIDX = users.findIndex(u => u.token === token);
if (userIDX === -1) {
throw new Error("Token non valido");
}
const user = users[userIDX];
if (user.hasLoggedYet && user.chatID && user.chatID !== String(chatID)) {
throw new Error("Questo token è già associato ad un altro account");
}
if (!user.hasLoggedYet) {
const newToken = generateReadableToken(32);
user.token = newToken;
user.hasLoggedYet = true;
user.chatID = String(chatID);
users[userIDX] = user;
saveUsers(users);
return { ...user, isFirstLogin: true, newToken };
}
user.chatID = String(chatID);
users[userIDX] = user;
saveUsers(users);
return { ...user, isFirstLogin: false };
}
function logout(chatID) {
const users = loadUsers();
const userIDX = users.findIndex(u => u.chatID === String(chatID));
if (userIDX === -1) {
return null;
}
saveUsers(users);
return users[userIDX];
}
function getUserWith(token) {
const users = loadUsers();
return users.find(u => u.token === token);
}
function getUserByChatID(chatID) {
const users = loadUsers();
return users.find(u => u.chatID === String(chatID));
}
async function linkBot(appInstance) {
app = appInstance;
if (!bot) {
console.warn("[MEB TELEGRAM] linkBot chiamato senza TOKEN: ritorno null.");
return null;
}
return bot;
}
function fetchFiles(chatId, page = 0) {
const logDirectory = path.join(__dirname, "..", "datasetModels/saved_datas");
try {
const logsData = loadLogsReferences();
const registeredFiles = new Set((logsData.references || []).map(r => r.name));
const items = fs.readdirSync(logDirectory);
const files = items.filter(item => {
const fullPath = path.join(logDirectory, item);
return fs.statSync(fullPath).isFile() && registeredFiles.has(item);
});
if (files.length === 0) {
bot.sendMessage(chatId, "📂 Non ci sono log salvati.");
return;
}
const sortedFiles = files
.map(file => ({
name: file,
time: fs.statSync(path.join(logDirectory, file)).mtime.getTime()
}))
.sort((a, b) => b.time - a.time)
.map(file => file.name);
const totalPages = Math.ceil(sortedFiles.length / CONFIG.filesPerPage);
let currentPage = page;
if (currentPage < 0) currentPage = 0;
if (currentPage > totalPages - 1) currentPage = totalPages - 1;
const startIdx = currentPage * CONFIG.filesPerPage;
const endIdx = startIdx + CONFIG.filesPerPage;
const pageFiles = sortedFiles.slice(startIdx, endIdx);
const fileButtons = pageFiles.map(file => [
{ text: `📄 ${file}`, callback_data: `request_file_${file}` }
]);
const navigationButtons = [];
if (totalPages > 1) {
const navRow = [];
if (currentPage > 0) {
navRow.push({ text: "←", callback_data: `page_${currentPage - 1}` });
}
navRow.push({ text: `📖 ${currentPage + 1}/${totalPages}`, callback_data: `page_info` });
if (currentPage < totalPages - 1) {
navRow.push({ text: "→", callback_data: `page_${currentPage + 1}` });
}
navigationButtons.push(navRow);
}
navigationButtons.push([{ text: "Annulla", callback_data: "dismiss" }]);
bot.sendMessage(chatId,
`📥 *Logs di Bordo*\n` +
`Ogni file corrisponde ad una *sessione*. Seleziona un file per scaricarlo.\n` +
`⚠️ Avrai solo *10 secondi* per salvare file e chiave.`,
{
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: [...fileButtons, ...navigationButtons] }
}
);
} catch (error) {
bot.sendMessage(chatId, `Errore lettura directory: ${error.message}`);
}
}
function getCurrentPosition() {
if (!app) return null;
const position = app.getSelfPath('navigation.position');
if (!position) return null;
return {
latitude: position.value.latitude,
longitude: position.value.longitude,
};
}
async function send(message) {
if (!bot) return;
const users = loadUsers();
const loggedUsers = users.filter(u => u.hasLoggedYet && u.chatID);
for (const user of loggedUsers) {
try {
await bot.sendMessage(user.chatID, message);
} catch (error) {
console.error(`[Telegram] Send error to ${user.chatID}:`, error.message);
}
}
}
// ==================== RENDER FUNCTIONS ====================
function renderPositionText() {
if (!app) return "❌ App non disponibile";
const pos = app.getSelfPath('navigation.position')?.value;
const sog = getSK('navigation.speedOverGround');
const cog = getSK('navigation.courseOverGroundTrue');
const heading = getSK('navigation.headingTrue');
const lat = pos?.latitude?.toFixed(5) ?? "N/A";
const lon = pos?.longitude?.toFixed(5) ?? "N/A";
const speed = sog != null ? (sog * 1.94384).toFixed(1) : "N/A"; // m/s to knots
const course = cog != null ? (cog * 180 / Math.PI).toFixed(0) : "N/A"; // rad to deg
const headingDeg = heading != null ? (heading * 180 / Math.PI).toFixed(0) : "N/A";
return `📍 *Posizione & Velocità*\n\n` +
`Latitudine: \`${lat}\`\n` +
`Longitudine: \`${lon}\`\n` +
`SOG: ${speed} kn\n` +
`COG: ${course}°\n` +
`Heading: ${headingDeg}°`;
}
function renderWindText() {
const speed = getSK('meb.wind.speed');
const direction = getSK('meb.wind.direction');
return `🌬️ *Vento*\n\n` +
`Velocità: ${speed} km/h\n` +
`Direzione: ${direction}°\n`;
}
function renderWavesText() {
const height = getSK('meb.waves.height');
const period = getSK('meb.waves.period');
const dir = getSK('meb.waves.direction');
return `🌊 *Onde*\n\n` +
`Altezza: ${height} m\n` +
`Periodo: ${period} s\n` +
`Direzione: ${dir}°`;
}
function renderForecastsText() {
const temp = getSK('meb.temperature');
const humidity = getSK('meb.humidity');
const pressure = getSK('meb.pressure');
const rain = getSK('meb.precipitation');
return `⛅️ *Previsioni Meteo*\n\n` +
`Temperatura: ${temp} °C\n` +
`Umidità: ${humidity} %\n` +
`Pressione: ${pressure} hPa\n`;
}
function renderBatteriesText() {
const voltage = getSK('electrical.batteries.traction.voltage');
const current = getSK('electrical.batteries.traction.current');
const soc = getSK('electrical.batteries.traction.stateOfCharge');
const power = getSK('electrical.batteries.traction.power');
return `🔋 *Batterie*\n\n` +
`Tensione: ${voltage?.toFixed(1) ?? "N/A"} V\n` +
`Corrente: ${current?.toFixed(1) ?? "N/A"} A\n` +
`SOC: ${soc != null ? (soc * 100).toFixed(0) : "N/A"} %\n` +
`Potenza: ${power?.toFixed(0) ?? "N/A"} W`;
}
function renderDashboardText() {
const posText = renderPositionText()
const windText = renderWindText()
const wavesText = renderWavesText()
const forecastText = renderForecastsText()
const battText = renderBatteriesText()
return `📊 *Dashboard Completa*\n` +
`\n${posText}\n\n` +
`\n${forecastText}\n\n` +
`\n${windText}\n\n` +
`\n${wavesText}\n\n` +
`\n${battText}`;
}
// ==================== REGISTRAZIONE HANDLERS ====================
function registerHandlers() {
if (!bot) return;
// Handler: /start
bot.onText(/\/start/, (msg) => {
const chatId = msg.chat.id;
if (isAuthenticated(chatId)) {
const menu = {
keyboard: [
[{ text: "📊 Dashboard" }],
[{ text: "Parametri di Bordo" }],
[{ text: "File di Logs" }],
[{ text: "Genera un nuovo log" }],
[{ text: "Stato dei Log" }]
],
resize_keyboard: true,
one_time_keyboard: false
};
bot.sendMessage(chatId,
"Benvenuto nel Data Console.\n" +
"• Visualizza i dati del computer di bordo\n" +
"• Ricevi aggiornamenti su parametri a scelta\n" +
"• Scarica i file di log della barca",
{ parse_mode: 'Markdown', reply_markup: menu }
);
} else {
bot.sendMessage(chatId,
"Benvenuto nel MEB Data Console!\n" +
"Per accedere ai dati è necessario un token di accesso.",
{ parse_mode: 'Markdown' }
);
bot.sendMessage(chatId, "👤 Login", {
reply_markup: {
inline_keyboard: [
[{ text: "❓ Come ottengo un token", callback_data: "token_login_question" }],
[{ text: "🔑 Ho un token", callback_data: "token_ready" }]
]
},
parse_mode: 'Markdown'
});
}
});
// Menu testuale
bot.onText(/📊 Dashboard/, (msg) => {
const chatId = msg.chat.id;
if (!isAuthenticated(chatId)) {
bot.sendMessage(chatId, "Effettua prima il login con /login <token>");
return;
}
const dashboardMsg = renderDashboardText();
bot.sendMessage(chatId, dashboardMsg, {
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: "🔄 Aggiorna", callback_data: "refresh_dashboard" }],
[{ text: "📡 Live (3s)", callback_data: "live_dashboard" }]
]
}
});
});
bot.onText(/File di Logs/, (msg) => {
const chatId = msg.chat.id;
if (!isAuthenticated(chatId)) {
bot.sendMessage(chatId, "Effettua prima il login con /login <token>");
return;
}
fetchFiles(chatId, 0);
});
bot.onText(/Parametri di Bordo/, (msg) => {
const chatId = msg.chat.id;
if (!isAuthenticated(chatId)) {
bot.sendMessage(chatId, "Effettua il login con /login <token>");
return;
}
bot.sendMessage(chatId, "*Parametri di Bordo*\nQui potrai visualizzare i parametri attuali del computer di bordo. Scegli il parametro che vuoi visualizzare dal menu qui sotto.", {
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: "📊 Dashboard", callback_data: "get_dashboard" }],
[{ text: "⛅️ Meteo", callback_data: "get_forecasts" }],
[{ text: "📍 Posizione", callback_data: "get_position" }],
[{ text: "🌬️ Vento", callback_data: "get_wind" }],
[{ text: "🌊 Onde", callback_data: "get_waves" }],
[{ text: "🔋 Batterie", callback_data: "get_batteries" }],
[{ text: "Annulla", callback_data: "dismiss" }]
]
}
});
});
// Login
bot.onText(/\/login\s+(.+)/, (msg, match) => {
const chatID = msg.chat.id;
const token = (match && match[1] || "").trim();
if (!token) {
bot.sendMessage(chatID, "Inserisci il token: /login <token>");
return;
}
try {
const result = login(token, chatID);
if (!result) {
bot.sendMessage(chatID, "Token non valido.");
return;
}
if (result.isFirstLogin) {
bot.sendMessage(chatID,
`*Primo accesso completato!*\n\n` +
`Il tuo nuovo token permanente:\n\`${result.newToken}\`\n\n` +
`Salvalo! Non potrà essere usato da altri account.`,
{ parse_mode: 'Markdown' }
);
} else {
bot.sendMessage(chatID, "✅ Login effettuato!");
}
const menu = {
keyboard: [
[{ text: "📊 Dashboard" }],
[{ text: "Parametri di Bordo" }],
[{ text: "File di Logs" }],
[{ text: "Genera un nuovo log" }],
[{ text: "Stato dei Log" }]
],
resize_keyboard: true
};
bot.sendMessage(chatID, "Menu principale:", { reply_markup: menu });
} catch (error) {
bot.sendMessage(chatID, `${error.message}`);
}
});
bot.onText(/\/logout/, (msg) => {
const chatID = msg.chat.id;
const user = logout(chatID);
if (!user) {
bot.sendMessage(chatID, "Non sei loggato.");
return;
}
bot.sendMessage(chatID, "Logout effettuato. Usa /login <token> per rientrare.");
});
// Admin commands
bot.onText(/\/newuser(?:\s+(.*))?/, (msg, match) => {
const chatID = msg.chat.id;
if (!isAdmin(chatID)) {
bot.sendMessage(chatID, "⛔ Non autorizzato.");
return;
}
const permissionsArg = (match && match[1] || "").trim();
const permissions = permissionsArg
? permissionsArg.split(',').map(p => p.trim()).filter(p => p)
: ["basic"];
try {
const newUser = createNewUser(permissions);
bot.sendMessage(chatID,
`✅ *Nuovo utente creato*\n\nToken: \`${newUser.token}\``,
{ parse_mode: 'Markdown' }
);
} catch (error) {
bot.sendMessage(chatID, `${error.message}`);
}
});
bot.onText(/\/addadmin\s+(\d+)/, (msg, match) => {
const chatID = msg.chat.id;
const newAdminID = match && match[1];
if (!isAdmin(chatID)) {
bot.sendMessage(chatID, "⛔ Non autorizzato.");
return;
}
const admins = loadAuthorizedAdmins();
if (admins.has(newAdminID)) {
bot.sendMessage(chatID, "Già admin.");
return;
}
admins.add(newAdminID);
saveAuthorizedAdmins(admins);
bot.sendMessage(chatID, `✅ Admin \`${newAdminID}\` aggiunto.`, { parse_mode: 'Markdown' });
});
bot.onText(/\/removeadmin\s+(\d+)/, (msg, match) => {
const chatID = msg.chat.id;
const adminToRemove = match && match[1];
if (!isAdmin(chatID)) {
bot.sendMessage(chatID, "⛔ Non autorizzato.");
return;
}
if (adminToRemove === String(chatID)) {
bot.sendMessage(chatID, "Non puoi rimuovere te stesso.");
return;
}
const admins = loadAuthorizedAdmins();
if (!admins.has(adminToRemove)) {
bot.sendMessage(chatID, "Non è admin.");
return;
}
admins.delete(adminToRemove);
saveAuthorizedAdmins(admins);
bot.sendMessage(chatID, `✅ Admin \`${adminToRemove}\` rimosso.`, { parse_mode: 'Markdown' });
});
bot.onText(/\/listusers/, (msg) => {
const chatID = msg.chat.id;
if (!isAdmin(chatID)) {
bot.sendMessage(chatID, "⛔ Non autorizzato.");
return;
}
const users = loadUsers();
if (users.length === 0) {
bot.sendMessage(chatID, "Nessun utente.");
return;
}
let message = `👥 *Utenti:* ${users.length}\n\n`;
users.forEach((user, idx) => {
const status = user.hasLoggedYet ? '✅' : '⏳';
message += `${idx + 1}. ${status} \`${user.chatID || 'N/A'}\`\n`;
});
bot.sendMessage(chatID, message, { parse_mode: 'Markdown' });
});
bot.onText(/\/mychatid/, (msg) => {
bot.sendMessage(msg.chat.id, `ChatID: \`${msg.chat.id}\``, { parse_mode: 'Markdown' });
});
// Interval control
bot.onText(/\/changei\s+(log|api)\s+(\d+)/, (msg, match) => {
const chatID = msg.chat.id;
if (!isAdmin(chatID)) {
bot.sendMessage(chatID, "⛔ Non autorizzato.");
return;
}
const type = match[1];
const seconds = parseInt(match[2], 10);
if (isNaN(seconds) || seconds < 1) {
bot.sendMessage(chatID, "❌ Secondi non validi (min 1).");
return;
}
const newIntervalMs = seconds * 1000;
// Debug: verifica stato app
if (!app) {
bot.sendMessage(chatID, "❌ App non inizializzata. Riprova tra qualche secondo.");
console.error('[Telegram] app è null in change_interval');
return;
}
if (!app.intervalControl) {
bot.sendMessage(chatID, "❌ Sistema intervalControl non disponibile. Il plugin potrebbe non essere ancora avviato.");
console.error('[Telegram] app.intervalControl non esiste');
return;
}
try {
const result = app.intervalControl.updateInterval(type, newIntervalMs);
if (result) {
const typeLabel = type === 'log' ? 'Log recording' : 'OpenMeteo API';
bot.sendMessage(chatID,
`✅ *${typeLabel}* aggiornato a *${seconds}s*`,
{ parse_mode: 'Markdown' }
);
} else {
bot.sendMessage(chatID, "❌ Tipo non valido. Usa: `log` o `api`", { parse_mode: 'Markdown' });
}
} catch (error) {
console.error('[Telegram] Errore change_interval:', error);
bot.sendMessage(chatID, `❌ Errore: ${error.message}`);
}
});
bot.onText(/\/intervals/, (msg) => {
const chatID = msg.chat.id;
if (!isAdmin(chatID)) {
bot.sendMessage(chatID, "⛔ Non autorizzato.");
return;
}
if (!app) {
bot.sendMessage(chatID, "❌ App non inizializzata.");
return;
}
if (!app.intervalControl) {
bot.sendMessage(chatID, "❌ Sistema intervalControl non disponibile.");
return;
}
try {
const intervals = app.intervalControl.getIntervals();
bot.sendMessage(chatID,
`⏱️ *Intervalli Attuali*\n\n` +
`📝 Log: *${intervals.log_interval / 1000}s*\n` +
`🌤️ API: *${intervals.openmeteo_interval / 1000}s*\n\n` +
`Per modificare:\n` +
`\`/changei log <sec>\`\n` +
`\`/changei api <sec>\``,
{ parse_mode: 'Markdown' }
);
} catch (error) {
console.error('[Telegram] Errore intervals:', error);
bot.sendMessage(chatID, `❌ Errore: ${error.message}`);
}
});
// Callback query handler
bot.on('callback_query', async (query) => {
const chatId = query.message.chat.id;
const messageId = query.message.message_id;
const data = query.data;
await bot.answerCallbackQuery(query.id);
if (!isAuthenticated(chatId) && !['token_login_question', 'token_ready'].includes(data)) {
bot.sendMessage(chatId, "Effettua prima il login.");
return;
}
switch (data) {
case 'dismiss':
bot.deleteMessage(chatId, messageId).catch(() => {});
break;
case 'token_login_question':
bot.sendMessage(chatId,
"Per ottenere un token, contatta un amministratore del sistema."
);
break;
case 'token_ready':
bot.sendMessage(chatId, "Usa: /login <token>");
break;
case 'get_dashboard':
case 'refresh_dashboard':
bot.editMessageText(renderDashboardText(), {
chat_id: chatId,
message_id: messageId,
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: "🔄 Aggiorna", callback_data: "refresh_dashboard" }],
[{ text: "📡 Live (3s)", callback_data: "live_dashboard" }],
[{ text: "⏹️ Chiudi", callback_data: "dismiss" }]
]
}
}).catch(() => {});
break;
case 'live_dashboard':
// Ferma eventuali live precedenti
if (liveParamIntervals.has(chatId)) {
clearInterval(liveParamIntervals.get(chatId));
}
const interval = setInterval(() => {
bot.editMessageText(renderDashboardText(), {
chat_id: chatId,
message_id: messageId,
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: "⏹️ Stop Live", callback_data: "stop_live" }]
]
}
}).catch(() => {
clearInterval(interval);
liveParamIntervals.delete(chatId);
});
}, CONFIG.liveUpdateInterval);
liveParamIntervals.set(chatId, interval);
break;
case 'stop_live':
if (liveParamIntervals.has(chatId)) {
clearInterval(liveParamIntervals.get(chatId));
liveParamIntervals.delete(chatId);
}
bot.editMessageText(renderDashboardText(), {
chat_id: chatId,
message_id: messageId,
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: "🔄 Aggiorna", callback_data: "refresh_dashboard" }],
[{ text: "📡 Live (3s)", callback_data: "live_dashboard" }],
[{ text: "⏹️ Chiudi", callback_data: "dismiss" }]
]
}
}).catch(() => {});
break;
case 'get_position':
bot.editMessageText(renderPositionText(), {
chat_id: chatId,
message_id: messageId,
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: [[{ text: "← Indietro", callback_data: "back_to_params" }]] }
}).catch(() => {});
break;
case 'get_wind':
bot.editMessageText(renderWindText(), {
chat_id: chatId,
message_id: messageId,
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: [[{ text: "← Indietro", callback_data: "back_to_params" }]] }
}).catch(() => {});
break;
case 'get_waves':
bot.editMessageText(renderWavesText(), {
chat_id: chatId,
message_id: messageId,
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: [[{ text: "← Indietro", callback_data: "back_to_params" }]] }
}).catch(() => {});
break;
case 'get_forecasts':
bot.editMessageText(renderForecastsText(), {
chat_id: chatId,
message_id: messageId,
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: [[{ text: "← Indietro", callback_data: "back_to_params" }]] }
}).catch(() => {});
break;
case 'get_batteries':
bot.editMessageText(renderBatteriesText(), {
chat_id: chatId,
message_id: messageId,
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: [[{ text: "← Indietro", callback_data: "back_to_params" }]] }
}).catch(() => {});
break;
case 'back_to_params':
bot.editMessageText("*Parametri di Bordo*\nQui potrai visualizzare i parametri attuali del computer di bordo. Scegli il parametro che vuoi visualizzare dal menu qui sotto.", {
chat_id: chatId,
message_id: messageId,
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: "📊 Dashboard Completa", callback_data: "get_dashboard" }],
[{ text: "⛅️ Meteo", callback_data: "get_forecasts" }],
[{ text: "📍 Posizione", callback_data: "get_position" }],
[{ text: "🌬️ Vento", callback_data: "get_wind" }],
[{ text: "🌊 Onde", callback_data: "get_waves" }],
[{ text: "🔋 Batterie", callback_data: "get_batteries" }],
[{ text: "Annulla", callback_data: "dismiss" }]
]
}
}).catch(() => {});
break;
default:
// Gestione paginazione file
if (data.startsWith('page_')) {
const page = parseInt(data.replace('page_', ''), 10);
if (!isNaN(page)) {
bot.deleteMessage(chatId, messageId).catch(() => {});
fetchFiles(chatId, page);
}
}
// Gestione richiesta file
else if (data.startsWith('request_file_')) {
const fileName = data.replace('request_file_', '');
const filePath = path.join(__dirname, "..", "datasetModels/saved_datas", fileName);
if (fs.existsSync(filePath)) {
const logsData = loadLogsReferences();
const fileRef = (logsData.references || []).find(r => r.name === fileName);
const key = fileRef?.key || "Chiave non trovata";
try {
const fileMsg = await bot.sendDocument(chatId, filePath, {
caption: `🔑 Chiave: \`${key}\`\n⚠️ Questo messaggio verrà eliminato tra 10 secondi.`,
parse_mode: 'Markdown'
});
// Elimina dopo 10 secondi
setTimeout(() => {
bot.deleteMessage(chatId, fileMsg.message_id).catch(() => {});
}, CONFIG.fileExpirationTime * 1000);
} catch (error) {
bot.sendMessage(chatId, `❌ Errore invio file: ${error.message}`);
}
} else {
bot.sendMessage(chatId, "❌ File non trovato.");
}
bot.deleteMessage(chatId, messageId).catch(() => {});
}
break;
}
});
} // Fine registerHandlers
module.exports = {
linkBot,
send,
loadUsers,
saveUsers,
getUserByChatID,
isAuthenticated,
isAdmin
};

View File

@@ -0,0 +1,24 @@
[
{
"token": "eccef678c73b825fd2af7a3ce76603aeef68c6280862f1c2",
"hasLogged": true,
"chatId": 5868470977,
"chatID": 5868470977
},
{
"token": "5A6MjMd6amSGgZbk6PZ9T9sdJKjWwbHM",
"chatID": "5868470977",
"isAuthorized": [
"basic"
],
"hasLoggedYet": true
},
{
"token": "af9aBSY9taEedmZXFhy3Fhns3VHtXSxT",
"chatID": "838642766",
"isAuthorized": [
"basic"
],
"hasLoggedYet": true
}
]