diff --git a/app.js b/app.js index 40ddc7d..2210545 100644 --- a/app.js +++ b/app.js @@ -3,29 +3,22 @@ import express from 'express'; import { InteractionType, InteractionResponseType, - InteractionResponseFlags, - MessageComponentTypes, - ButtonStyleTypes, + verifyKeyMiddleware, } from 'discord-interactions'; -import { VerifyDiscordRequest, getRandomEmoji, DiscordRequest } from './utils.js'; -import { getShuffledOptions, getResult } from './game.js'; +import { getRandomEmoji } from './utils.js'; // Create an express app const app = express(); // Get port, or default to 3000 const PORT = process.env.PORT || 3000; -// Parse request body and verifies incoming requests using discord-interactions package -app.use(express.json({ verify: VerifyDiscordRequest(process.env.PUBLIC_KEY) })); - -// Store for in-progress games. In production, you'd want to use a DB -const activeGames = {}; /** * Interactions endpoint URL where Discord will send HTTP requests + * Parse request body and verifies incoming requests using discord-interactions package */ -app.post('/interactions', async function (req, res) { +app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async function (req, res) { // Interaction type and data - const { type, id, data } = req.body; + const { type, data } = req.body; /** * Handle verification requests @@ -48,11 +41,17 @@ app.post('/interactions', async function (req, res) { type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { // Fetches a random emoji to send from a helper function - content: 'hello world ' + getRandomEmoji(), + content: `hello world ${getRandomEmoji()}`, }, }); } + + console.error(`unknown command: ${name}`); + return res.status(400).json({ error: 'unknown command' }); } + + console.error('unknown interaction type', type); + return res.status(400).json({ error: 'unknown interaction type' }); }); app.listen(PORT, () => { diff --git a/commands.js b/commands.js index 63e496c..d282e56 100644 --- a/commands.js +++ b/commands.js @@ -42,4 +42,4 @@ const CHALLENGE_COMMAND = { const ALL_COMMANDS = [TEST_COMMAND, CHALLENGE_COMMAND]; -InstallGlobalCommands(process.env.APP_ID, ALL_COMMANDS); \ No newline at end of file +InstallGlobalCommands(process.env.APP_ID, ALL_COMMANDS); diff --git a/examples/app.js b/examples/app.js index 19eaa61..9b8ac13 100644 --- a/examples/app.js +++ b/examples/app.js @@ -6,24 +6,24 @@ import { InteractionResponseFlags, MessageComponentTypes, ButtonStyleTypes, + verifyKeyMiddleware, } from 'discord-interactions'; -import { VerifyDiscordRequest, getRandomEmoji, DiscordRequest } from './utils.js'; +import { getRandomEmoji, DiscordRequest } from './utils.js'; import { getShuffledOptions, getResult } from './game.js'; // Create an express app const app = express(); // Get port, or default to 3000 const PORT = process.env.PORT || 3000; -// Parse request body and verifies incoming requests using discord-interactions package -app.use(express.json({ verify: VerifyDiscordRequest(process.env.PUBLIC_KEY) })); // Store for in-progress games. In production, you'd want to use a DB const activeGames = {}; /** * Interactions endpoint URL where Discord will send HTTP requests + * Parse request body and verifies incoming requests using discord-interactions package */ -app.post('/interactions', async function (req, res) { +app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async function (req, res) { // Interaction type and data const { type, id, data } = req.body; @@ -48,10 +48,11 @@ app.post('/interactions', async function (req, res) { type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { // Fetches a random emoji to send from a helper function - content: 'hello world ' + getRandomEmoji(), + content: `hello world ${getRandomEmoji()}`, }, }); } + // "challenge" command if (name === 'challenge' && id) { const userId = req.body.member.user.id; @@ -86,6 +87,9 @@ app.post('/interactions', async function (req, res) { }, }); } + + console.error(`unknown command: ${name}`); + return res.status(400).json({ error: 'unknown command' }); } /** @@ -167,6 +171,9 @@ app.post('/interactions', async function (req, res) { } } } + + console.error('unknown interaction type', type); + return res.status(400).json({ error: 'unknown interaction type' }); }); app.listen(PORT, () => { diff --git a/examples/button.js b/examples/button.js index acb453b..1dc8ed9 100644 --- a/examples/button.js +++ b/examples/button.js @@ -5,14 +5,13 @@ import { InteractionResponseType, MessageComponentTypes, ButtonStyleTypes, + verifyKeyMiddleware, } from 'discord-interactions'; -import { VerifyDiscordRequest } from '../utils.js'; // Create and configure express app const app = express(); -app.use(express.json({ verify: VerifyDiscordRequest(process.env.PUBLIC_KEY) })); -app.post('/interactions', function (req, res) { +app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), function (req, res) { // Interaction type and data const { type, data } = req.body; /** diff --git a/examples/command.js b/examples/command.js index 8d6552c..5aabb5a 100644 --- a/examples/command.js +++ b/examples/command.js @@ -1,13 +1,12 @@ import 'dotenv/config'; import express from 'express'; -import { InteractionType, InteractionResponseType } from 'discord-interactions'; -import { VerifyDiscordRequest, DiscordRequest } from '../utils.js'; +import { InteractionType, InteractionResponseType, verifyKeyMiddleware } from 'discord-interactions'; +import { DiscordRequest } from '../utils.js'; // Create and configure express app const app = express(); -app.use(express.json({ verify: VerifyDiscordRequest(process.env.PUBLIC_KEY) })); -app.post('/interactions', function (req, res) { +app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), function (req, res) { // Interaction type and data const { type, data } = req.body; /** diff --git a/examples/modal.js b/examples/modal.js index bb3da16..76bba3a 100644 --- a/examples/modal.js +++ b/examples/modal.js @@ -4,14 +4,13 @@ import { InteractionType, InteractionResponseType, MessageComponentTypes, + verifyKeyMiddleware, } from 'discord-interactions'; -import { VerifyDiscordRequest } from '../utils.js'; // Create and configure express app const app = express(); -app.use(express.json({ verify: VerifyDiscordRequest(process.env.PUBLIC_KEY) })); -app.post('/interactions', function (req, res) { +app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), function (req, res) { // Interaction type and data const { type, data } = req.body; /** diff --git a/examples/selectMenu.js b/examples/selectMenu.js index bbe12f3..1420f3e 100644 --- a/examples/selectMenu.js +++ b/examples/selectMenu.js @@ -4,14 +4,13 @@ import { InteractionType, InteractionResponseType, MessageComponentTypes, + verifyKeyMiddleware, } from 'discord-interactions'; -import { VerifyDiscordRequest } from '../utils.js'; // Create and configure express app const app = express(); -app.use(express.json({ verify: VerifyDiscordRequest(process.env.PUBLIC_KEY) })); -app.post('/interactions', function (req, res) { +app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), function (req, res) { // Interaction type and data const { type, data } = req.body; /** diff --git a/package.json b/package.json index 72fbc75..035a2f2 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "author": "Shay DeWael", "license": "MIT", "dependencies": { - "discord-interactions": "^3.2.0", + "discord-interactions": "^4.0.0", "dotenv": "^16.0.3", "express": "^4.18.2" }, diff --git a/utils.js b/utils.js index fbc7248..506aea6 100644 --- a/utils.js +++ b/utils.js @@ -1,18 +1,4 @@ import 'dotenv/config'; -import { verifyKey } from 'discord-interactions'; - -export function VerifyDiscordRequest(clientKey) { - return function (req, res, buf, encoding) { - const signature = req.get('X-Signature-Ed25519'); - const timestamp = req.get('X-Signature-Timestamp'); - - const isValidRequest = verifyKey(buf, signature, timestamp, clientKey); - if (!isValidRequest) { - res.status(401).send('Bad request signature'); - throw new Error('Bad request signature'); - } - }; -} export async function DiscordRequest(endpoint, options) { // append endpoint to root API URL