/** * πŸ›°οΈ Nodeloc Remote β€” Cloudflare Worker (v10) * * - Token TIDAK ada di kode Worker * - Multi-akun di localStorage browser * - Single Add + Bulk Add DNS record (1 target untuk banyak name) */ const NODELOC_BASE = "https://domain.nodeloc.com"; const corsHeaders = { "access-control-allow-origin": "*", "access-control-allow-headers": "content-type, x-nodeloc-token", "access-control-allow-methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS", }; const json = (data, status = 200) => new Response(JSON.stringify(data, null, 2), { status, headers: { "content-type": "application/json; charset=utf-8", ...corsHeaders }, }); const html = (body, status = 200) => new Response(body, { status, headers: { "content-type": "text/html; charset=utf-8" } }); const cors = () => new Response(null, { status: 204, headers: corsHeaders }); async function nodeloc(method, path, body, token) { const init = { method, headers: { Accept: "application/json, text/plain, */*", Authorization: `Bearer ${token}`, "User-Agent": "nodeloc-cf-worker/1.0", }, }; if (body !== undefined && body !== null) { init.headers["content-type"] = "application/json"; init.body = typeof body === "string" ? body : JSON.stringify(body); } const r = await fetch(`${NODELOC_BASE}${path}`, init); const text = await r.text(); let data; try { data = JSON.parse(text); } catch { data = text; } return { status: r.status, data }; } // ───────────────────────── HTML SHELL ───────────────────────── const SHELL = ` Nodeloc Remote
πŸ›°οΈ Nodeloc Remote
β€”
⏳ Memuat…
`; // ───────────────────────── Router ───────────────────────── export default { async fetch(request) { const url = new URL(request.url); const path = url.pathname; if (request.method === "OPTIONS") return cors(); if (path === "/" && request.method === "GET") return html(SHELL); if (path === "/health") return json({ ok: true, base: NODELOC_BASE }); const token = (request.headers.get("x-nodeloc-token") || "").trim(); if (!token) return json({ error: "Unauthorized: header x-nodeloc-token kosong" }, 401); try { if (path === "/api/domains" && request.method === "GET") { const { status, data } = await nodeloc("GET", "/api/domains", null, token); return json(data, status); } let m = path.match(/^\/api\/domains\/(\d+)\/dnssec$/); if (m && request.method === "GET") { const { status, data } = await nodeloc("GET", `/api/domains/${m[1]}/dnssec`, null, token); return json(data, status); } m = path.match(/^\/api\/domains\/(\d+)$/); if (m && request.method === "GET") { const { status, data } = await nodeloc("GET", `/api/domains/${m[1]}`, null, token); return json(data, status); } if (path === "/api/cyberpanel/accounts" && request.method === "GET") { const { status, data } = await nodeloc("GET", "/api/cyberpanel/accounts", null, token); return json(data, status); } m = path.match(/^\/api\/dns\/(\d+)\/records$/); if (m && request.method === "GET") { const { status, data } = await nodeloc("GET", `/api/dns/${m[1]}/records`, null, token); return json(data, status); } if (m && request.method === "POST") { const body = await request.json(); if (!body.name || !body.type || !body.content) { return json({ error: "field wajib: name, type, content" }, 400); } const payload = { name: body.name, type: body.type.toUpperCase(), content: body.content, ttl: body.ttl ?? 3600, priority: body.priority ?? null, is_active: body.is_active ?? true, }; const { status, data } = await nodeloc("POST", `/api/dns/${m[1]}/records`, payload, token); return json(data, status); } m = path.match(/^\/api\/dns\/(\d+)\/records\/(\d+)$/); if (m && request.method === "DELETE") { const { status, data } = await nodeloc("DELETE", `/api/dns/${m[1]}/records/${m[2]}`, null, token); return json(data, status); } if (m && (request.method === "PATCH" || request.method === "PUT")) { const body = await request.json(); const { status, data } = await nodeloc(request.method, `/api/dns/${m[1]}/records/${m[2]}`, body, token); return json(data, status); } if (path === "/api/proxy" && request.method === "POST") { const { method = "GET", path: p, body } = await request.json(); if (!p) return json({ error: "path wajib diisi" }, 400); const { status, data } = await nodeloc(method.toUpperCase(), p, body, token); return json(data, status); } return json({ error: "Not found", path }, 404); } catch (e) { return json({ error: e.message }, 500); } }, };