Implementasi Bot Telegram dalam Python dan JavaScript dengan penempatan ke AWS

Dan menempatkan bot Telegram baru ke AWS

Konten Halaman

Berikut adalah catatan saya dengan tutorial langkah demi langkah tentang cara mengimplementasikan dan mendeploy ke AWS sebuah bot Telegram. Saya telah menambahkan panduan cepat (long polling) dan jalur produksi (webhooks), dengan contoh dalam Python dan Node.js.

robot-kerja-di-IT

Bot Telegram adalah aplikasi yang berjalan di server Anda dan berkomunikasi dengan pengguna melalui Telegram. Kita akan mendaftarkan bot, menulis program kecil, dan menghubungkannya ke Bot API Telegram.

TL;DR

  1. Buat bot melalui @BotFather → dapatkan token.
  2. Bangun aplikasi kecil dengan python-telegram-bot atau Telegraf.
  3. Mulai dengan long polling secara lokal; beralih ke webhooks untuk produksi.

Apa yang Anda butuhkan

  • Akun Telegram (mobile atau desktop)

  • Terminal dasar + editor kode

  • Salah satu dari berikut:

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

Buat bot Anda dengan BotFather (dapatkan token)

  1. Di Telegram, cari @BotFather dan mulai percakapan.
  2. Kirim /newbot dan ikuti petunjuk untuk menamai bot Anda dan memilih nama pengguna unik (harus diakhiri dengan bot), misalnya example_helper_bot.
  3. BotFather merespons dengan token API seperti 123456:ABC-DEF.... Anggap ini seperti kata sandi; jangan masukkan ke Git. Anda selalu dapat menghasilkan ulang token ini melalui BotFather jika bocor.

Tips: Tutorial resmi Telegram membahas langkah-langkah ini secara eksak dan cara memverifikasi token Anda dengan getMe.


Pilih stack Anda

