195 lines
5.2 KiB
JavaScript
195 lines
5.2 KiB
JavaScript
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();
|
|
}); |