// In Minuten (1 Minute) const CHECK_INTERVAL_MINUTES = 1; const HISTORY_RETENTION_DAYS = 7; // Funktion, um einen einzelnen Dienst zu prüfen und die Antwortzeit zu messen async function checkService(service) { const startTime = performance.now(); try { const response = await fetch(service.adresse, { method: 'HEAD', mode: 'no-cors', cache: 'no-cache' }); const endTime = performance.now(); const responseTime = Math.round(endTime - startTime); return { status: 'online', responseTime }; } catch (error) { return { status: 'offline', responseTime: null }; } } // Funktion, um Verlaufsdaten zu aktualisieren async function updateHistory(serviceName, status) { const data = await chrome.storage.local.get({ history: {} }); const history = data.history; const now = new Date(); const hourKey = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}-${String(now.getHours()).padStart(2, '0')}`; if (!history[serviceName]) history[serviceName] = {}; if (!history[serviceName][hourKey]) history[serviceName][hourKey] = { checks: 0, up_checks: 0 }; history[serviceName][hourKey].checks++; if (status === 'online') history[serviceName][hourKey].up_checks++; await chrome.storage.local.set({ history }); } // Funktion, um alte Verlaufsdaten zu löschen async function cleanupHistory() { const data = await chrome.storage.local.get({ history: {} }); const history = data.history; const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - HISTORY_RETENTION_DAYS); const cutoffHourKey = `${cutoffDate.getFullYear()}-${String(cutoffDate.getMonth() + 1).padStart(2, '0')}-${String(cutoffDate.getDate()).padStart(2, '0')}-${String(cutoffDate.getHours()).padStart(2, '0')}`; for (const serviceName in history) { for (const hourKey in history[serviceName]) { if (hourKey < cutoffHourKey) delete history[serviceName][hourKey]; } if (Object.keys(history[serviceName]).length === 0) delete history[serviceName]; } await chrome.storage.local.set({ history }); } // Funktion zum Senden einer Discord-Benachrichtigung async function sendDiscordNotification(service, status, responseTime = null) { const settings = await chrome.storage.sync.get({ discordWebhookUrl: '' }); if (!settings.discordWebhookUrl) return; // Kein Webhook konfiguriert const isOnline = status === 'online'; const embed = { title: `Status-Update: ${service.name}`, url: service.adresse, description: isOnline ? '✅ Der Server ist wieder online.' : '❌ Der Server ist nicht erreichbar.', color: isOnline ? 0x31A24C : 0xE4606D, // Grün / Rot timestamp: new Date().toISOString(), fields: [ { name: 'Status', value: status.toUpperCase(), inline: true }, { name: 'Adresse', value: service.adresse, inline: true } ] }; if (isOnline && responseTime !== null) { embed.fields.push({ name: 'Antwortzeit', value: `${responseTime} ms`, inline: true }); } const payload = { username: 'Uptime Monitor', embeds: [embed] }; try { const response = await fetch(settings.discordWebhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { console.error('Discord-Webhook fehlgeschlagen:', response.statusText, await response.text()); } } catch (error) { console.error('Fehler beim Senden der Discord-Benachrichtigung:', error); } } // NEU: Funktion zum Senden einer Telegram-Benachrichtigung async function sendTelegramNotification(service, status, responseTime = null) { const settings = await chrome.storage.sync.get({ telegramBotToken: '', telegramChatId: '' }); if (!settings.telegramBotToken || !settings.telegramChatId) return; // Nicht konfiguriert const isOnline = status === 'online'; const emoji = isOnline ? '✅' : '❌'; let message = `${emoji} *${service.name}*\nStatus: ${status.toUpperCase()}\nAdresse: ${service.adresse}`; if (isOnline && responseTime !== null) { message += `\nAntwortzeit: ${responseTime} ms`; } const url = `https://api.telegram.org/bot${settings.telegramBotToken}/sendMessage`; const payload = { chat_id: settings.telegramChatId, text: message, parse_mode: 'Markdown' // Für Markdown-Formatierung }; try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { const errorData = await response.json(); console.error('Telegram-Bot API fehlgeschlagen:', response.statusText, errorData); } } catch (error) { console.error('Fehler beim Senden der Telegram-Benachrichtigung:', error); } } // MODIFIZIERT: Funktion, um alle Dienste zu prüfen und Benachrichtigungen zu senden async function checkAllServices() { const data = await chrome.storage.sync.get({ services: [], notifyOnline: false }); const services = data.services; const notifyOnline = data.notifyOnline; if (services.length === 0) return; const lastStatusData = await chrome.storage.local.get({ serviceStatus: {} }); const lastStatus = lastStatusData.serviceStatus; for (const service of services) { const currentResult = await checkService(service); const previousResult = lastStatus[service.name]; lastStatus[service.name] = currentResult; // Benachrichtigung für Offline-Wechsel if (previousResult?.status === 'online' && currentResult.status === 'offline') { chrome.notifications.create({ type: 'basic', iconUrl: 'icons/notification_warning.png', title: `Server "${service.name}" ist offline`, message: 'Der Dienst antwortet nicht mehr.', contextMessage: `Adresse: ${service.adresse}`, priority: 1, isClickable: true }); await sendDiscordNotification(service, 'offline'); await sendTelegramNotification(service, 'offline'); // NEU } // Benachrichtigung für Online-Wechsel (wenn aktiviert) if (notifyOnline && previousResult?.status === 'offline' && currentResult.status === 'online') { chrome.notifications.create({ type: 'basic', iconUrl: 'icons/notification_warning.png', title: `Server "${service.name}" ist wieder online!`, message: 'Der Dienst ist wieder erreichbar.', contextMessage: `Adresse: ${service.adresse}`, priority: 0, isClickable: true }); await sendDiscordNotification(service, 'online', currentResult.responseTime); await sendTelegramNotification(service, 'online', currentResult.responseTime); } // Verlaufsdaten aktualisieren await updateHistory(service.name, currentResult.status); } await chrome.storage.local.set({ serviceStatus: lastStatus }); } // Alarm und Setup-Logik async function setupAlarm() { const data = await chrome.storage.sync.get({ checkInterval: 1 }); const intervalMinutes = data.checkInterval; await chrome.alarms.clear('uptimeCheck'); chrome.alarms.create('uptimeCheck', { periodInMinutes: intervalMinutes }); } chrome.runtime.onInstalled.addListener(() => { setupAlarm(); }); chrome.runtime.onStartup.addListener(() => { setupAlarm(); }); chrome.alarms.onAlarm.addListener((alarm) => { if (alarm.name === 'uptimeCheck') checkAllServices(); }); // Nachrichtensystem für Einstellungen chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.type === 'updateInterval') { setupAlarm().then(() => sendResponse({ status: 'ok' })); return true; } if (message.type === 'cleanupHistory') { cleanupHistory().then(() => sendResponse({ status: 'ok' })); return true; } }); // Benachrichtigungs-Listener chrome.notifications.onClicked.addListener((notificationId) => { chrome.action.openPopup(); chrome.notifications.clear(notificationId); });