const MAX_LIVE_DURATION = 2 * 60 * 1000; // 2 minuti const UPDATE_INTERVAL = 2000; // 2 secondi // Mappa delle sessioni live attive: chiave = `chatId:botMessageId` const activeSessions = new Map(); /** * Restituisce il markup con i bottoni "Live" e "Chiudi" * @param {Number} userMessageId * @param {String} dataType - tipo di dati (logs, marine, weather, data) */ function liveMarkup(userMessageId, dataType) { return { inline_keyboard: [ [ { text: 'Live', callback_data: `live:${dataType}:${userMessageId}` }, { text: '<- Chiudi', callback_data: `close:${userMessageId}` } ] ] }; } /** * Restituisce il markup con il bottone "Stop" * @param {Number} userMessageId */ function stopMarkup(userMessageId) { return { inline_keyboard: [ [{ text: 'Stop', callback_data: `livestop:${userMessageId}` }] ] }; } /** * Formatta il tempo rimanente in MM:SS */ function formatTime(ms) { const totalSec = Math.ceil(ms / 1000); const min = Math.floor(totalSec / 60); const sec = totalSec % 60; return `${min}:${sec.toString().padStart(2, '0')}`; } /** * Avvia una sessione live * @param {Object} bot - istanza del bot * @param {Number} chatId * @param {Number} botMessageId - ID del messaggio del bot da aggiornare * @param {Number} userMessageId - ID del messaggio dell'utente * @param {Function} getTextFn - funzione che restituisce il testo aggiornato (senza timer) */ function startSession(bot, chatId, botMessageId, userMessageId, getTextFn) { const key = `${chatId}:${botMessageId}`; // Se esiste giĆ  una sessione, non avviarne una nuova if (activeSessions.has(key)) return; const startTime = Date.now(); // Pinna il messaggio bot.pinChatMessage(chatId, botMessageId, { disable_notification: true }).catch(() => {}); const interval = setInterval(async () => { const elapsed = Date.now() - startTime; const remaining = MAX_LIVE_DURATION - elapsed; if (remaining <= 0) { stopSession(bot, chatId, botMessageId, userMessageId); return; } try { const freshText = getTextFn(); const textWithTimer = freshText + `\n_Live: ${formatTime(remaining)} rimanenti_`; await bot.editMessageText(textWithTimer, { chat_id: chatId, message_id: botMessageId, parse_mode: 'Markdown', reply_markup: stopMarkup(userMessageId) }); } catch (error) { // Ignora errori di "message not modified" if (!error.message?.includes('message is not modified')) { console.error('[LIVE] Errore aggiornamento:', error.message); } } }, UPDATE_INTERVAL); activeSessions.set(key, { interval, userMessageId }); } /** * Ferma una sessione live, toglie il pin, elimina i messaggi */ async function stopSession(bot, chatId, botMessageId, userMessageId) { const key = `${chatId}:${botMessageId}`; const session = activeSessions.get(key); if (session) { clearInterval(session.interval); activeSessions.delete(key); } try { await bot.unpinChatMessage(chatId, { message_id: botMessageId }).catch(() => {}); await bot.deleteMessage(chatId, botMessageId); if (userMessageId) { await bot.deleteMessage(chatId, parseInt(userMessageId)); } } catch (error) { console.error('[LIVE] Errore chiusura sessione:', error.message); } } /** * Cerca una sessione attiva dal botMessageId */ function getSession(chatId, botMessageId) { return activeSessions.get(`${chatId}:${botMessageId}`); } module.exports = { liveMarkup, stopMarkup, startSession, stopSession, getSession };