Implementação de Bot do Telegram em Python e JavaScript com deploy na AWS

E implantando um novo bot do Telegram na AWS

Conteúdo da página

Aqui estão minhas notas com um tutorial passo a passo sobre como implementar e implantar um bot do Telegram na AWS. Adicionei um início rápido (long polling) e um caminho pronto para produção (webhooks), com exemplos em Python e Node.js.

robôs trabalhando em TI

Bots do Telegram são aplicativos que rodam em seus servidores e se comunicam com os usuários através do Telegram. Vamos registrar um bot, escrever um pequeno programa e conectá-lo à API de Bots do Telegram.

TL;DR (Resumo)

  1. Crie um bot via @BotFather → obtenha o token.
  2. Construa um pequeno aplicativo com python-telegram-bot ou Telegraf.
  3. Comece com long polling localmente; mude para webhooks em produção.

O que você precisará

  • Uma conta do Telegram (mobile ou desktop)

  • Terminal básico + editor de código

  • Um dos seguintes:

    • Python 3.10+ e pip
    • Node.js 18+ e npm/pnpm/yarn

Crie seu bot com o BotFather (obtenha o token)

  1. No Telegram, procure por @BotFather e inicie uma conversa.
  2. Envie /newbot e siga as instruções para nomear seu bot e escolher um nome de usuário único (deve terminar com bot), ex: exemplo_helper_bot.
  3. O BotFather responderá com um token de API como 123456:ABC-DEF.... Trate isso como uma senha; não o commit para o Git. Você pode sempre regenerá-lo via BotFather se ele for vazado.

Dica: O tutorial oficial do Telegram percorre exatamente esses passos e como verificar seu token com getMe.


Escolha sua stack

