Build a Discord Bot with Go - Step-by-Step Tutorial via Webhooks

Nik L. - Feb 14 - - Dev Community

Check out more articles:

  1. Building a Scalable Notification System with gRPC and Microservices
  2. Adding a Notification Feed in React Websites
  3. A Complete Guide on Notification Infrastructure for Modern Applications in 2023

1. Create a Discord Server

To get started, create a Discord server. This is necessary as you need administrative rights to add a bot to a server.

TDLR Requirement: Ensure you are an admin of the server.

2. Create a Discord Application

Visit Discord Developer Portal to begin creating your bot.

  • Create a new application.
  • Add a bot to the application.
  • Configure the bot settings and upload an image for it.
  • Note down the Application ID.

3. Add bot to your server

To add your bot to the server, follow these steps:

4. Get ready to code

Create the following directory structure:

├── config.json
├── main.go
└── bot
    └── bot.go
└── config
    └── config.go
Enter fullscreen mode Exit fullscreen mode

Initialize your project and install the required packages:

# Replace [YOUR\_USERNAME] and [YOUR\_PROJECT\_NAME] accordingly
$ go mod init github.com/[YOUR\_USERNAME]/[YOUR\_PROJECT\_NAME]
$ go get github.com/bwmarrin/discordgo
Enter fullscreen mode Exit fullscreen mode

5. JSON Configuration

Collect the token and bot prefix information from Steps 1 and 2:

{
    "token": "your_token_here",
    "BotPrefix": "!"
}
Enter fullscreen mode Exit fullscreen mode

5b. config/config.go

package config

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"
)

type Config struct {
    Token     string `json:"token"`
    BotPrefix string `json:"botPrefix"`
}

func ReadConfig() (*Config, error) {
    fmt.Println("Reading config.json...")
    data, err := ioutil.ReadFile("./config.json")
    if err != nil {
        return nil, err
    }
    fmt.Println("Unmarshalling config.json...")
    var cfg Config
    err = json.Unmarshal([]byte(data), &cfg)
    if err != nil {
        fmt.Println("Error unmarshalling config.json")
        return nil, err
    }
    return &cfg, nil
}
Enter fullscreen mode Exit fullscreen mode

6. bot/bot.go

package bot

import (
    "fmt"

    "github.com/alfredosa/GoDiscordBot/config"
    "github.com/bwmarrin/discordgo"
)

var BotId string
var goBot *discordgo.Session

func Start() {
    cfg, err := config.ReadConfig()
    if err != nil {
        fmt.Println("Failed reading configuration:", err)
        return
    }

    goBot, err = discordgo.New("Bot " + cfg.Token)
    if err != nil {
        fmt.Println("Failed initializing Discord Session:", err)
        return
    }

    u, err := goBot.User("@me")
    if err != nil {
        fmt.Println("Failed getting current User:", err)
        return
    }

    BotId = u.ID

    goBot.AddHandler(messageHandler)

    err = goBot.Open()
    if err != nil {
        fmt.Println("Failed opening connection to Discord:", err)
        return
    }

    fmt.Println("Bot is now connected!")
}

func messageHandler(s *discordgo.Session, e *discordgo.MessageCreate) {
    if e.Author.ID == BotId {
        return
    }

    prefix := config.BotPrefix
    if strings.HasPrefix(e.Content, prefix) {
        args := strings.Fields(e.Content)[strings.Index(e.Content, prefix):]
        cmd := args[0][len(prefix):]
        arguments := args[1:]

        switch cmd {
        case "ping":
            _, err := s.ChannelMessageSend(e.ChannelID, "Pong!")
            if err != nil {
                fmt.Println("Failed sending Pong response:", err)
            }
        default:
            _, err := s.ChannelMessageSend(e.ChannelID, fmt.Sprintf("Unknown command %q.", cmd))
            if err != nil {
                fmt.Println("Failed sending Unknown Command response:", err)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

7. Bind everything and start the bot in main.go

package main

import (
    "fmt"
    "github.com/alfredosa/GoDiscordBot/bot"
)

func main() {
    bot.Start()

    <-make(chan struct{})
}
Enter fullscreen mode Exit fullscreen mode

8. Build and run the bot

$ go build
$ ./GoDiscordBot
Enter fullscreen mode Exit fullscreen mode

9. Test the bot

  • Begin a private conversation with the bot and enter !ping, expecting a 'Pong!' response.
  • Mention the bot using '@botname ping', also receiving a 'Pong!' reply.

Similar to this, I personally run a developer-led community on Slack. Where we discuss these kinds of implementations, integrations, some truth bombs, weird chats, virtual meets, and everything that will help a developer remain sane ;) Afterall, too much knowledge can be dangerous too.

I'm inviting you to join our free community, take part in discussions, and share your freaking experience & expertise. You can fill out this form, and a Slack invite will ring your email in a few days. We have amazing folks from some of the great companies (Atlassian, Scaler, Cisco, IBM and more), and you wouldn't wanna miss interacting with them. Invite Form

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .