DEV Community

Edson Costa for Devs Norte

Posted on

Desenvolvendo um Bot do Telegram em Golang para Buscar Eventos da Comunidade Devs Norte no Sympla

Este é um guia de como cria um bot para Telegram capaz de buscar e exibir eventos da Comunidade Devs Norte através da plataforma Sympla. Vamos mergulhar no processo de desenvolvimento passo a passo.

Pré-requisitos

Antes de começarmos, assegure-se de ter o Go instalado em seu sistema. Além disso, será necessário ter uma no Telegram.

Passo 1: Configuração do Ambiente

Crie um novo diretório para o seu projeto

Cria e entrar na pasta

inicialize um módulo Go usando o seguinte comando:

go mod init nome-do-seu-projeto
Enter fullscreen mode Exit fullscreen mode

Certifique-se de ter as dependências necessárias instaladas:

go get github.com/joho/godotenv
Enter fullscreen mode Exit fullscreen mode
go get github.com/mymmrac/telego

Enter fullscreen mode Exit fullscreen mode

Passo 2: Configuração do Token

Agora, você precisa obter um token de autenticação do bot do Telegram para interagir com a API do Telegram. Siga estas etapas para obter o token:

  1. Acesse o BotFather no Telegram.
  2. Siga as instruções para criar um novo bot. Envie o comando /newbot e siga as instruções para fornecer um nome e um username para o seu bot.
  3. Após concluir o processo de criação do bot, o BotFather irá fornecer um token de acesso para o seu bot.
  4. Agora, crie um arquivo chamado .env no mesmo diretório do seu código e adicione o token como uma variável de ambiente.
TELEGRAM_BOT_TOKEN=seu_token_aqui
Enter fullscreen mode Exit fullscreen mode

Substitua seu_token_aqui pelo token fornecido pelo BotFather.

Passo 3: Escrevendo o Código

  1. Crie um arquivo main.go e coloque nele:
  2. Importações das bibliotecas necessárias.
  3. Definição das estruturas de dados necessárias para lidar com a resposta da API do Sympla.
  4. Implementação da função NewBot para criar uma nova instância do bot do Telegram.
  5. Implementação do método Start para iniciar o bot.
  6. Implementação dos métodos para registrar os comandos do bot e lidar com eventos relacionados a eventos disponíveis e encerrados.
  7. Implementação da função fetchSymplaEvents para fazer requisições à API do Sympla e obter eventos futuros ou passados.
  8. Implementação da função intArrayToString para converter uma lista de inteiros em uma string.
  9. Implementação da função formatEventsMessage para formatar a 9ensagem a ser enviada ao usuário com base nos eventos encontrados.
  10. Função main que carrega as variáveis de ambiente, cria uma instância do bot e inicia sua execução.

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "strings"

    "github.com/joho/godotenv"
    "github.com/mymmrac/telego"
    th "github.com/mymmrac/telego/telegohandler"
    tu "github.com/mymmrac/telego/telegoutil"
)
Enter fullscreen mode Exit fullscreen mode

package main: Define que este arquivo faz parte do pacote principal do programa.
Importações: Importamos as bibliotecas necessárias para o funcionamento do bot, incluindo godotenv para lidar com variáveis de ambiente, telego para interagir com a API do Telegram e telegohandler e telegoutil para lidar com os eventos e mensagens do Telegram.

type Bot struct {
    bot   *telego.Bot
    bh    *th.BotHandler
    token string
}
Enter fullscreen mode Exit fullscreen mode

Bot: Definimos uma estrutura Bot que contém o bot do Telegram, o manipulador de bot e o token de autenticação.

type SymplaResponse struct {
    Data []Event `json:"data"`
}
Enter fullscreen mode Exit fullscreen mode

SymplaResponse: Define uma estrutura para armazenar a resposta da API do Sympla.

type Location struct {
    Country      string  `json:"country"`
    Address      string  `json:"address"`
    AddressAlt   string  `json:"address_alt"`
    City         string  `json:"city"`
    AddressNum   string  `json:"address_num"`
    Name         string  `json:"name"`
    Longitude    float64 `json:"lon"`
    State        string  `json:"state"`
    Neighborhood string  `json:"neighborhood"`
    ZipCode      string  `json:"zip_code"`
    Latitude     float64 `json:"lat"`
}
Enter fullscreen mode Exit fullscreen mode

Location: Define uma estrutura para armazenar informações sobre a localização de um evento.

type Images struct {
    Original string `json:"original"`
    XS       string `json:"xs"`
    LG       string `json:"lg"`
}
Enter fullscreen mode Exit fullscreen mode

Images: Define uma estrutura para armazenar URLs de imagens relacionadas a um evento.