Você pode chamar a API de Bots HTTP bruta você mesmo, mas usar uma biblioteca mantida é mais rápido.

  • Python: python-telegram-bot (assíncrono, moderno). ([https://docs.python-telegram-bot.org])
  • Node.js: telegraf (maduro, amigável ao TypeScript). ([https://telegraf.js.org])

A própria API de Bots está documentada aqui e é a fonte da verdade para métodos como getUpdates e setWebhook.


Início Rápido: execute localmente com long polling

Long polling é perfeito para desenvolvimento local: seu bot pergunta repetidamente ao Telegram por novas atualizações via getUpdates. (Em produção, você provavelmente mudará para webhooks.)

O Telegram suporta duas formas mutuamente exclusivas de receber atualizações: getUpdates (polling) ou webhooks; as atualizações são mantidas por até 24 horas.

Opção A: Python (com python-telegram-bot)

Instalação e estrutura

python -m venv .venv && source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install python-telegram-bot

Código: bot.py

import os
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, ContextTypes, filters

TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]  # export TELEGRAM_BOT_TOKEN=123:ABC

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("👋 Olá! Envie-me algo e eu repetirei.")

async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(update.message.text)

def main():
    app = ApplicationBuilder().token(TOKEN).build()
    app.add_handler(CommandHandler("start", start))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
    app.run_polling()  # long polling

if __name__ == "__main__":
    main()

Execute:

export TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
python bot.py

Isso usa ApplicationBuilder da documentação estável atual.

Opção B: Node.js (com telegraf)

Instalação e estrutura

npm init -y
npm i telegraf

Código: index.js

const { Telegraf } = require('telegraf');

const bot = new Telegraf(process.env.BOT_TOKEN); // defina a var de ambiente BOT_TOKEN
bot.start((ctx) => ctx.reply('👋 Olá! Envie-me algo e eu repetirei.'));
bot.on('text', (ctx) => ctx.reply(ctx.message.text));

bot.launch();

// parada graciosa
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

Execute:

export BOT_TOKEN=123456:ABC-DEF...
node index.js

Isso espelha o exemplo “Começando” oficial do Telegraf.


Torne útil (comandos e botões)

Adicione um comando /help

Python

from telegram.ext import CommandHandler

async def help_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("/start – saudação\n/help – esta ajuda")

app.add_handler(CommandHandler("help", help_cmd))

CommandHandler é a maneira padrão de vincular /comandos.

Node (Telegraf)

bot.help((ctx) => ctx.reply('/start – saudação\n/help – esta ajuda'));

Botões de resposta rápida (teclado personalizado)

Python

from telegram import ReplyKeyboardMarkup

async def start(update: Update, context):
    keyboard = [["Ajuda", "Sobre"]]
    await update.message.reply_text(
        "Escolha uma opção:",
        reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    )

Node (Telegraf)

const { Markup } = require('telegraf');
bot.start((ctx) => {
  ctx.reply("Escolha uma opção:", Markup.keyboard([["Ajuda", "Sobre"]]).resize());
});

Produção: mude para webhooks

Em produção, o Telegram envia (push) atualizações para o seu endpoint HTTPS. Você pode definir isso com setWebhook, opcionalmente fornecendo um token secreto para verificar a solicitação via o cabeçalho X-Telegram-Bot-Api-Secret-Token.

Defina um webhook com curl:

TOKEN=123456:ABC-DEF...
WEBHOOK_URL="https://seu-dominio.com/telegram/${TOKEN}"  # inclua um caminho secreto
SECRET="meu-secreto-42"

curl -X POST "https://api.telegram.org/bot${TOKEN}/setWebhook" \
  -d url="${WEBHOOK_URL}" \
  -d secret_token="${SECRET}" \
  -d drop_pending_updates=true

Pontos-chave da especificação:

  • setWebhook requer uma URL HTTPS e suporta secret_token.
  • Enquanto um webhook estiver definido, você não pode usar getUpdates.
  • Portas suportadas incluem 443, 80, 88, 8443.

Opções de servidor de webhook

  • Node (Telegraf) webhook embutido:
bot.launch({
  webhook: {
    domain: "seu-dominio.com",
    port: 8080,
    // cabeçalho secreto opcional
    secretToken: process.env.WEBHOOK_SECRET
  }
});

O Telegraf expõe opções de webhook de primeira classe e integra-se com Express/Fastify/Cloudflare Workers, etc.

  • Python (python-telegram-bot) O PTB funciona bem com frameworks ASGI/WSGI (FastAPI, Starlette, Flask). Use ApplicationBuilder().token(...).build(), exponha uma rota POST que alimenta atualizações JSON recebidas em seu aplicativo e chame bot.set_webhook(...). Veja a documentação do ApplicationBuilder para padrões de construção. ([docs.python-telegram-bot.org][2])

Testando localmente? Use um túnel (ex: ngrok) para expor https://... ao Telegram, depois chame setWebhook com a URL pública.


Configure comandos do bot (opcional, mas amigável para o usuário)

Você pode definir a lista de comandos do bot (o que os usuários veem quando digitam /) de duas formas:

  • No BotFather via /mybots → Edit Bot → Edit Commands, ou
  • Programaticamente com setMyCommands usando sua biblioteca ou a API de Bots bruta.

O guia oficial do Telegram “Do BotFather ao Hello World” linka para manipulação de comandos mais avançada e exemplos se você quiser aprofundar.


Considerações de implantação

Qualquer host capaz de HTTPS funciona:

  • Uma pequena VM (Ubuntu + systemd)
  • Serverless (AWS Lambda/Cloud Functions) com integração de webhook
  • Containers em plataformas como Fly.io/Render/Heroku

A documentação do Telegraf inclui exemplos para Lambda, GCF, Express, Fastify, etc.


Checklist de segurança e confiabilidade

  • Mantenha o token secreto (vars de ambiente, gerenciador de segredos). Revogue no BotFather se vazado.
  • Use secret_token com webhooks e verifique o cabeçalho X-Telegram-Bot-Api-Secret-Token.
  • Não misture polling e webhooks; escolha um de cada vez.
  • Trate erros e retentativas: O Telegram reenviará respostas de webhook não-2xx. Registre adequadamente.
  • Esteja atento aos tipos de atualização (mensagens, callbacks, consultas inline, pagamentos, etc.) e inscreva-se apenas no que você precisa (allowed_updates).

Trabalhando diretamente com a API HTTP (opcional)

Você pode chamar endpoints como:

https://api.telegram.org/bot<token>/getMe
https://api.telegram.org/bot<token>/getUpdates
https://api.telegram.org/bot<token>/sendMessage

Use GET ou POST com JSON ou dados de formulário conforme a especificação.


O que fazer e ler a seguir

  • Referência oficial da API de Bots: métodos, objetos, limites, formatação, pagamentos, modo inline.
  • Guia oficial “Do BotFather ao ‘Hello World’”: walkthrough mais profundo e exemplos multilíngues.
  • Docs python-telegram-bot (estável): padrões assíncronos modernos.
  • Docs Telegraf: receitas rápidas, auxiliares de webhook e tipos TS.

Passos de implantação na AWS para a versão Python

Temos duas opções principais para implantar o bot do Telegram na infraestrutura AWS:

  • A) Serverless (API Gateway + Lambda + Secrets Manager) — mais barato/fácil de rodar, ótimo para tráfego modesto.
  • B) Containerizado (ECS Fargate + ALB + ACM) — nível de produção para tráfego constante e bibliotecas de longa execução como python-telegram-bot em modo webhook.

A) Serverless na AWS (API Gateway + Lambda)

