iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
💨

A Complete Guide to Discord Bot Development

に公開

1. Introduction

Discord Bots can be easily created using SDKs.
The range of expressions possible with Discord Bots is wide, including not only sending text messages but also embeds and voice messages.
In this article, I will introduce what you can express with a Discord Bot and points to keep in mind during operation when creating a new Discord Bot.

The content of this article is created using Go(v1.20) and discordgo(v0.27.1).
Also, since the content is independent for each chapter, please refer to the table of contents as needed.

Target Audience

  • People who don't quite know what can be done with a Discord Bot
  • People who want to create a Discord Bot
  • People who want to know about operating a Discord Bot

2. Types of Message Expressions in Discord Bot

2.1. Text Message

  • This is the basic message format.
  • You can send text up to 2000 characters.

Text Message

Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
_, err = dg.ChannelMessageSend(channelID, "Hello, Test Channel!")

https://github.com/sugar-cat7/example-discord-bot/tree/main/simple-message

2.2. Files

You can send and share files such as images, videos, and documents.
Message with attached file

Basic formats are supported, and as an example, the following can be attached:

Images: .jpg, .jpeg, .png, .gif, .webp
Videos: .mp4, .mov
Audio: .mp3, .wav
Text: .txt, .md, .log
Documents: .pdf, .doc, .docx, .ppt, .pptx, .xls, .xlsx
Compressed files: .zip, .rar, .tar.gz
Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
resp, err := http.Get("")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

// Send a file as a message
message := &discordgo.MessageSend{
    Content: "Image:",
    Files: []*discordgo.File{
        {
            Name:   "sugar.png",
            Reader: resp.Body,
        },
    },
}

_, err = dg.ChannelMessageSendComplex(channelID, message)

https://github.com/sugar-cat7/example-discord-bot/tree/main/file-message

2.3. Reactions

  • You can add reactions to messages using emojis.

  • There are two types of emojis that can be used as reactions.

  • Unicode Emoji

Reaction 1

  • Custom Emoji

Reaction 2

Implementation Example
// Unicode Emoji
err = dg.MessageReactionAdd(channelID, message.ID, "😀")

// Custom Emoji: needs to be encoded in name:id format.
err = dg.MessageReactionAdd(channelID, message.ID, "emoji_name:emoji_id")
  • emoji_id is the XXX part obtained from the sticker link.
    • https://cdn.discordapp.com/emojis/?XXX.webp

emoji_id

https://github.com/sugar-cat7/example-discord-bot/tree/main/reaction-message

2.4. Replies

  • You can reply to specific messages.

Reply

Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
m, _ := dg.ChannelMessageSend(channelID, "Hello, Test Channel!")
message := &discordgo.MessageSend{
    Content:   "This is a reply!",
    // Specify the relevant message ID and send the content
    Reference: &discordgo.MessageReference{MessageID: m.ID},
}
_, err = dg.ChannelMessageSendComplex(channelID, message)

https://github.com/sugar-cat7/example-discord-bot/tree/main/inline-reply

2.5. Threads

  • You can create message threads organized by topic.

  • Thread names: 1–100 characters.

  • The duration until the thread is hidden can be adjusted.

Threads

Implementation Example
thread, err := s.MessageThreadStartComplex(m.ChannelID, m.ID, &discordgo.ThreadStart{
   // see: https://discord.com/developers/docs/resources/channel#start-thread-from-message
    Name:                "Pong game with " + m.Author.Username,
    AutoArchiveDuration: 60,
    Invitable:           false,
    RateLimitPerUser:    10,
})
if err != nil {
    log.Println("Error starting thread:", err)
    return
}
_, err = s.ChannelMessageSend(thread.ID, "pong")

https://github.com/sugar-cat7/example-discord-bot/tree/main/thread-message

2.6. Context Menu

A menu that provides additional actions related to a message.

Context Menu

Implementation Example
func registerContextMenu(s *discordgo.Session, guildID string) {
	// Define the context menu
   // see: https://discord.com/developers/docs/interactions/application-commands#create-global-application-command
	cmd := &discordgo.ApplicationCommand{
		Name: "share-with-me",
		Type: discordgo.MessageApplicationCommand,
	}

	_, err := s.ApplicationCommandCreate(s.State.User.ID, guildID, cmd)
	if err != nil {
		log.Println("Failed to create context menu:", err)
	}
}

https://github.com/sugar-cat7/example-discord-bot/tree/main/contex-menu

2.7. Embed Messages

This is a rich message format.

Embed Message

Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
embed := &discordgo.MessageEmbed{
    Title:       "Embed Title",
    Description: "This is an embed message",
    Color:       0x00ff00, // Green
}
_, err = dg.ChannelMessageSendEmbed(channelID, embed)

