// Shared API helpers. // Content scripts must NEVER fetch the backend directly (Chrome Private Network // Access would prompt "allow Reddit to access local network"). All page-context // calls go through the background service worker instead. async function rcsGetSettings() { const stored = await chrome.storage.sync.get({ backendUrl: "", apiKey: "", }); return { backendUrl: (stored.backendUrl || "").replace(/\/+$/, ""), apiKey: stored.apiKey || "", }; } function rcsMustProxyViaBackground() { // Popup/options are chrome-extension:// and may fetch directly. // Content scripts run on https://reddit.com and must proxy. try { return typeof location === "undefined" || location.protocol !== "chrome-extension:"; } catch { return true; } } async function rcsFetchViaBackground(path, options = {}) { const response = await chrome.runtime.sendMessage({ type: "rcs.api", path, method: options.method || "GET", headers: options.headers || {}, body: options.body || null, }); if (!response || !response.ok) { throw new Error((response && response.error) || "backend request failed"); } return response.data; } async function rcsFetchDirect(path, options = {}) { const settings = await rcsGetSettings(); if (!settings.backendUrl) { throw new Error("Backend URL not configured"); } const headers = Object.assign( { Accept: "application/json" }, options.headers || {} ); if (settings.apiKey) { headers["X-API-Key"] = settings.apiKey; } const response = await fetch(`${settings.backendUrl}${path}`, { ...options, headers, credentials: "include", }); const text = await response.text(); let data = null; try { data = text ? JSON.parse(text) : null; } catch { data = { raw: text }; } if (!response.ok) { throw new Error(rcsProxyAuthErrorMessage(response.status, text, data)); } if (data && data.raw != null && rcsLooksLikeHtml(data.raw)) { throw new Error(rcsProxyAuthErrorMessage(response.status, text, data)); } return data; } function rcsLooksLikeHtml(text) { return typeof text === "string" && /^\s*