Discord Example App

repository·main·Indexed 20 days ago

https://github.com/discord/discord-example-app

A basic rock-paper-scissors Discord application built with JavaScript. This example demonstrates how to implement Discord slash commands, buttons, modals, and select menus using Node.js and the discord-interactions package.

Tokens
1.4K
Snippets
7
Records
7
Agent score
22%

What's inside discord-example-app

  1. Set up local interactivity with ngrok

    main

    Discord requires a public HTTPS endpoint to send interaction requests. For local development, use ngrok to tunnel traffic to your local machine.

    1. Start ngrok on port 3000:
      ngrok http 3000
    2. Copy the Forwarding URL: Find the URL starting with https:// (e.g., https://1234-someurl.ngrok.io).
    3. Configure Discord:
      • Go to your app's settings in the Discord Developer Portal.
      • On the General Information tab, locate the Interactions Endpoint URL field.
      • Paste your ngrok URL and append /interactions to the end (e.g., https://1234-someurl.ngrok.io/interactions).
      • Click Save Changes.
    ngrok http 3000
  2. Install and setup the Discord example app

    main

    To run the rock-paper-scissors example app locally, follow these steps:

    1. Prerequisites: Install NodeJS and create a Discord app in the Discord Developer Portal with the following permissions:
      • applications.commands
      • bot (with Send Messages enabled)
    2. Clone the repository:
      git clone https://github.com/discord/discord-example-app.git
    3. Install dependencies:
      cd discord-example-app
      npm install
    4. Configure credentials: Create a .env file based on .env.sample and populate it with your app's credentials.
    git clone https://github.com/discord/discord-example-app.git
    cd discord-example-app
    npm install
  3. Configure environment variables for the Discord app

    main

    The application requires specific credentials from your Discord application settings to function. Create a .env file in the project root and add the following keys:

    • APP_ID: Your application's ID.
    • DISCORD_TOKEN: Your bot's token.
    • PUBLIC_KEY: Your application's public key.

    Refer to .env.sample for the required format.

    APP_ID=your_app_id
    DISCORD_TOKEN=your_bot_token
    PUBLIC_KEY=your_public_key
  4. Handle Discord interactions via the /interactions endpoint

    main

    The application uses an Express server with a POST endpoint at /interactions to receive and process Discord interactions. To ensure security, the endpoint must use the verifyKeyMiddleware from the discord-interactions package, passing in your application's PUBLIC_KEY from your environment variables.

    Incoming requests contain an id, type, and data object. You must handle two primary interaction types:

    1. InteractionType.PING: Respond with InteractionResponseType.PONG to acknowledge the connection.
    2. InteractionType.APPLICATION_COMMAND: Process slash commands by checking the name property within the data object.

    When responding to a slash command, you can use InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE to send a message back to the channel.

    import { verifyKeyMiddleware, InteractionType, InteractionResponseType } from 'discord-interactions';
    
    app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async function (req, res) {
      const { id, type, data } = req.body;
    
      if (type === InteractionType.PING) {
        return res.send({ type: InteractionResponseType.PONG });
      }
    
      if (type === InteractionType.APPLICATION_COMMAND) {
        const { name } = data;
        // Handle commands here...
      }
    });
  5. Respond to slash commands with components

    main

    When responding to an APPLICATION_COMMAND interaction, you can include UI components in your response. For example, using InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, you can provide a data object containing components.

    To use modern component features, include the InteractionResponseFlags.IS_COMPONENTS_V2 flag. Components are defined by a type (e.g., MessageComponentTypes.TEXT_DISPLAY) and a content string.

    // Example response for a 'test' command
    return res.send({
      type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
      data: {
        flags: InteractionResponseFlags.IS_COMPONENTS_V2,
        components: [
          {
            type: MessageComponentTypes.TEXT_DISPLAY,
            content: `hello world ${getRandomEmoji()}`
          }
        ]
      },
    });