Criando um Bot do Telegram com Node.js

Olá, pessoal. Este é meu primeiro artigo por aqui e nele vamos aprender a fazer um Bot do Telegram que monitora serviços através de requisições HTTP. Fiz em Javascript/Node.js porque era a linguagem que eu vinha estudando ultimamente então foi uma boa oportunidade de aplicá-la e eu gostei do resultado.

As tecnologias trabalhadas aqui foram o Node.js, o Telegraf, que é um framework para construir Bots do Telegram em Node, o Axios, um cliente HTTP em Javascript, e o Docker para dar um toque mais profissional, rs. Tem também o próprio Telegram, naturalmente, onde vamos iniciar a criação do Bot e vê-lo funcionar.

Acho que um bom ponto de partida é entrar no Telegram e criar nosso Bot. Poucas coisas na vida são mais fáceis que isso: basta procurar pela conta BotFather:

BotFather

Ao iniciar uma conversa com o Pai dos Bots, são exibidos os comandos disponíveis para interagir com ele. Digitamos ou clicamos em /newbot, definimos um nome e em seguida um username, que deve obrigatoriamente terminar em ‘bot’. Feito isso, nosso Bot estará criado e o BotFather disponibilizará um token de acesso que usaremos daqui pra frente para comandar nosso Bot. O BotFather nos aconselha a manter o token em segurança, já que ele pode ser usado por qualquer um para controlar nosso Bot.

Bot Criado

Vamos agora ao Node.js. Primeiro, criamos um diretório raiz pro projeto e dentro dele o /src onde ficará o código Javascript:

mkdir -p telegram-bot/src
cd telegram-bot

Então, inicializamos o projeto…

npm init -y

…e instalamos o módulo Telegraf

npm install telegraf

Agora as primeiras linhas de código. Criamos um arquivo index.js em ./telegram-bot/src que será o entrypoint do projeto:

const Telegraf = require('telegraf')

const bot = new Telegraf(process.env.BOT_TOKEN)

bot.start((ctx) => ctx.reply("Hello world"))

bot.launch()

Nele, primeiro importamos o módulo Telegraf, então instanciamos um objeto bot, passando um único argumento, process.env.BOT_TOKEN (falaremos dele no próximo parágrafo). Em seguida, criamos nossa primeira “rota”, bot.start(), aqui estabelecemos o que o Bot fará ao receber o comando /start (isso acontece ao iniciarmos pela primeira vez uma conversa com ele ou, após isso, digitarmos /start no chat). Nesta versão inicial de nosso código, ele apenas responderá com um “Hello world”. Por fim, na última linha temos bot.launch() que inicializa o Bot.

Sobre o process.env.BOT_TOKEN, o process.env retorna um objeto contendo as variáveis de ambiente do usuário, e destas estamos pegando a que nos interessa que é a BOT_TOKEN. Uma alternativa seria passar o token diretamente no código, o que é completamente desaconselhável. Agora falta criarmos a variável de ambiente BOT_TOKEN e atribuir a ela o token que o BotFather nos passou instantes atrás. Neste momento vamos apenas exportar nossa variável no terminal (Linux/MacOS), mas depois, quando subirmos nosso projeto em uma imagem Docker, vamos usar uma solução mais elegante.

Então, no terminal basta executar:

export BOT_TOKEN=<O_TOKEN_QUE_O_BOTFATHER_NOS_PASSOU>

Nosso Bot já está pronto para ser executado! No diretório raiz, rodamos:

node src/index.js

No Telegram, já podemos interagir com ele:

Bot start

O que precisamos implementar agora é uma rota status que chamará um módulo responsável por fazer a requisição ao serviço, retornando seu status que, por sua vez, gerará uma resposta de nosso Bot.

Vamos instalar o axios, que é um módulo cliente HTTP.

npm install axios

Novo arquivosrc/status.js, bem simplezinho, checando o status da página inicial do Google:

const axios = require('axios')

const status = async () => {
    try {
        return await axios.get('https://www.google.com/', { timeout: 30000 })
    } catch(error) {
        return error
    }
}

module.exports = status

No arquivo principal do projeto, src/index.js, vamos importar o módulo status e criar a rota que o chamará:

const status = require('./status')

...

bot.command('status', async (ctx) => {

    try {
        const response = await status()

        if (response.status == 200) {
            await ctx.reply(`Google service: ✅`)
        } else {
            await ctx.reply(`Google service: ❌`)
        }

    } catch(error) {
        console.error(error)
    }
})

Projeto salvo, rodamos novamente o node src/index.js e vamos lá falar com nosso Bot:

Bot status

Prontinho! Se o serviço Google tiver fora do ar, o que é meio difícil, ele vai responder com o ❌.

Vamos fazer um ajuste no package.json para rodarmos nossa aplicação com npm start:

...

"scripts": {
    "start": "node src/index.js"
  }

...

Agora pra finalizar, vamos subir nosso projeto em Docker (e docker-compose)! Primeiro criamos um Dockerfile pra será o build de nossa imagem e depois um docker-compose.yml que subirá o serviço. São provavelmente os exemplos mais simples de Dockerfile e docker-compose que vocês verão por aí:

Dockerfile

FROM node:12.7.0-alpine

WORKDIR /app
COPY . .
RUN ["npm", "install"]

ENV BOT_TOKEN=<PUT_YOUR_TELEGRAM_TOKEN_BOT_HERE>

ENTRYPOINT ["npm", "start"]

docker-compose.yml

version: '3'
services:
  bot:
    build: .

(Sim, é só isso). Lembrando que os dois arquivos devem estar na raiz do projeto, no Dockerfile colocamos ali em ENV BOT_TOKEN o mesmo token que já vínhamos usando.

Agora vamos colocar nosso Bot no ar novamente, mas dessa vez usando docker-compose:

docker-compose up -d

O -d é pra ele subir em background, liberando o promp do terminal. Pra parar o serviço é docker-compose down. Se fizer alguma modificação no código, é só rodar docker-compose up -d --build que ele subirá construindo uma nova imagem.

Com o Bot no ar em Docker, podemos ir no Telegram novamente e continuar interagindo com nosso Bot!

Docker bot

Essa é uma versão bem simples e genérica, só pra ilustrar a implementação e o funcionamento. Pro artigo não ficar ainda maior, abstraí algumas explicações de códigos e comandos, mas coloquei os links com as referências de cada tecnologia. Qualquer dúvida é só dar um alô!

Share on:

comments powered by Disqus