Создаем Telegram бота: Урок второй
Итак, мы уже написали телеграм бота для отправки наших же сообшений нам в личные сообщения. Время повысить сложность кода и функциональность бота. Как я уже упоминала, возможности бота зависят не только от Telegram-API, но также и от языка программирования, на котором мы пишем. Все популярные языки программирования обладают примерно одинаковыми возможностями, отличается только реализация и сложность выполнения определенных узконаправленных команд. Также каждый язык программирования обладает своим уклоном, так называемой сильной стороной. Сильная сторона python – простота написания и чтения кода. Давайте же воспользуемся некотоыми функциями питона для расширения возможностей бота.
Второй бот
Задача такая: создать бота, отправляющего по специальной команде одну случайно выбранную картинку из папки заранее подготовленных. Моя реализация выглядит вот так:
import telebot
from random import randint
bot=telebot.TeleBot(“token”, parse_mode=None)
@bot.message_handler(commands=[“pic”])
def send_pic(message):
photo = open(f’pics/{randint(1, 5)}.png’, ‘rb’)
bot.send_photo(message.chat.id, photo)
@bot.message_handler(func=lambda m: True)
def advice(message):
bot.reply_to(message, “У бота есть команда /pic, опробуй её”)
bot.polling()
Сразу стоить обговорить пару условностей. Все сохраненные картинки нужно переименовать в числа от 1 и далее. Также в строке 6 стоит заменить выражение (1, 5) до (1, количество картинок), чтобы бот корректно отрабатывал. Эти две условности можно решить использованием модуля os, однако я считаю, что он будет излишним, так как слишком сложен для новичков. А теперь по порядку.
import telebot – импортирую библиотку для работы с Telegram-API
from random import randint – здесь я импортировала в мой файл не всю библиотеку со всеми функциями, а только функцию, которую я буду использовать, это позволяет программе выполняться быстрее и не загружать компьютер.
bot=telebot.TeleBot(“token”, parse_mode=None) – передаю исполнение всех следующих команд для бота переменной bot путем написания токена (замените token на свой bot token, который вы должны получить у бота @botfather)
@bot.message_handler(commands=[“pic”]) – указываю декоратор. Благодаря нему, бот будет реагировать на команду /pic и исполнять следующую функцию.
Следующую строку моей программы я разобью на три фрагмента, так как она достаточно сложна.
photo = open(…) – записываю в переменную photo (имя может быть любое) одну фотографию путем ее открытия в папке pics. Данная папка должна находиться в той же папке, что и наша программа.
f’pics/{…}.png’, ‘rb’<b> – во вторых кавычках я использую файл для чтения (r), а также я использую этот файл, как фото (b). префикс f означает, что выражение в кавычках является форматированным, то есть внутрь строки вы можете вставлять значения переменных с помощью имен переменных. Приведу маленький пример, чтобы все было понятно.
a = 4
b = ‘a’ # значение переменной b равно ‘a’
c = f‘{a}’ # значение переменной c равно 4
randint(1, 5) – В фигурных скобках я использую импортированную из библиотеки random команду randint, возвращающую одно псевдослучайное число из диапазона в скобках, то есть мне должно вернуться число от 1 до 5 всключительно.
photo = open(f’pics/{randint(1, 5)}.png’, ‘rb’) – таким образом, в переменную photo должна скопироваться одна из пяти картинок (1.png, 2png, 3.png, 4.png или 5.png). Если же формат ваших фото, например, jpeg, то поменяйте в этой строке соответствующую часть кода.
bot.send_photo(message.chat.id, photo) – я использую команду отправки фото. В скобках указываются чат, в который это фото нужно отправить, а также само фото.
@bot.message_handler(func=lambda m: True)
def advice(message):
bot.reply_to(message, “У бота есть команда /pic, опробуй её”)
Такую конструкцию вы уже встречали в первой части обучения. Этот декоратор отлавливает все сообщения и отвечает на них заготовленной фразой. Однако, так как этот декоратор, стоит в очереди вторым, сначала фильтрация проходит по первому декоратору, отправляющему изображения, и только потом подходит к этому декоратору, который в любом случае вызовется, так как он запрограммирован вызываться при любом сообщении. Таким образом можно без лишних строчек кода информировать пользователей о перечне доступных в вашем боте команд.
В конце стандартно пишем bot.polling() для связи программы с серверами телеграм.
После написания кода и сохранения в файл с окончанием .py надо запустить его. Я запущу код через командную строку.

