Het implementeren van een Telegram-bot in Python en JavaScript met implementatie op AWS

En het implementeren van een nieuw Telegram-bot op AWS

Inhoud

Hier zijn mijn aantekeningen met stap-voor-stap tutorial over hoe je implementeren en implementeren op AWS van een Telegram bot. Ik heb een quick start (long polling) en een productie-klare pad (webhooks) toegevoegd, met voorbeelden in Python en Node.js.

robots werken in IT

Telegram bots zijn apps die op je servers draaien en met gebruikers communiceren via Telegram. We zullen een bot registreren, een klein programma schrijven en het verbinden met Telegram’s Bot API.

TL;DR

  1. Maak een bot aan via @BotFather → krijg token.
  2. Bouw een klein app met python-telegram-bot of Telegraf.
  3. Start met long polling lokaal; schakel over naar webhooks voor productie.

Wat je nodig hebt

  • Een Telegram account (mobiel of desktop)

  • Basis terminal + code editor

  • Één van de volgende:

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

Maak je bot aan met BotFather (krijg het token)

  1. In Telegram, zoek naar @BotFather en start een chat.
  2. Stuur /newbot en volg de prompts om je bot te benoemen en een unieke gebruikersnaam te kiezen (moet eindigen met bot), bijvoorbeeld example_helper_bot.
  3. BotFather reageert met een API token zoals 123456:ABC-DEF.... Behandel dit als een wachtwoord; commit het niet naar Git. Je kunt het altijd opnieuw genereren via BotFather als het lekt.

Tip: Telegram’s officiële tutorial loopt deze exacte stappen door en laat zien hoe je je token verifieert met getMe.


Kies je stack

