Files
ogame_db/ogame-importer/content.js
T
2026-09-23 18:59:27 +02:00

98 lines
3.3 KiB
JavaScript

/* OGame Spy Auto-Importer — content script (isolated world)
*
* Esegue SOLO sulle pagine OGame (vedi manifest: *.ogame.gameforge.com).
*
* NON legge la clipboard (impossibile da content script: vale il permesso
* della pagina, non quello dell'estensione). Intercetta invece il token nel
* momento in cui viene copiato, tramite due sorgenti:
* 1) evento DOM 'copy' → Ctrl+C, tasto destro, execCommand('copy')
* 2) messaggio dal MAIN world → navigator.clipboard.writeText() (pulsante API)
*
* Il token intercettato viene inviato UNA volta al background che lo importa.
* Se il background è occupato o non ancora pronto, si concede un solo retry.
*/
'use strict';
// Stessa forma accettata dal server (ricerca dentro il testo copiato)
const TOKEN_SEARCH_RE = /(cr|sr|rr|mr)-[a-z]{2}-\d{1,3}-[0-9a-f]{40}/i;
const OGame_HOST_RE = /(^|\.)ogame\.gameforge\.com$/i;
const CHANNEL = 'ogame-spy-importer';
const RETRY_MS = 1500;
let autoImport = true;
const done = new Set(); // token già inviati con esito definitivo
const retried = new Set(); // token che hanno già usato il loro unico retry
let inflight = null; // token attualmente in invio
function isOgame() {
return OGame_HOST_RE.test(window.location.hostname);
}
function extractToken(text) {
if (!text || typeof text !== 'string') return null;
const m = text.match(TOKEN_SEARCH_RE);
return m ? m[0].toLowerCase() : null;
}
async function loadSettings() {
const d = await chrome.storage.local.get({ settings: undefined });
autoImport = !d.settings || d.settings.autoImport !== false;
}
async function sendCapture(token) {
try {
const r = await chrome.runtime.sendMessage({ type: 'capture', token });
return (r && r.status) || 'error';
} catch {
return 'unreachable'; // background non ancora pronto
}
}
async function handleToken(token) {
if (!token || !isOgame() || !autoImport) return;
// già gestito (o in corso): niente doppioni se scattano entrambe le sorgenti
if (done.has(token) || inflight === token) return;
inflight = token;
const status = await sendCapture(token);
inflight = null;
// 'busy'/'unreachable' = il background non ha risposto: un solo retry.
if (status === 'busy' || status === 'unreachable') {
if (!retried.has(token)) {
retried.add(token);
setTimeout(() => handleToken(token), RETRY_MS);
}
return;
}
// Esito definitivo: 'ok'/'dup'/'known' importato o già noto,
// 'error' fallito (il background ha già mostrato la notifica d'errore).
done.add(token);
}
// ---- sorgente 1: evento 'copy' (Ctrl+C, tasto destro, execCommand) ----
document.addEventListener('copy', (e) => {
try {
const text = e.clipboardData && e.clipboardData.getData('text');
const token = extractToken(text);
if (token) handleToken(token);
} catch (_) { /* noop */ }
}, true);
// ---- sorgente 2: writeText della pagina (main world → postMessage) ----
window.addEventListener('message', (e) => {
if (e.source !== window || !e.data || e.data.__ogameSpyImporter !== CHANNEL) return;
const token = extractToken(e.data.text);
if (token) handleToken(token);
});
chrome.storage.onChanged.addListener((changes, area) => {
if (area !== 'local' || !changes.settings) return;
autoImport = changes.settings.newValue.autoImport !== false;
});
(async function init() {
await loadSettings();
})();