https://github.com/sugar-cat7/example-discord-bot/tree/main/embed-message

  • The embed target can be customized.

Custom

2.8. TTS (Text-to-Speech) Messages

A message format that converts text to speech and reads it aloud.

Caution: Volume

https://youtu.be/Pazc7r_mJdo

  • If the user has disabled TTS, the message will appear as regular text.
  • Fine settings such as pitch and speed of the TTS voice cannot be customized.
  • TTS messages are only played in text channels.
Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
_, err = dg.ChannelMessageSendTTS(channelID, "Hello in Text-to-Speech!")

https://github.com/sugar-cat7/example-discord-bot/tree/main/tts-message

2.9. Components (Buttons and Select Menus)

UI components that can be used within messages.

https://discord.com/developers/docs/interactions/message-components#component-object

1. ButtonComponent

  • Interactive button components displayed within messages.
    • When a user clicks them, an interaction can be sent to the app.
    • They must be sent within an action row.
    • An action row can contain up to 5 buttons and cannot include a select menu component at the same time.

Button

Refer to the following for button types.
https://discord.com/developers/docs/interactions/message-components#button-object-button-styles

Implementation Example
&discordgo.MessageComponent{
    Type: discordgo.ButtonComponent,
    Label: "Click Me!",
    Style: discordgo.PrimaryButton, // Example: Primary button
    CustomID: "button_click",
}

https://github.com/sugar-cat7/example-discord-bot/tree/main/component-message

2. SelectMenuComponent

  • Interactive components where users select options from a dropdown list within a message.
    • Supports single-select and multi-select.
    • Must be sent within an action row, and one action row can contain only one select menu. Select menus and buttons cannot be included at the same time.

Select

Implementation Example
&discordgo.MessageComponent{
    &discordgo.SelectMenu{
        CustomID: "select_option",
        Options: []discordgo.SelectMenuOption{
            {
                Label: "Option 1",
                Value: "opt1",
            },
            {
                Label: "Option 2",
                Value: "opt2",
            },
        },
    },
}

3. TextInputComponent

  • Text input is an interactive component displayed in a modal.
    • Suitable for collecting short or long-form text.

Modal
*This component is only available in Interactions.

Implementation Example
discordgo.TextInput{
    CustomID:    "text_input",
    Placeholder: "Enter some text here",
    Style:       discordgo.TextInputParagraph,
}
  • It is a feature that allows you to respond to user actions using components such as buttons, select menus, and slash commands.

https://discord.com/developers/docs/interactions/receiving-and-responding

Types of Interactions:

  1. Slash Commands:

    • A feature to launch commands using /.
    • You can create custom commands to trigger specific actions or responses.
    • They can be registered for global use or only in specific servers.
  2. Message Components:

    • You can embed the components mentioned earlier (such as TextInput).
  3. Context Menus:

    • Right-click menus for adding custom actions to users or messages.
    • They have a registration and processing flow similar to slash commands.

When performing heavy processing, it is necessary to process asynchronously while keeping the time limit in mind.

The article below achieves asynchronous processing while returning a response to the Discord Bot by setting up an endpoint that accepts requests and redirects them to a PubSub queue.

https://zenn.dev/suzuesa/articles/2bf80f33013a14

2.10. Schedule

This is a scheduling feature that allows you to send messages at a specific time or date.

  • You can register up to 100 events.

Schedule

https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event

Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
params := &discordgo.GuildScheduledEventParams{
    Name:               "Event Name",
    Description:        "Event Description",
    ScheduledStartTime: &startTime,
    ScheduledEndTime:   &endTime,
    PrivacyLevel:       discordgo.GuildScheduledEventPrivacyLevelGuildOnly,
    EntityType:         discordgo.GuildScheduledEventEntityTypeExternal,
    EntityMetadata:     &discordgo.GuildScheduledEventEntityMetadata{Location: "Location Information"},
}

// Create a scheduled event
_, err = dg.GuildScheduledEventCreate(guildID, params)

https://github.com/sugar-cat7/example-discord-bot/tree/main/schedule-event

https://discord.com/developers/docs/resources/guild-scheduled-event#create-guild-scheduled-event

2.11. Audio Messages in Voice Channels

You can achieve voice communication with users.

Caution: Volume
https://youtu.be/bMsyCeMzY7w

https://discord.com/developers/docs/topics/voice-connections#voice

