Cloudflare Worker Code
/**
* Discord slash command verification proxy
* Uses your Discord application's PUBLIC_KEY
* Forwards verified requests to your n8n webhook
*/
async function handleRequest(request) {
const PUBLIC_KEY = "YOUR_APPLICATION_PUBLIC_KEY";
const BOT_URL = "YOUR_N8N_URL"
const encoder = new TextEncoder();
const signature = request.headers.get("x-signature-ed25519");
const timestamp = request.headers.get("x-signature-timestamp");
const body = await request.text();
// Verify signature
const isValid = await verifyDiscordRequest(body, signature, timestamp, PUBLIC_KEY);
if (!isValid) {
return new Response("Invalid request signature", { status: 401 });
}
const json = JSON.parse(body);
// Respond to Discord PING for endpoint verification
if (json.type === 1) {
return new Response(JSON.stringify({ type: 1 }), {
headers: { "Content-Type": "application/json" },
});
}
// Forward verified payload to your n8n webhook URL
await fetch(BOT_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(json),
});
// Respond to Discord to acknowledge
return new Response(JSON.stringify({ type: 5 }), {
headers: { "Content-Type": "application/json" },
});
}
// Helper: verify Discord request signature
async function verifyDiscordRequest(body, signature, timestamp, publicKey) {
const cryptoKey = await crypto.subtle.importKey(
"raw",
hexToBytes(publicKey),
{ name: "Ed25519", namedCurve: "Ed25519" },
false,
["verify"]
);
const message = concatUint8Arrays(
new TextEncoder().encode(timestamp),
new TextEncoder().encode(body)
);
return crypto.subtle.verify(
"Ed25519",
cryptoKey,
hexToBytes(signature),
message
);
}
// Helper: hex to Uint8Array
function hexToBytes(hex) {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return bytes;
}
// Helper: concatenate two Uint8Arrays
function concatUint8Arrays(a, b) {
const c = new Uint8Array(a.length + b.length);
c.set(a, 0);
c.set(b, a.length);
return c;
}
export default {
fetch: handleRequest
};CURL Command for Creating a Slash Command on Discord
curl -X POST "https://discord.com/api/v10/applications/YOUR_APP_ID/commands" \
-H "Authorization: Bot YOUR_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "joke",
"type": 1,
"description": "Get a joke for your topic",
"options": [
{
"name": "query",
"description": "Your query",
"type": 3,
"required": true
}
]
}'AI Agent System Prompt
You are a joke bot for discord. You reply with a joke based on the user input
Code Node
for (const item of $input.all()) {
const text = item.json.output; // your joke string
// Replace backslashes first to avoid double-escaping them
let escaped = text.replace(/\\/g, '\\\\');
// Then escape double quotes
escaped = escaped.replace(/"/g, '\\"');
item.json.escapedContent = escaped;
}
return $input.all();Discord URL
https://discord.com/api/v10/webhooks/{{ $('Webhook').item.json.body.application_id }}/{{ $('Webhook').item.json.body.token }}