Use isso quando quiser zero servidores e custo de ociosidade quase zero. O código abaixo lida diretamente com webhooks do Telegram (sem loop de eventos de longa execução).

  1. Prepare um manipulador Lambda minimalista (Python)

Crie handler.py:

import json, os, urllib.request

BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
SECRET_HEADER = os.environ.get("WEBHOOK_SECRET", "")  # deve corresponder ao secret_token do Bot API setWebhook

API_BASE = f"https://api.telegram.org/bot{BOT_TOKEN}"

def reply(chat_id: int, text: str):
    data = json.dumps({"chat_id": chat_id, "text": text}).encode()
    req = urllib.request.Request(f"{API_BASE}/sendMessage", data=data, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req) as resp:
        return resp.read()

def lambda_handler(event, context):
    # 1) Verificar o cabeçalho secreto do Telegram (definido ao configurar o webhook)
    if SECRET_HEADER:
        if event.get("headers", {}).get("X-Telegram-Bot-Api-Secret-Token") != SECRET_HEADER:
            return {"statusCode": 401, "body": "invalid secret"}

    # 2) Parsear atualização
    body = event.get("body") or "{}"
    update = json.loads(body)

    message = update.get("message") or update.get("edited_message")
    if not message:
        # ignorar atualizações não-mensagens (callback_query, inline_query, etc.) por enquanto
        return {"statusCode": 200, "body": "ok"}

    chat_id = message["chat"]["id"]
    text = (message.get("text") or "").strip()

    # 3) Roteamento simples
    if text.startswith("/start"):
        reply(chat_id, "👋 Olá do AWS Lambda! Envie qualquer texto e eu repetirei.")
    elif text.startswith("/help"):
        reply(chat_id, "/start – saudação\n/help – ajuda\n(Implicitado no AWS Lambda)")
    elif text:
        reply(chat_id, text)  # echo

    return {"statusCode": 200, "body": "ok"}

Isso usa chamadas HTTPS brutas à API de Bots para manter o Lambda leve e amigável ao cold-start. Você pode expandir o roteamento depois.

  1. Empacotar e implantar o Lambda
# Layout do projeto
# .
# ├─ handler.py
# └─ requirements.txt   # (deixe vazio para este exemplo minimalista)

