/* OGame Spy Auto-Importer — popup * Impostazioni piattaforma (IP/porta), toggle cattura/notifiche, * verifica connessione e import manuale di fallback. */ 'use strict'; const SETTINGS_KEY = 'settings'; const DEFAULTS = { host: 'localhost', port: 8899, autoImport: true, notifications: true }; // Forme accettate per l'import manuale (come lato server) const TOKEN_RE = /^(cr|sr|rr|mr)-[a-z]{2}-\d{1,3}-[0-9a-f]{40}$/i; const RID_ONLY_RE = /^[0-9a-f]{40}$/i; const refs = { host: document.getElementById('host'), port: document.getElementById('port'), targetUrl: document.getElementById('targetUrl'), btnCheck: document.getElementById('btnCheck'), statusDot: document.getElementById('statusDot'), statusText: document.getElementById('statusText'), autoImport: document.getElementById('autoImport'), notifications: document.getElementById('notifications'), btnImport: document.getElementById('btnImport'), importResult: document.getElementById('importResult'), lastImport: document.getElementById('lastImport'), }; // ---------------------------------------------------------------- utils function loadSettings() { return new Promise((resolve) => { chrome.storage.local.get({ [SETTINGS_KEY]: DEFAULTS }, (d) => resolve({ ...DEFAULTS, ...(d[SETTINGS_KEY] || {}) })); }); } function saveSettings(cfg) { return new Promise((resolve) => { chrome.storage.local.set({ [SETTINGS_KEY]: cfg }, () => resolve()); }); } function baseUrl(host, port) { return `http://${String(host || '').trim() || 'localhost'}:${port || 8899}`; } function setStatus(cls, html) { refs.statusDot.className = 'dot ' + cls; refs.statusText.innerHTML = html; } function renderLast(li) { if (!li) { refs.lastImport.textContent = 'Nessun import effettuato.'; return; } if (li.ok) { refs.lastImport.innerHTML = `✓ ${esc(li.message)}`; } else { refs.lastImport.innerHTML = `✗ ${esc(li.error)}`; } } function esc(s) { const d = document.createElement('div'); d.textContent = String(s == null ? '' : s); return d.innerHTML; } function updateTarget() { refs.targetUrl.textContent = `${baseUrl(refs.host.value, refs.port.value)}/api/reports`; } // ---------------------------------------------------------------- server check async function checkServer() { const host = refs.host.value.trim(); const port = refs.port.value.trim(); setStatus('wait', 'Verifica in corso…'); try { const res = await fetch(`${baseUrl(host, port)}/api/bootstrap`, { signal: AbortSignal.timeout(5000), }); const data = await res.json().catch(() => null); if (res.ok && data && data.ok) { const s = data.server || {}; const universe = s.number ? `s${s.number}-${s.community || ''}` : (s.domain || ''); setStatus('ok', `Connesso — ${esc(s.name || 'piattaforma')}` + (universe ? `${esc(universe)} · ${esc(s.galaxies || '?')} galassie` : '')); return true; } setStatus('err', `Risposta del server: ${esc((data && data.error) || 'HTTP ' + res.status)}`); return false; } catch { setStatus('err', `Server non raggiungibile su ${esc(baseUrl(host, port))}.
Controlla IP/porta e che la piattaforma sia avviata.`); return false; } } // ---------------------------------------------------------------- import dalla clipboard async function importFromClipboard() { let text; try { text = await navigator.clipboard.readText(); } catch { refs.importResult.className = 'result err'; refs.importResult.textContent = '✗ Impossibile leggere la clipboard.'; return; } const token = text.trim(); refs.importResult.textContent = ''; if (!token) { refs.importResult.className = 'result err'; refs.importResult.textContent = 'La clipboard è vuota. Copia un API string da OGame prima.'; return; } if (!TOKEN_RE.test(token) && !RID_ONLY_RE.test(token)) { refs.importResult.className = 'result err'; refs.importResult.textContent = 'Formato non riconosciuto. Atteso: sr-ar-170-<40 hex> o solo l\'id.'; return; } refs.btnImport.disabled = true; refs.btnImport.textContent = 'Importazione…'; try { const r = await chrome.runtime.sendMessage({ type: 'importManual', token }); if (r && r.ok) { refs.importResult.className = 'result ok'; refs.importResult.textContent = (r.created ? '✓ Importato — ' : '✓ Già presente — ') + (r.message || ''); } else { refs.importResult.className = 'result err'; refs.importResult.textContent = '✗ ' + ((r && r.error) || 'Errore sconosciuto'); } } catch { refs.importResult.className = 'result err'; refs.importResult.textContent = '✗ Impossibile contattare il background. Ricarica l\'estensione.'; } finally { refs.btnImport.disabled = false; refs.btnImport.textContent = 'Importa ora'; } } // ---------------------------------------------------------------- init async function init() { const cfg = await loadSettings(); refs.host.value = cfg.host; refs.port.value = cfg.port; refs.autoImport.checked = cfg.autoImport !== false; refs.notifications.checked = cfg.notifications !== false; updateTarget(); // ultimo esito import (dal background) try { const st = await chrome.runtime.sendMessage({ type: 'getState' }); if (st && st.ok) renderLast(st.lastImport); } catch { /* background non attivo: ignora */ } // nessuna verifica automatica: la connessione si controlla solo col // pulsante "Verifica connessione" setStatus('', 'Premi “Verifica connessione” per testare il server'); } // ---------------------------------------------------------------- eventi function onHostPortChanged() { updateTarget(); // solo il pulsante "Verifica" interroga il server setStatus('', 'Impostazioni salvate — premi “Verifica connessione”'); } refs.host.addEventListener('change', async () => { const cfg = await loadSettings(); await saveSettings({ ...cfg, host: refs.host.value.trim() || DEFAULTS.host }); onHostPortChanged(); }); refs.port.addEventListener('change', async () => { const cfg = await loadSettings(); const p = parseInt(refs.port.value, 10); refs.port.value = (p >= 1 && p <= 65535) ? p : DEFAULTS.port; await saveSettings({ ...cfg, port: refs.port.value }); onHostPortChanged(); }); refs.autoImport.addEventListener('change', async () => { const cfg = await loadSettings(); await saveSettings({ ...cfg, autoImport: refs.autoImport.checked }); }); refs.notifications.addEventListener('change', async () => { const cfg = await loadSettings(); await saveSettings({ ...cfg, notifications: refs.notifications.checked }); }); refs.btnCheck.addEventListener('click', checkServer); refs.btnImport.addEventListener('click', importFromClipboard); // aggiornamento live mentre il popup è aperto (es. import automatico in corso) chrome.storage.onChanged.addListener((changes, area) => { if (area !== 'local' || !changes.lastImport) return; renderLast(changes.lastImport.newValue); }); init();