import fs from "node:fs"; import path from "node:path"; import { settings } from "./config.js"; const DEFAULT_CLIENT_SETTINGS = { homeBypassEnabled: false, sharedProxyEnabled: false, sharedProxyControlUrl: "", sharedProxy: null, }; function normalizeProxyPort(value, fallback = settings.proxyPort) { const parsed = Number.parseInt(value, 10); const min = Number.isInteger(settings.clientProxyPortStart) ? settings.clientProxyPortStart : settings.proxyPort; const max = Number.isInteger(settings.clientProxyPortEnd) ? settings.clientProxyPortEnd : min; const fallbackPort = Number.isInteger(fallback) && fallback >= min && fallback <= max ? fallback : min; if (!Number.isInteger(parsed) || parsed < min || parsed > max) { return fallbackPort; } return parsed; } function readJson(filePath, fallback) { try { if (!fs.existsSync(filePath)) return fallback; return JSON.parse(fs.readFileSync(filePath, "utf8")); } catch { return fallback; } } function writeJson(filePath, value) { fs.mkdirSync(path.dirname(filePath), { recursive: true }); fs.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf8"); } function normalizeUrl(value) { const raw = String(value || "").trim(); if (!raw) return ""; try { const url = new URL(raw); if (!["http:", "https:"].includes(url.protocol)) return ""; url.hash = ""; url.search = ""; return url.toString().replace(/\/$/, ""); } catch { return ""; } } function normalizeSharedProxy(value) { if (!value || typeof value !== "object") return null; const host = String(value.host || "").trim(); const port = Number.parseInt(value.port, 10); const protocol = value.protocol === "http" ? "http" : "socks5"; if (!host || !Number.isInteger(port) || port <= 0 || port > 65535) { return null; } return { host, port, protocol, checkedAt: value.checkedAt || null, }; } export function normalizeClientSettings(input = {}) { const sharedProxy = normalizeSharedProxy(input.sharedProxy); const sharedProxyEnabled = Boolean(input.sharedProxyEnabled && sharedProxy); return { homeBypassEnabled: Boolean(input.homeBypassEnabled), proxyPort: normalizeProxyPort(input.proxyPort), sharedProxyEnabled, sharedProxyControlUrl: normalizeUrl(input.sharedProxyControlUrl), sharedProxy, }; } export function readClientSettings() { return normalizeClientSettings({ ...DEFAULT_CLIENT_SETTINGS, proxyPort: settings.proxyPort, ...readJson(settings.clientSettingsPath, {}), }); } export function writeClientSettings(input) { const normalized = normalizeClientSettings({ ...readClientSettings(), ...(input && typeof input === "object" ? input : {}), }); writeJson(settings.clientSettingsPath, normalized); return normalized; }