После этого я захожу в своего бота и пишу любой текст:

Как можно видеть, выполняется второй декоратор нашего кода, и бот рассказывает нам о своих командах.
Если я введу нужную команду, то бот отошлет мне одну из заготовленных картинок:
Я специально не добавила картинку с названием 5.png, чтобы показать вам, что будет, если неправильно указать число картинок.
В терминале появляется огромное количество текста, сообщающего об одной ошибке “нет такого файла!”. Если вы запустили вашу программу не в терминале, а в специальной среде разработки, то результат будет тем же самым, и в диалоговом окне появятся те же строки, что у меня на картинке. Важно отметить, что при обнаружении в коде критической ошибки, программа останавливается и бот перестает работать, чтобы его перезапустить, достаточно перезапустить файл, предварительно исправив ошибку.

В этой программе мы использовали форматированную строку, открытие файла, а также функцию библиотеки random. Все это аспекты именно языка python, а не Telegram-API или библиотеки telebot.
Теория
В качестве текстовых аргументов, на которые реагирует бот можно указать не только команды и функции (примером функции служит второй декоратор в предыдущем примере, принимаающем все оставшиеся сообщения), но также аргрументом могут быть любые другие слова, выбранные на ваше усмотрение. Реализуется эта фильтрация путем использования регулярных выражений, на которых я не буду слишком долго задерживаться, покажу лишь основы:
@bot.message_handler(regexp=“слово”) данный декоратор реагирует на слово “слово”. Чтобы использовать свои слова, просто замените “слово” на свои выражения. Также тут можно использовать специальные комбинации регулярных выражений, например \d означает любую цифру, \d{4} уже будет 4 любые цифры в ряд и так далее. \s – это пробелы, а символ “.” это любой возможный символ. * означает “от 0 до бесконечности повторений символа перед звездой). Тогда выражение “.*” будет принимать любую входящую строку точно также, как и второй декоратор из второго написанного бота.
Также в обоих примерах бот отвечал на наше сообщение, однако мы можем заставить его просто писать нам. Для этого в функции под декоратором укажите следующее:
bot.send_message(message.chat.id, “ваш текст”)
Также бот позволяет добавить немного интерактива, путем добавления в меню бота кнопок.
Разберем пример бота с кнопками, выполняющего определенные действия по их нажатию.
Третий бот
import telebot
from telebot import types
from random import randint
bot=telebot.TeleBot(«token», parse_mode=None)
markup = types.ReplyKeyboardMarkup(row_width=2)
btn1 = types.KeyboardButton(‘random picture’)
btn2 = types.KeyboardButton(‘lucky number’)
markup.add(btn1, btn2)
@bot.message_handler(regexp=»random picture»)
def send_pic(message):
photo = open(f’pics/{randint(1, 5)}.png’, ‘rb’)
bot.send_photo(message.chat.id, photo)
@bot.message_handler(regexp=»lucky number»)
def num(message):
bot.reply_to(message, f»Your lucky number for now is {randint(1, 100)}»)
@bot.message_handler(func=lambda m: True)
def inst(message):
bot.send_message(message.chat.id, «Choose one bot function:», reply_markup=markup)
bot.polling()
Как можно видеть, бот работает отлично:
При нажатии на одну из кнопок, происходит действие, написанное на самой кнопке. Если у вас не было такой клавиатуры, то бот включит ее.
Разберу только ту часть, которую еще не объясняла:
from telebot import types – помимо полного импорта телебота добавляю отдельно функцию types, чтобы вызывать ее по команде types, а не telebot.types. Таким образом, я оптимизировала код и сделал его более читаемым.
markup = types.ReplyKeyboardMarkup(row_width=2) – присваиваю переменной markup значение клавиатуры из двух кнопок.
btn1 = types.KeyboardButton(‘random picture’)
btn2 = types.KeyboardButton(‘lucky number’) добавляю эти кнопки. Такие кнопки выводят то же значение, что написано на них при их появлении.
markup.add(btn1, btn2) – сопоставила места для пустых кнопок с новонаписанными кнопками.
bot.send_message(message.chat.id, «Choose one bot function:», reply_markup=markup) – В последнем, собирающем все остальные введенные строки, декораторе бот сообщает о выборе функций бота и показывает клавиатуру с кнопками.
Возможно вам понадобится спрятать клавиатуру, при определенных действиях пользователя. В таком случае выполните данную строчку кода: markup = types.ReplyKeyboardRemove()