api docs, generator
This commit is contained in:
194
static/js/generator.js
Normal file
194
static/js/generator.js
Normal file
@@ -0,0 +1,194 @@
|
||||
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 script = `#!/usr/bin/env python3
|
||||
import json
|
||||
import re
|
||||
import requests
|
||||
|
||||
BASE_URL = ${JSON.stringify(baseUrl)}
|
||||
ENDPOINT = ${JSON.stringify(endpoint)}
|
||||
|
||||
payload = ${JSON.stringify(payload, null, 4)}
|
||||
|
||||
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 show JSON error, else text
|
||||
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:
|
||||
# fallback extension
|
||||
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();
|
||||
});
|
||||
Reference in New Issue
Block a user