Je kunt de raw HTTP Bot API zelf aanroepen, maar het gebruik van een onderhouden bibliotheek is sneller.

  • Python: python-telegram-bot (async, modern). ([https://docs.python-telegram-bot.org])
  • Node.js: telegraf (mature, TypeScript-vriendelijk). ([https://telegraf.js.org])

De Bot API zelf is hier gedocumenteerd en is de bron van waarheid voor methoden zoals getUpdates en setWebhook.


Quick Start: draai lokaal met long polling

Long polling is perfect voor lokale ontwikkeling: je bot vraagt Telegram herhaaldelijk om nieuwe updates via getUpdates. (In productie, zul je waarschijnlijk overgeschakeld hebben naar webhooks.)

Telegram ondersteunt twee mutueel uitsluitende manieren om updates te ontvangen: getUpdates (polling) of webhooks; updates worden maximaal 24 uur bewaard.

Optie A: Python (met python-telegram-bot)

Installeer & scaffold

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("👋 Hallo! Stuur me iets en ik herhalen het.")

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()

Voer het uit:

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

Dit gebruikt ApplicationBuilder van de huidige stabiele documentatie.

Optie B: Node.js (met telegraf)

Installeer & scaffold

npm init -y
npm i telegraf

Code: index.js

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

const bot = new Telegraf(process.env.BOT_TOKEN); // set BOT_TOKEN env var
bot.start((ctx) => ctx.reply('👋 Hallo! Stuur me iets en ik herhalen het.'));
bot.on('text', (ctx) => ctx.reply(ctx.message.text));

bot.launch();

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

Voer het uit:

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

Dit spiegelt het officiële Telegraf “Getting started” voorbeeld.


Maak het nuttig (commando’s & knoppen)

Voeg een /help commando toe

Python

from telegram.ext import CommandHandler

async def help_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("/start – groet\n/help – deze hulp")

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

CommandHandler is de standaard manier om /commando's te binden.

Node (Telegraf)

bot.help((ctx) => ctx.reply('/start – groet\n/help – deze hulp'));

Snelle antwoordknoppen (aangepaste toetsenbord)

Python

from telegram import ReplyKeyboardMarkup

async def start(update: Update, context):
    keyboard = [["Help", "Over mij"]]
    await update.message.reply_text(
        "Kies een optie:",
        reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    )

Node (Telegraf)

const { Markup } = require('telegraf');
bot.start((ctx) => {
  ctx.reply("Kies een optie:", Markup.keyboard([["Help", "Over mij"]]).resize());
});

Productie: schakel over naar webhooks

In productie stuurt Telegram updates naar je HTTPS eindpunt. Je kunt dit instellen met setWebhook, optioneel met een geheime token zodat je de aanvraag kunt verifiëren via de X-Telegram-Bot-Api-Secret-Token header.

Stel een webhook in met curl:

TOKEN=123456:ABC-DEF...
WEBHOOK_URL="https://your-domain.com/telegram/${TOKEN}"  # include a secret path
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

Belangrijke punten uit de specificatie:

  • setWebhook vereist een HTTPS URL en ondersteunt secret_token.
  • Terwijl een webhook is ingesteld, kun je niet getUpdates gebruiken.
  • Ondersteunde poorten zijn 443, 80, 88, 8443.

Webhook server opties

  • Node (Telegraf) ingebouwde webhook:
bot.launch({
  webhook: {
    domain: "your-domain.com",
    port: 8080,
    // optionele geheime header
    secretToken: process.env.WEBHOOK_SECRET
  }
});

Telegraf biedt eerste klas webhook opties en integreert met Express/Fastify/Cloudflare Workers, enzovoort.

  • Python (python-telegram-bot) PTB werkt goed met ASGI/WSGI frameworks (FastAPI, Starlette, Flask). Gebruik ApplicationBuilder().token(...).build(), exposeer een POST route die de binnenkomende JSON updates voert naar je applicatie, en roep bot.set_webhook(...) aan. Zie de ApplicationBuilder documentatie voor constructiepatronen. ([docs.python-telegram-bot.org][2])

Testen lokaal? Gebruik een tunnel (bijvoorbeeld ngrok) om https://... te blootstellen aan Telegram, en roep dan setWebhook aan met de openbare URL.


Configureren van bot commando’s (optioneel maar gebruikersvriendelijk)

Je kunt de lijst van bot commando’s (wat gebruikers zien wanneer ze / typen) definiëren via:

  • In BotFather via /mybots → Bewerk Bot → Bewerk Commando’s, of
  • Programmatisch met setMyCommands via je bibliotheek of raw Bot API.

Telegram’s officiële “Van BotFather naar ‘Hello World’” gids verwijs naar meer geavanceerde commando handling en voorbeelden als je verder wilt gaan.


Overwegingen voor implementatie

Elke HTTPS-gecapteerde host werkt:

  • Een kleine VM (Ubuntu + systemd)
  • Serverless (AWS Lambda/Cloud Functions) met webhook integratie
  • Containers op Fly.io/Render/Heroku-achtige platforms

Telegraf’s documentatie bevat voorbeelden voor Lambda, GCF, Express, Fastify, enzovoort.


Checklist voor beveiliging en betrouwbaarheid

  • Houd het token geheim (omgevingsvariabelen, geheimenbeheer). Onttrek het in BotFather als het gelekt is.
  • Gebruik secret_token met webhooks en verifieer de X-Telegram-Bot-Api-Secret-Token header.
  • Mix niet polling en webhooks; kies er één voor.
  • Verwerk fouten & herproeven: Telegram herprobeerd niet-2xx webhook reacties. Log juist.
  • Wees voorzichtig met update types (berichten, callbacks, inline queries, betalingen, enzovoort) en abonneer je alleen op wat je nodig hebt (allowed_updates).

Werken direct met de HTTP API (optioneel)

Je kunt endpoints aanroepen zoals:

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

Gebruik GET of POST met JSON of form data zoals in de specificatie.


Wat je als volgende moet doen en lezen

  • Officiële Bot API referentie: methoden, objecten, limieten, opmaak, betalingen, inline modus.
  • Officiële “Van BotFather naar ‘Hello World’” gids: dieper walkthrough en voorbeelden in meerdere talen.
  • python-telegram-bot documentatie (stabiel): moderne async patronen.
  • Telegraf documentatie: snelle recepten, webhook helpers en TS types.

AWS implementatiestappen voor de Python versie

We hebben twee hoofdopties voor implementatie van de Telegram bot op AWS infrastructuur:

  • A) Serverless (API Gateway + Lambda + Secrets Manager) — goedkoopst/eenvoudigst om te draaien, ideaal voor matige verkeer.
  • B) Containerized (ECS Fargate + ALB + ACM) — productie-klare voor stabiel verkeer en lange lopende bibliotheken zoals python-telegram-bot in webhook modus.

A) Serverless op AWS (API Gateway + Lambda)

Gebruik dit wanneer je geen servers wilt en bijna nul inactieve kosten wilt. Het onderstaande code verwerkt Telegram webhooks direct (geen langlopende event loop).

  1. Voorbereiden van een minimale Lambda handler (Python)

Maak handler.py:

import json, os, urllib.request

BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
SECRET_HEADER = os.environ.get("WEBHOOK_SECRET", "")  # moet overeenkomen met Bot API setWebhook secret_token

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) Verifieer Telegram's geheime header (ingesteld wanneer je de webhook configureert)
    if SECRET_HEADER:
        if event.get("headers", {}).get("X-Telegram-Bot-Api-Secret-Token") != SECRET_HEADER:
            return {"statusCode": 401, "body": "ongeldig geheim"}

    # 2) Pars update
    body = event.get("body") or "{}"
    update = json.loads(body)

    message = update.get("message") or update.get("edited_message")
    if not message:
        # negeer niet-bericht updates (callback_query, inline_query, enzovoort) voor nu
        return {"statusCode": 200, "body": "ok"}

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

    # 3) Eenvoudige routing
    if text.startswith("/start"):
        reply(chat_id, "👋 Hallo van AWS Lambda! Stuur me iets en ik herhalen het.")
    elif text.startswith("/help"):
        reply(chat_id, "/start – groet\n/help – help\n(Geïmplementeerd op AWS Lambda)")
    elif text:
        reply(chat_id, text)  # echo

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

