pyTelegramBot — боты в Telegram
pyTelegramBotAPI устанавливается как pip install pytelegrambotapi, в коде чаще пишут import telebot. Библиотека обращается к Telegram Bot API: бот — это программа на вашем компьютере или сервере, которая получает обновления (сообщения, команды, нажатия кнопок) и отправляет ответы.
Telegram-бот — быстрый способ дать пользователю интерфейс без веб-сайта. Типичные сценарии:
- опросы и викторины;
- напоминания;
- FAQ;
- уведомления об ошибках;
- мини-игры.
| Термин | Смысл |
|---|---|
| Token | Секретный ключ доступа к API (выдаёт @BotFather) |
| Update | Событие от Telegram (сообщение, callback кнопки и т.д.) |
| Long polling | Бот сам периодически запрашивает новые обновления |
| Webhook | Telegram отправляет обновления POST-запросом на ваш HTTPS-URL |
Путеводитель: Инструменты и среды. HTTP в Python: requests, файлы и JSON: Работа с файлами, сетью и внешними API.
Подготовка окружения
- В Telegram откройте @BotFather.
- Команда
/newbot→ имя и username (должен оканчиваться наbot). - Сохраните токен. Это пароль бота — не публикуйте его в репозитории.
Виртуальное окружение изолирует зависимости проекта:
python -m venv bot_env
# Windows
bot_env\Scripts\activate
# Linux / macOS
source bot_env/bin/activate
pip install pytelegrambotapi
Токен храните в переменной окружения:
# Windows PowerShell
$env:BOT_TOKEN="123456:ABC..."
# Linux / macOS
export BOT_TOKEN="123456:ABC..."
При попадании токена в git выполните /revoke в BotFather, создайте новый токен и добавьте .env в .gitignore.
Проверка: напишите боту /start в Telegram после первого запуска скрипта.
Минимальный бот
Код ITЗагрузка примера кода…
TeleBot(...)создаёт экземпляр бота.@bot.message_handler(...)связывает тип сообщения с функцией-обработчиком.infinity_polling()держит процесс активным и забирает обновления с серверов Telegram.
Запуск: python bot.py.
Команды, меню и текстовые фразы
Обработчики
| Декоратор | Срабатывает когда |
|---|---|
@bot.message_handler(commands=["ping"]) | Сообщение /ping |
@bot.message_handler(content_types=["photo"]) | Фото |
@bot.message_handler(func=lambda m: m.text and "привет" in m.text.lower()) | Свой фильтр |
Объект message содержит chat.id, from_user, text, document и др. — см. типы Bot API.
Меню команд в клиенте Telegram
Список команд в меню бота (кнопка "/" у поля ввода) задаётся через Bot API:
from telebot import types
bot.set_my_commands([
types.BotCommand("start", "Запуск"),
types.BotCommand("help", "Справка"),
types.BotCommand("menu", "Главное меню"),
])
Вызовите set_my_commands один раз при старте (в if __name__ == "__main__" перед polling).
Реакция на ключевые слова
Текст без слэша обрабатывается отдельным handler или веткой внутри общего:
@bot.message_handler(func=lambda m: m.text and m.text.lower() in ("привет", "здравствуйте"))
def greet(message):
bot.reply_to(message, "Привет! Команды: /help")
Порядок регистрации handlers важен: узкие фильтры регистрируйте раньше общего func=lambda m: True.
Клавиатуры
Reply-клавиатура (кнопки под полем ввода)
from telebot import types
@bot.message_handler(commands=["menu"])
def menu(message):
kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
kb.add("Игра", "О боте", "Помощь")
bot.send_message(message.chat.id, "Выберите пункт:", reply_markup=kb)
@bot.message_handler(func=lambda m: m.text == "Помощь")
def help_btn(message):
bot.send_message(message.chat.id, "Команды: /start, /menu")
Нажатие кнопки приходит в бот как обычное текстовое сообщение с подписью кнопки — для него нужен свой message_handler.
Inline-кнопки (под сообщением)
Кнопка со ссылкой:
markup = types.InlineKeyboardMarkup()
markup.add(types.InlineKeyboardButton("Сайт", url="https://example.com"))
bot.send_message(message.chat.id, "Ссылки:", reply_markup=markup)
Кнопки с callback (викторина, "Да/Нет") — в чат текст не уходит, приходит CallbackQuery:
Код ITЗагрузка примера кода…
callback_data— короткая строка (до 64 байт), по ней различают нажатия.edit_message_textменяет текст исходного сообщения вместо нового.answer_callback_queryобязателен, иначе клиент долго показывает индикатор загрузки.
Медиа
Бот может отправлять не только текст:
# Фото с диска
with open("meme.jpg", "rb") as photo:
bot.send_photo(message.chat.id, photo, caption="Мем дня")
# Фото по URL (если Telegram может его скачать)
bot.send_photo(message.chat.id, "https://example.com/image.jpg")
# Документ, голос, стикер
bot.send_document(message.chat.id, open("manual.pdf", "rb"))
bot.send_voice(message.chat.id, open("hint.ogg", "rb"))
Приём медиа от пользователя — через content_types:
@bot.message_handler(content_types=["photo"])
def on_photo(message):
file_id = message.photo[-1].file_id # наибольшее разрешение
bot.reply_to(message, f"Получил фото, file_id={file_id}")
Лимиты и форматы — в документации Bot API.
Пошаговый диалог (состояния)
Состояние — этап сценария — бот ждёт имя, потом возраст, потом подтверждение. В telebot для коротких анкет удобен register_next_step_handler:
Код ITЗагрузка примера кода…
Для длинных сценариев и продакшена чаще берут словарь состояний по user_id, Redis или БД. В python-telegram-bot тот же смысл даёт ConversationHandler — пример в лаборатории / Примеры / 122.
Хранение данных
В памяти процесса
SCORES: dict[int, int] = {} # user_id → очки
@bot.message_handler(commands=["score"])
def show_score(message):
points = SCORES.get(message.from_user.id, 0)
bot.reply_to(message, f"Ваш счёт: {points}")
Подходит для демо. После перезапуска скрипта данные пропадают.
JSON-файл
import json
from pathlib import Path
DB_PATH = Path("scores.json")
def load_scores() -> dict:
if not DB_PATH.exists():
return {}
return json.loads(DB_PATH.read_text(encoding="utf-8"))
def save_scores(data: dict) -> None:
DB_PATH.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
Ключи в JSON для user_id лучше хранить строками: str(user_id).
SQLite
Для десятков и сотен пользователей надёжнее встроенная SQLite:
Код ITЗагрузка примера кода…
Подробнее про слой доступа к данным — Работа с базами данных в Python и кейс Telegram Bot MVP (шаг с storage/sqlite.py).
Внешние API
Бот часто показывает данные с другого сервиса — погода, курс, случайная цитата:
import requests
@bot.message_handler(commands=["quote"])
def random_quote(message):
try:
r = requests.get("https://api.quotable.io/random", timeout=10)
r.raise_for_status()
data = r.json()
text = f"«{data['content']}» — {data['author']}"
except requests.RequestException:
text = "Сервис временно недоступен. Попробуйте позже."
bot.reply_to(message, text)
Правила:
- всегда задавайте timeout;
- оборачивайте сетевой вызов в
try/exceptи сообщайте пользователю понятный текст; - ключи внешних API (OpenWeatherMap и т.д.) — только в переменных окружения.
Теория HTTP и контрактов API — интеграционное взаимодействие.
Ошибки и логирование
Без логов бот "молча" падает при обрыве сети или неверном токене:
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)
@bot.message_handler(commands=["start"])
def start(message):
logger.info("user %s started", message.from_user.id)
bot.reply_to(message, "Привет!")
Оборачивайте рискованные места (файлы, HTTP, БД) в try/except, логируйте исключение и отправляйте пользователю короткое сообщение вместо трассировки.
Напоминания и отложенные сообщения
В python-telegram-bot есть встроенный job_queue. В telebot для учебных задач достаточно threading.Timer или библиотеки schedule:
import threading
def remind(chat_id: int, text: str, delay_sec: int) -> None:
def job():
bot.send_message(chat_id, text)
threading.Timer(delay_sec, job).start()
@bot.message_handler(commands=["remind"])
def cmd_remind(message):
remind(message.chat.id, "Напоминание сработало!", 10)
bot.reply_to(message, "Через 10 секунд пришлю сообщение.")
Ограничение Telegram: бот не может первым написать пользователю, который ещё не нажал /start в этом чате. Массовая "рассылка всем" без согласия нарушает правила платформы.
Ежедневные задачи (цитата в 9:00) на сервере удобнее вешать на cron или планировщик ОС, который вызывает отдельный скрипт с send_message.
Long polling и webhook
Учебные боты обычно используют infinity_polling() — библиотека сама опрашивает getUpdates.
| Режим | Когда уместен |
|---|---|
| Polling | Локальная разработка, демо, небольшая нагрузка |
| Webhook | Продакшен, низкая задержка, стабильная нагрузка, есть HTTPS |
Для webhook нужен публичный HTTPS-URL и настройка на стороне Bot API. Пошагово — в Примеры / 122 и кейсе MVP.
Пока скрипт не запущен (или сервер выключен), бот не отвечает — процесс должен работать постоянно или перезапускаться (systemd, Docker, PaaS).
Выбор библиотеки
| Библиотека | Стиль | Кому подходит |
|---|---|---|
pyTelegramBot (telebot) | Синхронный, декораторы | Первый бот, кружок, простые сценарии |
| python-telegram-bot (PTB v20+) | async/await, Application | Учебные курсы, структурированные проекты, ConversationHandler |
| aiogram | async/await, FSM | Продвинутые async-боты, высокая нагрузка |
Один и тот же Bot API — меняется только обёртка на Python. Уведомления без входящих команд (мониторинг) — в Веб-разработка и REST API на Python.
Деплой учебного бота
| Вариант | Плюсы | Минусы |
|---|---|---|
| Локальный ПК | Бесплатно, просто отладка | Бот офлайн, когда компьютер выключен |
| VPS (минимальный сервер) | Полный контроль, systemd | Нужна базовая админка |
| PaaS (Replit, PythonAnywhere и аналоги) | Быстрый старт | Лимиты бесплатного тарифа |
Минимум на сервере:
- скопировать проект и
.envсBOT_TOKEN; python -m venv .venv && pip install -r requirements.txt;- запуск через systemd или Docker, чтобы процесс поднимался после сбоя;
- для webhook — reverse proxy (Nginx, Caddy) с TLS — пример конфига nginx.
Продакшен-чеклист (Docker, webhook, тесты handlers) — Примеры решений для Python бота.
Безопасность и ограничения
- Токен = полный доступ к боту; при утечке —
/revokeв BotFather. - Бот в группе по умолчанию видит не все сообщения (режим Privacy в BotFather).
- Лимиты отправки — порядка 30 сообщений/сек в один чат; при превышении API вернёт
RetryAfter. - Соблюдайте FAQ Telegram для ботов.
Админ-команды защищайте списком разрешённых user_id, а не "секретной" командой в тексте помощи.
Частые ошибки новичков
- Токен в коде и в истории git.
- Нет
try/exceptна сеть и файлы — процесс завершается. - Общий
fallbackперехватывает команды, зарегистрированные позже. - Состояние диалога только в RAM — после рестарта пользователь "застревает" в сценарии.
- Inline-кнопки без
answer_callback_query.
Как масштабировать учебного бота
- Разнести код —
handlers/,services/,storage/(см. кейс 6). - Хранить состояние в SQLite, PostgreSQL или Redis.
- Rate limit на тяжёлые команды.
- Мониторинг и алерты — Автоматизация задач и DevOps-скрипты.
Идеи финальных проектов — викторина с очками, "угадай число", бот-расписание, мем по кнопке, FAQ с inline-меню.
См. также
- Автоматизация и скрипты
- Сокеты и HTTP
- Инструменты и среды
- Telegram Bot на Python — кейс MVP
- Примеры решений для Python-бота
Базовый разбор HTTP и HTTPS — HTTP как основа веб-интеграций.