Skip to content

Making a Ping-Pong Bot

Creating a Discord Bot

  1. Go to https://discord.com/developers/applications
  2. Create an Application
  3. Give the application an awesome name (this will be used as the bots initial username)

    name

  4. Click Save Changes

  5. Open the Bot tab

    create bot

  6. Click Add Bot and confirm

  7. Public bots are invitable using only their ID, so unselect this option if you want this bot to be private.

    public bot

    You only want require code grant enabled if you plan to use an oauth2 flow, the general user will not need this.

Add your Discord Bot to a Server

  1. Retrieve your application/client ID from the General Information tab

    client id

  2. Create an OAuth2 authorization URL (reference docs). Users who want to use Interaction Commands should also add the applications.commands scope, though this scope is now implicitly provided. Some example URLs:

    • https://discord.com/api/oauth2/authorize?client_id=492747769036013578&scope=bot
    • https://discord.com/api/oauth2/authorize?client_id=492747769036013578&scope=bot+applications.commands

    Note

    This can be done from the Bot tab at the very bottom. Here you can select the scope bot and some permissions required for your bots functionality (optional).

  3. Open the authorization dialogue (click link from step 2)

  4. Select your Server (Requires permission to manage server)
  5. Click Authorize

    authorize

Connecting to Discord with a Bot Account

  1. Retrieve your Bot Token from your application dashboard by navigating to the "Bot" tab and pressing the "Reset Token" button.

    get token

    Caution

    Do not show this token to anyone, ever. It will allow an attacker to gain full control of your bot.
    If you have accidentally shown or pasted your token, the "Reset Token" button will invalidate any old tokens.

  2. Set up your JDA project:

Download

  1. Create a JDABuilder instance using the static method JDABuilder.createDefault, adding your token.

    JDABuilder Configuration

    The JDABuilder is the key to configuring JDA and is where options like intents and caching options are contained. The Javadocs page is useful for explaining the different configurations. Bear in mind that access to some events (for example member join events) require specific intents to be enabled. Check the docs for the event if you're not sure.

  2. Build JDA using JDABuilder.build().

    public static void main(String[] arguments) throws Exception
    {
        JDA api = JDABuilder.createDefault(BOT_TOKEN).build();
    }
    

    Tip

    It is often better to load your token in from an external file or environment variable, especially if you plan on publishing the source code. This makes it harder to accidentally leak your token either in asking for help or when pushing code to your VCS. It is not recommended to use program arguments to handle any sensitive data, as program arguments are visible to other users of the system.

Making a Ping-Pong Protocol

Privileged Message Content Intent

Be aware that the ability for bots to read the text of messages is gated behind a privileged intent. This means that bots will not have access to it by default. Bots in under 100 servers can manually enable it in their bot dashboard. In order to access the GatewayIntent.MESSAGE_CONTENT intent, it needs to be explicitly enabled in the JDABuilder.

  1. Setup your JDA instance (see Connecting To Discord)
  2. Implement an EventListener or extend ListenerAdapter

    Main.java
    public static void main(String[] arguments) throws Exception
    {
        JDA api = JDABuilder.createDefault(BOT_TOKEN)
                            .enableIntents(GatewayIntent.GUILD_MESSAGES)
                            .addEventListeners(new MyListener())
                            .build();
    }
    
    MyListener.java
    public class MyListener extends ListenerAdapter 
    {
        @Override
        public void onMessageReceived(MessageReceivedEvent event)
        {
            if (event.getAuthor().isBot()) return;
            // We don't want to respond to other bot accounts, including ourselves
            Message message = event.getMessage();
            String content = message.getContentRaw(); 
            // getContentRaw() is an atomic getter
            // getContentDisplay() is a lazy getter which modifies the content for e.g. console view (strip discord formatting)
            if (content.equals("!ping"))
            {
                MessageChannel channel = event.getChannel();
                channel.sendMessage("Pong!").queue(); // Important to call .queue() on the RestAction returned by sendMessage(...)
            }
        }
    }
    

    Info

    More information about RestActions can be found here, and more information about listening to events can be found here.

  3. Register your listener with either JDABuilder.addEventListeners(new MyListener()) or JDA.addEventListeners(new MyListener()) (see Events)

Making a Slash Command Bot

For additional information on slash commands and interactions in general, please visit the Interactions page.

  1. As with above, set up your IDE, bot and JDA instance.
  2. Find the ID of the guild you want to test with. If you have Discord's developer mode active, you can right-click the guild and copy its ID.
  3. To use slash commands, they have to be registered in advance. We'll use a ready listener to find out when JDA is ready.
    In this listener we will get the testing guild from JDA and register a simple command with it.

        public class SlashBotExample extends ListenerAdapter{
    
            public static void main(String[] args){
                //JDA initialisation here
                jda.addEventListener(new SlashBotExample());
            }
    
            @Override
            public void onReady(ReadyEvent event){
                event.getJDA().getGuildById(GUILD_ID).updateCommands()
                        .addCommands(Commands.slash("hello", "Wave to say hi!"))
                        .queue();
            }
        }
    
    If you see a "Missing Access" exception when trying to update the commands, then ensure that the bot has the correct scope (applications.commands) in this guild.
    You can re-invite the bot without kicking it to update the scopes.

    Information

    updateCommands() will overwrite the current commands with the ones you provide. Calling updateCommands().queue() will clear all of this bot's commands from that guild.

  4. Next up, you should see your command in the client. However, nothing happens when you run your command, and Discord tells you that the application did not respond. To fix this, we need our bot to tell Discord that we know something happened. You can read more about interactions on the Interactions page for more information about how interactions are acknowledged. To respond to our command here, we will be listening for the SlashCommandInteractionEvent.

        public class SlashBotExample extends ListenerAdapter{
    
            public static void main(String[] args){
                //JDA initialisation here
                jda.addEventListener(new SlashBotExample());
            }
    
            @Override
            public void onReady(ReadyEvent event){
                event.getJDA().getGuildById(GUILD_ID).updateCommands()
                        .addCommands(Commands.slash("hello", "Wave to say hi!"))
                        .queue();
            }
    
            @Override
            public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
                if (event.getName().equals("hello")) {
                    event.reply("Hello back to you!").queue();
                }
            }
        }
    

    Guild and Global Commands

    These commands are created in the guild and do not show anywhere else. Global commands can be created using the JDA object, more information can be found on the Interactions page. This guide uses guild commands as they are easier to debug - guild commands will fail with an error if a scope is missing.