Implémentation d'un bot Telegram en Python et en JavaScript avec déploiement sur AWS
Et déployer un nouveau bot Telegram sur AWS
Voici mes notes avec un tutoriel étape par étape sur la façon d’implémenter et déployer sur AWS un bot Telegram. J’ai ajouté un démarrage rapide (polling long) et un chemin prêt pour la production (webhooks), avec des exemples en Python et Node.js.
Les bots Telegram sont des applications qui s’exécutent sur vos serveurs et communiquent avec les utilisateurs via Telegram. Nous allons enregistrer un bot, écrire un petit programme et le connecter à l’API Bot de Telegram.
TL;DR
- Créer un bot via @BotFather → obtenir le token.
- Construire une petite application avec python-telegram-bot ou Telegraf.
- Commencer avec le polling long localement ; passer aux webhooks pour la production.
Ce dont vous aurez besoin
-
Un compte Telegram (mobile ou bureau)
-
Un terminal de base + un éditeur de code
-
L’un des suivants :
- Python 3.10+ et
pip
- Node.js 18+ et
npm
/pnpm
/yarn
- Python 3.10+ et
Créer votre bot avec BotFather (obtenir le token)
- Dans Telegram, cherchez @BotFather et commencez un chat.
- Envoyez
/newbot
et suivez les instructions pour nommer votre bot et choisir un nom d’utilisateur unique (doit se terminer parbot
), par exempleexample_helper_bot
. - BotFather répond avec un token API comme
123456:ABC-DEF...
. Traitez-le comme un mot de passe ; ne l’ajoutez pas à Git. Vous pouvez toujours le régénérer via BotFather s’il est divulgué.
Conseil : Le tutoriel officiel de Telegram passe en revue ces étapes exactes et explique comment vérifier votre token avec
getMe
.
Choisir votre pile
Vous pouvez appeler directement l’API Bot HTTP brute, mais l’utilisation d’une bibliothèque maintenue est plus rapide.
- Python :
python-telegram-bot
(asynchrone, moderne). ([https://docs.python-telegram-bot.org]) - Node.js :
telegraf
(mûr, compatible TypeScript). ([https://telegraf.js.org])
L’API Bot elle-même est documentée ici et est la source de vérité pour des méthodes comme getUpdates
et setWebhook
.
Démarrage rapide : exécuter localement avec polling long
Le polling long est parfait pour le développement local : votre bot demande répétitivement à Telegram de nouvelles mises à jour via getUpdates
. (En production, vous passerez probablement aux webhooks.)
Telegram prend en charge deux façons mutuellement exclusives de recevoir des mises à jour :
getUpdates
(polling) ou webhooks ; les mises à jour sont conservées pendant 24 heures maximum.
Option A : Python (avec python-telegram-bot
)
Installer et configurer
python -m venv .venv && source .venv/bin/activate # Windows : .venv\Scripts\activate
pip install python-telegram-bot
Code : 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("👋 Bonjour ! Envoyez-moi quelque chose et je le répéterai.")
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 long
if __name__ == "__main__":
main()
Exécuter :
export TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
python bot.py
Cela utilise ApplicationBuilder
des documents stables actuels.
Option B : Node.js (avec telegraf
)
Installer et configurer
npm init -y
npm i telegraf
Code : index.js
const { Telegraf } = require('telegraf');
const bot = new Telegraf(process.env.BOT_TOKEN); // définir la variable d'environnement BOT_TOKEN
bot.start((ctx) => ctx.reply('👋 Bonjour ! Envoyez-moi quelque chose et je le répéterai.'));
bot.on('text', (ctx) => ctx.reply(ctx.message.text));
bot.launch();
// arrêt gracieux
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));
Exécuter :
export BOT_TOKEN=123456:ABC-DEF...
node index.js
Cela reflète l’exemple officiel de “Démarrage” de Telegraf.
Rendre utile (commandes et boutons)
Ajouter une commande /help
Python
from telegram.ext import CommandHandler
async def help_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text("/start – saluer\n/help – cette aide")
app.add_handler(CommandHandler("help", help_cmd))
CommandHandler
est la méthode standard pour lier les /commandes
.
Node (Telegraf)
bot.help((ctx) => ctx.reply('/start – saluer\n/help – cette aide'));
Réponse rapide avec des boutons (clavier personnalisé)
Python
from telegram import ReplyKeyboardMarkup
async def start(update: Update, context):
keyboard = [["Aide", "À propos"]]
await update.message.reply_text(
"Choisissez une option :",
reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
)
Node (Telegraf)
const { Markup } = require('telegraf');
bot.start((ctx) => {
ctx.reply("Choisissez une option :", Markup.keyboard([["Aide", "À propos"]]).resize());
});
Production : passer aux webhooks
En production, Telegram pousse les mises à jour vers votre point de terminaison HTTPS. Vous pouvez le définir avec setWebhook
, en fournissant éventuellement un jeton secret afin de vérifier la demande via l’en-tête X-Telegram-Bot-Api-Secret-Token
.
Définir un webhook avec curl
:
TOKEN=123456:ABC-DEF...
WEBHOOK_URL="https://votre-domaine.com/telegram/${TOKEN}" # inclure un chemin secret
SECRET="mon-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
Points clés de la spécification :
setWebhook
nécessite une URL HTTPS et prend en chargesecret_token
.- Tant qu’un webhook est défini, vous ne pouvez pas utiliser
getUpdates
. - Les ports pris en charge incluent 443, 80, 88, 8443.
Options du serveur webhook
- Node (webhook intégré de Telegraf) :
bot.launch({
webhook: {
domain: "votre-domaine.com",
port: 8080,
// jeton secret en-tête facultatif
secretToken: process.env.WEBHOOK_SECRET
}
});
Telegraf expose des options de webhook de première classe et s’intègre avec Express/Fastify/Cloudflare Workers, etc.
- Python (
python-telegram-bot
) PTB fonctionne bien avec les frameworks ASGI/WSGI (FastAPI, Starlette, Flask). UtilisezApplicationBuilder().token(...).build()
, exposez une route POST qui alimente les mises à jour JSON entrantes dans votre application, et appelezbot.set_webhook(...)
. Consultez les documentsApplicationBuilder
pour les schémas de construction. ([docs.python-telegram-bot.org][2])
Testez localement ? Utilisez un tunnel (par exemple,
ngrok
) pour exposerhttps://...
à Telegram, puis appelezsetWebhook
avec l’URL publique.
Configuration des commandes du bot (facultatif mais convivial pour les utilisateurs)
Vous pouvez définir la liste des commandes du bot (ce que les utilisateurs voient lorsqu’ils tapent /
) soit :
- Dans BotFather via /mybots → Éditer le bot → Éditer les commandes, ou
- Programmatoirement avec
setMyCommands
à l’aide de votre bibliothèque ou de l’API Bot brute.
Le guide officiel de Telegram « De BotFather à « Hello World » » fait référence à des exemples de gestion des commandes plus avancés si vous souhaitez aller plus loin.
Considérations de déploiement
Tout hôte capable de gérer HTTPS fonctionne :
- Un petit VM (Ubuntu + systemd)
- Serverless (AWS Lambda/Fonctions Cloud) avec intégration webhook
- Conteneurs sur des plateformes comme Fly.io/Render/Heroku
Les documents de Telegraf incluent des exemples pour Lambda, GCF, Express, Fastify, etc.
Checklist de sécurité et de fiabilité
- Gardez le token secret (variables d’environnement, gestionnaire de secrets). Révoquez-le via BotFather s’il est divulgué.
- Utilisez
secret_token
avec les webhooks et vérifiez l’en-têteX-Telegram-Bot-Api-Secret-Token
. - Ne mélangez pas le polling et les webhooks ; choisissez-en un seul à la fois.
- Gérez les erreurs et les réessais : Telegram réessayera les réponses des webhooks non 2xx. Journalisez correctement.
- Soyez attentif aux types de mises à jour (messages, requêtes de rappel, requêtes inline, paiements, etc.) et souscrivez uniquement à ceux dont vous avez besoin (
allowed_updates
).
Travailler directement avec l’API HTTP (optionnel)
Vous pouvez appeler des endpoints comme :
https://api.telegram.org/bot<token>/getMe
https://api.telegram.org/bot<token>/getUpdates
https://api.telegram.org/bot<token>/sendMessage
Utilisez GET ou POST avec JSON ou des données de formulaire selon la spécification.
Ce à faire et à lire ensuite
- Référence officielle de l’API Bot : méthodes, objets, limites, mise en forme, paiements, mode inline.
- Guide officiel « De BotFather à « Hello World » » : walkthrough plus approfondi et exemples multilingues.
- Documentation python-telegram-bot (stable) : schémas modernes asynchrones.
- Documentation Telegraf : recettes rapides, assistants webhook et types TS.
Étapes de déploiement sur AWS pour la version Python
Nous avons deux options principales pour le déploiement du bot Telegram sur l’infrastructure AWS :
- A) Serverless (API Gateway + Lambda + Secrets Manager) — le moins cher et le plus facile à exécuter, idéal pour un trafic modeste.
- B) Conteneurisé (ECS Fargate + ALB + ACM) — de qualité production pour un trafic stable et des bibliothèques longues comme
python-telegram-bot
en mode webhook.
A) Serverless sur AWS (API Gateway + Lambda)
Utilisez cela lorsque vous souhaitez zéro serveur et un coût d’inactivité presque nul. Le code ci-dessous gère directement les webhooks Telegram (aucun boucle d’événement longue).
- Préparez un gestionnaire Lambda minimal (Python)
Créez handler.py
:
import json, os, urllib.request
BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
SECRET_HEADER = os.environ.get("WEBHOOK_SECRET", "") # doit correspondre au secret_token configuré dans l'API 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) Vérifiez l'en-tête secret de Telegram (configuré lors de la configuration du webhook)
if SECRET_HEADER:
if event.get("headers", {}).get("X-Telegram-Bot-Api-Secret-Token") != SECRET_HEADER:
return {"statusCode": 401, "body": "secret invalide"}
# 2) Analysez la mise à jour
body = event.get("body") or "{}"
update = json.loads(body)
message = update.get("message") or update.get("edited_message")
if not message:
# ignorez les mises à jour non-message (callback_query, inline_query, etc.) pour l'instant
return {"statusCode": 200, "body": "ok"}
chat_id = message["chat"]["id"]
text = (message.get("text") or "").strip()
# 3) Routage simple
if text.startswith("/start"):
reply(chat_id, "👋 Bonjour depuis AWS Lambda ! Envoyez tout texte et je le répéterai.")
elif text.startswith("/help"):
reply(chat_id, "/start – saluer\n/help – aide\n(Déployé sur AWS Lambda)")
elif text:
reply(chat_id, text) # écho
return {"statusCode": 200, "body": "ok"}
Cela utilise des appels HTTPS bruts à l’API Bot pour garder Lambda léger et amical aux débuts froids. Vous pouvez étendre le routage ultérieurement.
- Empaquetez et déployez la Lambda
# Structure du projet
# .
# ├─ handler.py
# └─ requirements.txt # (laissez vide pour cet exemple minimal)
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}'
Rôle IAM (<LambdaExecutionRole>
) doit avoir AWSLambdaBasicExecutionRole
pour les logs CloudWatch.
Préférez stocker votre token dans AWS Secrets Manager et le charger à l’initialisation — cet exemple utilise les variables d’environnement pour la brièveté.
- Créer un point de terminaison HTTPS (API Gateway)
# API HTTP (non REST) pour une latence plus faible
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)
# Ajouter une route par défaut 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 # par exemple, https://abc123.execute-api.ap-somewhere.amazonaws.com
Assurez-vous que la permission Lambda est automatiquement ajoutée ; si ce n’est pas le cas :
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"
- Pointez Telegram vers votre 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
Envoyez /start
à votre bot — les messages passeront par API Gateway → Lambda.
- Logs, réessais et mises à jour
- Suivez les logs :
aws logs tail /aws/lambda/telegram-bot-webhook --follow
- Telegram réessaie lorsque votre point de terminaison n’est pas 2xx ; gardez les réponses rapides.
- Pour déployer du nouveau code : ré-zippez +
aws lambda update-function-code --function-name telegram-bot-webhook --zip-file fileb://function.zip
.
B) python-telegram-bot
conteneurisé sur ECS Fargate + ALB
Utilisez cela lorsque vous souhaitez l’ergonomie de
python-telegram-bot
(PTB) avec une application asynchrone correcte et des connexions persistantes. Nous exécuterons PTB derrière un équilibreur de charge HTTPS.
- Code de l’application (FastAPI + webhook 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 # application PTB
async def start_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text("🚀 Bonjour depuis 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))
# Aucun run_polling() ; nous alimenterons les webhooks manuellement.
@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} # ignorer silencieusement
data = await request.json()
update = Update.de_json(data, tg_app.bot)
await tg_app.process_update(update)
return {"ok": True}
Point d’entrée 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"]
Construire et publier :
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
- Service ECS Fargate derrière un ALB
- Créez un groupe de sécurité autorisant l’entrée 443 sur l’ALB ; les tâches ECS autorisent 8080 depuis le groupe de sécurité ALB.
- Créez un Application Load Balancer (ALB) avec un écouteur HTTPS (443) et un certificat ACM pour votre domaine.
- Groupe cible : HTTP 8080 (type de cible IP), chemin de vérification de santé
/
(FastAPI affiche 404 ; vous pouvez ajouter@app.get("/")
pour le chemin de santé).
Créez une définition de tâche (Fargate) avec :
- Image de conteneur :
$ECR:latest
- Mappage de port : 8080
- Variables d’environnement :
TELEGRAM_BOT_TOKEN
,WEBHOOK_SECRET
- Rôle de tâche : rôle de base pour les logs CloudWatch.
Créez un Service ECS :
- Type de lancement Fargate, nombre souhaité de tâches 1+.
- Attachez au groupe cible ALB.
Notez le domaine HTTPS public de l’ALB (ou utilisez Route 53 pour pointer votre nom de domaine).
- Informez Telegram de votre URL de webhook
TOKEN=<TOKEN_FROM_BOTFATHER>
SECRET="my-secret-42"
WEBHOOK_URL="https://votre.domaine.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"]'
- Échelle et opération
- Échelle les tâches ECS vers le haut/bas ; l’ALB répartira le trafic.
- Tournez les tokens dans Secrets Manager, mettez à jour le service avec de nouvelles variables d’environnement de tâche.
- Utilisez CloudWatch Logs pour les logs d’application et les logs d’accès ALB (S3).
Quel devrions-nous choisir ?
- Lambda + API Gateway : le plus simple, le moins cher à faible volume ; idéal pour les bots qui effectuent quelques appels par minute.
- ECS Fargate + ALB : le meilleur choix lorsque vous souhaitez l’expérience complète de
python-telegram-bot
, des middlewares personnalisés, des tâches en arrière-plan et un trafic stable.
Checklist rapide (pour les deux approches)
- Utilisez un point de terminaison HTTPS +
secret_token
et vérifiez l’en-têteX-Telegram-Bot-Api-Secret-Token
. - Choisissez webhook OU polling (pas les deux).
- Persistance de la configuration dans Secrets Manager, pas dans le code.
- Ajoutez l’observabilité : CloudWatch Logs + métriques (alarmes 5xx).
- Gérez uniquement les types de mise à jour dont vous avez besoin ; étendez plus tard.
Liens utiles
- https://docs.python-telegram-bot.org
- https://telegraf.js.org
- https://core.telegram.org/bots/tutorial
- https://core.telegram.org/bots/api
- Vue d’ensemble d’AWS CDK, exemples TypeScript et Python et considérations de performance
- Performance d’AWS Lambda : JavaScript vs Python vs Golang
- Lambda en couches avec AWS SAM et Python
- AWS SAM + AWS SQS + Python PowerTools
- Feuille de triche Python
- uv - Nouveau package Python, gestionnaire de projet et d’environnement
- Installer Node.js