Implementering av Telegram-bot i Python och JavaScript med distribution till AWS

Och distribuerar en ny Telegram-bot till AWS

Sidinnehåll

Här är mina anteckningar med en steg-för-steg-guide på hur man implementerar och distribuerar en Telegram-bot till AWS. Jag har lagt till en snabbstart (long polling) och en produktionsklar väg (webhooks), med exempel i Python och Node.js.

robotar som arbetar inom IT

Telegram-botar är appar som körs på dina servrar och kommunicerar med användare via Telegram. Vi kommer att registrera en bot, skriva ett litet program och ansluta det till Telegrams Bot API.

TL;DR

  1. Skapa en bot via @BotFather → få token.
  2. Bygg en liten app med python-telegram-bot eller Telegraf.
  3. Börja med long polling lokalt; byt till webhooks för produktion.

Vad du kommer att behöva

  • Ett Telegram-konto (mobil eller desktop)

  • Grundläggande terminal + kodredigerare

  • Ett av följande:

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

Skapa din bot med BotFather (få token)

  1. I Telegram, söker du efter @BotFather och startar en chatt.
  2. Skicka /newbot och följ anvisningarna för att namnge din bot och välja ett unikt användarnamn (måste sluta med bot), t.ex. example_helper_bot.
  3. BotFather svarar med en API-token som 123456:ABC-DEF.... Behandla detta som ett lösenord; lägg inte det i Git. Du kan alltid regenerera det via BotFather om det läcker ut.

Tips: Telegrams officiella guide går igenom dessa exakta steg och hur du verifierar din token med getMe.


Välj din stack

