Центр непрерывного образования

факультет компьютерных наук НИУ ВШЭ

Сейчас телеграм‑боты используют практически все. С помощью телеграм‑бота можно собрать заявки, оформить «предложку» для своего канала или использовать в каких‑то еще рабочих целях. Я работаю преподавателем, поэтому использую телеграм‑боты для анонимных отзывов и вопросов от студентов. А также как небольшой интерактивный справочник с информацией о курсе.

В этой статье я попробовала собрать всю основную информацию о том, как написать бота, начиная от получения токена и заканчивая деплоем бота на яндекс клауде.

Маргарита Бурова

Преподаватель и эксперт Центра непрерывного образования ФКН НИУ ВШЭ, руководитель Edtech-программ по DS и DA Wildberries&Russ

Первое, с чего начинается создание бота — это получение токена от BotFather https://t.me/BotFather. Вам нужно попасть в него, ввести команду /newbot, придумать имя (имя может быть любое) и уникальный username (должен заканчиваться на bot, например, mytestbot). После этого вы получите токен — это ключ для доступа к Telegram Bot API. Храните его в секрете!

Теперь можем перейти к написанию кода. Мы будем использовать библиотеку telebot. Для начала ее следует установить:

!pip install pyTelegramBotAPI

Теперь можем начинать создание бота! Импортируем нашу библиотеку и создаем экземпляр бота. В качестве аргумента передается непосредственно токен.

import telebot # импортируем библиотеку

bot = telebot.TeleBot("BOT_TOKEN") # создаем экземпляр бота

В Telegram команды начинаются с символа слэша (/), и внутри JSON‑сообщения они содержатся в поле entities. Для обработки команд в Python‑ботах обычно используется декоратор @bot.message_handler, который перехватывает сообщения с указанными командами и передает их в соответствующие функции‑обработчики (коллбеки).

Давайте рассмотрим пример простой обработки команды /start:

@bot.message_handler(commands=['start'])
def start(message):
    bot.send_message(
        chat_id=message.chat.id,
        text='Привет! Напиши мне что-нибудь.'
    )

Что здесь происходит:

  • Декоратор @bot.message_handler(commands=['start']) подписывает функцию start на команду /start. То есть функция, которая идет за ним, будет вызываться именно по команде /start.

  • Объект message — это уже разобранный JSON с полезными данными, такими как message.chat.id (идентификатор чата), message.from_user.username (имя пользователя) и message.date (время сообщения).

  • Метод send_message отправляет текст обратно в тот же чат, откуда пришло сообщение (первый аргумент в нем обозначает «адрес» получателя, а второй — непосредственно текст сообщения).

Чтобы не ограничиваться только командами, можно ориентироваться на входящие сообщения с разными типами данных. Например, перехватывать все входящие текстовые сообщения и отвечать на них, к примеру, эхо‑сообщением:

@bot.message_handler(content_types=['text'])
def echo(message):
    bot.send_message(
        message.chat.id,
        f'Вы написали: {message.text}'
    )

Здесь у хендлера указывается, что он реагирует на текстовый контент:

content_types=['text']

Хендлеры в библиотеке Telebot для Python — это функции, которые реагируют на входящие сообщения или события от пользователей Telegram и обрабатывают их в соответствии с заданными условиями. Они реализуются с помощью декоратора @bot.message_handler, который регистрирует функцию как обработчик сообщений с определенным фильтром. Это позволяет создавать интерактивных и функциональных ботов, реагирующих на команды, текст, типы контента и другие параметры сообщений. Они могут реагировать не только на команды и текст, но и на различные типы контента, а также на события, связанные с сообщениями.

Для того, чтобы обрабатывать разные типы данных, нужно настраивать параметр content_types в декораторе @bot.message_handler. По умолчанию это ['text'], но можно указать, например, 'photo', 'audio', 'video', 'document' и другие.

Допустим, давайте посмотрим на функцию, которая срабатывает только при получении фотографии, скачивает ее и сохраняет локально:

@bot.message_handler(content_types=['photo'])  # Обработчик сообщений с типом "фото"
def photo_handler(message):
    # Получаем фото в самом большом доступном разрешении (последний элемент списка photo)
    photo = message.photo[-1]
    file_id = photo.file_id  # Получаем file_id изображения
    file_info = bot.get_file(file_id)  # Получаем информацию о файле (включает путь к нему)
    downloaded_file = bot.download_file(file_info.file_path)  # Загружаем файл с серверов Telegram

    # Формируем уникальное имя файла на основе ID чата и file_id
    file_name = f"{message.chat.id}_{file_id}.jpg"
    # Открываем файл для записи в бинарном режиме и сохраняем фото
    with open(file_name, 'wb') as new_file:
        new_file.write(downloaded_file)

    # Отправляем пользователю подтверждение о загрузке фото
    bot.reply_to(message, "Фотография загружена и сохранена на сервере.")

