diff --git a/BungeeCord-Chrome/background.js b/BungeeCord-Chrome/background.js index f4dde14..dbac1eb 100644 --- a/BungeeCord-Chrome/background.js +++ b/BungeeCord-Chrome/background.js @@ -1,111 +1,187 @@ -// 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 || ''; - - if (fetchUrl) { - if (!/^https?:\/\//i.test(fetchUrl)) fetchUrl = 'http://' + fetchUrl; - try { - const controller = new AbortController(); - const id = setTimeout(() => controller.abort(), timeoutMs); - const resp = await fetch(fetchUrl, { method: 'GET', signal: controller.signal }); - clearTimeout(id); - - 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)) return parsed; - } catch {} - } - } catch {} - } - - 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 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); - - 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)) return json; - } catch {} - } - - return { online: false, players: [], max_players: 0, version: 'unknown', motd: '' }; +// 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 + }; } \ No newline at end of file