Du kan ringa den rena HTTP Bot API själv, men att använda en underhållen bibliotek är snabbare.

  • Python: python-telegram-bot (async, modern). ([https://docs.python-telegram-bot.org])
  • Node.js: telegraf (mogen, TypeScript-vänlig). ([https://telegraf.js.org])

Bot API i sig är dokumenterad här och är källan till sanningen för metoder som getUpdates och setWebhook.


Snabbstart: kör lokalt med long polling

Long polling är perfekt för lokal utveckling: din bot frågar Telegram upprepade gånger efter nya uppdateringar via getUpdates. (I produktion kommer du troligen att byta till webhooks.)

Telegram stöder två ömsesidigt exklusiva sätt att ta emot uppdateringar: getUpdates (polling) eller webhooks; uppdateringar sparas i upp till 24 timmar.

Alternativ A: Python (med python-telegram-bot)

Installera & skapa mall

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

Kod: 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("👋 Hej! Skicka något till mig och jag kommer att echo det.")

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

Kör det:

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

Det här använder ApplicationBuilder från de aktuella stabila dokumenten.

Alternativ B: Node.js (med telegraf)

Installera & skapa mall

npm init -y
npm i telegraf

Kod: index.js

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

const bot = new Telegraf(process.env.BOT_TOKEN); // sätt BOT_TOKEN miljövariabel
bot.start((ctx) => ctx.reply('👋 Hej! Skicka något till mig och jag kommer att echo det.'));
bot.on('text', (ctx) => ctx.reply(ctx.message.text));

bot.launch();

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

Kör det:

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

Det här speglar det officiella Telegraf-exemplet “Getting started”.


Gör det användbart (kommandon & knappar)

Lägg till ett /help-kommando

Python

from telegram.ext import CommandHandler

async def help_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("/start – hälsa\n/help – denna hjälp")

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

CommandHandler är det standard sättet att binda /kommandon.

Node (Telegraf)

bot.help((ctx) => ctx.reply('/start – hälsa\n/help – denna hjälp'));

Snabba svarknappar (anpassat tangentbord)

Python

from telegram import ReplyKeyboardMarkup

async def start(update: Update, context):
    keyboard = [["Hjälp", "Om"]]
    await update.message.reply_text(
        "Välj ett alternativ:",
        reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    )

Node (Telegraf)

const { Markup } = require('telegraf');
bot.start((ctx) => {
  ctx.reply("Välj ett alternativ:", Markup.keyboard([["Hjälp", "Om"]]).resize());
});

Produktion: byt till webhooks

I produktion skickar Telegram uppdateringar till din HTTPS-ändpunkt. Du kan ställa in detta med setWebhook, valfritt genom att ange en hemlig token så att du kan verifiera begäran via X-Telegram-Bot-Api-Secret-Token-rubriken.

Ställ in en webhook med curl:

TOKEN=123456:ABC-DEF...
WEBHOOK_URL="https://din-domän.com/telegram/${TOKEN}"  # inkludera en hemlig sökväg
SECRET="min-hemlighet-42"

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

Viktiga punkter från specifikationen:

  • setWebhook kräver en HTTPS-URL och stöder secret_token.
  • Medan en webhook är inställd kan du inte använda getUpdates.
  • Stödda portar inkluderar 443, 80, 88, 8443.

Webhook-serveralternativ

  • Node (Telegraf) inbyggd webhook:
bot.launch({
  webhook: {
    domain: "din-domän.com",
    port: 8080,
    // valfri hemlig rubrik
    secretToken: process.env.WEBHOOK_SECRET
  }
});

Telegraf exponerar förstaklassiga webhook-alternativ och integrerar med Express/Fastify/Cloudflare Workers etc.

  • Python (python-telegram-bot) PTB fungerar bra med ASGI/WSGI-ramverk (FastAPI, Starlette, Flask). Använd ApplicationBuilder().token(...).build(), exponera en POST-rutt som matar inkommande JSON-uppdateringar i din applikation och ring bot.set_webhook(...). Se ApplicationBuilder-dokumentationen för konstruktionsmönster. ([docs.python-telegram-bot.org][2])

Testar du lokalt? Använd en tunnel (t.ex. ngrok) för att exponera https://... för Telegram, sedan ring setWebhook med den offentliga URL:en.


Konfigurera botkommandon (valfritt men användarvänligt)

Du kan definiera listan över botkommandon (vad användare ser när de skriver /) antingen:

  • I BotFather via /mybots → Redigera bot → Redigera kommandon, eller
  • Programmatiskt med setMyCommands med ditt bibliotek eller ren Bot API.

Telegrams officiella guide “From BotFather to Hello World” länkar till mer avancerad hantering av kommandon och exempel om du vill gå djupare.


Distributionsöverväganden

Något HTTPS-kompatibelt värd fungerar:

  • En liten VM (Ubuntu + systemd)
  • Serverless (AWS Lambda/Cloud Functions) med webhook-integration
  • Containrar på Fly.io/Render/Heroku-liknande plattformar

Telegrafs dokumentation innehåller exempel för Lambda, GCF, Express, Fastify etc.


Säkerhets- och pålitlighetschecklista

  • Håll token hemlig (miljövariabler, hemlighetshanterare). Återkalla i BotFather om den läcker ut.
  • Använd secret_token med webhooks och verifiera X-Telegram-Bot-Api-Secret-Token-rubriken.
  • Blanda inte polling och webhooks; välj en åt gången.
  • Hantera fel & återförsök: Telegram kommer att återförsöka icke-2xx webhook-svar. Logga lämpligt.
  • Var medveten om uppdateringstyper (meddelanden, återkopplingar, inline-förfrågningar, betalningar etc.) och prenumerera endast på vad du behöver (allowed_updates).

Arbeta direkt med HTTP API:et (valfritt)

Du kan ringa ändpunkter som:

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

Använd GET eller POST med JSON eller formdata enligt specifikationen.


Vad du ska göra och läsa näst

  • Officiell Bot API-referens: metoder, objekt, gränser, formatering, betalningar, inline-läge.
  • Officiell guide “From BotFather to ‘Hello World’”: djupare genomgång och flerspråkiga exempel.
  • python-telegram-bot-dokumentation (stabil): moderna async-mönster.
  • Telegraf-dokumentation: snabba recept, webhook-hjälpmedel och TS-typer.

AWS-distributionssteg för Python-versionen

Vi har två huvudalternativ för distribution av Telegram-botten till AWS-infrastruktur:

  • A) Serverless (API Gateway + Lambda + Secrets Manager) — billigast/enklast att köra, bra för måttlig trafik.
  • B) Containeriserad (ECS Fargate + ALB + ACM) — produktionsklass för stabil trafik och långlivade bibliotek som python-telegram-bot i webhook-läge.

A) Serverless på AWS (API Gateway + Lambda)

Använd detta när du vill ha noll servrar och nästan noll kostnad i viloläge. Koden nedan hanterar Telegram-webhooks direkt (ingen långlivad event-loop).

  1. Förbered en minimal Lambda-handler (Python)

Skapa handler.py:

import json, os, urllib.request

BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
SECRET_HEADER = os.environ.get("WEBHOOK_SECRET", "")  # måste matcha 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) Verifiera Telegram's hemliga header (inställd när du konfigurerar webhook)
    if SECRET_HEADER:
        if event.get("headers", {}).get("X-Telegram-Bot-Api-Secret-Token") != SECRET_HEADER:
            return {"statusCode": 401, "body": "invalid secret"}

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

    message = update.get("message") or update.get("edited_message")
    if not message:
        # ignorera icke-meddelandeuppdateringar (callback_query, inline_query, etc.) för tillfället
        return {"statusCode": 200, "body": "ok"}

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

    # 3) Enkel vägledning
    if text.startswith("/start"):
        reply(chat_id, "👋 Hej från AWS Lambda! Skicka vilken text som helst och jag kommer att echoa den.")
    elif text.startswith("/help"):
        reply(chat_id, "/start – hälsa\n/help – hjälp\n(Distribuerad på AWS Lambda)")
    elif text:
        reply(chat_id, text)  # echo

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

Detta använder rå HTTPS-anrop till Bot API för att hålla Lambda lätt och kylstart-vänlig. Du kan expandera vägledningen senare.

  1. Paketera & distribuera Lambda
# Projektlayout
# .
# ├─ handler.py
# └─ requirements.txt   # (lämna tomt för detta minimala exempel)

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-roll (<LambdaExecutionRole>) behöver AWSLambdaBasicExecutionRole för CloudWatch Logs.

Föredrar att lagra din token i AWS Secrets Manager och ladda den vid initiering—detta exempel använder miljövariabler för enkelhetens skull.

  1. Skapa ett HTTPS-ändpunkt (API Gateway)
# HTTP API (inte REST) för lägre latens
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)

