discord-interactions-js

repository·main·Indexed 19 days ago

https://github.com/discord/discord-interactions-js

A lightweight library providing types and helper functions for implementing Discord webhooks, including slash command interactions and real-time webhook events. It includes tools for signature verification via the verifyKey function and dedicated Express-compatible middleware (verifyKeyMiddleware and verifyWebhookEventMiddleware), as well as TypeScript types and enums for building Discord Message Components such as buttons, select menus, and text inputs.

Tokens
4.5K
Snippets
21
Records
21
Agent score
66%

What's inside discord-interactions

  1. Run the library examples

    main

    To run the provided examples, build the project, export your Discord App Public Key, and run the desired example file using Node.js.

    npm run build 
    export CLIENT_PUBLIC_KEY=${Your Discord App Public Key} 
    node examples/express_app.js # or choose a different example
  2. Verify Interaction request signatures

    main

    To ensure requests to your endpoint are actually coming from Discord, use the verifyKey function. You must provide the raw request body, the X-Signature-Ed25519 header, the X-Signature-Timestamp header, and your Discord App Public Key.

    Important: req.rawBody must be populated by a middleware. Do not use middlewares like body-parser on interaction routes as they can tamper with the raw body and cause verification to fail.

    const signature = req.get('X-Signature-Ed25519');
    const timestamp = req.get('X-Signature-Timestamp');
    const isValidRequest = await verifyKey(req.rawBody, signature, timestamp, 'MY_CLIENT_PUBLIC_KEY');
    if (!isValidRequest) {
      return res.status(401).end('Bad request signature');
    }
  3. Verify Webhook Event signatures

    main

    To verify real-time notifications (Webhook Events) from Discord, use verifyKey with the same parameters as interaction verification. For Express-like APIs, use verifyWebhookEventMiddleware to simplify the process.

    app.post(
    	'/events',
    	verifyWebhookEventMiddleware(process.env.CLIENT_PUBLIC_KEY),
    	(req, res) => {
    		console.log("📨 Event Received!")
            console.log(req.body);
    	},
    );
  4. Use verifyKeyMiddleware for Express-like APIs

    main

    If you are using an Express-like framework, you can use verifyKeyMiddleware to automatically handle signature verification for interaction routes. This simplifies your route handlers by abstracting the signature check.

    app.post('/interactions', verifyKeyMiddleware('MY_CLIENT_PUBLIC_KEY'), (req, res) => {
      const message = req.body;
      if (message.type === InteractionType.APPLICATION_COMMAND) {
        res.send({
          type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
          data: {
            content: 'Hello world',
          },
        });
      }
    });
  5. Reference: Message Component Types and Structures

    main

    The library provides TypeScript types and enums for building Discord Message Components (buttons, selects, etc.).

    | Type/Enum | Description |
    |---|---|
    | `MessageComponentTypes` | An enum of message component types that can be used in messages and modals. |
    | `ActionRow` | Type for Action Rows |
    | `Button` | Type for Buttons |
    | `ButtonStyleTypes` | Enum for Button Styles |
    | `StringSelect` | Type for String Selects |
    | `StringSelectOption` | Type for String Select Options |
    | `UserSelect` | Type for User Selects |
    | `RoleSelect` | Type for Role Selects |
    | `MentionableSelect` | Type for Mentionable Selects |
    | `ChannelSelect` | Type for Channel Selects |
    | `InputText` | Type for Text Inputs |
    | `TextStyleTypes` | Enum for Text Style Types |
    | `Section` | Type for Sections |
    | `TextDisplay` | Type for Text Displays |
    | `Thumbnail` | Type for Thumbnails |
    | `MediaGallery` | Type for Media Galleries |
    | `MediaGalleryItem` | Type for Media Gallery Item |
    | `FileComponent` | Type for File Components |
    | `Separator` | Type for Separators |
    | `Container` | Type for Containers |
    | `UnfurledMediaItem` | Type for Unfurled Media Item |
  6. Reference: Webhook Event Enums

    main

    Use these enums to process incoming event webhooks.

    | Enum | Description |
    |---|---|
    | `WebhookType` | An enum of interaction types that can be POSTed to your webhook endpoint. |
    | `WebhookEventType` | An enum of response types you may provide in reply to Discord's webhook. |
  7. Reference: Interaction Enums

    main

    These enumerations help identify the type of interaction received and the type of response your application should provide to Discord.

    | Enum | Description |
    |---|---|
    | `InteractionType` | An enum of interaction types that can be POSTed to your webhook endpoint. |
    | `InteractionResponseType` | An enum of response types you may provide in reply to Discord's webhook. |
    | `InteractionResponseFlags` | An enum of flags you can set on your response data. |
  8. Verify Discord interaction signatures with `verifyKey`

    main

    Use verifyKey to manually validate that an incoming request payload from Discord is authentic. This is useful if you are not using the provided Express middleware.

    Parameters:

    • rawBody: The raw payload data (can be Uint8Array, ArrayBuffer, Buffer, or string).
    • signature: The signature string from the X-Signature-Ed25519 header.
    • timestamp: The timestamp string from the X-Signature-Timestamp header.
    • clientPublicKey: Your Discord application's public key (as a hex string or a CryptoKey).

    Returns: A Promise<boolean> which is true if the signature is valid, false otherwise.

    import { verifyKey } from 'discord-interactions';
    
    const isValid = await verifyKey(
      rawBody,
      signatureHeader,
      timestampHeader,
      CLIENT_PUBLIC_KEY
    );
  9. Create TextInput components

    main

    The TextInput component is used to collect text input from a user (typically within a Modal).

    Key properties:

    • custom_id: Unique identifier for the input.
    • style: Either TextStyleTypes.SHORT or TextStyleTypes.PARAGRAPH.
    • label: The label displayed above the input.
    • min_length / max_length: Constraints on the input size.
    • required: Whether the input must be filled.
    • placeholder: Hint text shown in the input.
    const textInput: TextInput = {
      type: MessageComponentTypes.INPUT_TEXT,
      custom_id: 'user_feedback',
      style: TextStyleTypes.PARAGRAPH,
      label: 'Your Feedback',
      placeholder: 'Please enter your thoughts...',
      required: true
    };
  10. Use `verifyKeyMiddleware` for Express interaction webhooks

    main

    The verifyKeyMiddleware is an Express-compatible middleware designed to secure routes receiving Discord Interactions (like Slash Commands, Message Components, or Modals).

    Key Behaviors:

    • It automatically validates the X-Signature-Ed25519 and X-Signature-Timestamp headers.
    • If the interaction is a PING (InteractionType.PING), it automatically responds with a PONG (InteractionResponseType.PONG) and terminates the request.
    • If validation fails, it returns a 401 status code.
    • On success, it attaches the parsed JSON body to req.body and calls next().

    Important Note: To avoid issues with signature verification, it is highly recommended to disable body-parsing middleware (like express.json()) for your interaction routes so that req.body remains a raw buffer.

    import express from 'express';
    import { verifyKeyMiddleware } from 'discord-interactions';
    
    const app = express();
    const PUBLIC_KEY = 'YOUR_DISCORD_PUBLIC_KEY';
    
    // Apply middleware to your interaction endpoint
    // Note: Do NOT use express.json() on this specific route
    app.post('/interactions', verifyKeyMiddleware(PUBLIC_KEY), (req, res) => {
      const interaction = req.body;
      // Handle interaction logic here
    });
  11. Create Button components

    main

    Buttons are interactive components that can be used for custom actions, links, or premium features. The Button type is a union of CustomButton, LinkButton, and PremiumButton.

    • CustomButton: Requires a custom_id and a style from ButtonStyleTypes (PRIMARY, SECONDARY, SUCCESS, or DANGER). Used for handling interaction events.
    • LinkButton: Requires a url and uses ButtonStyleTypes.LINK.
    • PremiumButton: Requires a sku_id and uses ButtonStyleTypes.PREMIUM.

    All buttons can optionally include an emoji and a label (except for Link and Premium buttons which have specific requirements).

    // Example of a Custom Button
    const myButton: Button = {
      type: MessageComponentTypes.BUTTON,
      custom_id: 'my_action_id',
      style: ButtonStyleTypes.PRIMARY,
      label: 'Click Me'
    };
    
    // Example of a Link Button
    const linkButton: Button = {
      type: MessageComponentTypes.BUTTON,
      style: ButtonStyleTypes.LINK,
      url: 'https://example.com',
      label: 'Visit Website'
    };