Wdrażanie bota Telegrama w Pythonie i JavaScript z wdrożeniem na AWS

I wdrażanie nowego bota Telegram na AWS

Page content

Oto moje notatki z krok po kroku instrukcją, jak zaimplementować i wdrożyć na AWS bota Telegrama. Dodaję szybki start (długi poling) oraz ścieżkę do wdrożenia (webhooki), z przykładami w Pythonie i Node.js.

roboty pracujące w IT

Botty Telegrama to aplikacje działające na Twoich serwerach i komunikujące się z użytkownikami przez Telegram. Zarejestrujemy bota, napiszemy małą aplikację i połączymy ją z Bot API Telegrama.

TL;DR

  1. Utwórz bota przez @BotFather → otrzymaj token.
  2. Zbuduj małą aplikację z python-telegram-bot lub Telegraf.
  3. Zacznij od długi poling lokalnie; przejdź do webhooków w środowisku produkcyjnym.

Co będzie potrzebne

  • Konto Telegrama (telefon lub komputer)

  • Podstawowy terminal + edytor kodu

  • Jeden z poniższych:

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

Utwórz swojego bota za pomocą BotFather (uzyskaj token)

  1. W Telegramie wyszukaj @BotFather i rozpocznij rozmowę.
  2. Wyślij /newbot i postępuj zgodnie z instrukcjami, aby nadać nazwę swojemu botowi i wybrać unikalną nazwę użytkownika (musi kończyć się na bot), np. example_helper_bot.
  3. BotFather odpowiada tokenem API takim jak 123456:ABC-DEF.... Traktuj go jak hasło; nie dodawaj go do Git. Zawsze możesz go ponownie wygenerować przez BotFather, jeśli zostanie wyciek.

Wskazówka: Oficjalny tutorial Telegrama pokazuje dokładnie te same kroki i pokazuje, jak zweryfikować token za pomocą getMe.


Wybierz swój stos technologiczny

