اگر ربات تلگرام روی لپتاپ شما کار میکند اما با بستن ترمینال یا قطع اینترنت از دسترس خارج میشود، فرایند اجرا به محیطی ناپایدار وابسته است. برای دیپلوی ربات تلگرام باید برنامه را روی سرویسی اجرا کنید که فرایند را زنده نگه دارد، Secret ها را بیرون از کد ذخیره کند و لاگ و وضعیت اجرا را نشان دهد.
برای بیشتر رباتهای production، webhook انتخاب مناسبی است: تلگرام هر Update را با درخواست HTTPS به برنامه میفرستد. long polling هم معتبر است، اما به پردازشی دائمی نیاز دارد و روی هر سرویس میزبانی قابل اجرا نیست.
پاسخ سریع: برای اجرای دائمی ربات چه لازم دارید؟
یک ربات همیشهروشن به چهار بخش نیاز دارد:
-
یک فرایند پایدار برای اجرای برنامه
-
نگهداری امن توکن BotFather بهصورت Secret
-
لاگ و Health Check برای تشخیص توقف یا خطا
-
یکی از دو روش دریافت Update: webhook یا getUpdates
اگر هاست شما URL عمومی HTTPS ارائه میدهد، webhook معمولاً با سرویسهای وب سازگارتر است. برای long polling باید مطمئن شوید میزبان از Worker یا فرایندی که پورت HTTP باز نمیکند پشتیبانی میکند.
در پاستا میتوانید پروژه را از Repository گیت، Dockerfile، Docker Image عمومی، ZIP یا سورس تشخیصدادهشده وارد کنید. کنسول وضعیت Build و استقرار را نشان میدهد و از متغیر محیطی، Secret، لاگ، HTTPS و Health Check پشتیبانی میکند. قیمت، منابع و پلنهای قابلخرید ممکن است تغییر کنند؛ پیش از ساخت سرویس، مشخصات و هزینه نمایشدادهشده در paasta.cloud را بررسی کنید.
long polling یا webhook؛ کدام روش برای ربات شما مناسب است؟
در long polling، برنامه شما مرتب از Telegram Bot API درباره Updateهای تازه میپرسد. در webhook، تلگرام Update را به یک URL عمومی میفرستد. این دو روش همزمان کار نمیکنند؛ تا وقتی webhook فعال است، متد getUpdates کار نخواهد کرد. مستندات رسمی Telegram Bot API این رفتار را توضیح میدهد.
|
معیار |
long polling |
webhook |
|
ورودی عمومی HTTPS |
لازم نیست |
لازم است |
|
نوع اجرا |
Worker دائمی |
سرویس وب |
|
راهاندازی اولیه |
سادهتر |
نیازمند ثبت URL |
|
سازگاری با Health Check مبتنی بر HTTP |
نیازمند افزودن endpoint جداگانه |
طبیعیتر |
|
مقیاسدادن افقی |
نیازمند طراحی دقیق |
ممکن است، بهشرط مدیریت تکرار Update |
|
مناسب برای توسعه محلی |
بله |
معمولاً با تونل یا دامنه آزمایشی |
برای یک ربات کوچک، long polling کد کمتری میخواهد. اگر پلتفرم فقط سرویس وب میزبانی کند یا انتظار داشته باشد برنامه روی پورتی مشخص گوش کند، webhook انتخاب عملیتری است.
در webhook باید URL از اینترنت قابل دسترس باشد، HTTPS معتبر داشته باشد و درخواست POST بپذیرد. تلگرام پس از دریافت پاسخ ناموفق، تحویل Update را دوباره امتحان میکند؛ بنابراین handler باید تکرار یک update_id را بدون ایجاد اثر جانبی ناخواسته مدیریت کند.
نمونه عملی دیپلوی ربات تلگرام با FastAPI و webhook
نمونه زیر یک ربات حداقلی پایتون است. /health برای Health Check و /telegram/webhook برای دریافت درخواستهای تلگرام استفاده میشود. توکن و Secret داخل Repository قرار نمیگیرند.
۱. برنامه را برای دریافت webhook آماده کنید
فایل app.py:
import os
from contextlib import asynccontextmanager
import httpx
from fastapi import FastAPI, Header, HTTPException, Request
BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
WEBHOOK_SECRET = os.environ["TELEGRAM_WEBHOOK_SECRET"]
PUBLIC_BASE_URL = os.environ["PUBLIC_BASE_URL"].rstrip("/")
WEBHOOK_PATH = "/telegram/webhook"
TELEGRAM_API = f"https://api.telegram.org/bot{BOT_TOKEN}"
@asynccontextmanager
async def lifespan(app: FastAPI):
async with httpx.AsyncClient(timeout=10) as client:
response = await client.post(
f"{TELEGRAM_API}/setWebhook",
json={
"url": f"{PUBLIC_BASE_URL}{WEBHOOK_PATH}",
"secret_token": WEBHOOK_SECRET,
},
)
response.raise_for_status()
yield
app = FastAPI(lifespan=lifespan)
@app.get("/health")
async def health():
return {"status": "ok"}
@app.post(WEBHOOK_PATH)
async def telegram_webhook(
request: Request,
x_telegram_bot_api_secret_token: str | None = Header(default=None),
):
if x_telegram_bot_api_secret_token != WEBHOOK_SECRET:
raise HTTPException(status_code=403)
update = await request.json()
message = update.get("message") or {}
chat = message.get("chat") or {}
text = message.get("text")
if chat.get("id") and text:
async with httpx.AsyncClient(timeout=10) as client:
response = await client.post(
f"{TELEGRAM_API}/sendMessage",
json={
"chat_id": chat["id"],
"text": f"پیام شما دریافت شد: {text}",
},
)
response.raise_for_status()
return {"ok": True}
Telegram مقدار secret_token را در هدر X-Telegram-Bot-Api-Secret-Token میفرستد. با بررسی این هدر، درخواستهای ناشناس را پیش از ورود به منطق ربات رد میکنید. محدودیت قالب و طول این مقدار در مرجع setWebhook آمده است.
فایل requirements.txt:
fastapi
httpx
uvicorn
نسخه کتابخانهها را پس از آزمایش پروژه pin کنید تا تغییر وابستگیها باعث تفاوت میان Buildها نشود.
۲. برنامه را Containerize کنید
مثال فرضی زیر برنامه را روی پورت 8000 اجرا میکند. اگر پورت سرویس متفاوت است، متغیر PORT و تنظیمات سرویس را هماهنگ کنید.
FROM python:3-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["sh", "-c", "uvicorn app:app --host 0.0.0.0 --port ${PORT:-8000}"]
این Container داده پایداری روی فایلسیستم محلی نگه نمیدارد. اگر ربات وضعیت کاربر یا نتیجه پردازش را ذخیره میکند، از دیتابیس یا فضای ذخیرهسازی متناسب با داده استفاده کنید. پاستا دیسک پایدار و دیتابیس مدیریتشده ارائه میکند، اما نوع، نسخه و پلن قابلخرید را باید هنگام استقرار بررسی کنید.
راهنمای دیپلوی «FastAPI و Flask از لوکال تا production» اجرای Uvicorn، تنظیم پورت و Health Check را توضیح میدهد.
۳. پروژه را روی پاستا بسازید
Repository را به GitHub یا GitLab متصل کنید، یا پروژه را با ZIP و Dockerfile وارد کنید. اگر پاستا نوع پروژه یا Dockerfile را تشخیص داد، نتیجه را پیش از Build بررسی کنید:
-
فایل شروع برنامه همان app.py باشد.
-
دستور اجرا به 0.0.0.0 گوش کند، نه 127.0.0.1.
-
پورت Container با تنظیم سرویس هماهنگ باشد.
-
مسیر Health Check روی /health قرار بگیرد.
-
هیچ توکن یا رمز واقعی در Repository و Dockerfile وجود نداشته باشد.
پس از شروع Build، وضعیت آن را در جریان استقرار ببینید. موفقشدن Build فقط به معنی ساختهشدن Image است؛ وضعیت اجرا، Health Check و لاگ Runtime را هم بررسی کنید.
ربات خود را روی پاستا اجرا کنید و دیگر نگران قطعی نباشید
۴. متغیرها و Secrets ها را تنظیم کنید
این مقادیر را در تنظیمات سرویس قرار دهید:
TELEGRAM_BOT_TOKEN=<secret>
TELEGRAM_WEBHOOK_SECRET=<secret>
PUBLIC_BASE_URL=https://bot.example.com
PORT=8000
TELEGRAM_BOT_TOKEN و TELEGRAM_WEBHOOK_SECRET باید Secret باشند. آنها را در فایل .env قابلCommit، Dockerfile، پیام Prompt یا اسکرینشات عمومی قرار ندهید.
PUBLIC_BASE_URL باید دامنه HTTPS واقعی سرویس باشد. پس از آمادهشدن اپلیکیشن، پاستا میتواند آدرس HTTPS روی دامنه خود در اختیار سرویس قرار دهد؛ دامنه شخصی نیز قابل اتصال است.
برنامه نمونه هنگام شروع، setWebhook را صدا میزند. اجرای دوباره برنامه همان URL را ثبت میکند و دادهای را حذف نمیکند. در استقرارهای چند Replica بهتر است ثبت webhook را بهعنوان مرحلهای کنترلشده انجام دهید، نه همزمان در تمام Replicaها.