В этом статье я покажу как создать Telegram бота с помощью Python, поскольку не нашел хорошей русскоязычной статьи по этой теме.
Создание бота
Бот создается с помощью BotFather через Telegram. После команды /newbot
надо просто следовать инструкции.

В конце мы получаем токен для управления ботом и работы с Telegram API.
pyTelegramBotApi
Ссылки на документации всех библиотек будут в конце.
Создадим простого бота, отвечающего на команду /start
, с помощью этой библиотеки:
import telebot
bot = telebot.TeleBot('1408700689:AAGVqcqscWWK7DnuNHahd0w1eNklfjPEVxE')
@bot.message_handler(commands=['start'])
def start(message):
bot.send_message(message.chat.id, 'It works!')
bot.polling()
pyTelegramBotApi является просто обёрткой для всего Telegram Bot API, но здесь разберутся только основные составляющие.
Взаимодействие с ботом происходит через переменную bot (токен надо вставить свой).
Декоратор @message_handler реагирует на входящие сообщение.
Message – это объект из Bot API, содержащий в себе информацию о сообщении. Полезные поля:
message.chat.id – идентификатор чата
message.from.id – идентификатор пользователя
message.text – текст сообщения
Функция send_message принимает идентификатор чата (берем его из сообщения) и текст для отправки.
Примеры функций
Отправка изображений
Можно отправлять фото из локального хранилища, но удобнее это делать по ссылке. Код аналогичен предыдущему:
@bot.message_handler(commands=['start'])
def start(message):
bot.send_photo(message.chat.id, photo=photo_url, caption='It works!')
Замена клавиатуры
У ботов есть функция замены стандартной клавиатуры на кнопочную. Для этого у всех функций есть опциональный аргумент reply_markup:
from telebot import types
@bot.message_handler(commands=['start'])
def start(message):
markup = types.ReplyKeyboardMarkup()
buttonA = types.KeyboardButton('A')
buttonB = types.KeyboardButton('B')
buttonC = types.KeyboardButton('C')
markup.row(buttonA, buttonB)
markup.row(buttonC)
bot.send_message(message.chat.id, 'It works!', reply_markup=markup)
ReplyKeyboardMarkup – и есть та самая клавиатура. Метод row() создает ряд (максимум 12) из кнопок, передаваемых в качестве аргумента.
Также есть особенная клавиатура types.ReplyMarkupRemove(), которая меняет клавиатуру на стандартную.
Клавиатура для сообщений
Можно создавать клавиатуру для отдельного сообщения. Передавать его нужно так же в аргумент reply_markup:
from telebot import types
@bot.message_handler(commands=['start'])
def start(message):
markup = types.InlineKeyboardMarkup()
buttonA = types.InlineKeyboardButton('A', callback_data='a')
buttonB = types.InlineKeyboardButton('B', callback_data='b')
buttonC = types.InlineKeyboardButton('C', callback_data='c')
markup.row(buttonA, buttonB)
markup.row(buttonC)
bot.send_message(message.chat.id, 'It works!', reply_markup=markup)
У кнопок есть несколько режимов, в зависимости от второго аргумента. Подробнее можно прочитать в официальной документации, но я остановлюсь только на callback_data.
При нажатии на такую кнопку боту придет отдельный CallbackQuery, который нужно обрабатывать подобно сообщению:
@bot.callback_query_handler(func=lambda call: True)
def handle(call):
bot.send_message(call.message.chat.id, 'Data: {}'.format(str(call.data)))
bot.answer_callback_query(call.id)
Для обработки обязательно указать аргумент func для "отсеивания" Callback запросов.
После обработки каждого запроса нужно выполнить команду answer_callback_query, чтобы Telegram понял, что запрос обработан. В поле callback.data хранится информация из callback_data нажатой кнопки.
Изменение сообщений
У ботов есть функция изменения своих сообщений (можно использовать, чтобы сделать перелистывание страниц, например). Для этого нужно воспользоваться методом edit_message_text (edit_message_caption для картинок):
@bot.callback_query_handler(lambda call: True)
def handle(call):
bot.send_message(chat_id=call.message.chat.id, message_id=call.message.id, text='It works!')
bot.answer_callback_query(call.id)
Смысл аргументов понятен из их названия.
Flask
Если запустить бота, то через какое-то время он упадет с ошибкой Connection to api.telegram.org timed out.
Чтобы это исправить нужно использовать вебхук:
from flask import Flask, request
import telebot
token = '1408700689:AAGVqcqscWWK7DnuNHahd0w1eNklfjPEVxE'
bot = telebot.TeleBot(token)
app = Flask(__name__)
@bot.message_handler(commands=['start'])
def start(message):
bot.send_message(message.chat.id, 'It works!')
@app.route("/" + token, methods=['POST'])
def getMessage():
bot.process_new_updates([telebot.types.Update.de_json(request.stream.read().decode("utf-8"))])
return "!", 200
bot.remove_webhook()
bot.set_webhook('https://test.com/' + token)
app.run()
Этот код при запуске сначала удалит вебхук, если такой был, и установит его на желаемый. Все запросы, которые приходят в функцию getMessage будут направляться в bot с помощью метода process_new_updates. Этот код уже можно использовать для запуска, например, на Heroku.
P.S. Чтобы работать с длинными диалогами, я хранил для каждого пользователя в базе данных его текущее состояние.
Полезные ссылки
https://flask.palletsprojects.com/en/1.1.x/ – Flask
https://pypi.org/project/pyTelegramBotAPI/ – pyTelegramBotApi
https://core.telegram.org/bots/api – Telegram Bot API