Możesz samodzielnie wywoływać surowy HTTP Bot API, ale korzystanie z utrzymywanego biblioteki jest szybsze.

  • Python: python-telegram-bot (asynchroniczny, nowoczesny). ([https://docs.python-telegram-bot.org])
  • Node.js: telegraf (dojrzały, przyjazny dla TypeScript). ([https://telegraf.js.org])

Sam Bot API jest tutaj opisany i jest źródłem prawdy dla metod takich jak getUpdates i setWebhook.


Szybki start: uruchom lokalnie z użyciem long polling

Long polling jest idealny do lokalnego rozwoju: Twój bot wielokrotnie pyta Telegrama o nowe aktualizacje za pomocą getUpdates. (W środowisku produkcyjnym prawdopodobnie przejdziesz na webhooki.)

Telegram obsługuje dwa wzajemnie wykluczające się sposoby otrzymywania aktualizacji: getUpdates (poling) lub webhooki; aktualizacje są przechowywane maksymalnie przez 24 godziny.

Opcja A: Python (z python-telegram-bot)

Zainstaluj i stwórz szkielet

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("👋 Witaj! Wyślij mi coś, a ja go powtórzę.")

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

Uruchom:

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

To korzysta z ApplicationBuilder z aktualnych stabilnych dokumentacji.

Opcja B: Node.js (z telegraf)

Zainstaluj i stwórz szkielet

npm init -y
npm i telegraf

Kod: index.js

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

const bot = new Telegraf(process.env.BOT_TOKEN); // ustaw zmienną środowiskową BOT_TOKEN
bot.start((ctx) => ctx.reply('👋 Witaj! Wyślij mi coś, a ja go powtórzę.'));
bot.on('text', (ctx) => ctx.reply(ctx.message.text));

bot.launch();

// zakończenie z poziomu systemu
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

Uruchom:

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

To odbiega od oficjalnego przykładu Telegraf “Getting started”.


Zrób to przydatnym (komendy i przyciski)

Dodaj komendę /help

Python

from telegram.ext import CommandHandler

async def help_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("/start – witaj\n/help – ten pomoc")

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

CommandHandler to standardowy sposób na wiązanie /komend.

Node (Telegraf)

bot.help((ctx) => ctx.reply('/start – witaj\n/help – ten pomoc'));

Szybkie odpowiedzi z przyciskami (niestandardowy klawiatury)

Python

from telegram import ReplyKeyboardMarkup

async def start(update: Update, context):
    keyboard = [["Pomoc", "O mnie"]]
    await update.message.reply_text(
        "Wybierz opcję:",
        reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    )

Node (Telegraf)

const { Markup } = require('telegraf');
bot.start((ctx) => {
  ctx.reply("Wybierz opcję:", Markup.keyboard([["Pomoc", "O mnie"]]).resize());
});

Produkcja: przejdź na webhooki

W środowisku produkcyjnym, Telegram wysyła aktualizacje do Twojego punktu końcowego HTTPS. Można to ustawić za pomocą setWebhook, opcjonalnie dostarczając tajny token, dzięki czemu możesz zweryfikować żądanie za pomocą nagłówka X-Telegram-Bot-Api-Secret-Token.

Ustaw webhook za pomocą curl:

TOKEN=123456:ABC-DEF...
WEBHOOK_URL="https://twoja-domena.com/telegram/${TOKEN}"  # dodaj tajny ścieżkę
SECRET="moj-tajny-42"

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

Główne punkty z dokumentacji:

  • setWebhook wymaga URL HTTPS i obsługuje secret_token.
  • Podczas ustawienia webhooka nie możesz używać getUpdates.
  • Obsługiwane porty obejmują 443, 80, 88, 8443.

Opcje serwera webhooka

  • Node (Telegraf) wbudowany webhook:
bot.launch({
  webhook: {
    domain: "twoja-domena.com",
    port: 8080,
    // opcjonalny tajny nagłówek
    secretToken: process.env.WEBHOOK_SECRET
  }
});

Telegraf udostępnia pierwszorzędne opcje webhooka i integruje się z Express/Fastify/Cloudflare Workers itp.

  • Python (python-telegram-bot) PTB działa dobrze z ramami ASGI/WSGI (FastAPI, Starlette, Flask). Użyj ApplicationBuilder().token(...).build(), wyeksponuj trasę POST, która przekazuje przychodzące JSON aktualizacje do Twojej aplikacji, i wywołaj bot.set_webhook(...). Zobacz dokumentację ApplicationBuilder dla wzorców konstrukcji. ([docs.python-telegram-bot.org][2])

Testowanie lokalnie? Użyj tunelu (np. ngrok), aby wyeksponować https://... dla Telegrama, a następnie wywołaj setWebhook z publicznym URL.


Konfiguracja komend botów (opcjonalnie, ale przyjazna dla użytkownika)

Możesz zdefiniować listę komend botów (co widzą użytkownicy, gdy wpisują /) albo:

  • W BotFather przez /mybots → Edytuj Bot → Edytuj Komendy, albo
  • Programowo za pomocą setMyCommands używając Twojej biblioteki lub surowego Bot API.

Oficjalny “Od BotFather do ‘Hello World’” przewodnik łączy się z bardziej zaawansowanym obsługą komend i przykładami, jeśli chcesz poszukać głębszych informacji.


Rozważania dotyczące wdrażania

Dowolny host z możliwością HTTPS:

  • Mały VM (Ubuntu + systemd)
  • Bezserwerowy (AWS Lambda/Cloud Functions) z integracją webhooka
  • Kontenery na platformach takich jak Fly.io/Render/Heroku

Dokumentacja Telegrafu zawiera przykłady dla Lambda, GCF, Express, Fastify itp.


Lista sprawdzania bezpieczeństwa i niezawodności

  • Zachowaj token tajny (zmienne środowiskowe, menedżer tajnych danych). Anuluj w BotFather, jeśli zostanie wyciek.
  • Użyj secret_token z webhookami i zweryfikuj nagłówek X-Telegram-Bot-Api-Secret-Token.
  • Nie mieszaj polinga i webhooków; wybierz jeden w jednym czasie.
  • Obsłuż błędy i ponowne próby: Telegram ponownie będzie próbował wysyłać odpowiedzi nie 2xx webhooka. Zapisuj odpowiednio.
  • Bądź świadomy typów aktualizacji (wiadomości, kwerendy zwrotne, inline queries, płatności itp.) i subskrybuj tylko to, czego potrzebujesz (allowed_updates).

Praca bezpośrednio z HTTP API (opcjonalnie)

Możesz wywoływać punkty końcowe takie jak:

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

Użyj GET lub POST z JSON lub danymi formularza zgodnie z dokumentacją.


Co dalej robić i czytanie

  • Oficjalna referencja Bot API: metody, obiekty, limity, formatowanie, płatności, tryb inline.
  • Oficjalny przewodnik “Od BotFather do ‘Hello World’”: głębszy przewodnik i przykłady wielojęzyczne.
  • Dokumentacja python-telegram-bot (stabilna): nowoczesne wzorce asynchroniczne.
  • Dokumentacja Telegrafu: szybkie przepisy, pomocniki webhooka i TS typy.

Krok po kroku wdrażania na AWS dla wersji Python

Mamy dwa główne opcje wdrażania bota Telegrama na infrastrukturze AWS:

  • A) Bezserwerowy (API Gateway + Lambda + Secrets Manager) — najtańszy i najprostszy do uruchomienia, świetny dla niewielkiego ruchu.
  • B) Konteneryzowany (ECS Fargate + ALB + ACM) — produkcyjny dla stabilnego ruchu i długotrwałych bibliotek takich jak python-telegram-bot w trybie webhooka.

A) Bezserwerowy na AWS (API Gateway + Lambda)

Użyj tego, gdy chcesz zero serwerów i bliskozero kosztów w stanie bezczynności. Poniższy kod obsługuje webhooki Telegrama bezpośrednio (bez długotrwałego pętli zdarzeń).

  1. Przygotuj minimalny handler Lambda (Python)

Utwórz handler.py:

import json, os, urllib.request

BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
SECRET_HEADER = os.environ.get("WEBHOOK_SECRET", "")  # musi odpowiadać tajnemu tokenowi ustawionemu w 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) Zweryfikuj tajny nagłówek Telegrama (ustawiony, gdy konfigurujesz webhook)
    if SECRET_HEADER:
        if event.get("headers", {}).get("X-Telegram-Bot-Api-Secret-Token") != SECRET_HEADER:
            return {"statusCode": 401, "body": "nieprawidłowy sekret"}

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

    message = update.get("message") or update.get("edited_message")
    if not message:
        # zignoruj aktualizacje nie będące wiadomościami (callback_query, inline_query itp.) na razie
        return {"statusCode": 200, "body": "ok"}

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

    # 3) Prosta routa
    if text.startswith("/start"):
        reply(chat_id, "👋 Witaj z AWS Lambda! Wyślij dowolny tekst i ja go powtórzę.")
    elif text.startswith("/help"):
        reply(chat_id, "/start – witaj\n/help – pomoc\n(Wdrożony na AWS Lambda)")
    elif text:
        reply(chat_id, text)  # echo

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

To korzysta z surowych wywołań HTTPS do Bot API, aby zachować Lambda lekką i przyjazną dla cold start. Możesz rozszerzyć routę później.

  1. Pakuj i wdrażaj Lambda
# Struktura projektu
# .
# ├─ handler.py
# └─ requirements.txt   # (pozostaw pusty dla tego minimalnego przykładu)

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

Rola IAM (<LambdaExecutionRole>) potrzebuje AWSLambdaBasicExecutionRole dla CloudWatch Logs.

Preferuj przechowywanie swojego tokena w AWS Secrets Manager i ładowanie go przy inicjalizacji — ten przykład używa zmiennych środowiskowych dla uproszczenia.

  1. Utwórz punkt końcowy HTTPS (API Gateway)
# HTTP API (nie REST) dla niższej opóźnienia
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)

