// ==================== BAGIAN 1: BACKEND LOGIC ==================== // Global memory state untuk tracking visitor real-time const visitorState = { totalHits: 0, activeVisitors: new Map(), historyLogs: [] }; export default { async fetch(request, env) { const url = new URL(request.url); const path = url.pathname.replace(/^\//, ""); // Track Visitor traffic const clientIp = request.headers.get("cf-connecting-ip") || request.headers.get("x-forwarded-for") || "127.0.0.1"; const userAgent = request.headers.get("user-agent") || "Unknown Device"; const country = request.cf?.country || "ID"; const city = request.cf?.city || "Unknown City"; const now = Date.now(); if (path !== "get-visitor-stats" && path !== "visitor-heartbeat") { visitorState.totalHits++; const visitorKey = `${clientIp}_${userAgent.substring(0, 30)}`; visitorState.activeVisitors.set(visitorKey, { ip: clientIp, ua: userAgent, path: url.pathname, country: country, city: city, lastSeen: now }); visitorState.historyLogs.unshift({ ip: clientIp, ua: userAgent, path: url.pathname, country: country, city: city, time: new Date().toLocaleTimeString("id-ID") }); if (visitorState.historyLogs.length > 30) { visitorState.historyLogs.pop(); } } // Bersihkan visitor offline (> 60 detik) for (const [key, v] of visitorState.activeVisitors.entries()) { if (now - v.lastSeen > 60000) { visitorState.activeVisitors.delete(key); } } // --- API VISITOR STATS --- if (path === "get-visitor-stats") { const activeList = Array.from(visitorState.activeVisitors.values()); return new Response(JSON.stringify({ totalHits: visitorState.totalHits, onlineCount: activeList.length, activeList: activeList, history: visitorState.historyLogs }), { headers: { "Content-Type": "application/json" } }); } if (path === "visitor-heartbeat") { const visitorKey = `${clientIp}_${userAgent.substring(0, 30)}`; visitorState.activeVisitors.set(visitorKey, { ip: clientIp, ua: userAgent, path: "Dashboard Active", country: country, city: city, lastSeen: now }); return new Response(JSON.stringify({ status: "ok" }), { headers: { "Content-Type": "application/json" } }); } // --- API INTERNAL: KV ADMIN & SETTINGS SYNC (MY_KV) --- if (path === "api-get-settings") { if (!env.MY_KV) { return new Response(JSON.stringify({ error: "MY_KV binding tidak ditemukan!" }), { status: 500, headers: { "Content-Type": "application/json" } }); } try { const [adminPin, presetsRaw, customTabsRaw] = await Promise.all([ env.MY_KV.get("CF_ADMIN_PIN"), env.MY_KV.get("CF_SCRIPT_PRESETS"), env.MY_KV.get("CF_CUSTOM_TABS") ]); return new Response(JSON.stringify({ hasPin: Boolean(adminPin), presets: presetsRaw ? JSON.parse(presetsRaw) : null, customTabs: customTabsRaw ? JSON.parse(customTabsRaw) : [] }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ error: err.message }), { status: 500, headers: { "Content-Type": "application/json" } }); } } if (path === "api-verify-admin" && request.method === "POST") { if (!env.MY_KV) return new Response(JSON.stringify({ success: false, msg: "Binding MY_KV belum dipasang!" }), { status: 500 }); try { const { pin } = await request.json(); let savedPin = await env.MY_KV.get("CF_ADMIN_PIN"); if (!savedPin) { await env.MY_KV.put("CF_ADMIN_PIN", pin.trim()); return new Response(JSON.stringify({ success: true, isNew: true, msg: "PIN Admin berhasil dibuat di KV!" }), { headers: { "Content-Type": "application/json" } }); } if (savedPin === pin.trim()) { return new Response(JSON.stringify({ success: true, isNew: false, msg: "Login Admin Berhasil!" }), { headers: { "Content-Type": "application/json" } }); } return new Response(JSON.stringify({ success: false, msg: "PIN Salah!" }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } if (path === "api-save-custom-tabs" && request.method === "POST") { if (!env.MY_KV) return new Response(JSON.stringify({ success: false, msg: "Binding MY_KV belum dipasang!" }), { status: 500 }); try { const { tabs } = await request.json(); await env.MY_KV.put("CF_CUSTOM_TABS", JSON.stringify(tabs || [])); return new Response(JSON.stringify({ success: true, msg: "Custom Tabs berhasil disimpan ke KV!" }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } if (path === "api-save-presets" && request.method === "POST") { if (!env.MY_KV) return new Response(JSON.stringify({ success: false, msg: "Binding MY_KV belum dipasang!" }), { status: 500 }); try { const { presets } = await request.json(); await env.MY_KV.put("CF_SCRIPT_PRESETS", JSON.stringify(presets || [])); return new Response(JSON.stringify({ success: true, msg: "Preset Scripts berhasil disimpan ke KV!" }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } const getAccountId = async (email, apiKey) => { const res = await fetch("https://api.cloudflare.com/client/v4/memberships", { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const data = await res.json(); if (!data.success || !data.result || data.result.length === 0) { throw new Error("Email atau API Key CF salah / tidak punya akses!"); } return data.result[0].account.id; }; const fetchTunnelDual = async (accountId, subPath, options, headers) => { let res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/cfd_tunnel${subPath}`, { ...options, headers }); if (res.status === 404 || !res.ok) { const fallbackRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/tunnels${subPath}`, { ...options, headers }); if (fallbackRes.ok || res.status === 404) { res = fallbackRes; } } return res; }; if (request.method === "POST") { const formData = await request.formData(); const action = path; // --- WORKER: LIST --- if (action === "list-workers") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services?per_page=100`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result.map(w => w.id) : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ error: err.message }), { status: 500 }); } } // --- WORKER ENV / SECRET: LIST --- if (action === "list-worker-vars") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const target = formData.get("target_worker").trim().toLowerCase(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/bindings`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); if (data.success) { const varBindings = data.result.filter(b => b.type === "plain_text" || b.type === "secret_text"); return new Response(JSON.stringify(varBindings), { headers: { "Content-Type": "application/json" } }); } return new Response(JSON.stringify([]), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- WORKER ENV / SECRET: ADD / UPDATE --- if (action === "put-worker-var") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const accountId = await getAccountId(email, apiKey); const target = formData.get("target_worker").trim().toLowerCase(); const varName = formData.get("var_name").trim(); const varValue = formData.get("var_value"); const varType = formData.get("var_type"); if (varType === "secret_text") { const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/secrets`, { method: "PUT", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey, "Content-Type": "application/json" }, body: JSON.stringify({ name: varName, text: varValue, type: "secret_text" }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? `Secret env.${varName} berhasil disimpan di ${target}!` : (data.errors?.[0]?.message || "Gagal menyimpan secret variable.") }), { headers: { "Content-Type": "application/json" } }); } else { const currentSettingsRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/bindings`, { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const currentSettings = await currentSettingsRes.json(); let bindings = currentSettings.success && Array.isArray(currentSettings.result) ? currentSettings.result : []; bindings = bindings.filter(b => !(b.name === varName && b.type === "plain_text")); bindings.push({ type: "plain_text", name: varName, text: varValue }); const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ bindings: bindings })], { type: "application/json" })); const bindRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const bindData = await bindRes.json(); return new Response(JSON.stringify({ success: bindData.success, msg: bindData.success ? `Variable env.${varName} berhasil disimpan di ${target}!` : (bindData.errors?.[0]?.message || "Gagal menyimpan variable.") }), { headers: { "Content-Type": "application/json" } }); } } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- WORKER ENV / SECRET: DELETE --- if (action === "delete-worker-var") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const accountId = await getAccountId(email, apiKey); const target = formData.get("target_worker").trim().toLowerCase(); const varName = formData.get("var_name").trim(); const varType = formData.get("var_type"); if (varType === "secret_text") { const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/secrets/${varName}`, { method: "DELETE", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? `Secret env.${varName} berhasil dihapus dari ${target}!` : (data.errors?.[0]?.message || "Gagal menghapus secret.") }), { headers: { "Content-Type": "application/json" } }); } else { const currentSettingsRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/bindings`, { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const currentSettings = await currentSettingsRes.json(); let bindings = currentSettings.success && Array.isArray(currentSettings.result) ? currentSettings.result : []; bindings = bindings.filter(b => !(b.name === varName && b.type === "plain_text")); const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ bindings: bindings })], { type: "application/json" })); const bindRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const bindData = await bindRes.json(); return new Response(JSON.stringify({ success: bindData.success, msg: bindData.success ? `Variable env.${varName} berhasil dihapus!` : (bindData.errors?.[0]?.message || "Gagal menghapus variable.") }), { headers: { "Content-Type": "application/json" } }); } } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- WORKER SUBDOMAIN: GET ROOT WORKERS.DEV SUBDOMAIN --- if (action === "get-account-subdomain") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/subdomain`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, subdomain: data.success && data.result ? data.result.subdomain : "" }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, subdomain: "", error: err.message }), { status: 500 }); } } // --- WORKER SUBDOMAIN: UPDATE ROOT WORKERS.DEV SUBDOMAIN --- if (action === "update-account-subdomain") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const newSubdomain = formData.get("new_subdomain").trim().toLowerCase(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/subdomain`, { method: "PUT", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ subdomain: newSubdomain }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? `Subdomain berhasil diubah ke: ${newSubdomain}.workers.dev` : (data.errors?.[0]?.message || "Gagal mengubah subdomain.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- WORKER SUBDOMAIN: TOGGLE WORKERS.DEV STATUS PER WORKER --- if (action === "toggle-worker-subdomain") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const target = formData.get("target_worker").trim().toLowerCase(); const enabled = formData.get("enabled") === "true"; const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/subdomain`, { method: "POST", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ enabled }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? `Rute *.workers.dev untuk ${target} berhasil di-${enabled ? 'aktifkan' : 'nonaktifkan'}!` : (data.errors?.[0]?.message || "Gagal mengubah setelan rute worker.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- ZONES / DOMAIN UTAMA: LIST --- if (action === "list-zones") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const res = await fetch(`https://api.cloudflare.com/client/v4/zones?account.id=${accountId}&per_page=50`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result.map(z => ({ name: z.name, id: z.id })) : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- TUNNEL: LIST TUNNELS --- if (action === "list-tunnels") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const headers = { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") }; const res = await fetchTunnelDual(accountId, "?is_deleted=false&per_page=50", { method: "GET" }, headers); const data = await res.json(); let tunnels = data.success ? data.result : []; tunnels.sort((a, b) => { const timeA = new Date(a.modified_at || a.created_at || 0).getTime(); const timeB = new Date(b.modified_at || b.created_at || 0).getTime(); return timeB - timeA; }); return new Response(JSON.stringify(tunnels), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- TUNNEL: CREATE TUNNEL --- if (action === "create-tunnel") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const tunnelName = formData.get("tunnel_name").trim().toLowerCase(); const randomBytes = new Uint8Array(32); crypto.getRandomValues(randomBytes); let binary = ""; randomBytes.forEach(b => binary += String.fromCharCode(b)); const tunnelSecret = btoa(binary); const headers = { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }; const res = await fetchTunnelDual(accountId, "", { method: "POST", body: JSON.stringify({ name: tunnelName, tunnel_secret: tunnelSecret, config_src: "cloudflare" }) }, headers); const data = await res.json(); let generatedToken = ""; let tunnelId = ""; if (data.success && data.result) { tunnelId = data.result.id; const tokenPayload = { a: accountId, t: tunnelId, s: tunnelSecret }; generatedToken = btoa(JSON.stringify(tokenPayload)); } return new Response(JSON.stringify({ success: data.success, msg: data.success ? `Tunnel "${tunnelName}" berhasil dibuat!` : (data.errors?.[0]?.message || "Gagal membuat tunnel."), tunnel_id: tunnelId, token: generatedToken }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- TUNNEL: GET TOKEN --- if (action === "get-tunnel-token") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const accountId = await getAccountId(email, apiKey); const tunnelId = formData.get("tunnel_id"); const headers = { "X-Auth-Email": email, "X-Auth-Key": apiKey }; let token = ""; let errMsg = ""; const res = await fetchTunnelDual(accountId, `/${tunnelId}/token`, { method: "GET" }, headers); const raw = await res.text(); try { const parsed = JSON.parse(raw); if (parsed.success && parsed.result) { token = typeof parsed.result === "string" ? parsed.result : (parsed.result.token || ""); } else if (parsed.errors && parsed.errors.length > 0) { errMsg = parsed.errors[0].message; } } catch(e) { if (res.ok && raw && !raw.includes(" i.hostname); } } } catch(e) {} if (ingressList.length === 0) { try { const zonesRes = await fetch(`https://api.cloudflare.com/client/v4/zones?account.id=${accountId}&per_page=50`, { headers }); const zonesData = await zonesRes.json(); if (zonesData.success && zonesData.result) { const dnsTarget = `${tunnelId}.cfargotunnel.com`; for (const z of zonesData.result) { const dnsRes = await fetch(`https://api.cloudflare.com/client/v4/zones/${z.id}/dns_records?type=CNAME&content=${dnsTarget}`, { headers }); const dnsData = await dnsRes.json(); if (dnsData.success && dnsData.result) { dnsData.result.forEach(rec => { ingressList.push({ hostname: rec.name, service: `CNAME Terpasang -> ${rec.content}` }); }); } } } } catch(e) {} } return new Response(JSON.stringify({ success: true, ingress: ingressList }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: true, ingress: [] }), { headers: { "Content-Type": "application/json" } }); } } // --- TUNNEL: ADD / EDIT INGRESS ROUTE --- if (action === "add-tunnel-route") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const accountId = await getAccountId(email, apiKey); const tunnelId = formData.get("tunnel_id"); const zoneId = formData.get("zone_id"); const subdomain = formData.get("subdomain").trim().toLowerCase(); const mainDomain = formData.get("main_domain").trim().toLowerCase(); const serviceUrl = formData.get("service_url").trim(); const hostname = subdomain ? `${subdomain}.${mainDomain}` : mainDomain; const headers = { "X-Auth-Email": email, "X-Auth-Key": apiKey, "Content-Type": "application/json" }; const confRes = await fetchTunnelDual(accountId, `/${tunnelId}/configurations`, { method: "GET" }, headers); let ingress = []; if (confRes.ok) { const confData = await confRes.json(); ingress = confData.result?.config?.ingress || []; } ingress = ingress.filter(r => r.hostname !== hostname && r.service !== "http_status:404"); ingress.push({ hostname: hostname, service: serviceUrl }); ingress.push({ service: "http_status:404" }); const saveRes = await fetchTunnelDual(accountId, `/${tunnelId}/configurations`, { method: "PUT", body: JSON.stringify({ config: { ingress: ingress } }) }, headers); const saveData = await saveRes.json(); if (!saveData.success) { return new Response(JSON.stringify({ success: false, msg: saveData.errors?.[0]?.message || "Gagal menyimpan Ingress route." }), { status: 400 }); } try { const dnsTarget = `${tunnelId}.cfargotunnel.com`; const dnsListRes = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records?name=${hostname}`, { headers }); const dnsListData = await dnsListRes.json(); if (dnsListData.success && dnsListData.result.length > 0) { const recId = dnsListData.result[0].id; await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recId}`, { method: "PUT", headers, body: JSON.stringify({ type: "CNAME", name: hostname, content: dnsTarget, proxied: true, ttl: 1 }) }); } else { await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`, { method: "POST", headers, body: JSON.stringify({ type: "CNAME", name: hostname, content: dnsTarget, proxied: true, ttl: 1 }) }); } } catch(e) {} return new Response(JSON.stringify({ success: true, msg: `Route ${hostname} -> ${serviceUrl} berhasil disimpan & aktif!` }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- TUNNEL: DELETE INGRESS ROUTE --- if (action === "delete-tunnel-route") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const accountId = await getAccountId(email, apiKey); const tunnelId = formData.get("tunnel_id"); const hostname = formData.get("hostname").trim(); const headers = { "X-Auth-Email": email, "X-Auth-Key": apiKey, "Content-Type": "application/json" }; const confRes = await fetchTunnelDual(accountId, `/${tunnelId}/configurations`, { method: "GET" }, headers); let ingress = []; if (confRes.ok) { const confData = await confRes.json(); ingress = confData.result?.config?.ingress || []; } ingress = ingress.filter(r => r.hostname !== hostname && r.service !== "http_status:404"); ingress.push({ service: "http_status:404" }); const saveConfRes = await fetchTunnelDual(accountId, `/${tunnelId}/configurations`, { method: "PUT", body: JSON.stringify({ config: { ingress: ingress } }) }, headers); const saveConfData = await saveConfRes.json(); return new Response(JSON.stringify({ success: saveConfData.success, msg: saveConfData.success ? `Route untuk ${hostname} berhasil dihapus!` : "Gagal menghapus route." }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- SSL/TLS: GET SETTINGS --- if (action === "get-ssl-settings") { try { const zoneId = formData.get("zone_id"); const headers = { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") }; const [sslRes, httpsRes, rewritesRes, tlsVerRes, tls13Res] = await Promise.all([ fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/ssl`, { headers }), fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/always_use_https`, { headers }), fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/automatic_https_rewrites`, { headers }), fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/min_tls_version`, { headers }), fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/tls_1_3`, { headers }) ]); const [sslData, httpsData, rewritesData, tlsVerData, tls13Data] = await Promise.all([ sslRes.json(), httpsRes.json(), rewritesRes.json(), tlsVerRes.json(), tls13Res.json() ]); return new Response(JSON.stringify({ success: true, ssl: sslData.result?.value || "full", always_use_https: httpsData.result?.value || "off", automatic_https_rewrites: rewritesData.result?.value || "off", min_tls_version: tlsVerData.result?.value || "1.0", tls_1_3: tls13Data.result?.value || "on" }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- SSL/TLS: UPDATE SETTINGS --- if (action === "update-ssl-settings") { try { const zoneId = formData.get("zone_id"); const headers = { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") }; const sslMode = formData.get("ssl_mode"); const alwaysHttps = formData.get("always_use_https"); const rewrites = formData.get("automatic_https_rewrites"); const minTls = formData.get("min_tls_version"); const tls13 = formData.get("tls_1_3"); await Promise.all([ fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/ssl`, { method: "PATCH", headers, body: JSON.stringify({ value: sslMode }) }), fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/always_use_https`, { method: "PATCH", headers, body: JSON.stringify({ value: alwaysHttps }) }), fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/automatic_https_rewrites`, { method: "PATCH", headers, body: JSON.stringify({ value: rewrites }) }), fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/min_tls_version`, { method: "PATCH", headers, body: JSON.stringify({ value: minTls }) }), fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/tls_1_3`, { method: "PATCH", headers, body: JSON.stringify({ value: tls13 }) }) ]); return new Response(JSON.stringify({ success: true, msg: "Pengaturan SSL/TLS & HTTPS Berhasil Diperbarui!" }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- EMAIL ROUTING: GET SETTINGS --- if (action === "get-email-settings") { try { const zoneId = formData.get("zone_id"); const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/email/routing`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, result: data.result }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- EMAIL ROUTING: ENABLE AUTO MX/SPF --- if (action === "enable-email-routing") { try { const zoneId = formData.get("zone_id"); const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/email/routing/enable`, { method: "POST", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "Sukses konfigurasi MX/SPF Cloudflare Email Routing!" : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- EMAIL ROUTING: GET CATCH-ALL --- if (action === "get-email-catchall") { try { const zoneId = formData.get("zone_id"); const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/email/routing/rules/catch_all`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, result: data.result }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- EMAIL ROUTING: UPDATE CATCH-ALL --- if (action === "update-email-catchall") { try { const zoneId = formData.get("zone_id"); const enabled = formData.get("catchall_enabled") === "true"; const actionType = formData.get("catchall_action"); const targetValue = formData.get("catchall_target"); let actions = []; if (actionType === "worker") { actions.push({ type: "worker", value: [targetValue] }); } else { actions.push({ type: "forward", value: [targetValue] }); } const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/email/routing/rules/catch_all`, { method: "PUT", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ enabled: enabled, actions: actions, matchers: [{ type: "all" }] }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "Konfigurasi Catch-All Berhasil Diperbarui!" : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- EMAIL ROUTING: LIST DESTINATIONS --- if (action === "list-email-destinations") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/email/routing/addresses?per_page=100`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- EMAIL ROUTING: ADD DESTINATION --- if (action === "add-email-destination") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const emailAddress = formData.get("email_address").trim(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/email/routing/addresses`, { method: "POST", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ email: emailAddress }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "Email berhasil didaftarkan! Cek inbox/spam buat verifikasi." : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- EMAIL ROUTING: DELETE DESTINATION --- if (action === "delete-email-destination") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const addressId = formData.get("address_id"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/email/routing/addresses/${addressId}`, { method: "DELETE", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false }), { status: 500 }); } } // --- KV: LIST NAMESPACES --- if (action === "list-kv-namespaces") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces?per_page=100`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- KV: CREATE NAMESPACE --- if (action === "create-kv-namespace") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const title = formData.get("namespace_title").trim(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces`, { method: "POST", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ title }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "KV Namespace Berhasil Dibuat!" : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- KV: DELETE NAMESPACE --- if (action === "delete-kv-namespace") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const nsId = formData.get("namespace_id"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${nsId}`, { method: "DELETE", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "Namespace Berhasil Dihapus!" : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- KV: LIST KEYS --- if (action === "list-kv-pairs") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const nsId = formData.get("namespace_id"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${nsId}/keys?per_page=100`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- KV: WRITE PAIR --- if (action === "put-kv-pair") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const nsId = formData.get("namespace_id"); const key = formData.get("kv_key").trim(); const value = formData.get("kv_value"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${nsId}/values/${key}`, { method: "PUT", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") }, body: value }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "Key-Value Berhasil Disimpan!" : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- KV: DELETE PAIR --- if (action === "delete-kv-pair") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const nsId = formData.get("namespace_id"); const key = formData.get("kv_key"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${nsId}/values/${key}`, { method: "DELETE", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false }), { status: 500 }); } } // --- KV: LIST CURRENT BINDINGS --- if (action === "list-kv-bindings") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const targetWorker = formData.get("target_worker").trim().toLowerCase(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/bindings`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); if (data.success) { const kvBindings = data.result.filter(b => b.type === "kv_namespace"); return new Response(JSON.stringify(kvBindings), { headers: { "Content-Type": "application/json" } }); } return new Response(JSON.stringify([]), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- KV: BIND TO WORKER SERVICE --- if (action === "bind-kv-worker") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const targetWorker = formData.get("target_worker").trim().toLowerCase(); const bindingName = formData.get("binding_name").trim(); const namespaceId = formData.get("namespace_id"); const accountId = await getAccountId(email, apiKey); const currentSettingsRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/bindings`, { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const currentSettings = await currentSettingsRes.json(); let bindings = currentSettings.success && Array.isArray(currentSettings.result) ? currentSettings.result : []; bindings = bindings.filter(b => !(b.type === "kv_namespace" && b.name === bindingName)); bindings.push({ type: "kv_namespace", name: bindingName, namespace_id: namespaceId }); const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ bindings: bindings })], { type: "application/json" })); const bindRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const bindData = await bindRes.json(); return new Response(JSON.stringify({ success: bindData.success, msg: bindData.success ? `Sukses mengikat KV ke Worker ${targetWorker}! Variabel: env.${bindingName}` : (bindData.errors?.[0]?.message || "Gagal melakukan binding KV.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- KV: DELETE BINDING --- if (action === "delete-kv-binding") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const targetWorker = formData.get("target_worker").trim().toLowerCase(); const bindingName = formData.get("binding_name").trim(); const accountId = await getAccountId(email, apiKey); const currentSettingsRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/bindings`, { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const currentSettings = await currentSettingsRes.json(); let bindings = currentSettings.success && Array.isArray(currentSettings.result) ? currentSettings.result : []; bindings = bindings.filter(b => !(b.type === "kv_namespace" && b.name === bindingName)); const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ bindings: bindings })], { type: "application/json" })); const bindRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const bindData = await bindRes.json(); return new Response(JSON.stringify({ success: bindData.success, msg: bindData.success ? `Binding env.${bindingName} berhasil dicopot dari Worker ${targetWorker}!` : (bindData.errors?.[0]?.message || "Gagal menghapus binding KV.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- R2: LIST BUCKETS --- if (action === "list-r2-buckets") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/buckets`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result.buckets : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- R2: CREATE BUCKET --- if (action === "create-r2-bucket") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const bucketName = formData.get("bucket_name").trim().toLowerCase(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/buckets`, { method: "POST", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ name: bucketName }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? `Bucket R2 "${bucketName}" berhasil dibuat, bos!` : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- R2: DELETE BUCKET --- if (action === "delete-r2-bucket") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const bucketName = formData.get("bucket_name"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/buckets/${bucketName}`, { method: "DELETE", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "Bucket R2 berhasil dihapus!" : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- R2: LIST OBJECTS / DATA --- if (action === "list-r2-objects") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const bucketName = formData.get("bucket_name"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/buckets/${bucketName}/objects?per_page=100`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- R2: UPLOAD DATA / OBJECT --- if (action === "upload-r2-object") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const bucketName = formData.get("bucket_name"); const objectKey = formData.get("object_key").trim(); const file = formData.get("file_data"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/buckets/${bucketName}/objects/${encodeURIComponent(objectKey)}`, { method: "PUT", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": file ? (file.type || "application/octet-stream") : "application/octet-stream" }, body: file }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? `File/Data "${objectKey}" berhasil diupload!` : (data.errors?.[0]?.message || "Gagal upload file.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- R2: READ / DOWNLOAD DATA --- if (action === "get-r2-object") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const bucketName = formData.get("bucket_name"); const objectKey = formData.get("object_key"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/buckets/${bucketName}/objects/${encodeURIComponent(objectKey)}`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); return new Response(res.body, { headers: { "Content-Disposition": `attachment; filename="${objectKey}"` } }); } catch (err) { return new Response("Error: " + err.message, { status: 500 }); } } // --- R2: DELETE DATA / OBJECT --- if (action === "delete-r2-object") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const bucketName = formData.get("bucket_name"); const objectKey = formData.get("object_key"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/buckets/${bucketName}/objects/${encodeURIComponent(objectKey)}`, { method: "DELETE", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "File berhasil dihapus!" : "Gagal menghapus file." }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- R2: LIST CURRENT BINDINGS --- if (action === "list-r2-bindings") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const targetWorker = formData.get("target_worker").trim().toLowerCase(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/bindings`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); if (data.success) { const r2Bindings = data.result.filter(b => b.type === "r2_bucket"); return new Response(JSON.stringify(r2Bindings), { headers: { "Content-Type": "application/json" } }); } return new Response(JSON.stringify([]), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- R2: BIND TO WORKER SERVICE --- if (action === "bind-r2-worker") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const targetWorker = formData.get("target_worker").trim().toLowerCase(); const bindingName = formData.get("binding_name").trim(); const bucketName = formData.get("bucket_name"); const accountId = await getAccountId(email, apiKey); const currentSettingsRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/bindings`, { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const currentSettings = await currentSettingsRes.json(); let bindings = currentSettings.success && Array.isArray(currentSettings.result) ? currentSettings.result : []; bindings = bindings.filter(b => !(b.type === "r2_bucket" && b.name === bindingName)); bindings.push({ type: "r2_bucket", name: bindingName, bucket_name: bucketName }); const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ bindings: bindings })], { type: "application/json" })); const bindRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const bindData = await bindRes.json(); return new Response(JSON.stringify({ success: bindData.success, msg: bindData.success ? `Sukses mengikat R2 Bucket ke Worker ${targetWorker}! Variabel: env.${bindingName}` : (bindData.errors?.[0]?.message || "Gagal melakukan binding R2.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- R2: DELETE BINDING --- if (action === "delete-r2-binding") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const targetWorker = formData.get("target_worker").trim().toLowerCase(); const bindingName = formData.get("binding_name").trim(); const accountId = await getAccountId(email, apiKey); const currentSettingsRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/bindings`, { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const currentSettings = await currentSettingsRes.json(); let bindings = currentSettings.success && Array.isArray(currentSettings.result) ? currentSettings.result : []; bindings = bindings.filter(b => !(b.type === "r2_bucket" && b.name === bindingName)); const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ bindings: bindings })], { type: "application/json" })); const bindRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const bindData = await bindRes.json(); return new Response(JSON.stringify({ success: bindData.success, msg: bindData.success ? `Binding R2 env.${bindingName} berhasil dicopot dari Worker ${targetWorker}!` : (bindData.errors?.[0]?.message || "Gagal menghapus binding R2.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- D1: LIST DATABASES --- if (action === "list-d1-databases") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database?per_page=100`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- D1: CREATE DATABASE --- if (action === "create-d1-database") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const name = formData.get("database_name").trim(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database`, { method: "POST", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ name }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? `D1 Database "${name}" berhasil dibuat!` : (data.errors?.[0]?.message || "Gagal membuat DB D1.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- D1: DELETE DATABASE --- if (action === "delete-d1-database") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const dbId = formData.get("database_id"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database/${dbId}`, { method: "DELETE", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "Database D1 berhasil dihapus!" : (data.errors?.[0]?.message || "Gagal menghapus database.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- D1: EXECUTE QUERY (READ / EDIT / DELETE SQL) --- if (action === "execute-d1-query") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const dbId = formData.get("database_id"); const sql = formData.get("sql_query").trim(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database/${dbId}/query`, { method: "POST", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ sql }) }); const data = await res.json(); return new Response(JSON.stringify(data), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, error: err.message }), { status: 500 }); } } // --- D1: LIST CURRENT BINDINGS --- if (action === "list-d1-bindings") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const targetWorker = formData.get("target_worker").trim().toLowerCase(); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/bindings`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); if (data.success) { const d1Bindings = data.result.filter(b => b.type === "d1"); return new Response(JSON.stringify(d1Bindings), { headers: { "Content-Type": "application/json" } }); } return new Response(JSON.stringify([]), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- D1: BIND TO WORKER SERVICE --- if (action === "bind-d1-worker") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const targetWorker = formData.get("target_worker").trim().toLowerCase(); const bindingName = formData.get("binding_name").trim(); const dbId = formData.get("database_id"); const accountId = await getAccountId(email, apiKey); const currentSettingsRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/bindings`, { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const currentSettings = await currentSettingsRes.json(); let bindings = currentSettings.success && Array.isArray(currentSettings.result) ? currentSettings.result : []; bindings = bindings.filter(b => !(b.type === "d1" && b.name === bindingName)); bindings.push({ type: "d1", name: bindingName, id: dbId }); const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ bindings: bindings })], { type: "application/json" })); const bindRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const bindData = await bindRes.json(); return new Response(JSON.stringify({ success: bindData.success, msg: bindData.success ? `Sukses mengikat D1 DB ke Worker ${targetWorker}! Variabel: env.${bindingName}` : (bindData.errors?.[0]?.message || "Gagal melakukan binding D1.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- D1: DELETE BINDING --- if (action === "delete-d1-binding") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const targetWorker = formData.get("target_worker").trim().toLowerCase(); const bindingName = formData.get("binding_name").trim(); const accountId = await getAccountId(email, apiKey); const currentSettingsRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/bindings`, { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const currentSettings = await currentSettingsRes.json(); let bindings = currentSettings.success && Array.isArray(currentSettings.result) ? currentSettings.result : []; bindings = bindings.filter(b => !(b.type === "d1" && b.name === bindingName)); const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ bindings: bindings })], { type: "application/json" })); const bindRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${targetWorker}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const bindData = await bindRes.json(); return new Response(JSON.stringify({ success: bindData.success, msg: bindData.success ? `Binding D1 env.${bindingName} berhasil dicopot dari Worker ${targetWorker}!` : (bindData.errors?.[0]?.message || "Gagal menghapus binding D1.") }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- WORKER: GET CODE --- if (action === "get-worker-code") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const target = formData.get("target_worker").trim().toLowerCase(); const codeRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/content`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); let code = await codeRes.text(); if (code.includes('name="index.js"')) { code = code.replace(/^--[\s\S]*?name="index.js"[\s\S]*?\r?\n\r?\n/, "").replace(/\r?\n--[a-f0-9]+--\s*$/, ""); } return new Response(code, { headers: { "Content-Type": "text/plain" } }); } catch (err) { return new Response("Error: " + err.message, { status: 500 }); } } // --- WORKER: GET RUNTIME SETTINGS --- if (action === "get-worker-settings") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const target = formData.get("target_worker").trim().toLowerCase(); let compatDate = "2024-01-01"; let compatFlags = ""; let placementType = "default"; let placementRegion = "ap-southeast-3"; let placementProvider = "aws"; let placementHost = ""; const settingsRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/settings`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const settingsData = await settingsRes.json(); if (settingsData.success && settingsData.result) { compatDate = settingsData.result.compatibility_date || compatDate; if (settingsData.result.compatibility_flags) { compatFlags = settingsData.result.compatibility_flags.join(", "); } if (settingsData.result.placement) { const p = settingsData.result.placement; if (p.mode === "smart") { placementType = "smart"; } else if (p.mode === "targeted") { if (p.region) { placementType = "region"; if (p.region.startsWith("aws:")) { placementProvider = "aws"; placementRegion = p.region.replace("aws:", ""); } else if (p.region.startsWith("gcp:")) { placementProvider = "gcp"; placementRegion = p.region.replace("gcp:", ""); } else { placementRegion = p.region; } } else if (p.host) { placementType = "service"; placementHost = p.host; } } } } return new Response(JSON.stringify({ compatibility_date: compatDate, compatibility_flags: compatFlags, placement_type: placementType, placement_provider: placementProvider, placement_region: placementRegion, placement_host: placementHost }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ error: err.message }), { status: 500 }); } } // --- WORKER: UPDATE PLACEMENT REGION --- if (action === "update-worker-placement") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const target = formData.get("target_worker").trim().toLowerCase(); const placementType = formData.get("placement_type") || "default"; const provider = formData.get("placement_provider") || "aws"; const placementRegion = formData.get("placement_region") || "ap-southeast-3"; const placementHost = formData.get("placement_host")?.trim() || ""; const accountId = await getAccountId(email, apiKey); let placementObj = { mode: "off" }; if (placementType === "smart") { placementObj = { mode: "smart" }; } else if (placementType === "region") { placementObj = { mode: "targeted", region: `${provider}:${placementRegion}` }; } else if (placementType === "service") { placementObj = { mode: "targeted", host: placementHost }; } const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ placement: placementObj })], { type: "application/json" })); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const data = await res.json(); if (!data.success) { return new Response(JSON.stringify({ success: false, msg: data.errors?.[0]?.message || "Gagal mengubah setelan placement." }), { status: 400 }); } return new Response(JSON.stringify({ success: true, msg: `Placement (${placementType.toUpperCase()}) Berhasil Diperbarui di Cloudflare!` }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- WORKER: UPDATE COMPATIBILITY --- if (action === "update-worker-compatibility") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const target = formData.get("target_worker").trim().toLowerCase(); const compatDate = formData.get("compatibility_date")?.trim() || "2024-01-01"; const compatFlagsRaw = formData.get("compatibility_flags")?.trim() || ""; const accountId = await getAccountId(email, apiKey); const flagsArray = compatFlagsRaw ? compatFlagsRaw.split(",").map(f => f.trim()).filter(Boolean) : []; const multipartForm = new FormData(); multipartForm.append("settings", new Blob([JSON.stringify({ compatibility_date: compatDate, compatibility_flags: flagsArray })], { type: "application/json" })); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/settings`, { method: "PATCH", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: multipartForm }); const data = await res.json(); if (!data.success) { return new Response(JSON.stringify({ success: false, msg: data.errors?.[0]?.message || "Gagal mengubah compatibility." }), { status: 400 }); } return new Response(JSON.stringify({ success: true, msg: `Compatibility Settings Berhasil Disimpan!` }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- WORKER: DEPLOY / CREATE --- if (action === "deploy-worker") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const target = formData.get("target_worker").trim().toLowerCase(); const code = formData.get("worker_code"); const accountId = await getAccountId(email, apiKey); const deployData = new FormData(); deployData.append("metadata", new Blob([JSON.stringify({ main_module: "index.js", compatibility_date: "2024-01-01" })], { type: "application/json" }), "metadata.json"); deployData.append("index.js", new Blob([code], { type: "application/javascript+module" }), "index.js"); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/content`, { method: "PUT", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey }, body: deployData }); const deployResult = await res.json(); if (!res.ok || !deployResult.success) { return new Response(JSON.stringify({ success: false, msg: deployResult.errors?.[0]?.message || "Gagal deploy kodingan ke Cloudflare." }), { status: 400 }); } try { await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}/environments/production/subdomain`, { method: "POST", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey, "Content-Type": "application/json" }, body: JSON.stringify({ enabled: true }) }); } catch(e) {} let generatedUrl = ""; try { const subRes = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/subdomain`, { headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const subData = await subRes.json(); const cfSubdomain = subData.success && subData.result ? subData.result.subdomain : ""; if (cfSubdomain) { generatedUrl = `https://${target}.${cfSubdomain}.workers.dev`; } } catch(e) {} return new Response(JSON.stringify({ success: true, msg: `Sukses Deploy Worker "${target}"!`, worker_url: generatedUrl }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- WORKER: DELETE PERMANENT --- if (action === "delete-worker-cf") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const target = formData.get("target_worker").trim().toLowerCase(); const accountId = await getAccountId(email, apiKey); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/services/${target}`, { method: "DELETE", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? `Worker "${target}" berhasil dihapus permanen!` : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- DOMAIN: LIST --- if (action === "list-domains") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/domains`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ error: err.message }), { status: 500 }); } } // --- DOMAIN: ADD --- if (action === "add-domain") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const subdomain = formData.get("subdomain").trim().toLowerCase(); const mainDomain = formData.get("main_domain").trim().toLowerCase(); const service = formData.get("target_worker").trim().toLowerCase(); const zoneId = formData.get("zone_id").trim(); const accountId = await getAccountId(email, apiKey); const hostname = subdomain ? `${subdomain}.${mainDomain}` : mainDomain; const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/domains`, { method: "PUT", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey, "Content-Type": "application/json" }, body: JSON.stringify({ environment: "production", hostname, service, zone_id: zoneId || undefined }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "Domain Berhasil Ditambahkan!" : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- DOMAIN: DELETE --- if (action === "delete-domain") { try { const email = formData.get("cf_email"); const apiKey = formData.get("cf_api_key"); const domainId = formData.get("domain_id"); const accountId = await getAccountId(email, apiKey); const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/domains/${domainId}`, { method: "DELETE", headers: { "X-Auth-Email": email, "X-Auth-Key": apiKey } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false }), { status: 500 }); } } // --- DNS: LIST RECORDS --- if (action === "list-dns") { try { const zoneId = formData.get("zone_id"); const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records?per_page=100`, { headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify(data.success ? data.result : []), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify([]), { status: 500 }); } } // --- DNS: ADD RECORD --- if (action === "add-dns") { try { const zoneId = formData.get("zone_id"); const type = formData.get("dns_type"); const name = formData.get("dns_name").trim().toLowerCase(); const content = formData.get("dns_content").trim(); const ttl = parseInt(formData.get("dns_ttl")) || 1; const proxied = formData.get("dns_proxied") === "true"; const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`, { method: "POST", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ type, name, content, ttl, proxied }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "DNS Record Berhasil Ditambahkan!" : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- DNS: UPDATE RECORD --- if (action === "update-dns") { try { const zoneId = formData.get("zone_id"); const recordId = formData.get("record_id"); const type = formData.get("dns_type"); const name = formData.get("dns_name").trim().toLowerCase(); const content = formData.get("dns_content").trim(); const ttl = parseInt(formData.get("dns_ttl")) || 1; const proxied = formData.get("dns_proxied") === "true"; const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recordId}`, { method: "PUT", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ type, name, content, ttl, proxied }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "DNS Record Berhasil Diperbarui!" : data.errors[0].message }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message }), { status: 500 }); } } // --- DNS: DELETE RECORD --- if (action === "delete-dns") { try { const zoneId = formData.get("zone_id"); const recordId = formData.get("record_id"); const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recordId}`, { method: "DELETE", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key") } }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false }), { status: 500 }); } } // --- DOMAIN: ADD NEW ZONE --- if (action === "add-new-zone") { try { const accountId = await getAccountId(formData.get("cf_email"), formData.get("cf_api_key")); const domainName = formData.get("new_domain_name").trim().toLowerCase(); const res = await fetch(`https://api.cloudflare.com/client/v4/zones`, { method: "POST", headers: { "X-Auth-Email": formData.get("cf_email"), "X-Auth-Key": formData.get("cf_api_key"), "Content-Type": "application/json" }, body: JSON.stringify({ name: domainName, account: { id: accountId }, type: "full" }) }); const data = await res.json(); return new Response(JSON.stringify({ success: data.success, msg: data.success ? "Domain Utama Berhasil Ditambahkan ke Cloudflare!" : data.errors[0].message, name_servers: data.success ? data.result.name_servers : [] }), { headers: { "Content-Type": "application/json" } }); } catch (err) { return new Response(JSON.stringify({ success: false, msg: err.message, name_servers: [] }), { status: 500 }); } } } return new Response(renderFullDashboard(), { headers: { "Content-Type": "text/html; charset=utf-8" } }); } }; // ==================== BAGIAN 2: FRONTEND UI & LOGIC ==================== function renderFullDashboard() { return ` Cloudflare Worker Multi-Account Premium

