import { CONFIG } from "./config.js"; const HOST = "si.komelt.local_history_archive"; const QUEUE_KEY = "pendingVisits"; const MAX_QUEUE = 2000; async function queued() { const { [QUEUE_KEY]: visits = [] } = await chrome.storage.local.get(QUEUE_KEY); return visits; } async function persist(visits) { await chrome.storage.local.set({ [QUEUE_KEY]: visits.slice(-MAX_QUEUE) }); } async function archiveLocally(visits) { if (!visits.length) return true; try { const reply = await chrome.runtime.sendNativeMessage(HOST, { type: "visits", visits }); return reply?.ok === true; } catch (error) { console.warn("Local archive unavailable", error.message); return false; } } async function sendToCollector(visits) { // Empty settings deliberately disable sending; the local SQLite archive still works. if (!CONFIG.collectorUrl || !CONFIG.apiToken) return true; const remoteVisits = visits .filter((visit) => { if (typeof visit?.url !== "string") return false; try { const protocol = new URL(visit.url).protocol; return protocol === "http:" || protocol === "https:"; } catch { return false; } }) .map((visit) => ({ ...visit, title: String(visit.title ?? "").slice(0, 1000) })); try { for (let offset = 0; offset < remoteVisits.length; offset += 100) { const response = await fetch(CONFIG.collectorUrl, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${CONFIG.apiToken}` }, body: JSON.stringify({ device_id: CONFIG.deviceId, visits: remoteVisits.slice(offset, offset + 100) }) }); if (!response.ok) { const detail = (await response.text()).trim().slice(0, 1000); throw new Error(`HTTP ${response.status}${detail ? `: ${detail}` : ""}`); } } return true; } catch (error) { console.warn("Collector unavailable", error.message); return false; } } async function flush() { const visits = await queued(); if (!visits.length) return; const [localOk, remoteOk] = await Promise.all([archiveLocally(visits), sendToCollector(visits)]); if (localOk && remoteOk) await persist([]); } chrome.history.onVisited.addListener(async (item) => { const visits = await queued(); visits.push({ url: item.url, title: item.title || "", visit_time: new Date(item.lastVisitTime || Date.now()).toISOString(), transition: "observed", source: "chrome-extension" }); await persist(visits); await flush(); }); chrome.runtime.onStartup.addListener(flush); chrome.runtime.onInstalled.addListener(flush); chrome.alarms.create("local-history-archive-flush", { periodInMinutes: 1 }); chrome.alarms.onAlarm.addListener(flush);