# Dodaj domyślną trasę 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  # np. https://abc123.execute-api.ap-somewhere.amazonaws.com

Upewnij się, że prawa do Lambda są automatycznie dodane; jeśli nie:

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. Skieruj Telegrama do Twojego webhooka
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

Wyślij /start do swojego bota — wiadomości przepłyną przez API Gateway → Lambda.

  1. Logi, ponowne próby i aktualizacje
  • Obserwuj logi: aws logs tail /aws/lambda/telegram-bot-webhook --follow
  • Telegram ponownie próbuje, jeśli Twój punkt końcowy nie zwraca 2xx; utrzymuj odpowiedzi szybkie.
  • Aby wdrożyć nowy kod: ponownie zip + aws lambda update-function-code --function-name telegram-bot-webhook --zip-file fileb://function.zip.

B) Konteneryzowany python-telegram-bot na ECS Fargate + ALB

Użyj tego, gdy chcesz ergonomikę python-telegram-bot (PTB) z odpowiednią aplikacją asynchroniczną i trwałą połączeniami. Uruchomimy PTB za HTTPS load balancerem.

  1. Kod aplikacji (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 aplikacja

async def start_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("🚀 Witaj na 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))
    # Brak run_polling(); będziemy ręcznie przekazywać webhooki.

@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}  # zignoruj cicho

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

uvicorn punkt wejścia: 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"]

Zbuduj i wypchnij:

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. Usługa ECS Fargate za ALB
  • Utwórz Grupę Bezpieczeństwa, pozwalającą na wejście 443 na ALB; ECS zadania pozwalają 8080 od grupy bezpieczeństwa ALB.
  • Utwórz Application Load Balancer (ALB) z HTTPS nasłuchiwaniem (443) i certyfikatem ACM dla swojej domeny.
  • Grupa docelowa: HTTP 8080 (typ docelowy IP), ścieżka sprawdzania kondycji / (FastAPI zwraca 404; możesz dodać @app.get("/") ścieżkę kondycji).

Utwórz Definicję zadania (Fargate) z:

  • Obraz kontenera: $ECR:latest
  • Mapowanie portów: 8080
  • Zmienne środowiskowe: TELEGRAM_BOT_TOKEN, WEBHOOK_SECRET
  • Rola zadania: podstawowa logika CloudWatch.

Utwórz Usługę ECS:

  • Typ uruchomienia Fargate, liczba żądana 1+.
  • Dołącz do grupy docelowej ALB.

Zanotuj publiczną domenę HTTPS ALB (lub użyj Route 53, aby wskazać swoje nazwy DNS).

  1. Poinformuj Telegrama o Twojej ścieżce webhooka
TOKEN=<TOKEN_FROM_BOTFATHER>
SECRET="my-secret-42"
WEBHOOK_URL="https://twoja.domena.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. Skalowanie i operowanie
  • Skaluj zadania ECS w górę/w dół; ALB rozproszy ruch.
  • Rotuj tokeny w Secrets Manager, aktualizuj usługę z nowymi zmiennymi środowiskowymi zadania.
  • Użyj CloudWatch Logs dla logów aplikacji i logów ALB (S3).

Który powinniśmy wybrać?

  • Lambda + API Gateway: najprostszy, najtańszy przy niskim przepływie; idealny dla botów, które wykonują kilka wywołań na minutę.
  • ECS Fargate + ALB: najlepszy, gdy chcesz pełną python-telegram-bot doświadczenie, niestandardowe middlewary, zadania w tle i stabilny przepływ.

Szybki checklist (obie podejścia)

  • Użyj punktu końcowego HTTPS + secret_token i zweryfikuj nagłówek X-Telegram-Bot-Api-Secret-Token.
  • Wybierz webhooka lub poling (nie oba).
  • Przechowuj konfigurację w Secrets Manager, nie w kodzie.
  • Dodaj obserwowalność: CloudWatch Logs + metryki (alarmy 5xx).
  • Obsłuż tylko typy aktualizacji, które potrzebujesz; rozszerz później.

Przydatne linki