maxza258's picture
Upload 23 files
ebf054f verified
Raw
History Blame
3.05 kB
import { normalizeUrl } from "./url.js";
const REMOTE_DEFAULTS_URL ="https://raw.githubusercontent.com/Kuju29/TextPhantomOCR_Overlay/refs/heads/main/defaults_api.json";
const DEFAULT_API_URL_FALLBACK = "";
const RESET_API_URL_FALLBACK = "";
const FETCH_TIMEOUT_MS = 2000;
const TTL_MS = 12 * 60 * 60 * 1000;
function now() {
return Date.now();
}
function coerceUrl(v) {
return typeof v === "string" ? normalizeUrl(v) : "";
}
function parseMaybeJson(raw) {
if (typeof raw !== "string") return null;
const t = raw.trim();
if (!t) return null;
try {
return JSON.parse(t);
} catch {
if (!(t.startsWith("{") && t.endsWith("}"))) return null;
const q1 = t.replace(/([{,]\s*)([A-Za-z0-9_]+)\s*:/g, '$1"$2":');
const q2 = q1.includes("'") && !q1.includes('"') ? q1.replace(/'/g, '"') : q1;
try {
return JSON.parse(q2);
} catch {
return null;
}
}
}
async function fetchRemoteDefaults() {
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);
try {
const res = await fetch(REMOTE_DEFAULTS_URL, {
method: "GET",
headers: { accept: "application/json" },
cache: "no-store",
signal: ctrl.signal,
});
if (!res.ok) return null;
const raw = await res.text();
const data = parseMaybeJson(raw);
if (!data || typeof data !== "object") return null;
const defaultApiUrl =
coerceUrl(data.defaultApiUrl) ||
coerceUrl(data.DEFAULTS_API) ||
coerceUrl(data.apiUrlDefault) ||
coerceUrl(data.default_api_url);
const resetApiUrl =
coerceUrl(data.resetApiUrl) ||
coerceUrl(data.apiUrlReset) ||
coerceUrl(data.reset_api_url);
if (!defaultApiUrl && !resetApiUrl) return null;
return {
defaultApiUrl: defaultApiUrl || "",
resetApiUrl: resetApiUrl || "",
};
} catch {
return null;
} finally {
clearTimeout(t);
}
}
export async function ensureApiDefaults({ force = false } = {}) {
const stored = await chrome.storage.local.get({
apiUrlDefault: DEFAULT_API_URL_FALLBACK,
apiUrlReset: RESET_API_URL_FALLBACK,
apiDefaultsFetchedAt: 0,
});
const current = {
defaultApiUrl: coerceUrl(stored.apiUrlDefault) || DEFAULT_API_URL_FALLBACK,
resetApiUrl: coerceUrl(stored.apiUrlReset) || RESET_API_URL_FALLBACK,
fetchedAt: Number(stored.apiDefaultsFetchedAt) || 0,
};
const fresh = current.fetchedAt && now() - current.fetchedAt <= TTL_MS;
if (!force && fresh) return current;
const remote = await fetchRemoteDefaults();
if (!remote) return current;
const next = {
defaultApiUrl: remote.defaultApiUrl || current.defaultApiUrl,
resetApiUrl: remote.resetApiUrl || current.resetApiUrl,
fetchedAt: now(),
};
await chrome.storage.local.set({
apiUrlDefault: next.defaultApiUrl,
apiUrlReset: next.resetApiUrl,
apiDefaultsFetchedAt: next.fetchedAt,
});
return next;
}
export const API_DEFAULTS = {
REMOTE_DEFAULTS_URL,
DEFAULT_API_URL_FALLBACK,
RESET_API_URL_FALLBACK,
};