type StartDateFormats struct {
    Pt string `json:"pt"`
    En string `json:"en"`
    Es string `json:"es"`
}
type EndDateFormats struct {
    Pt string `json:"pt"`
    En string `json:"en"`
    Es string `json:"es"`
}
Enter fullscreen mode Exit fullscreen mode

StartDateFormats e EndDateFormats: Definem estruturas para armazenar formatos de data de início e fim de um evento.

type Event struct {
    Name             string           `json:"name"`
    Images           Images           `json:"images"`
    Location         Location         `json:"location"`
    StartDateFormats StartDateFormats `json:"start_date_formats"`
    EndDateFormats   EndDateFormats   `json:"end_date_formats"`
    URL              string           `json:"url"`
}
Enter fullscreen mode Exit fullscreen mode

Event: Define uma estrutura para representar um evento, incluindo seu nome, imagens, localização, datas e URL.

func NewBot(token string) (*Bot, error) {
    bot, err := telego.NewBot(token, telego.WithDefaultDebugLogger())
    if err != nil {
        return nil, err
    }

    updates, err := bot.UpdatesViaLongPolling(nil)
    if err != nil {
        return nil, err
    }

    bh, err := th.NewBotHandler(bot, updates)
    if err != nil {
        return nil, err
    }

    return &Bot{
        bot:   bot,
        bh:    bh,
        token: token,
    }, nil
}
Enter fullscreen mode Exit fullscreen mode

NewBot: Esta função cria uma nova instância do bot do Telegram, configura os manipuladores de atualização e retorna uma estrutura Bot inicializada.

func (b *Bot) Start() {
    defer b.bh.Stop()
    defer b.bot.StopLongPolling()

    b.registerCommands()

    b.bh.Start()
}
Enter fullscreen mode Exit fullscreen mode

Start: Método que inicia o bot. Ele registra os comandos e inicia o manipulador de bot para receber atualizações do Telegram.

func (b *Bot) registerCommands() {
    b.registerBotCommand()
    b.registerEventCommands()
}
Enter fullscreen mode Exit fullscreen mode

registerCommands: Método que registra todos os comandos disponíveis do bot.

func (b *Bot) registerBotCommand() {
    b.bh.Handle(func(bot *telego.Bot, update telego.Update) {
        infoMessage := `
👋 Bem-vindo ao Bot da Comunidade Devs Norte! 🚀

Este bot está aqui para ajudá-lo a encontrar os eventos mais recentes e emocionantes hospedados no Sympla pela nossa comunidade.

Para consultar os eventos disponíveis, basta digitar /disponiveis. E se estiver interessado nos eventos que já passaram, digite /encerrados.

Fique à vontade para explorar e participar dos eventos que mais lhe interessarem!😊
`

        _, _ = bot.SendMessage(tu.Message(
            tu.ID(update.Message.Chat.ID),
            infoMessage,
        ))
    }, th.CommandEqual("start"))
}
Enter fullscreen mode Exit fullscreen mode

registerBotCommand: Método que registra o comando /start, que envia uma mensagem de boas-vindas ao usuário quando o bot é iniciado.

func (b *Bot) registerEventCommands() {
    b.registerAvailableEventsCommand()
    b.registerClosedEventsCommand()
}
Enter fullscreen mode Exit fullscreen mode

registerEventCommands: Método que registra os comandos relacionados aos eventos disponíveis e encerrados.

func (b *Bot) registerAvailableEventsCommand() {
    b.bh.Handle(func(bot *telego.Bot, update telego.Update) {
        events, err := fetchSymplaEvents("future")
        if err != nil {
            fmt.Println("Erro ao buscar eventos:", err)
            return
        }
        message := formatEventsMessage(events)
        _, _ = bot.SendMessage(tu.Message(
            tu.ID(update.Message.Chat.ID),
            message,
        ))
    }, th.CommandEqual("disponíveis"))
}
Enter fullscreen mode Exit fullscreen mode

registerAvailableEventsCommand: Método que registra o comando /disponiveis, que busca e exibe eventos futuros.

func (b *Bot) registerClosedEventsCommand() {
    b.bh.Handle(func(bot *telego.Bot, update telego.Update) {
        events, err := fetchSymplaEvents("past")
        if err != nil {
            fmt.Println("Erro ao buscar eventos:", err)
            return
        }
        message := formatEventsMessage(events)
        _, _ = bot.SendMessage(tu.Message(
            tu.ID(update.Message.Chat.ID),
            message,
        ))
    }, th.CommandEqual("encerrados"))
}
Enter fullscreen mode Exit fullscreen mode

