// background.js const POLL_INTERVAL_SEC = 2; // Alarm erstellen chrome.runtime.onInstalled.addListener(() => { chrome.alarms.create('periodicRefresh', { periodInMinutes: POLL_INTERVAL_SEC / 60 }); }); chrome.alarms.onAlarm.addListener((alarm) => { if (alarm.name === 'periodicRefresh') { refreshAllServers().catch(console.error); } }); // Message Listener chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg && msg.cmd === 'refreshNow') { refreshAllServers() .then(statuses => sendResponse({ ok: true, statuses })) .catch(err => sendResponse({ ok: false, error: String(err) })); return true; } }); async function refreshAllServers() { const obj = await chrome.storage.local.get('servers'); const servers = obj.servers || []; if (servers.length === 0) { await chrome.storage.local.set({ serverStatuses: {} }); chrome.action.setBadgeText({ text: '' }); return {}; } const results = {}; let totalOnlinePlayers = 0; const tasks = servers.map(async (srv) => { try { const data = await fetchServerStatus(srv, 2000); results[srv.id] = { ok: true, server: srv, fetched: Date.now(), data }; if (data) { if (Array.isArray(data.players)) totalOnlinePlayers += data.players.length; else if (typeof data.players === 'number') totalOnlinePlayers += data.players; } } catch (e) { results[srv.id] = { ok: false, server: srv, fetched: Date.now(), error: String(e) }; } }); await Promise.all(tasks); await chrome.storage.local.set({ serverStatuses: results }); const badgeText = totalOnlinePlayers > 0 ? String(totalOnlinePlayers) : ''; chrome.action.setBadgeText({ text: badgeText }); chrome.action.setBadgeBackgroundColor({ color: '#3b82f6' }); return results; } async function fetchServerStatus(server, timeoutMs = 2000) { let serverObj = typeof server === 'string' ? { id: 'legacy', url: server } : server; let fetchUrl = serverObj.url || ''; // 1. Direkte URL-Abfrage if (fetchUrl) { if (!/^https?:\/\//i.test(fetchUrl)) fetchUrl = 'http://' + fetchUrl; try { const startTime = performance.now(); const controller = new AbortController(); const id = setTimeout(() => controller.abort(), timeoutMs); const resp = await fetch(fetchUrl, { method: 'GET', signal: controller.signal }); clearTimeout(id); const endTime = performance.now(); const latency = Math.round(endTime - startTime); if (resp.ok) { let text = await resp.text(); const lastBrace = text.lastIndexOf('}'); if (lastBrace !== -1) text = text.substring(0, lastBrace + 1); text = text.trim(); try { const parsed = JSON.parse(text); if (parsed && (typeof parsed.online !== 'undefined' || Array.isArray(parsed.players) || parsed.version)) { parsed.ping = latency; // Ping hinzufügen return parsed; } } catch (e) { // Parsing fehlgeschlagen → Fallback-Objekt mit Ping return { online: false, players: [], max_players: 0, version: 'unknown', motd: '', ping: latency > timeoutMs ? null : latency // bei Timeout kein sinnvoller Ping }; } } // HTTP nicht ok → Offline mit gemessener Latenz (falls unter Timeout) return { online: false, players: [], max_players: 0, version: 'unknown', motd: '', ping: latency > timeoutMs ? null : latency }; } catch (e) { // Timeout oder Netzwerkfehler return { online: false, players: [], max_players: 0, version: 'unknown', motd: '', ping: null }; } } // 2. WordPress AJAX-Abfrage const wpSite = serverObj.wpSite ? String(serverObj.wpSite).replace(/\/$/, '') : null; const wpServerId = serverObj.wpServerId ? String(serverObj.wpServerId) : null; if (wpSite && wpServerId) { try { const ajaxUrl = wpSite + '/wp-admin/admin-ajax.php'; const body = 'action=mcss_fetch&server_id=' + encodeURIComponent(wpServerId); const startTime = performance.now(); const controller2 = new AbortController(); const id2 = setTimeout(() => controller2.abort(), timeoutMs); const resp2 = await fetch(ajaxUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body, signal: controller2.signal }); clearTimeout(id2); const endTime = performance.now(); const latency = Math.round(endTime - startTime); if (!resp2.ok) throw new Error('WP AJAX HTTP ' + resp2.status); const json = await resp2.json(); if (json && (typeof json.online !== 'undefined' || Array.isArray(json.players) || json.version)) { json.ping = latency; // Ping hinzufügen return json; } // JSON nicht im erwarteten Format return { online: false, players: [], max_players: 0, version: 'unknown', motd: '', ping: latency > timeoutMs ? null : latency }; } catch (e) { return { online: false, players: [], max_players: 0, version: 'unknown', motd: '', ping: null }; } } // Keine gültige Konfiguration return { online: false, players: [], max_players: 0, version: 'unknown', motd: '', ping: null }; }