Feature Implementation Example Description
Joining/Leaving Voice Channels dg.ChannelVoiceJoin(...) / v.Disconnect() Basic methods for the Bot to join or leave a voice channel.
Receiving Audio v.OpusRecv Method for the Bot to receive audio from other users. Specifically, it is possible to obtain PCM data.
Sending Audio v.OpusSend Method for the Bot to send audio to other users. Specifically, it receives audio data in Opus format.
User Mute Control dg.GuildMemberMute(...) Method to mute or unmute a specific user.
User Volume Adjustment - (No direct method in Discord API) Feature to adjust a user's volume. Specific implementation requires manipulating the audio data.
Playing Audio Files Custom implementation required Read an audio file, convert it to Opus format, and use v.OpusSend to send it to the voice channel.
Interactive Command Processing with Users Custom implementation required Receive commands from users in a text channel and implement interactive processing, such as changing the behavior of the Voice Bot accordingly.
Implementation Example
dg, err := discordgo.New("Bot " + TOKEN)
...
// Accepts the ID of the guild and channel the bot joins, as well as options like mute or speaker status as arguments.
v, err := dg.ChannelVoiceJoin(guildID, channelID, true, false)
  • Sending sound effects in a voice channel
    • Load audio files in dca format
func playSound(s *discordgo.Session, guildID, channelID string) (err error) {
	vc, err := s.ChannelVoiceJoin(guildID, channelID, false, true)
	if err != nil {
		return err
	}
	defer vc.Disconnect()

	time.Sleep(250 * time.Millisecond)
	vc.Speaking(true)
	for _, buff := range buffer {
		vc.OpusSend <- buff
	}
	vc.Speaking(false)
	time.Sleep(250 * time.Millisecond)

	return nil
}
  • Recording

https://github.com/sugar-cat7/example-discord-bot/tree/main/voice-bot

  • Sound effects

https://github.com/sugar-cat7/example-discord-bot/tree/main/airhorn-message

https://discord.com/developers/docs/topics/voice-connections#encrypting-and-sending-voice

3. Discord Bot Operation

3.1. Development Languages

The main languages for developing Bots and the characteristics of their respective SDKs are as follows:

https://discord.com/developers/docs/topics/community-resources

There are many languages available for developing Discord Bots. Below is a summary of the main languages, their SDK characteristics, and information sources.

Language SDK Characteristics OSS
Python Possible to develop advanced Bots by combining with rich libraries. Primarily supports asynchronous processing. discord.py, hikari
JavaScript Library for Bots running on Node.js. Supports asynchronous processing, enabling efficient Bot development. discord.js, Eris
Java Enables Bot development leveraging type safety. Suitable for developing and operating large-scale Bots. JDA, Discord4J
C# Enables Bot development based on the .NET framework. Supports asynchronous processing and event-driven architecture. Discord.Net, DSharpPlus
Go Enables development of high-performance Bots excelling in concurrency by leveraging Go's characteristics. discordgo
Clojure Bot development in a functional language running on the JVM. discljord
C++ Bot development focused on performance. D++
Lua Bot development in a lightweight scripting language. Discordia
PHP Bot development emphasizing integration with web applications. DiscordPHP
Rust Safe and high-performance Bot development. Serenity
Ruby Bot development leveraging object-oriented features. discordrb

3.2. Interactions

There are many libraries and tools to support Interactions.
They provide helpers for security and authentication checks, which are essential when receiving Interactions via Webhooks, as well as data model types.
Some of the representative ones are introduced below.

Language Characteristics Source
C# Support for Interactions via outgoing webhooks. Discord.Net.Rest
Dart Includes Slash commands support and Commands framework; works cross-platform and allows control over all outgoing HTTP requests and WebSocket messages. nyxx
Go Fast API wrapper with minimal caching. Tempest
Javascript Provides types and helper functions useful for implementing Interactions webhooks. discord-interactions-js
Python Interactions support library for Python. discord-interactions-python
PHP Provides types and helper functions useful for implementing Interactions webhooks. discord-interactions-php

3.3. API Types

Simple type definitions for the Discord API.

Name Language
dasgo Go
discord-api-types JavaScript

3.4. Tools Supporting Discord Bot Development

Game SDK Tools

