const baseUrl = window.location.origin; const variantsByApp = { haproxy: [ { value: "map", label: "map (recommended)" }, { value: "acl", label: "acl" }, { value: "lua", label: "lua" }, ], apache: [ { value: "24", label: "24 (recommended)" }, { value: "22", label: "22 (legacy)" }, ], nginx: [ { value: "geo", label: "geo (recommended)" }, { value: "deny", label: "deny (recommended)" }, { value: "map", label: "map (not recommended)" }, ], }; function $(id) { return document.getElementById(id); } function setBaseUrl() { const el = $("baseUrl"); if (el) el.textContent = baseUrl; } function normalizeCountries(input) { return String(input || "") .split(",") .map(s => s.trim().toUpperCase()) .filter(Boolean); } function updateModeUI() { const mode = $("pyMode").value; const rawOn = mode === "raw"; const genOn = mode === "generate"; $("pyRawFormatBox").style.display = rawOn ? "block" : "none"; $("pyAsJsBox").style.display = rawOn ? "block" : "none"; $("pyJsVarBox").style.display = rawOn ? "block" : "none"; $("pyAppTypeBox").style.display = genOn ? "block" : "none"; $("pyAppVariantBox").style.display = genOn ? "block" : "none"; if (genOn) { updateVariantOptions(); } else { updateRawJsFields(); } } function updateVariantOptions() { const app = $("pyAppType").value; const select = $("pyAppVariant"); const hint = $("variantHint"); select.innerHTML = ""; (variantsByApp[app] || []).forEach(v => { const opt = document.createElement("option"); opt.value = v.value; opt.textContent = v.label; select.appendChild(opt); }); if (app === "haproxy") hint.textContent = "Recommended: haproxy + map"; else if (app === "apache") hint.textContent = "Recommended: apache + 24"; else if (app === "nginx") hint.textContent = "Recommended: nginx + geo or deny (avoid map)"; else hint.textContent = ""; } function updateRawJsFields() { const fmt = $("pyRawFormat").value; const asJs = $("pyAsJs").value === "true"; const allowJs = fmt === "raw-cidr_json"; $("pyAsJs").disabled = !allowJs; $("pyJsVar").disabled = !allowJs || !asJs; if (!allowJs) { $("pyAsJs").value = "false"; } } function buildPythonScript() { const mode = $("pyMode").value; const countries = normalizeCountries($("pyCountries").value); const aggregate = $("pyAggregate").value === "true"; const useCache = $("pyCache").value === "true"; let endpoint = ""; const payload = { countries, aggregate, use_cache: useCache }; if (mode === "raw") { endpoint = "/api/generate/raw"; payload.app_type = $("pyRawFormat").value; if (payload.app_type === "raw-cidr_json") { const asJs = $("pyAsJs").value === "true"; payload.as_js = asJs; if (asJs) payload.js_var = $("pyJsVar").value || "geoipBlocklist"; } } else { endpoint = "/api/generate"; payload.app_type = $("pyAppType").value; payload.app_variant = $("pyAppVariant").value; } const payloadJson = JSON.stringify(payload, null, 4); const script = `#!/usr/bin/env python3 import json import re import requests BASE_URL = ${JSON.stringify(baseUrl)} ENDPOINT = ${JSON.stringify(endpoint)} payload_json = """${payloadJson}""" payload = json.loads(payload_json) resp = requests.post(BASE_URL + ENDPOINT, json=payload, timeout=120) print("Status:", resp.status_code) print("X-From-Cache:", resp.headers.get("X-From-Cache")) print("X-Cache-Type:", resp.headers.get("X-Cache-Type")) print("X-Generated-At:", resp.headers.get("X-Generated-At")) ct = (resp.headers.get("Content-Type") or "").lower() if resp.status_code >= 400: try: print(json.dumps(resp.json(), indent=2)) except Exception: print(resp.text) raise SystemExit(1) if "application/json" in ct: print(json.dumps(resp.json(), indent=2)) else: filename = "output" cd = resp.headers.get("Content-Disposition") or "" m = re.search(r'filename="?([^"]+)"?', cd) if m: filename = m.group(1) else: if "text/csv" in ct: filename += ".csv" elif "javascript" in ct: filename += ".js" elif "text/plain" in ct: filename += ".txt" else: filename += ".bin" with open(filename, "wb") as f: f.write(resp.content) print("Saved to:", filename) `; $("pythonScriptOutput").textContent = script; } async function copyPythonScript() { const text = $("pythonScriptOutput").textContent || ""; await navigator.clipboard.writeText(text); } function bind() { const topCopy = document.getElementById("btnCopyPyTop"); if (topCopy) topCopy.addEventListener("click", copyPythonScript); $("pyMode").addEventListener("change", updateModeUI); $("pyAppType").addEventListener("change", updateVariantOptions); $("pyRawFormat").addEventListener("change", updateRawJsFields); $("pyAsJs").addEventListener("change", updateRawJsFields); $("btnGenPy").addEventListener("click", () => { updateRawJsFields(); buildPythonScript(); }); $("btnCopyPy").addEventListener("click", copyPythonScript); updateModeUI(); buildPythonScript(); } document.addEventListener("DOMContentLoaded", () => { setBaseUrl(); bind(); });