🛠️ Cloudflare Worker Multi-Account

🔑 Belum punya Global API Key Cloudflare?
Silahkan klik di sini untuk mengambil Global API Key akun Cloudflare kamu (masuk ke menu API Tokens lalu klik View pada baris Global API Key).
Loading akun...
Load list management...
Preset Script Tersedia:
Preset Script Tersedia:

📋 Daftar Environment Variables & Secrets Terpasang:

Silahkan pilih target worker terlebih dahulu, bos.

🌐 Root Subdomain (*.workers.dev)

Subdomain Akun Saat Ini: Loading...
Mengubah subdomain akan mengganti semua URL live worker kamu menjadi https://nama-worker.subdomainbaru.workers.dev.
*.workers.dev Rute:

1. Manajemen Cloudflare Tunnel

Load data tunnel...

2. Tambah / Hubungkan Public Hostname (Ingress Route)

Contoh: http://localhost:8080 (Web), tcp://localhost:22 (SSH), socks://localhost:1080.

📋 Daftar Public Hostname & Target Port Terpasang:

Pilih tunnel di atas terlebih dahulu, bos.

1. Pendaftaran Destinasi Email Forwarding

Load list destinasi...

2. Konfigurasi Rute Domain & Set MX Records

🆕 Buat Namespace Baru


🔗 Ikat (Bind) KV Namespace ke Worker


📋 Daftar Binding KV Terpasang Saat Ini

Silahkan pilih worker terlebih dahulu, bos.

📝 Manajemen Key-Value Data

1. Buat & Kelola Bucket R2


2. Upload Data & Baca/Unduh Objek R2

📋 Daftar File Objek di Bucket:

Pilih bucket di atas dulu, bos.

3. Ikat (Bind) R2 Storage ke Worker

📋 Daftar Binding R2 Terpasang Saat Ini

Silahkan pilih worker terlebih dahulu, bos.

1. Buat & Kelola Cloudflare D1 Database


2. Eksekusi SQL (Baca / Edit / Hapus Baris Data)


3. Ikat (Bind) D1 Database ke Worker

📋 Daftar Binding D1 Terpasang Saat Ini

Silahkan pilih worker terlebih dahulu, bos.

🛠️ Tambah Menu / Tab Dinamis Baru (Simpan ke KV)

Masukkan script / kode HTML tools yang ingin dijadikan menu baru di dashboard:


📋 Daftar Menu Custom Terpasang:

`; }