The network layer of the Discord Game SDK is similar to other game platforms (e.g., Valve's Steamworks SDK).
By using the following OSS, you can simplify development across multiple platforms by providing a unified interface for shared features.

Tool Name Details Supported Platforms
HouraiNetworking Library for Unity3D Unity3D

Dispatch Tools

Tools used when publishing games on Discord using Discord's Dispatch tools.

Tool Name Details
JohnyTheCarrot's Dispatch CLI Webhook support when pushing game updates

Permission Calculators

Discord permissions are complex, but they can be easily calculated using the tools below.

Tool Name Details
FiniteReality's Permissions Calculator Permission calculation tool
abalabahaha's Permissions Calculator Permission calculation tool

Intent Calculators

Can be used to calculate intents. (Intents are used to subscribe a Bot to specific sets of events.)

Tool Name Details
ziad87's Intent Calculator Intent calculation tool
Larko's Intent Calculator Intent calculation tool

Embed Visualizers

Tools useful for visualizing Embeds.

Tool Name Details
Autocode Embed Builder Embed visualizer
JohnyTheCarrot's Embed Previewer Browser extension for testing Embed display within Discord

3.5. Hosting Options (Free Tiers)

There are various options for hosting your Bot.
Representative managed services that can be run 24/7 on a free tier are as follows:

Service Name Cost (Month) RAM CPU Storage Network Transfer Notes
Render $0 (Limits apply) 512 MB 0.1 vCPU - - Limit Details
fly.io Free plan available 256 MB (up to 3 VMs) Shared CPU (up to 3 VMs) 3 GB (Total) 160 GB 3 VMs (Total of V2 apps, V1 apps, Machines)
replit Free plan available 0.5 GiB 0.5 vCPUs 10 GiB 10 GiB (Development) Unlimited Public Repls
Railway First $5 free $10/GB/month $20/vCPU/month $0.25/GB/month (Optional) $0.10/GB Transfer rates from August 1, 2023

Besides the above, hosting choices vary depending on the Bot's features, such as only operating via Interactions or not accepting user input.
If 24/7 operation is not necessary and using only HTTP Interactions is sufficient, consider hosting via FaaS such as Lambda or Cloudflare Workers.

3.6. When Making it Publicly Available

When releasing a Discord Bot to the public, attention is required for various aspects such as security, user convenience, and API limitations.

Basic Information

https://discord.com/developers/applications

  • If the Bot is to be made public, it must be configured in the Discord Developer Portal.
  • Public settings can be configured in the "OAuth2" tab of the Discord Developer Portal.
  • If you are adding the Bot to more than 100 servers, a separate application is required. (Identity verification will be performed on the Dev Portal once it is added to more than 75 servers.)

Permissions and Feature Restrictions

To prevent misuse, it is basic practice to grant only the minimum necessary permissions to the bot.
Bot permission management uses a whitelist-style authorization system. (Actions cannot be executed unless permissions are explicitly granted to the bot.)

Permissions

Also, by setting command permissions on the server side, it is possible to restrict the execution of command (/hoge) Interactions for each user.

https://zenn.dev/voiscord/articles/e0e3595a44ecf4

https://support.discord.com/hc/ja/articles/4644915651095-コマンド権限

About API Limits

The Discord API has certain limits. Exceeding these may cause the Bot to temporarily stop working.

https://discord.com/developers/docs/topics/rate-limits

1. Rate Limit Types and Details

Type Description Limit
Per-route Limits for individual endpoints. Depends on HTTP method and endpoint type. Refer to the X-RateLimit-Bucket header. Value shown in the X-RateLimit-Limit header
Global Limits for requests made by the bot or user as a whole. 50 requests per second
Emoji-specific Endpoints related to emojis have different limits than normal. No specific limit is provided
Invalid Request Limits for invalid HTTP requests. Primarily related to 401, 403, and 429 statuses. 10,000 requests per 10 minutes

2. Main Rate Limit Related Headers

Header Name Description
X-RateLimit-Limit Request limit for that endpoint
X-RateLimit-Remaining Remaining number of requests
X-RateLimit-Reset Epoch time when the rate limit resets (seconds since 00:00:00 UTC on January 1, 1970)
X-RateLimit-Reset-After Time until the rate limit resets (seconds)
X-RateLimit-Bucket Unique identifier for the rate limit
X-RateLimit-Global Flag returned only during a 429 response, indicating a global rate limit hit
X-RateLimit-Scope Returned only during a 429 response, indicating the type of rate limit: user, global, or resource

The API response is returned as HTTP 429. The response includes a Retry-After header or retry_after field, indicating the wait time before retrying.

Important Note: To avoid hitting rate limits, applications should properly parse response headers and operate according to the limits. In particular, properly handling error responses such as 401 or 403 can reduce the risk of hitting the invalid request limit.

4. Introduction of Publicly Available Bots

  • You can view a ranking of publicly available Discord Bots.

https://top.gg/

  • VOICEVOX Text-to-Speech Bot

https://zenn.dev/kuronekoserver/articles/6080dd36129a15

  • (Created by the author) Bot that notifies of streaming for a Vtuber group
    Tweet

5. References

https://discord.com/developers/docs/intro

https://scrapbox.io/discordpy-japan/

https://pkg.go.dev/github.com/bwmarrin/discordgo

https://zenn.dev/voiscord/articles/e0e3595a44ecf4

https://zenn.dev/suzuesa/articles/2bf80f33013a14

Discussion