Pular para o conteúdo principal

victorstein.dev

88/100 Dias de Golang - Bot para discord

Table of Contents

# Bot para discord

Vamos criar um bot para discord usando Golang. Quero focar na parte somente de criar as funções para o bot, a parte de configuração dele no discord você pode procurar em outros lugares, vou deixa uma lista aqui:

  1. Como criar um bot para o Discord
  2. Como criar um bot do Discord

A única coisa que você precisa dessa etapa é o token gerado pelo discord. A ideia é fazer dois posts, um mostrando o primeiro comando e outro organizando o projeto e deixando ele mais “profissional”. Nesse primeiro, vamos configurar o projeto, instalar libs e criar um comando ping.

Veja a estrutura que usaremos de pastas:

discord-bot-go/
├── cmd/
│   └── bot/
│       └── main.go
├── config/
│   └── config.go
├── internal/
│   ├── bot/
│   │   ├── client.go
│   │   └── handlers.go
├── go.mod
└── .env

No .env devemos adicionar o token fornecido pelo discord

DISCORD_BOT_TOKEN=seu_token_aqui

Vamos iniciar criando o arquivo config.go a função dele é carregar o token do arquivo .env, iremos usar a lib godotenv

package config

import (
	"log"
	"os"

	"github.com/joho/godotenv"
)

func LoadToken() string {
	err := godotenv.Load()
	if err != nil {
		log.Fatal("Erro ao carregar .env")
	}

	token := os.Getenv("DISCORD_BOT_TOKEN")
	if token == "" {
		log.Fatal("Token não encontrado no .env")
	}

	return token
}

Dentro do arquivo internal/bot/client.go temos a estrutura inicial de conexão do bot. Iremos usar a biblioteca discordgo.

package bot

import (
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/bwmarrin/discordgo"
)

func Start(token string) {
	dg, err := discordgo.New("Bot " + token)
	if err != nil {
		log.Fatalf("Erro ao criar sessão do Discord: %v", err)
	}

	dg.AddHandler(messageCreate)

	err = dg.Open()
	if err != nil {
		log.Fatalf("Erro ao abrir conexão com Discord: %v", err)
	}
	log.Println("Bot está online. Pressione CTRL+C para sair.")

	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
	<-stop

	dg.Close()
}

Na linha:

dg.AddHandler(messageCreate)

Fazemos o registro da função que irá tratar as mensagens. Mas a parte legal desse código são essas 3 linhas:

stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
<-stop

Essa estrutura é usada para capturar sinais do sistema operacional e encerrar a aplicação de forma controlada. Primeiro, é criado um canal chamado stop que receberá valores do tipo os.Signal. Em seguida, a função signal.Notify registra esse canal para escutar sinais específicos como SIGINT (geralmente enviado ao pressionar Ctrl+C), SIGTERM (usado para encerramento gracioso em servidores), e os.Interrupt. A linha <-stop bloqueia a execução do programa até que algum desses sinais seja recebido.

No arquivo internal/bot/handlers.go iremos definir as funções de cada comando. No nosso caso uma bem simples, o usuário envia !ping e retornamos Pong.

package bot

import (
	"strings"

	"github.com/bwmarrin/discordgo"
)

func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
	if m.Author.Bot {
		return
	}

	content := strings.ToLower(m.Content)

	if content == "!ping" {
		s.ChannelMessageSend(m.ChannelID, "Pong")
	}
}

E nosso arquivo cmd/bot/main.go temos a “conexão” entre as partes.

package main

import (
	"discord-bot-go/config"
	"discord-bot-go/internal/bot"
)

func main() {
	token := config.LoadToken()
	bot.Start(token)
}

Antes de executar, lembrar de instalar as bibliotecas com:

go mod tidy

E para executar:

go run cmd/bot/main.go