209 lines
7.0 KiB
JavaScript
209 lines
7.0 KiB
JavaScript
/* 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 = `<span style="color:#6fdc8c">✓</span> ${esc(li.message)}`;
|
|
} else {
|
|
refs.lastImport.innerHTML = `<span style="color:#ff8a80">✗</span> ${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 — <b>${esc(s.name || 'piattaforma')}</b>` +
|
|
(universe ? `<small>${esc(universe)} · ${esc(s.galaxies || '?')} galassie</small>` : ''));
|
|
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))}.<br><small>Controlla IP/porta e che la piattaforma sia avviata.</small>`);
|
|
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();
|