Implementando um Bot do Telegram em Python e JavaScript com implantação na AWS
E implantando um novo bot do Telegram na AWS
Aqui estão minhas notas com um tutorial passo a passo sobre como implementar e implantar em AWS um bot do Telegram. Adicionei um início rápido (polling longo) e um caminho pronto para produção (webhooks), com exemplos em Python e Node.js.
Bots do Telegram são aplicativos que executam em seus servidores e conversam com usuários através do Telegram. Vamos registrar um bot, escrever um pequeno programa e conectá-lo à API do Bot do Telegram.
TL;DR
- Crie um bot via @BotFather → obtenha o token.
- Construa um pequeno aplicativo com python-telegram-bot ou Telegraf.
- Comece com polling longo localmente; mude para webhooks em produção.
O que você precisará
-
Uma conta do Telegram (móvel ou desktop)
-
Terminal básico + editor de código
-
Um dos seguintes:
- Python 3.10+ e
pip
- Node.js 18+ e
npm
/pnpm
/yarn
- Python 3.10+ e
Crie seu bot com o BotFather (obtenha o token)
- No Telegram, procure por @BotFather e inicie uma conversa.
- Envie
/newbot
e siga as instruções para nomear seu bot e escolher um nome de usuário único (deve terminar combot
), por exemplo,example_helper_bot
. - O BotFather responde com um token da API como
123456:ABC-DEF...
. Trate isso como uma senha; não o comite no Git. Você sempre pode regenerá-lo via BotFather se ele vazar.
Dica: O tutorial oficial do Telegram passa por essas etapas exatas e como verificar seu token com
getMe
.
Escolha sua pilha
Você pode chamar diretamente a HTTP Bot API, 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 com TypeScript). ([https://telegraf.js.org])
A própria Bot API está documentada aqui e é a fonte de verdade para métodos como getUpdates
e setWebhook
.
Início Rápido: execute localmente com polling longo
O polling longo é 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
)
Instale e estruture
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() # polling longo
if __name__ == "__main__":
main()
Execute-o:
export TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
python bot.py
Isso usa ApplicationBuilder
das documentações atuais estáveis.
Opção B: Node.js (com telegraf
)
Instale e estruture
npm init -y
npm i telegraf
Código: index.js
const { Telegraf } = require('telegraf');
const bot = new Telegraf(process.env.BOT_TOKEN); // defina a variável 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 suave
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));
Execute-o:
export BOT_TOKEN=123456:ABC-DEF...
node index.js
Isso espelha o exemplo oficial de “Começando” do Telegraf.
Torne-o ú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 – cumprimentar\n/help – este ajuda")
app.add_handler(CommandHandler("help", help_cmd))
CommandHandler
é o método padrão para vincular /comandos
.
Node (Telegraf)
bot.help((ctx) => ctx.reply('/start – cumprimentar\n/help – este 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 atualizações para seu endpoint HTTPS. Você pode definir isso com setWebhook
, opcionalmente fornecendo um token secreto para que você possa 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 suportasecret_token
.- Enquanto um webhook estiver definido, você não pode usar
getUpdates
. - Portas suportadas incluem 443, 80, 88, 8443.
Opções do servidor de webhook
- Node (Telegraf) webhook embutido:
bot.launch({
webhook: {
domain: "seu-dominio.com",
port: 8080,
// token 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). UseApplicationBuilder().token(...).build()
, exponha uma rota POST que alimente as atualizações JSON recebidas para sua aplicação e chamebot.set_webhook(...)
. Veja as documentações doApplicationBuilder
para padrões de construção. ([docs.python-telegram-bot.org][2])
Testando localmente? Use um túnel (por exemplo,
ngrok
) para exporhttps://...
ao Telegram, depois chamesetWebhook
com a URL pública.
Configuração de 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:
- Em BotFather via /mybots → Editar Bot → Editar Comandos, ou
- Programaticamente com
setMyCommands
usando sua biblioteca ou a API Bot raw.
O guia oficial do Telegram “De BotFather para ‘Hello World’” vincula-se a exemplos mais avançados de manipulação de comandos se quiser ir mais longe.
Considerações sobre implantação
Qualquer host capaz de HTTPS funciona:
- Um pequeno VM (Ubuntu + systemd)
- Serverless (AWS Lambda/Funções da Nuvem) com integração de webhook
- Containers em plataformas como Fly.io/Render/Heroku
As documentações do Telegraf incluem exemplos para Lambda, GCF, Express, Fastify, etc.
Checklist de segurança e confiabilidade
- Mantenha o token secreto (variáveis de ambiente, gerenciador de segredos). Revogue-o no BotFather se vazado.
- Use
secret_token
com webhooks e verifique o cabeçalhoX-Telegram-Bot-Api-Secret-Token
. - Não misture polling e webhooks; escolha um de cada vez.
- Trate erros e retenções: o Telegram repetirá respostas de webhook que não sejam 2xx. Registre apropriadamente.
- Esteja atento aos tipos de atualização (mensagens, callbacks, consultas inline, pagamentos, etc.) e inscreva-se apenas no que precisar (
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 em seguida
- Referência oficial da Bot API: métodos, objetos, limites, formatação, pagamentos, modo inline.
- Guia oficial “De BotFather para ‘Hello World’”: caminhada mais detalhada e exemplos em múltiplos idiomas.
- Documentação do python-telegram-bot (estável): padrões modernos de assincronia.
- Documentação do Telegraf: receitas rápidas, ajudantes de webhook e tipos TS.
Passos para implantação no AWS para a versão Python
Temos duas opções principais para implantação do bot do Telegram na infraestrutura AWS:
- A) Serverless (API Gateway + Lambda + Secrets Manager) — mais barato e fácil de executar, excelente para tráfego modesto.
- B) Containerizado (ECS Fargate + ALB + ACM) — adequado para tráfego constante e bibliotecas de longa execução como
python-telegram-bot
no modo webhook.
A) Serverless no AWS (API Gateway + Lambda)
Use isso quando quiser zero servidores e custo quase zero em ociosidade. O código abaixo lida diretamente com webhooks do Telegram (sem loop de eventos de longa execução).
- Prepare um manipulador mínimo de Lambda (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 definido na API do Bot
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) Verifique 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": "segredo inválido"}
# 2) Parse atualização
body = event.get("body") or "{}"
update = json.loads(body)
message = update.get("message") or update.get("edited_message")
if not message:
# ignore atualizações não de mensagem (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 – cumprimentar\n/help – ajuda\n(Implantado no AWS Lambda)")
elif text:
reply(chat_id, text) # eco
return {"statusCode": 200, "body": "ok"}
Isso usa chamadas HTTP brutas à API do Bot para manter o Lambda leve e amigável com cold starts. Você pode expandir o roteamento depois.
- Empacote e implante a Lambda
# Layout do projeto
# .
# ├─ handler.py
# └─ requirements.txt # (deixe vazio para este exemplo mínimo)
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_DO_BOTFATHER>,WEBHOOK_SECRET=my-secret-42}'
Função IAM (<LambdaExecutionRole>
) precisa de AWSLambdaBasicExecutionRole
para logs do CloudWatch.
Prefira armazenar seu token no AWS Secrets Manager e carregá-lo na inicialização — este exemplo usa variáveis de ambiente por brevidade.
- Crie um endpoint HTTPS (API Gateway)
# API HTTP (não REST) para menor latência
API_ID=$(aws apigatewayv2 create-api \
--name telegram-webhook \
--protocol-type HTTP \
--target arn:aws:lambda:<REGIÃO>:<ACCOUNT_ID>:function:telegram-bot-webhook \
--query 'ApiId' --output text)
# Adicione uma rota padrão POST /webhook
aws apigatewayv2 create-integration \
--api-id $API_ID \
--integration-type AWS_PROXY \
--integration-uri arn:aws:lambda:<REGIÃO>:<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 # e.g., https://abc123.execute-api.ap-somewhere.amazonaws.com
Certifique-se de que a permissão da 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:<REGIÃO>:<ACCOUNT_ID>:$API_ID/*/*/webhook"
- Aponte o Telegram para seu webhook
TOKEN=<TOKEN_DO_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.
- Logs, tentativas e atualizações
- Observe os logs:
aws logs tail /aws/lambda/telegram-bot-webhook --follow
- O Telegram tenta novamente quando seu endpoint não é 2xx; mantenha as respostas rápidas.
- Para implantar novos códigos: re-zipe +
aws lambda update-function-code --function-name telegram-bot-webhook --zip-file fileb://function.zip
.
B) python-telegram-bot
containerizado em ECS Fargate + ALB
Use isso quando quiser a ergonomia do
python-telegram-bot
(PTB) com uma aplicação assíncrona adequada e conexões persistentes. Vamos executar o PTB atrás de um balanceador de carga HTTPS.
- Código da aplicação (FastAPI + webhook do PTB)
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 # aplicação 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))
# Não execute run_polling(); alimentaremos os 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} # ignore silenciosamente
data = await request.json()
update = Update.de_json(data, tg_app.bot)
await tg_app.process_update(update)
return {"ok": True}
Entrada do uvicorn
: uvicorn app:app --host 0.0.0.0 --port 8080
- 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"]
Construa e envie:
aws ecr create-repository --repository-name telegram-ptb || true
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGIÃO=<REGIÃO>
ECR="$ACCOUNT_ID.dkr.ecr.$REGIÃO.amazonaws.com/telegram-ptb"
aws ecr get-login-password --region $REGIÃO | docker login --username AWS --password-stdin "$ACCOUNT_ID.dkr.ecr.$REGIÃO.amazonaws.com"
docker build -t telegram-ptb .
docker tag telegram-ptb:latest $ECR:latest
docker push $ECR:latest
- Serviço ECS Fargate atrás de um ALB
- Crie um Grupo de Segurança permitindo entrada 443 no ALB; as tarefas ECS permitem 8080 do grupo de segurança do ALB.
- Crie um Balanceador de Carga de Aplicação (ALB) com um ouvinte HTTPS (443) e um certificado ACM para seu domínio.
- Grupo de alvo: HTTP 8080 (tipo de alvo IP), caminho de verificação
/
(FastAPI serve 404; você pode adicionar@app.get("/")
rota de saúde).
Crie uma Definição de Tarefa (Fargate) com:
- Imagem do contêiner:
$ECR:latest
- Mapeamento de porta: 8080
- Variáveis de ambiente:
TELEGRAM_BOT_TOKEN
,WEBHOOK_SECRET
- Função de tarefa: papel básico de logs do CloudWatch.
Crie um Serviço ECS:
- Tipo de lançamento Fargate, contagem desejada 1+.
- Anexe ao grupo de alvo do ALB.
Note o domínio HTTPS público do ALB (ou use Route 53 para apontar seu nome de DNS).
- Informe ao Telegram sua URL do webhook
TOKEN=<TOKEN_DO_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"]'
- Escalabilidade e operação
- Escalando tarefas ECS para cima/baixo; o ALB distribuirá o tráfego.
- Roteie tokens no Secrets Manager, atualize o serviço com novas variáveis de ambiente da tarefa.
- Use CloudWatch Logs para logs da aplicação e logs de acesso do ALB (S3).
Qual devemos escolher?
- Lambda + API Gateway: mais simples, mais barato em baixo volume; excelente para bots que fazem algumas chamadas por minuto.
- ECS Fargate + ALB: melhor quando quiser a experiência completa do
python-telegram-bot
, middlewares personalizados, trabalhos em segundo plano e tráfego constante.
Checklist rápido (ambos os abordagens)
- Use endpoint HTTPS +
secret_token
e verifique o cabeçalhoX-Telegram-Bot-Api-Secret-Token
. - Escolha webhook OU polling (não ambos).
- Persista a configuração em Secrets Manager, não no código.
- Adicione observabilidade: logs do CloudWatch + métricas (alarmes 5xx).
- Trate apenas os tipos de atualização que você precisa; expanda depois.
Links úteis
- https://docs.python-telegram-bot.org
- https://telegraf.js.org
- https://core.telegram.org/bots/tutorial
- https://core.telegram.org/bots/api
- Visão Geral do AWS CDK, Exemplos em TypeScript e Python e Considerações de Desempenho
- Desempenho da AWS Lambda: JavaScript vs Python vs Golang
- Lambda Camadas com AWS SAM e Python
- AWS SAM + AWS SQS + Python PowerTools
- Folha de Dicas do Python
- uv - Novo Gerenciador de Pacotes, Projetos e Ambientes do Python
- Instale o Node.js