Anda dapat memanggil Bot API HTTP mentah sendiri, tetapi menggunakan perpustakaan yang dipelihara akan lebih cepat.

  • Python: python-telegram-bot (asinkron, modern). ([https://docs.python-telegram-bot.org])
  • Node.js: telegraf (matang, ramah TypeScript). ([https://telegraf.js.org])

Bot API itu sendiri didokumentasikan di sini dan merupakan sumber kebenaran untuk metode seperti getUpdates dan setWebhook.


Quick Start: jalankan secara lokal dengan long polling

Long polling sempurna untuk pengembangan lokal: bot Anda secara berkala meminta Telegram untuk pembaruan baru melalui getUpdates. (Di produksi, Anda kemungkinan besar akan beralih ke webhooks.)

Telegram mendukung dua cara saling eksklusif untuk menerima pembaruan: getUpdates (polling) atau webhooks; pembaruan disimpan hingga 24 jam.

Opsi A: Python (dengan python-telegram-bot)

Instal & scaffold

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

Kode: 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("👋 Halo! Kirimkan sesuatu ke saya dan saya akan mengulangkannya.")

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

Jalankan:

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

Ini menggunakan ApplicationBuilder dari dokumen stabil saat ini.

Opsi B: Node.js (dengan telegraf)

Instal & scaffold

npm init -y
npm i telegraf

Kode: index.js

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

const bot = new Telegraf(process.env.BOT_TOKEN); // set BOT_TOKEN env var
bot.start((ctx) => ctx.reply('👋 Halo! Kirimkan sesuatu ke saya dan saya akan mengulangkannya.'));
bot.on('text', (ctx) => ctx.reply(ctx.message.text));

bot.launch();

// berhenti dengan cara yang lembut
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

Jalankan:

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

Ini meniru contoh “Getting started” resmi Telegraf.


Buat bot yang berguna (perintah & tombol)

Tambahkan perintah /help

Python

from telegram.ext import CommandHandler

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

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

CommandHandler adalah cara standar untuk mengikat /perintah.

Node (Telegraf)

bot.help((ctx) => ctx.reply('/start – sapa\n/help – bantuan'));

Tombol respons cepat (keyboard kustom)

Python

from telegram import ReplyKeyboardMarkup

async def start(update: Update, context):
    keyboard = [["Bantuan", "Tentang"]]
    await update.message.reply_text(
        "Pilih opsi:",
        reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    )

Node (Telegraf)

const { Markup } = require('telegraf');
bot.start((ctx) => {
  ctx.reply("Pilih opsi:", Markup.keyboard([["Bantuan", "Tentang"]]).resize());
});

Produksi: beralih ke webhooks

Di produksi, Telegram mengirimkan pembaruan ke endpoint HTTPS Anda. Anda dapat mengatur ini dengan setWebhook, secara opsional menyediakan token rahasia sehingga Anda dapat memverifikasi permintaan melalui header X-Telegram-Bot-Api-Secret-Token.

Atur webhook dengan curl:

TOKEN=123456:ABC-DEF...
WEBHOOK_URL="https://your-domain.com/telegram/${TOKEN}"  # termasuk jalur rahasia
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

Poin penting dari spesifikasi:

  • setWebhook memerlukan URL HTTPS dan mendukung secret_token.
  • Saat webhook diatur, Anda tidak dapat menggunakan getUpdates.
  • Port yang didukung termasuk 443, 80, 88, 8443.

Opsi server webhook

  • Node (Telegraf) webhook bawaan:
bot.launch({
  webhook: {
    domain: "your-domain.com",
    port: 8080,
    // token rahasia opsional
    secretToken: process.env.WEBHOOK_SECRET
  }
});

Telegraf menampilkan opsi webhook kelas satu dan terintegrasi dengan Express/Fastify/Cloudflare Workers, dll.

  • Python (python-telegram-bot) PTB bekerja baik dengan kerangka kerja ASGI/WSGI (FastAPI, Starlette, Flask). Gunakan ApplicationBuilder().token(...).build(), ekspos rute POST yang menyediakan JSON pembaruan masuk ke aplikasi Anda, dan panggil bot.set_webhook(...). Lihat dokumen ApplicationBuilder untuk pola konstruksi. ([docs.python-telegram-bot.org][2])

Menguji secara lokal? Gunakan tunnel (misalnya, ngrok) untuk mengekspos https://... ke Telegram, lalu panggil setWebhook dengan URL publik.


Konfigurasi perintah bot (opsional tetapi ramah pengguna)

Anda dapat mendefinisikan daftar perintah bot (apa yang pengguna lihat saat mereka mengetik /) baik:

  • Di BotFather melalui /mybots → Edit Bot → Edit Commands, atau
  • Secara programmatic dengan setMyCommands menggunakan library Anda atau Bot API mentah.

Panduan resmi Telegram “Dari BotFather ke ‘Hello World’” mengarah ke penanganan perintah yang lebih lanjut dan contoh jika Anda ingin melangkah lebih jauh.


Pertimbangan deployment

Setiap host yang mampu HTTPS bekerja:

  • VM kecil (Ubuntu + systemd)
  • Serverless (AWS Lambda/Cloud Functions) dengan integrasi webhook
  • Container di Fly.io/Render/platform mirip Heroku

Dokumen Telegraf mencakup contoh untuk Lambda, GCF, Express, Fastify, dll.


Daftar pemeriksaan keamanan dan keandalan

  • Jaga token tetap rahasia (variabel lingkungan, manajer rahasia). Cabut di BotFather jika bocor.
  • Gunakan secret_token dengan webhook dan verifikasi header X-Telegram-Bot-Api-Secret-Token.
  • Jangan campurkan polling dan webhook; pilih satu pada satu waktu.
  • Tangani kesalahan & retry: Telegram akan mencoba ulang respons webhook non-2xx. Catat dengan tepat.
  • Perhatikan jenis pembaruan (pesan, callback, inline query, pembayaran, dll.) dan langgani hanya yang Anda butuhkan (allowed_updates).

Bekerja langsung dengan HTTP API (opsional)

Anda dapat memanggil endpoint seperti:

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

Gunakan GET atau POST dengan JSON atau form data sesuai spesifikasi.


Apa yang selanjutnya harus Anda lakukan dan baca

  • Referensi Bot API resmi: metode, objek, batas, format, pembayaran, mode inline.
  • Panduan resmi “Dari BotFather ke ‘Hello World’”: walkthrough yang lebih dalam dan contoh multi-bahasa.
  • Dokumen python-telegram-bot (stabil): pola async modern.
  • Dokumen Telegraf: resep cepat, helper webhook, dan tipe TS.

Langkah deployment ke AWS untuk versi Python

Kami memiliki dua opsi utama untuk deployment bot Telegram ke infrastruktur AWS:

  • A) Serverless (API Gateway + Lambda + Secrets Manager) — termurah/mudah dijalankan, cocok untuk lalu lintas sedang.
  • B) Containerized (ECS Fargate + ALB + ACM) — produksi-grade untuk lalu lintas stabil dan library yang berjalan lama seperti python-telegram-bot dalam mode webhook.

A) Serverless di AWS (API Gateway + Lambda)

Gunakan ini ketika Anda ingin zero server dan biaya idle mendekati nol. Kode di bawah ini menangani webhook Telegram secara langsung (tidak ada event loop yang berjalan lama).

  1. Persiapkan handler Lambda minimal (Python)

Buat handler.py:

import json, os, urllib.request

BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
SECRET_HEADER = os.environ.get("WEBHOOK_SECRET", "")  # harus cocok dengan secret_token Bot API 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) Verifikasi header rahasia Telegram (dihubungkan saat Anda mengatur webhook)
    if SECRET_HEADER:
        if event.get("headers", {}).get("X-Telegram-Bot-Api-Secret-Token") != SECRET_HEADER:
            return {"statusCode": 401, "body": "secret tidak valid"}

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

    message = update.get("message") or update.get("edited_message")
    if not message:
        # abaikan pembaruan non-pesan (callback_query, inline_query, dll.) untuk saat ini
        return {"statusCode": 200, "body": "ok"}

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

    # 3) Routing sederhana
    if text.startswith("/start"):
        reply(chat_id, "👋 Halo dari AWS Lambda! Kirimkan teks apa pun dan saya akan mengulangkannya.")
    elif text.startswith("/help"):
        reply(chat_id, "/start – sapa\n/help – bantuan\n(Di deploy di AWS Lambda)")
    elif text:
        reply(chat_id, text)  # mengulang

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

Ini menggunakan panggilan HTTPS mentah ke Bot API untuk menjaga Lambda tetap ringkas dan ramah cold-start. Anda dapat memperluas routing nanti.

  1. Paket & deploy Lambda
# Layout proyek
# .
# ├─ handler.py
# └─ requirements.txt   # (biarkan kosong untuk contoh minimal ini)

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

Peran IAM (<LambdaExecutionRole>) memerlukan AWSLambdaBasicExecutionRole untuk CloudWatch Logs.

Lebih baik menyimpan token Anda di AWS Secrets Manager dan memuatnya saat inisialisasi—contoh ini menggunakan variabel lingkungan untuk kejelasan.

  1. Buat endpoint HTTPS (API Gateway)
# HTTP API (bukan REST) untuk latensi lebih rendah
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)

