Programování

Telegram bot v Pythonu s python-telegram-bot (v20+)

Krok za krokem k Telegram botovi v Pythonu – BotFather, příkazy, tlačítka, konverzace, upozornění a nasazení přes polling i webhook. Asynchronní API v20+.

12. 10. 2026 · 4 min čtení

Telegram boti jsou praktičtí na notifikace ze serveru, jednoduché asistenty nebo rodinné nástroje. Knihovna python-telegram-bot (PTB) je od verze 20 plně asynchronní a starší návody s Updater a dispatcher už nefungují. Tady je aktuální postup.

1. Vytvoření bota přes BotFather

  1. V Telegramu otevřete chat s @BotFather.
  2. Pošlete /newbot, zadejte zobrazované jméno a uživatelské jméno končící na bot.
  3. BotFather vrátí token ve tvaru 123456:ABC-.... Uložte ho mimo kód.

Příkazem /setcommands můžete nastavit nabídku příkazů, kterou uživatel uvidí po napsání /.

2. Instalace

python3 -m venv .venv
source .venv/bin/activate
pip install "python-telegram-bot>=21"
export TELEGRAM_TOKEN="123456:ABC..."

3. První bot

import logging
import os
from telegram import Update
from telegram.ext import (
    Application, CommandHandler, MessageHandler, ContextTypes, filters,
)

logging.basicConfig(level=logging.INFO)
logging.getLogger("httpx").setLevel(logging.WARNING)

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(
        f"Ahoj {update.effective_user.first_name}! Napiš /pomoc."
    )

async def pomoc(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("/start – přivítání\n/kurz – ukázka tlačítek")

async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(update.message.text.upper())

def main():
    app = Application.builder().token(os.environ["TELEGRAM_TOKEN"]).build()
    app.add_handler(CommandHandler("start", start))
    app.add_handler(CommandHandler("pomoc", pomoc))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
    app.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == "__main__":
    main()

run_polling() se postará o smyčku událostí sama – nevolejte kolem ní asyncio.run. Ztlumení loggeru httpx je užitečné, protože jinak na úrovni INFO loguje každý dotaz na Telegram včetně URL s tokenem.

Handlery se vyhodnocují v pořadí přidání; první, který zprávu přijme, ji zpracuje. Proto filtr ~filters.COMMAND – aby echo nepřebíjelo příkazy.

4. Argumenty příkazů

async def secti(update: Update, context: ContextTypes.DEFAULT_TYPE):
    try:
        cisla = [float(x) for x in context.args]
    except ValueError:
        await update.message.reply_text("Použití: /secti 1 2 3")
        return
    await update.message.reply_text(f"Součet: {sum(cisla)}")

app.add_handler(CommandHandler("secti", secti))

context.args obsahuje slova za příkazem.

5. Inline tlačítka

from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import CallbackQueryHandler

async def kurz(update: Update, context: ContextTypes.DEFAULT_TYPE):
    klavesnice = InlineKeyboardMarkup([
        [InlineKeyboardButton("EUR", callback_data="mena:EUR"),
         InlineKeyboardButton("USD", callback_data="mena:USD")],
    ])
    await update.message.reply_text("Vyber měnu:", reply_markup=klavesnice)

async def tlacitko(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()  # zruší „načítání“ na tlačítku
    mena = query.data.split(":", 1)[1]
    await query.edit_message_text(f"Vybral(a) jsi {mena}.")

app.add_handler(CommandHandler("kurz", kurz))
app.add_handler(CallbackQueryHandler(tlacitko, pattern=r"^mena:"))

callback_data má limit 64 bajtů – ukládejte do něj jen identifikátor, ne celá data.

6. Ukládání stavu

PTB nabízí slovníky context.user_data a context.chat_data. Aby přežily restart, zapněte perzistenci:

from telegram.ext import PicklePersistence

persistence = PicklePersistence(filepath="bot_data.pickle")
app = Application.builder().token(TOKEN).persistence(persistence).build()

Pro vážnější použití je lepší vlastní databáze (SQLite stačí).

7. Posílání zpráv z cronu nebo serveru

Pro jednorázovou notifikaci nepotřebujete celou aplikaci – stačí HTTP požadavek na Bot API:

curl -s "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage" \
  -d chat_id=123456789 \
  -d text="Záloha dokončena ✅"

Své chat_id zjistíte tak, že botovi napíšete a otevřete https://api.telegram.org/bot<TOKEN>/getUpdates.

Uvnitř aplikace lze plánovat úlohy přes JobQueue (instalace pip install "python-telegram-bot[job-queue]"):

async def pripominka(context: ContextTypes.DEFAULT_TYPE):
    await context.bot.send_message(chat_id=context.job.chat_id, text="Napij se vody 💧")

async def zapni(update: Update, context: ContextTypes.DEFAULT_TYPE):
    context.job_queue.run_repeating(pripominka, interval=3600, chat_id=update.effective_chat.id)
    await update.message.reply_text("Připomínky zapnuty.")

8. Polling vs. webhook

Polling Webhook
Nastavení žádné veřejná HTTPS adresa
Vhodné pro vývoj, malé boty, server za NAT produkci s vyšším provozem
Metoda PTB run_polling() run_webhook(...)

Pro webhook nainstalujte python-telegram-bot[webhooks] a typicky ho provozujte za Nginxem s certifikátem. Pro většinu osobních botů je polling naprosto dostačující.

Časté chyby

  • Conflict: terminated by other getUpdates request – běží dvě instance bota se stejným tokenem.
  • Bot ve skupině nereaguje na zprávy – výchozí privacy mode posílá botovi jen příkazy a odpovědi. Vypnete ho v BotFather přes /setprivacy.
  • Starý kód s Updater(token, use_context=True) – to je API verze 13. Přepište na Application.builder().

Bota pak stačí spustit na serveru jako službu systemd, aby běžel i po restartu.