registerClosedEventsCommand: Método que registra o comando /encerrados, que busca e exibe eventos passados.

func fetchSymplaEvents(eventType string) ([]Event, error) {
    // Define os IDs dos organizadores
    organizerIDs := []int{3125215, 5478152}

    // Define o serviço a ser chamado na API do Sympla com base no tipo de evento
    service := "/v4/search"
    if eventType == "past" {
        service = "/v4/events/past"
    }

    // Monta o corpo da requisição
    requestBody := fmt.Sprintf(`{
        "service": "%s",
        "params": {
            "only": "name,images,location,start_date_formats,end_date_formats,url",
            "organizer_id": %s,
            "sort": "date",
            "order_by": "desc",
            "limit": "6",
            "page": 1
        },
        "ignoreLocation": true
    }`, service, intArrayToString(organizerIDs))

    // Faz a requisição HTTP para a API do Sympla
    resp, err := http.Post("https://www.sympla.com.br/api/v1/search", "application/json", strings.NewReader(requestBody))
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    // Lê a resposta da requisição
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    // Decodifica a resposta JSON em uma estrutura SymplaResponse
    var symplaResp SymplaResponse
    if err := json.NewDecoder(bytes.NewReader(body)).Decode(&symplaResp); err != nil {
        return nil, err
    }

    // Retorna os eventos encontrados na resposta
    return symplaResp.Data, nil
}
Enter fullscreen mode Exit fullscreen mode

fetchSymplaEvents: Esta função faz uma requisição para a API do Sympla para buscar eventos, com base no tipo de evento (futuro ou passado), e retorna uma lista de eventos encontrados.

func intArrayToString(arr []int) string {
    strArr := make([]string, len(arr))
    for i, num := range arr {
        strArr[i] = fmt.Sprint(num)
    }
    return "[" + strings. Join(strArr, ",") + "]"
}
Enter fullscreen mode Exit fullscreen mode

intArrayToString: Esta função converte uma lista de inteiros em uma string formatada para ser usada na construção do corpo da requisição para a API do Sympla.

func formatEventsMessage(events []Event) string {
    message := "#BOT Devs Norte 🤖\n\n\n"
    if events == nil || len(events) == 0 {
        message += "Ops... Nem um evento disponivel no momento, mas não fique triste logo estaremos fazendo mais eventos! 🥺\n\n\n"
    } else {
        message += "🎉 Eventos: 🎉\n\n\n"
        for _, event := range events {
            message += fmt.Sprintf("- %s\n  Local: %s\n  Data: %s\n  URL: %s\n \n\n\n", event. Name, event.Location.City, event.StartDateFormats.Pt, event.URL)
            message += "----------------------------------------\n\n\n"
        }
    }
    return message
}
}
Enter fullscreen mode Exit fullscreen mode

formatEventsMessage: Esta função formata uma mensagem a ser enviada ao usuário com base nos eventos encontrados.

func main() {
    // Carrega as variáveis de ambiente do arquivo .env
    if err := godotenv.Load(); err != nil {
        fmt.Println("Erro ao carregar o arquivo .env:", err)
        os.Exit(1)
    }

    // Obtém o token do bot do Telegram das variáveis de ambiente
    token := os.Getenv("TELEGRAM_BOT_TOKEN")
    if token == "" {
        fmt.Println("Token do bot do Telegram não fornecido")
        os.Exit(1)
    }

    // Cria uma nova instância do bot e inicia sua execução
    bot, err := NewBot(token)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    bot.Start()
}
Enter fullscreen mode Exit fullscreen mode

main: A função main é o ponto de entrada do programa. Ela carrega as variáveis de ambiente do arquivo .env, obtém o token do bot do Telegram, cria uma instância do bot e inicia sua execução.

Passo 5: Executar o Código

No diretório do projeto.
execute o código Go:

go run main. Go
Enter fullscreen mode Exit fullscreen mode

Isso iniciará o bot do Telegram. Agora você pode acessar o bot no Telegram e interagir com ele usando os comandos /start, /disponiveis e /encerrados.

Bot no Telegram

Você pode encontrar o código completo do projeto no repositório GitHub aqui.

Espero que essa explicação detalhada ajude a entender como o código funciona e como cada parte contribui para o funcionamento do bot do Telegram. Se tiver mais alguma dúvida ou precisar de mais alguma explicação, estou à disposição!

Top comments (3)

Collapse
 
suamirochadev profile image
Suami Rocha

Adoreii! Ficou incrivel, parabéns Edson!! 🙏👏👏👏

Collapse
 
ecsistem profile image
Edson Costa

Muito obrigado!

Collapse
 
julinux profile image
Julio Saraiva

The best!