{"flow":{"id":44,"summary":"Verify the Discord Request, Defer and trigger a flow","versions":[174,178,179,192,196,197,198],"created_by":"faton ramadani2","created_at":"2023-06-07T13:01:03.083Z","votes":0,"approved":false,"apps":["discord"],"value":{"modules":[{"id":"a","value":{"lock":"","path":"f/discordBot/verifyAndDefer","type":"rawscript","content":"import { REST } from \"npm:@discordjs/rest@1.7.1\";\nimport { API, MessageFlags } from \"npm:@discordjs/core@0.6.0\";\nimport {\n  JobService,\n  type Resource,\n} from \"https://deno.land/x/windmill@v1.108.0/mod.ts\";\n\nimport {\n  InteractionResponseType,\n  InteractionType,\n  verifyKey,\n} from \"npm:discord-interactions@3.4.0\";\n\ntype DiscordInteraction = {\n  id: string;\n  token: string;\n  type: InteractionType;\n};\n\nexport async function main(\n  x_signature_ed25519: string,\n  x_signature_timestamp: string,\n  raw_string: string,\n  token: string,\n  discord_config: Resource<\"discord_bot_configuration\">,\n  workspace: string,\n  path: string,\n) {\n  const rest = new REST({ version: \"10\" }).setToken(token);\n  const api = new API(rest);\n  const interaction: DiscordInteraction = JSON.parse(raw_string);\n\n  // We'll need the http request body as a string and the two headers to verify the request signature\n  // https://discord.com/developers/docs/interactions/receiving-and-responding#security-and-authorization\n  const isVerified = verifyKey(\n    raw_string,\n    x_signature_ed25519,\n    x_signature_timestamp,\n    discord_config.public_key,\n  );\n\n  if (!isVerified) {\n    throw new Error(\"The request signature is not valid\");\n  }\n\n  // If we get a PING, we need to respond with a PONG\n  const type = interaction.type as InteractionType;\n  if (type === InteractionType.PING) {\n    return { type: InteractionResponseType.PONG };\n  }\n\n  await JobService.runFlowByPath({\n    workspace,\n    path,\n    requestBody: {\n      interaction,\n    },\n  });\n\n  await api.interactions.defer(interaction.id, interaction.token, {\n    flags: MessageFlags.Ephemeral,\n  });\n}\n","language":"deno","input_transforms":{"path":{"type":"static","value":"f"},"token":{"type":"static","value":""},"workspace":{"type":"static","value":""},"raw_string":{"expr":"flow_input.raw_string","type":"javascript"},"discord_config":{"type":"static","value":""},"x_signature_ed25519":{"expr":"flow_input.x_signature_ed25519","type":"javascript"},"x_signature_timestamp":{"expr":"flow_input.x_signature_timestamp","type":"javascript"}}},"summary":"Verify and defer"}]},"schema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["x_signature_ed25519","x_signature_timestamp","raw_string"],"properties":{"raw_string":{"type":"string","format":"","default":"","description":""},"x_signature_ed25519":{"type":"string","format":"","default":null,"description":""},"x_signature_timestamp":{"type":"string","format":"","default":null,"description":""}}},"description":"Used in the Knowlegdable Discord bot as an entry point for the bot.","recording":null,"vcreated_at":"2023-06-29T09:40:57.867Z","vcreated_by":"faton ramadani2","comments":[]}}