# Tambahkan rute default 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  # contoh, https://abc123.execute-api.ap-somewhere.amazonaws.com

Pastikan izin Lambda ditambahkan secara otomatis; jika tidak:

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. Arahkan Telegram ke webhook Anda
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

Kirim /start ke bot Anda—pesan akan mengalir melalui API Gateway → Lambda.

  1. Log, retry, dan pembaruan
  • Pantau log: aws logs tail /aws/lambda/telegram-bot-webhook --follow
  • Telegram akan mencoba ulang ketika endpoint Anda tidak 2xx; pertahankan respons cepat.
  • Untuk mengeluarkan kode baru: re-zip + aws lambda update-function-code --function-name telegram-bot-webhook --zip-file fileb://function.zip.

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

Gunakan ini ketika Anda ingin ergonomika python-telegram-bot (PTB) dengan aplikasi async yang tepat dan koneksi yang bertahan lama. Kita akan menjalankan PTB di balik load balancer HTTPS.

  1. Kode aplikasi (FastAPI + webhook PTB)

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  # aplikasi PTB

async def start_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("🚀 Halo dari 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))
    # Tidak ada run_polling(); kita akan memberi makan webhook secara manual.

@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}  # abaikan secara diam-diam

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

Bangun & 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. Layanan ECS Fargate di balik ALB
  • Buat Security Group yang memungkinkan masuk 443 di ALB; ECS tasks memungkinkan 8080 dari ALB SG.
  • Buat Application Load Balancer (ALB) dengan listener HTTPS (443) dan sertifikat ACM untuk domain Anda.
  • Grup target: HTTP 8080 (jenis target IP), jalur kesehatan / (FastAPI menyajikan 404; Anda dapat menambahkan @app.get("/") jalur kesehatan).

Buat Task Definition (Fargate) dengan:

  • Gambar kontainer: $ECR:latest
  • Pemetaan port: 8080
  • Variabel lingkungan: TELEGRAM_BOT_TOKEN, WEBHOOK_SECRET
  • Peran tugas: peran dasar CloudWatch logging.

Buat ECS Service:

  • Jenis peluncuran Fargate, jumlah diinginkan 1+.
  • Hubungkan ke grup target ALB.

Catat domain HTTPS publik ALB (atau gunakan Route 53 untuk mengarahkan nama DNS Anda).

  1. Beri tahu Telegram URL webhook Anda
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 & operasikan
  • Skala tugas ECS naik/turun; ALB akan menyebar lalu lintas.
  • Putar ulang token di Secrets Manager, perbarui layanan dengan lingkungan tugas baru.
  • Gunakan CloudWatch Logs untuk log aplikasi dan log akses ALB (S3).

Yang mana yang harus kita pilih?

  • Lambda + API Gateway: paling sederhana, termurah di volume rendah; cocok untuk bot yang melakukan beberapa panggilan per menit.
  • ECS Fargate + ALB: terbaik ketika Anda ingin pengalaman penuh python-telegram-bot, middleware kustom, pekerjaan latar belakang, dan lalu lintas stabil.

Daftar pemeriksaan cepat (kedua pendekatan)

  • Gunakan endpoint HTTPS + secret_token dan verifikasi header X-Telegram-Bot-Api-Secret-Token.
  • Pilih webhook ATAU polling (tidak keduanya).
  • Simpan konfigurasi di Secrets Manager, bukan dalam kode.
  • Tambahkan observabilitas: CloudWatch Logs + metrik (alarm 5xx).
  • Tangani hanya jenis pembaruan yang Anda butuhkan; perluas nanti.

Tautan berguna