"use server"; import { CustomProxyValidationError, parseCustomProxyYaml, } from "@/lib/custom-proxy"; import { revalidatePath } from "next/cache"; import { requireAdminAccess } from "@/lib/session"; import { createNode, deleteNode, normalizeNodeType, updateNode, } from "@/lib/store"; function boolFromForm(value: FormDataEntryValue | null) { return value === "on"; } function validateCustomYaml(nodeType: string, formData: FormData) { if (nodeType !== "custom") return; try { parseCustomProxyYaml(String(formData.get("custom_config_yaml") ?? "")); } catch (error) { if (error instanceof CustomProxyValidationError) return { error: error.message }; throw error; } } export async function createNodeAction(formData: FormData) { await requireAdminAccess(); const nodeType = normalizeNodeType( String(formData.get("node_type") ?? "hy2"), ); const validation = validateCustomYaml(nodeType, formData); if (validation) return validation; const name = String(formData.get("name") ?? "").trim(); const clientName = String(formData.get("client_name") ?? "").trim(); await createNode({ nodeType, slug: String(formData.get("slug") ?? "").trim(), name, authToken: String(formData.get("auth_token") ?? "").trim() || null, hy2Listen: String(formData.get("hy2_listen") ?? "").trim() || "", serverHost: String(formData.get("server_host") ?? "").trim(), serverPort: Number(formData.get("server_port") ?? 443), clientName: clientName || (nodeType === "hy2" ? name : ""), bandwidthUpMbps: Number(formData.get("bandwidth_up_mbps") ?? 30), bandwidthDownMbps: Number(formData.get("bandwidth_down_mbps") ?? 30), skipCertVerify: boolFromForm(formData.get("skip_cert_verify")), sni: String(formData.get("sni") ?? "").trim() || null, customConfigYaml: String(formData.get("custom_config_yaml") ?? ""), trafficStatsUrl: String(formData.get("traffic_stats_url") ?? "").trim(), trafficStatsListen: String(formData.get("traffic_stats_listen") ?? "").trim() || ":9999", trafficStatsSecret: String( formData.get("traffic_stats_secret") ?? "", ).trim(), enabled: boolFromForm(formData.get("enabled")), pollIntervalSeconds: Number(formData.get("poll_interval_seconds") ?? 15), }); revalidatePath("/admin/nodes"); revalidatePath("/admin/subscriptions"); revalidatePath("/admin/dashboard"); } export async function updateNodeAction(formData: FormData) { await requireAdminAccess(); const nodeType = normalizeNodeType( String(formData.get("node_type") ?? "hy2"), ); const validation = validateCustomYaml(nodeType, formData); if (validation) return validation; const name = String(formData.get("name") ?? "").trim(); const clientName = String(formData.get("client_name") ?? "").trim(); await updateNode({ id: Number(formData.get("id")), nodeType, slug: String(formData.get("slug") ?? "").trim(), name, authToken: String(formData.get("auth_token") ?? "").trim(), hy2Listen: String(formData.get("hy2_listen") ?? "").trim() || "", serverHost: String(formData.get("server_host") ?? "").trim(), serverPort: Number(formData.get("server_port") ?? 443), clientName: clientName || (nodeType === "hy2" ? name : ""), bandwidthUpMbps: Number(formData.get("bandwidth_up_mbps") ?? 30), bandwidthDownMbps: Number(formData.get("bandwidth_down_mbps") ?? 30), skipCertVerify: boolFromForm(formData.get("skip_cert_verify")), sni: String(formData.get("sni") ?? "").trim() || null, customConfigYaml: String(formData.get("custom_config_yaml") ?? ""), trafficStatsUrl: String(formData.get("traffic_stats_url") ?? "").trim(), trafficStatsListen: String(formData.get("traffic_stats_listen") ?? "").trim() || ":9999", trafficStatsSecret: String( formData.get("traffic_stats_secret") ?? "", ).trim(), enabled: boolFromForm(formData.get("enabled")), pollIntervalSeconds: Number(formData.get("poll_interval_seconds") ?? 15), }); revalidatePath("/admin/nodes"); revalidatePath("/admin/subscriptions"); revalidatePath("/admin/dashboard"); } export async function deleteNodeAction(formData: FormData) { await requireAdminAccess(); await deleteNode(Number(formData.get("id"))); revalidatePath("/admin/nodes"); revalidatePath("/admin/subscriptions"); revalidatePath("/admin/dashboard"); }