Также можно использовать хендлеры для обработки событий. В Telegram события обычно связаны с разными типами сообщений или действиями пользователя. Можно реагировать на такие события, используя фильтры по типу контента.

Допустим, мы хотим приветствовать в чате каждого нового участника после его добавления:

# Обработчик события добавления нового участника в чат
@bot.message_handler(content_types=['new_chat_members'])
def new_member_handler(message):
    # Перебираем всех новых участников, добавленных в чат
    for new_member in message.new_chat_members:
        # Отправляем приветственное сообщение каждому новому участнику
        bot.send_message(message.chat.id, f"Добро пожаловать, {new_member.first_name}!")

Событие также прописывается в типе контента: content_types=['new_chat_members'] означает, что бот будет реагировать только на сообщения, содержащие информацию о новых участниках.

Когда кто‑то добавляется в чат, телеграм отправляет сообщение с типом new_chat_members. Бот перехватывает его, потому что тип совпадает, и вызывает нужную функцию.

Также можно прописать свою собственную функцию, которая будет возвращать True или False. К примеру, такая функция будет реагировать на любое сообщение, содержащее слово «привет» в любом регистре:

@bot.message_handler(func=lambda message: 'привет' in message.text.lower())
def greet_handler(message):
    bot.send_message(message.chat.id, f"Привет, {message.from_user.first_name}!")

Для общения с пользователями необязательно использовать исключительно текстовые сообщения, а можно создать клавиатуру и считывать ответы через кнопки.

@bot.message_handler(commands=['start'])
def send_keyboard(message):
    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    keyboard.add(types.KeyboardButton("Кнопка 1"))
    keyboard.add(types.KeyboardButton("Кнопка 2"))
    keyboard.add(types.KeyboardButton("Кнопка 3"))
    bot.send_message(message.chat.id, "Выберите кнопку:", reply_markup=keyboard)

@bot.message_handler(func=lambda message: message.text in ["Кнопка 1", "Кнопка 2", "Кнопка 3"])
def handle_button(message):
    if message.text == "Кнопка 1":
        bot.send_message(message.chat.id, "Вы нажали Кнопку 1!")
    elif message.text == "Кнопка 2":
        bot.send_message(message.chat.id, "Вы нажали Кнопку 2!")
    else:
        bot.send_message(message.chat.id, "Вы нажали Кнопку 3!")

Здесь в начале вызывается @bot.message_handler(commands=['start']) — декоратор, который регистрирует функцию send_keyboard как обработчик сообщений с командой /start. Внутри функции создается объект клавиатуры ReplyKeyboardMarkup с параметром resize_keyboard=True, который автоматически подгоняет размер клавиатуры под экран пользователя. Далее добавляются три кнопки с текстами «Кнопка 1», «Кнопка 2» и «Кнопка 3». Затем бот отправляет сообщение «Выберите кнопку:» с прикрепленной клавиатурой, которую увидит пользователь.

Можно создавать любое количество кнопок, впоследствии обрабатывая результат нажатия на них другими функциями.

В примерах выше для отправки ответа пользователю я везде использовала send_message. На самом деле, можно отправлять не только текстовые сообщения, но и другие виды контента. Например:

  • send_photo(chat_id, photo) — отправка фотографии.

  • send_audio(chat_id, audio) — отправка аудиофайла.

  • send_document(chat_id, document) — отправка документов (файлов).

  • send_sticker(chat_id, sticker) — отправка стикеров.

Мы немного посмотрели на основные особенности создания бота, так что теперь давайте посмотрим, как реализовать запуск!

Для постоянного получения обновлений от Telegram API используется бесконечный цикл:

bot.polling(none_stop=True, interval=0)
  • none_stop=True позволяет библиотеке не останавливать работу при возникновении исключений внутри обработчиков.

  • interval=0 означает, что запросы к серверу будут отправляться без задержек. Чтобы избежать превышения лимитов API (около 100 запросов в секунду на токен), можно установить интервал, например, 0.5 секунды.

Важно отметить, что в таком случае бот будет работать только в том случае, пока код запущен у вас на компьютере. Это рабочий вариант, если вы просто хотите собирать какие‑то отзывы или предложения (во время отсутствия запущенного кода сообщения от пользователей будут просто накапливаться и придут вам целой кучей), но если нужно реализовать полноценный диалог с человеком — такой вариант уже не подходит. Для развертывания бота и его непрерывного использования я использую яндекс клауд — в конце статьи я расскажу, как задеплоить бот на облако и пользоваться им постоянно.