zip -r function.zip handler.py
aws lambda create-function \
  --function-name telegram-bot-webhook \
  --runtime python3.11 \
  --role arn:aws:iam::<ACCOUNT_ID>:role/<LambdaExecutionRole> \
  --handler handler.lambda_handler \
  --timeout 10 \
  --memory-size 256 \
  --zip-file fileb://function.zip \
  --environment Variables='{TELEGRAM_BOT_TOKEN=<TOKEN_FROM_BOTFATHER>,WEBHOOK_SECRET=my-secret-42}'

Papel IAM (<LambdaExecutionRole>) precisa de AWSLambdaBasicExecutionRole para CloudWatch Logs.

Prefira armazenar seu token no AWS Secrets Manager e carregá-lo na inicialização—este exemplo usa vars de ambiente para brevidade.

  1. Crie um endpoint HTTPS (API Gateway)
# HTTP API (não REST) para menor latência
API_ID=$(aws apigatewayv2 create-api \
  --name telegram-webhook \
  --protocol-type HTTP \
  --target arn:aws:lambda:<REGION>:<ACCOUNT_ID>:function:telegram-bot-webhook \
  --query 'ApiId' --output text)

# Adicionar rota padrão POST /webhook
aws apigatewayv2 create-integration \
  --api-id $API_ID \
  --integration-type AWS_PROXY \
  --integration-uri arn:aws:lambda:<REGION>:<ACCOUNT_ID>:function:telegram-bot-webhook \
  --payload-format-version 2.0

aws apigatewayv2 create-route \
  --api-id $API_ID \
  --route-key "POST /webhook" \
  --target "integrations/$(
    aws apigatewayv2 get-integrations --api-id $API_ID --query 'Items[0].IntegrationId' --output text
  )"

aws apigatewayv2 create-deployment --api-id $API_ID
GW_URL=$(aws apigatewayv2 get-apis --query "Items[?ApiId=='$API_ID'].ApiEndpoint" --output text)
echo $GW_URL  # ex., https://abc123.execute-api.ap-somewhere.amazonaws.com

Garanta que a permissão do Lambda seja adicionada automaticamente; se não:

aws lambda add-permission \
  --function-name telegram-bot-webhook \
  --statement-id apigw \
  --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com \
  --source-arn "arn:aws:execute-api:<REGION>:<ACCOUNT_ID>:$API_ID/*/*/webhook"
  1. Aponte o Telegram para seu webhook
TOKEN=<TOKEN_FROM_BOTFATHER>
WEBHOOK_URL="$GW_URL/webhook"
SECRET="my-secret-42"

curl -X POST "https://api.telegram.org/bot${TOKEN}/setWebhook" \
  -d url="${WEBHOOK_URL}" \
  -d secret_token="${SECRET}" \
  -d drop_pending_updates=true

Envie /start para seu bot—as mensagens fluirão através do API Gateway → Lambda.

  1. Logs, retentativas e atualizações
  • Acompanhe logs: aws logs tail /aws/lambda/telegram-bot-webhook --follow
  • O Telegram faz retentativas quando seu endpoint não retorna 2xx; mantenha respostas rápidas.
  • Para lançar novo código: re-zip + aws lambda update-function-code --function-name telegram-bot-webhook --zip-file fileb://function.zip.

B) python-telegram-bot containerizado no ECS Fargate + ALB

Use isso quando quiser a ergonomia do python-telegram-bot (PTB) com um aplicativo assíncrono adequado e conexões persistentes. Executaremos o PTB atrás de um load balancer HTTPS.

  1. Código do aplicativo (FastAPI + PTB webhook)

app.py:

import os, asyncio
from fastapi import FastAPI, Request, Header
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, ContextTypes, filters

TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
SECRET = os.environ.get("WEBHOOK_SECRET", "")

app = FastAPI()
tg_app = None  # aplicativo PTB

async def start_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("🚀 Olá do ECS Fargate + PTB!")