Dit gebruikt raw HTTPS aanroepen naar de Bot API om Lambda lank en koudstartvriendelijk te houden. Je kunt routing later uitbreiden.

  1. Pakket en implementeer de Lambda
# Project lay-out
# .
# ├─ handler.py
# └─ requirements.txt   # (laat leeg voor dit minimale voorbeeld)

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}'

IAM rol (<LambdaExecutionRole>) moet AWSLambdaBasicExecutionRole hebben voor CloudWatch Logs.

Voorkeur is het opslaan van je token in AWS Secrets Manager en het laden bij initialisatie—dit voorbeeld gebruikt omgevingsvariabelen voor korte dure.

  1. Creëer een HTTPS eindpunt (API Gateway)
# HTTP API (niet REST) voor lagere latentie
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)

# Voeg een standaard route POST /webhook toe
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  # bijvoorbeeld, https://abc123.execute-api.ap-somewhere.amazonaws.com

Zorg ervoor dat de Lambda-permissie automatisch wordt toegevoegd; als dat niet het geval is:

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. Stuur Telegram naar je 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

Stuur /start naar je bot—berichten zullen via API Gateway → Lambda stromen.

  1. Logs, herproeven en updates
  • Bekijk logs: aws logs tail /aws/lambda/telegram-bot-webhook --follow
  • Telegram herprobeert wanneer je eindpunt niet 2xx is; houd reacties snel.
  • Om nieuwe code uit te rollen: herpak + aws lambda update-function-code --function-name telegram-bot-webhook --zip-file fileb://function.zip.

B) Containerized python-telegram-bot op ECS Fargate + ALB

Gebruik dit wanneer je de ergonomie van python-telegram-bot (PTB) wilt met een echte async app en blijvende connecties. We zullen PTB uitvoeren achter een HTTPS load balancer.

  1. App code (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  # PTB applicatie

async def start_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("🚀 Hallo van 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))
    # Geen run_polling(); we zullen webhooks handmatig voeden.

@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}  # negeer stil

    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"]

Build & push:

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. ECS Fargate service achter een ALB
  • Maak een Beveiligingsgroep die binnenkomend 443 toestaat op de ALB; ECS taken toestaan 8080 van de ALB SG.
  • Maak een Application Load Balancer (ALB) met een HTTPS listener (443) en een ACM certificaat voor je domein.
  • Doelgroep: HTTP 8080 (IP doeltype), gezondheidstestpad / (FastAPI levert 404; je kunt @app.get("/") gezondheidspad toevoegen).

Maak een Taakdefinitie (Fargate) met:

  • Container beeld: $ECR:latest
  • Poorttoewijzing: 8080
  • Omgevingsvariabelen: TELEGRAM_BOT_TOKEN, WEBHOOK_SECRET
  • Taakrol: basis CloudWatch logboekregistratie.

Maak een ECS Service:

  • Starttype Fargate, gewenste aantal 1+.
  • Koppel aan de ALB doelgroep.

Noteer het openbare HTTPS domein van de ALB (of gebruik Route 53 om je DNS naam te wijzigen).

  1. Vertel Telegram je webhook URL
TOKEN=<TOKEN_FROM_BOTFATHER>
SECRET="my-secret-42"
WEBHOOK_URL="https://your.domain.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. Schaal & bedien
  • Schaal ECS taken op en neer; ALB zal het verkeer verspreiden.
  • Roate tokens in Secrets Manager, update service met nieuwe taak omgevingsvariabelen.
  • Gebruik CloudWatch Logs voor app logs en ALB toegang logs (S3).

Welke moeten we kiezen?

  • Lambda + API Gateway: eenvoudigst, goedkoopst bij lage volume; ideaal voor bots die een paar oproepen per minuut doen.
  • ECS Fargate + ALB: beste wanneer je de volledige python-telegram-bot ervaring wilt, aangepaste middelware, achtergrondtaken en stabiel verkeer.

Snelle checklist (beide aanpakken)

  • Gebruik HTTPS eindpunt + secret_token en verifieer de X-Telegram-Bot-Api-Secret-Token header.
  • Kies webhook OF polling (niet beide).
  • Bewaar configuratie in Secrets Manager, niet in code.
  • Voeg observabiliteit toe: CloudWatch Logs + metrieken (5xx alarms).
  • Verwerk alleen de update types die je nodig hebt; breid later uit.