Wdrażanie bota Telegrama w Pythonie i JavaScript z wdrożeniem na AWS
I wdrażanie nowego bota Telegram na AWS
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.
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
- Utwórz bota przez @BotFather → otrzymaj token.
- Zbuduj małą aplikację z python-telegram-bot lub Telegraf.
- 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
- Python 3.10+ i
Utwórz swojego bota za pomocą BotFather (uzyskaj token)
- W Telegramie wyszukaj @BotFather i rozpocznij rozmowę.
- Wyślij
/newbot
i postępuj zgodnie z instrukcjami, aby nadać nazwę swojemu botowi i wybrać unikalną nazwę użytkownika (musi kończyć się nabot
), np.example_helper_bot
. - 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ługujesecret_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żyjApplicationBuilder().token(...).build()
, wyeksponuj trasę POST, która przekazuje przychodzące JSON aktualizacje do Twojej aplikacji, i wywołajbot.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łajsetWebhook
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łówekX-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ń).
- 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.
- 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.
- 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"
- 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.
- 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.
- 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
- 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
- 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).
- 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"]'
- 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łówekX-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
- https://docs.python-telegram-bot.org
- https://telegraf.js.org
- https://core.telegram.org/bots/tutorial
- https://core.telegram.org/bots/api
- Przegląd AWS CDK, przykłady w TypeScript i Pythonie oraz rozważania dotyczące wydajności
- Wydajność AWS Lambda: JavaScript vs Python vs Golang
- Warstwowe Lambdy z AWS SAM i Pythonem
- AWS SAM + AWS SQS + Python PowerTools
- Python Cheatsheet
- uv - Nowy pakiet Pythona, projekt i menedżer środowisk
- Instalacja Node.js