Итак, давайте подведем промежуточный итог.

Создание Telegram‑бота с помощью модуля Telebot начинается с получения уникального токена у BotFather и установки библиотеки pyTelegramBotAPI. После этого в Python создается объект бота с этим токеном, который служит интерфейсом для взаимодействия с Telegram API. Основной принцип работы — регистрация функций‑обработчиков (хендлеров) с помощью декораторов @bot.message_handler, которые реагируют на входящие сообщения, команды или определенные типы контента. Внутри таких функций можно анализировать сообщения, получать данные пользователя и отправлять ответы с помощью методов бота, например, send_message или reply_to.

Далее запускается цикл запроса новых сообщений методом bot.polling() или bot.infinity_polling(), который обеспечивает непрерывную работу бота и обработку событий в реальном времени.

Теперь давайте попробуем рассмотреть вариант, когда наш бот располагается на облаке и нам не нужен bot.polling(). Для этого напишу элементарный пример бота, который содержит кнопки, функции, перенаправление информации.

Допустим, я создаю для студентов Telegram‑бот, в котором есть кнопки с разной справочной информацией (ДЗ, дедлайны, оценки) и есть кнопка для анонимного отзыва, который сразу придет мне в чате.

Простейший вариант такого бота следующий:

import telebot
from telebot import types

# Токен бота (замените на ваш токен)
TOKEN = '...'

bot = telebot.TeleBot(TOKEN)

# ID администратора (замените на настоящий ID)
ADMIN_ID = 123456789

# Обработчик команды /start
@bot.message_handler(commands=['start'])
def start(message):
    markup = types.ReplyKeyboardMarkup(row_width=2)
    info_button = types.KeyboardButton('Справочная информация')
    feedback_button = types.KeyboardButton('Анонимный отзыв')
    markup.add(info_button, feedback_button)
    bot.send_message(message.chat.id, 'Выберите опцию:', reply_markup=markup)

Этот блок кода реализует обработчик команды /start для Telegram‑бота. Когда пользователь отправляет боту команду /start, вызывается функция start, которая создает пользовательскую клавиатуру с двумя кнопками — «Справочная информация» и «Анонимный отзыв». Для этого используется объект ReplyKeyboardMarkup с параметром row_width=2, чтобы разместить кнопки в одной строке. Затем эти кнопки добавляются на клавиатуру, и бот отправляет пользователю сообщение с текстом «Выберите опцию:», прикрепляя к нему созданную клавиатуру. Таким образом, пользователь получает удобный интерфейс для выбора одной из двух предложенных опций прямо в чате с ботом.

# Обработчик текстовых сообщений
@bot.message_handler(func=lambda message: True)
def handle_message(message):
    if message.text == 'Справочная информация':
        bot.send_message(message.chat.id, 'Это справочная информация о боте.')
    elif message.text == 'Анонимный отзыв':
        msg = bot.send_message(message.chat.id, 'Пожалуйста, напишите ваш анонимный отзыв:')
        bot.register_next_step_handler(msg, send_feedback)
    else:
        bot.send_message(message.chat.id, 'Пожалуйста, используйте кнопки для взаимодействия с ботом.')

Этот блок кода создает универсальный обработчик для всех входящих сообщений бота с помощью декоратора @bot.message_handler(func=lambda message: True), который срабатывает на любое сообщение. Внутри функции handle_message происходит проверка текста сообщения: если пользователь нажал кнопку «Справочная информация», бот отправляет соответствующий информационный текст; если выбрана кнопка «Анонимный отзыв», бот просит пользователя написать отзыв и регистрирует следующий обработчик send_feedback для обработки этого ответа. Если же сообщение не соответствует ни одной из кнопок, бот отправляет предупреждение, что нужно использовать кнопки для взаимодействия. Таким образом, этот блок обеспечивает реакцию бота на нажатия кнопок, созданных ранее, и корректно обрабатывает ввод пользователя, направляя его либо к справочной информации, либо к отправке анонимного отзыва, либо информируя о некорректном вводе.

# Функция отправки отзыва администратору
def send_feedback(message):
    feedback = message.text
    bot.send_message(ADMIN_ID, f'Анонимный отзыв: {feedback}')
    bot.send_message(message.chat.id, 'Спасибо за ваш отзыв!')

Здесь функция send_feedback принимает отзыв пользователя, пересылает его администратору и благодарит пользователя за оставленный отзыв.