# Lägg till en standardväg 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  # t.ex., https://abc123.execute-api.ap-somewhere.amazonaws.com

Se till att Lambda-behörighet läggs till automatiskt; om inte:

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. Peka Telegram till din 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

Skicka /start till din bot—meddelanden kommer att flöda genom API Gateway → Lambda.

  1. Loggar, återförsök och uppdateringar
  • Titta på loggar: aws logs tail /aws/lambda/telegram-bot-webhook --follow
  • Telegram gör återförsök när din ändpunkt inte är 2xx; håll svaren snabba.
  • För att distribuera ny kod: repaketera + aws lambda update-function-code --function-name telegram-bot-webhook --zip-file fileb://function.zip.

B) Containeriserad python-telegram-bot på ECS Fargate + ALB

Använd detta när du vill ha ergonomin av python-telegram-bot (PTB) med en ordentlig async-app och permanenta anslutningar. Vi kommer att köra PTB bakom en HTTPS-lastbalanserare.

  1. App-kod (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-application

async def start_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("🚀 Hej från 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))
    # Ingen run_polling(); vi kommer att mata webhooks manuellt.

@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}  # ignorera tyst

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

Bygg & skicka:

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-tjänst bakom en ALB
  • Skapa en Säkerhetsgrupp som tillåter inkommande 443 på ALB; ECS-uppgifter tillåter 8080 från ALB SG.
  • Skapa en Application Load Balancer (ALB) med en HTTPS-lyssnare (443) och ett ACM-certifikat för ditt domännamn.
  • Målgrupp: HTTP 8080 (IP-måltyp), hälsokontrollsväg / (FastAPI serverar 404; du kan lägga till @app.get("/") hälsoruta).

Skapa en Uppgiftsdefinition (Fargate) med:

  • Containerbild: $ECR:latest
  • Portmappning: 8080
  • Miljövariabler: TELEGRAM_BOT_TOKEN, WEBHOOK_SECRET
  • Uppgiftroll: grundläggande CloudWatch-loggning.

Skapa en ECS-tjänst:

  • Starttyp Fargate, önskat antal 1+.
  • Koppla till ALB-målgruppen.

Anteckna den offentliga HTTPS-domänen för ALB (eller använd Route 53 för att peka ditt DNS-namn).

  1. Berätta för Telegram din 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. Skala och drifta
  • Skala ECS-uppgifter upp/ner; ALB kommer att fördela trafik.
  • Rotera tokens i Secrets Manager, uppdatera tjänst med ny uppgiftmiljö.
  • Använd CloudWatch Logs för apploggning och ALB access logs (S3).

Vilken ska vi välja?

  • Lambda + API Gateway: enklast, billigast vid låg volym; bra för botar som gör några anrop per minut.
  • ECS Fargate + ALB: bäst när du vill ha hela python-telegram-bot-upplevelsen, anpassade mellanhänder, bakgrundsjobb och stabil trafik.

Snabbchecklista (båda tillvägagångssätten)

  • Använd HTTPS-ändpunkt + secret_token och verifiera X-Telegram-Bot-Api-Secret-Token-headern.
  • Välj webhook ELLER polling (inte båda).
  • Lagra konfiguration i Secrets Manager, inte i koden.
  • Lägg till observabilitet: CloudWatch Logs + mätvärden (5xx-alarm).
  • Hantera endast de uppdateringstyperna du behöver; expandera senare.

Användbara länkar