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

ecsistem

Edson Costa

Posted on April 21, 2024

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!

💖 💪 🙅 🚩
ecsistem
Edson Costa

Posted on April 21, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related