async def echo(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(update.message.text)

@app.on_event("startup")
async def on_startup():
    global tg_app
    tg_app = ApplicationBuilder().token(TOKEN).build()
    tg_app.add_handler(CommandHandler("start", start_cmd))
    tg_app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
    # Sem run_polling(); alimentaremos webhooks manualmente.

@app.post("/telegram/webhook")
async def telegram_webhook(request: Request, x_telegram_bot_api_secret_token: str | None = Header(default=None)):
    if SECRET and (x_telegram_bot_api_secret_token != SECRET):
        return {"ok": True}  # ignorar silenciosamente

    data = await request.json()
    update = Update.de_json(data, tg_app.bot)
    await tg_app.process_update(update)
    return {"ok": True}

uvicorn entrypoint: uvicorn app:app --host 0.0.0.0 --port 8080

  1. Dockerfile
FROM python:3.11-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
RUN pip install --no-cache-dir fastapi uvicorn[standard] python-telegram-bot==21.*
COPY app.py .
EXPOSE 8080
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]

Construir e enviar:

aws ecr create-repository --repository-name telegram-ptb || true
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION=<REGION>
ECR="$ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/telegram-ptb"

aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin "$ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com"
docker build -t telegram-ptb .
docker tag telegram-ptb:latest $ECR:latest
docker push $ECR:latest
  1. Serviço ECS Fargate atrás de um ALB
  • Crie um Security Group permitindo entrada 443 no ALB; tarefas ECS permitem 8080 do SG do ALB.
  • Crie um Application Load Balancer (ALB) com um ouvinte HTTPS (443) e um certificado ACM para seu domínio.
  • Grupo de destinos: HTTP 8080 (tipo de destino IP), caminho de verificação de saúde / (FastAPI serve 404; você pode adicionar rota @app.get("/") de saúde).

Crie uma Definição de Tarefa (Fargate) com:

  • Imagem do container: $ECR:latest
  • Mapeamento de porta: 8080
  • Vars de ambiente: TELEGRAM_BOT_TOKEN, WEBHOOK_SECRET
  • Papel da tarefa: log básico do CloudWatch.

Crie um Serviço ECS:

  • Tipo de lançamento Fargate, contagem desejada 1+.
  • Anexado ao grupo de destinos do ALB.

Observe o domínio HTTPS público do ALB (ou use Route 53 para apontar seu nome DNS).

  1. Avise ao Telegram sua URL de webhook
TOKEN=<TOKEN_FROM_BOTFATHER>
SECRET="my-secret-42"
WEBHOOK_URL="https://seu.dominio.com/telegram/webhook"

curl -X POST "https://api.telegram.org/bot${TOKEN}/setWebhook" \
  -d url="${WEBHOOK_URL}" \
  -d secret_token="${SECRET}" \
  -d drop_pending_updates=true \
  -d allowed_updates='["message","edited_message","callback_query"]'
  1. Escalar e operar
  • Escalar tarefas ECS para cima/baixo; o ALB espalhará o tráfego.
  • Rodear tokens no Secrets Manager, atualizar serviço com nova tarefa env.
  • Use CloudWatch Logs para logs do app e logs de acesso do ALB (S3).

Qual devemos escolher?

  • Lambda + API Gateway: mais simples, mais barato em baixo volume; ótimo para bots que fazem poucas chamadas por minuto.
  • ECS Fargate + ALB: melhor quando você quer a experiência completa do python-telegram-bot, middlewares personalizados, jobs em segundo plano e tráfego constante.

Checklist rápido (ambas as abordagens)

  • Use endpoint HTTPS + secret_token e verifique o cabeçalho X-Telegram-Bot-Api-Secret-Token.
  • Escolha webhook OU polling (não ambos).
  • Persista configuração no Secrets Manager, não no código.
  • Adicione observabilidade: CloudWatch Logs + métricas (alarmas 5xx).
  • Trate apenas os tipos de atualização que você precisa; expanda depois.

Assinar

Receba novos artigos sobre sistemas, infraestrutura e engenharia de IA.