# Запуск бота
bot.polling()

Теперь давайте задеплоим его на яндекс клауде! Вот основные шаги для того, чтобы это сделать:

  1. Перейдите на сайт Yandex Cloud и войдите с помощью Яндекс ID.

  2. В консоли управления подтвердите создание первого облака и перейдите к созданию платежного аккаунта.

  3. Откройте раздел Биллинг, нажмите Создать аккаунт, заполните необходимые данные: страну, имя аккаунта, ФИО, номер карты, почту и телефон.

  4. После создания платежного аккаунта зайдите в консоль управления.

  5. В меню выберите Cloud Functions.

  6. В правом верхнем углу нажмите Создать функцию, придумайте имя для функции (например, telegram‑bot).

  7. В качестве языка программирования выберите Python. Откроется редактор кода, в который вы сможете вставить код своего бота.

  8. Сразу добавьте файл requirements.txt, внутри которого запишем внешнюю библиотеку pyTelegramBotAPI, которая установится при сборке нашей функции.

В начале кода функции (после импорта модулей) пропишите функцию:

def handler(event,context): # основная функция для обработки действий бота
    body = json.loads(event['body'])
    update = telebot.types.Update.de_json(body)
    bot.process_new_updates([update])

Этот код — часть webhook‑обработчика Telegram‑бота, которая:

  • Получает HTTP‑запрос с обновлением от Telegram,

  • Парсит JSON из тела запроса,

  • Преобразует данные в объект Update,

  • Передает обновление в библиотеку telebot для дальнейшей обработки.

Таким образом, бот реагирует на действия пользователей (сообщения, команды и т. д.) через webhook.

Также не забудьте в начале кода добавить import json для работы с json‑форматом.

Далее нажмите снизу кнопку «Сохранить изменения», а затем включите опцию «Публичная функция» на появившемся экране и скопируйте ссылку для вызова.

Теперь нужно соединить бот с функцией:

Здесь происходит настройка механизма Webhook для Telegram‑бота. Webhook — это URL‑адрес, который вы передаете Telegram через API методом.set_webhook(). После этого сервер Telegram при каждом новом обновлении (например, когда пользователь пишет боту) автоматически отправляет данные об этом обновлении на указанный URL в формате JSON. Таким образом, вместо постоянного опроса сервера Telegram (polling), бот получает сообщения и события в тот же момент!

Мы сначала берем нашу функцию, затем с помощью метода.set_webhook() мы регистрируем этот URL в Telegram, чтобы Telegram знал, куда отправлять обновления для вашего бота. После установки webhook можно проверить его статус вызовом print(bot.get_webhook_info()), что позволит убедиться, что webhook успешно установлен и работает.

Мой бот работает. Для пользователей он выглядит так:

Далее могу оставить отзыв:

На мой аккаунт администратора в этот же момент пришел этот отзыв:

Теперь вы можете написать своего бота, добавить команды и кнопки, а потом задеплоить его на яндекс клауде! При регистрации там есть возможность получения гранта, но в целом поддержка такого бота для локальных задач (для небольшого количества пользователей) обходится буквально в копейки.

Если было сложно разобраться в коде или вы чувствуете, что не хватает базовых знаний по Python — не переживайте. Начать всегда можно с простого!

Рекомендуем бесплатный Мегаинтенсив по анализу данных, где я провожу занятия про введение в синтаксис Python.

Комментарии (6)


  1. twistfire92
    28.05.2025 08:44

    А токен бота на всеобщее обозрение зачем выставили?


    1. kasyanenko Автор
      28.05.2025 08:44

      Добрый день! Бот на момент публикации был удален, а токен не является активным. Так или иначе, убрали из публикации. Благодарим за внимательность!)


  1. Manuman
    28.05.2025 08:44

    Здравствуйте, спасибо за статью. Очень интересно.

    Помогите, пожалуйста, разобраться с файлом requirements.txt , не до конца понимаю что там прописать для добавления в зависимости библиотеки pyTelegramBotAPI . Документацию читал, но не понял.


    1. zaelcovsky
      28.05.2025 08:44

      pyTelegramBotAPI==4.27.0

      вот так в отдельной строке, на первое время сойдет


  1. zaelcovsky
    28.05.2025 08:44

    Было бы неплохо еще выкладывать репо с кодом проекта как часто делают блогеры на ютубе например, тогда и вопросов меньше будет, как у человека выше.


  1. Vitaly_Progress
    28.05.2025 08:44

    А запустить бота возможно на каком-нибудь бесплатном сервере?