Bot message handler что это



Скачай курс
в приложении
Перейти в приложение
Открыть мобильную версию сайта
© 2013 — 2023. Stepik
Наши условия использования и конфиденциальности

Public user contributions licensed under cc-wiki license with attribution required
Введение, простой echo-бот
Приветствую тебя, читатель! Telegram Bot API – это мощный инструмент для вообще чего угодно. Автоматизация действий, работа с пользователями, онлайн-магазины, игры и много чего ещё. В этом учебнике мы научимся писать ботов для Telegram на языке Python.
Сразу оговорюсь: тот бот, который получится в итоге — это лишь прототип, цель всех этих постов — рассказать об основах ботостроения, показать, как можно за короткое время написать простого бота для своих нужд.
Язык программирования будет Python 3, но это не означает, что любители PHP, Ruby и т.д. в пролёте; все основные принципы совпадают. Я не буду особо останавливаться на описании самого языка, желающие могут ознакомиться с документацией по Python здесь.
Подготовка к запуску
Взаимодействие ботов с людьми основано на HTTP-запросах. Чтобы не мучаться с обработкой «сырых» данных, воспользуемся библиотекой pyTelegramBotAPI, которая берет на себя все нюансы отправки и получения запросов, позволяя сконцентрироваться непосредственно на логике. Установка библиотеки предельно простая:
pip install pytelegrambotapi python3
Скриншот из терминала с запущенным интерпретатором Python
Обратите внимание: библиотека называется pyTelegramBotAPI , а не telebot . Последнюю ставить не нужно!
Теперь можно выйти из режима Python-консоли (Ctrl+Z или Ctrl+D, или exit() )
Пишем простого echo-бота
Ну, довольно слов, перейдем к делу. В качестве практики к первому уроку, напишем бота, повторяющего присланное текстовое сообщение. Создадим каталог, а внутри него 2 файла: bot.py и config.py . Я рекомендую выносить различные константы и настройки в файл config.py , дабы не загромождать другие. В файл config.py впишем:
# Токен ненастоящий :) Подставьте свой token = '1234567890:AAE_abCDEFghijKLmNOpqRsTuVWxyz'
Теперь надо научить бота реагировать на сообщения. Напишем обработчик, который будет реагировать на все текстовые сообщения.
@bot.message_handler(content_types=["text"]) def repeat_all_messages(message): # Название функции не играет никакой роли bot.send_message(message.chat.id, message.text)
У читателя возникнет вопрос: зачем там символ “@”? Что это вообще за message_handler ? Дело в том, что после приёма сообщения от Telegram его надо обработать по-разному в зависимости от того, что это за сообщение: текст “привет” или текст “пока”, может быть, вообще стикер или музыка. Первое, что придёт в голову – написать множество конструкций if-then-else , но такой подход некрасивый и позволяет быстро запутаться.
Для решения этой проблемы автор библиотеки pyTelegramBotAPI реализовал механизм хэндлеров, которые используют питоновские декораторы (пока просто запомним это слово). В хэндлере описывается, в каком случае необходимо выполнять ту или иную функцию. Например, хэндлер @bot.message_handler(content_types=[«text»]) выполнит нижестоящую функцию, если от Telegram придёт текстовое сообщение, а хэндлер @bot.message_handler(commands=[«start»]) сработает при получении команды /start.
Теперь запустим бесконечный цикл получения новых записей со стороны Telegram:
if __name__ == '__main__': bot.infinity_polling()
Функция infinity_polling запускает т.н. Long Polling, бот должен стараться не прекращать работу при возникновении каких-либо ошибок. При этом, само собой, за ботом нужно следить, ибо сервера Telegram периодически перестают отвечать на запросы или делают это с большой задержкой приводя к ошибкам 5xx)
Итак, полный код файла bot.py выглядит следующим образом:
import config import telebot bot = telebot.TeleBot(config.token) @bot.message_handler(content_types=["text"]) def repeat_all_messages(message): # Название функции не играет никакой роли bot.send_message(message.chat.id, message.text) if __name__ == '__main__': bot.infinity_polling()
Готово! Осталось запустить бота: python3 bot.py
Бот работает
На этом первый урок окончен.
Handler
Хендлеры это конечная точка в обработке событий. Хендлеры могут быть блокирующими (если нашелся подходящий хендлер другие уже не проверяются и не выполняются) и не блокирующими (в таком случае количество выполняемых хендлеров не ограничено и зависит от того какие пройдут). По умолчанию все хендлеры являются блокирующими
Хендлеры помечаются (лейблируются) с помощью декораторов. За это отвечает Labeler high-level инстанс с которым вы работаете. Пример с ботом:
1 2 3 4 5 6 7 8 9
from vkbottle.bot import Bot, Message bot = Bot("token") @bot.on.message() async def any_message(message: Message): await message.answer("Привет я бот") bot.run_forever()
Хендлеры ботов
message
Этот хендлер показан в примере выше
Хендлер на все сообщения (и из чата, и из личных сообщений)
chat_message
Хендлер на сообщения из чатов
private_message
Хендлер на сообщения из личных диалогов
Типы хендлеров выше не делают ничего необычного, просто оперируют предустановленным правилом PeerRule :
- в message он не предустанавливается
- в chat_message — PeerRule(True)
- в private_message — PeerRule(False)
В качестве аргументов декоратор принимает инстансы правил ( ABCRule ), а в качестве kwargs он принимает значение из custom_rules (подробнее в туториале
Если правило вернуло словарь, то он будет распакован и передан в качестве аргументов в хендлер, если он принимает их:
1 2 3 4 5 6 7 8 9 10 11 12 13
# Кастомное правило MyRule возвращает словарь `` @bot.on.message(MyRule()) async def some_key_handler(message: Message, some_key: str): await message.answer(f"some_key=some_value>") @bot.on.message(MyRule()) async def regular_handler(message: Message): await message.answer("Этот хендлер не принимает аргумент 'some_key', поэтому он и не был передан") @bot.on.message(MyRule()) async def kwargs_handler(message: Message, **kwargs): await message.answer(f"В хендлере переданы аргументы: kwargs>") # В хендлере переданы аргументы:
Типы обработчиков модуля python-telegram-bot
Внимание! Пакеты python-telegram-bot версии 13.x будут придерживаться многопоточной парадигмы программирования (*на данный момент актуальна версия 13.15). Пакеты версий 20.x и новее предоставляют чистый асинхронный Python интерфейс для Telegram Bot API. Дополнительно смотрите основные изменения в пакете python-telegram-bot версии 20.x.
Обработчик сообщений — это экземпляр, производный от базового класса telegram.ext.Handler , который отвечает за передачу различных видов сообщений (текст, звук, встроенный запрос, нажатия кнопок и т. д.) в соответствующую функцию обратного вызова.
Например, если надо, чтобы бот отвечал на команду /start , нужно использовать обработчик telegram.ext.CommandHandler , который сопоставляет ввод команды пользователя /start с обратным вызовом с именем start_callback :
Например, обработка команды /start для python-telegram-bot версии 13.x:
. def start_callback(update, context): update.message.reply_text("Welcome to my awesome bot!") . updater = Updater('TOKEN') dispatcher = updater.dispatcher dispatcher.add_handler(CommandHandler("start", start_callback))
Пример обработки команды /start для асинхронного python-telegram-bot версии 20.x:
. async def start_callback(update, context): await update.message.reply_text("Welcome to my awesome bot!") . application = ApplicationBuilder().token('TOKEN').build() application.add_handler(CommandHandler("start", start_callback))
Обработчики сообщений пакета python-telegram-bot :
Для разных типов пользовательского ввода в полученных от telegram.Update сообщениях будут установлены разные атрибуты. Например, входящее сообщение приведет к update.message , содержащему отправленное сообщение. Нажатие встроенной кнопки приведет к установке update.callback_query . Чтобы различать все эти сообщения, модуль telegram.ext содержит следующие обработчики:
- Класс MessageHandler(filters, callback) предназначен для обработки всех сообщений Telegram. Они могут содержать текст, мультимедиа или обновления статуса и т.д. Будете использовать в 70% случаев совместно с фильтрами сообщений.
- Класс CommandHandler(command, callback, filters=None) предназначен для обработки команд. Команды представляют собой сообщения, которые начинаются с / . Будете использовать в 20% случаев.
- Класс CallbackQueryHandler(callback) предназначен для обработки запросов обратного вызова Telegram (нажатие кнопок встроенной клавиатуры).
- Класс ConversationHandler(entry_points, states, fallbacks) предназначен для ведения разговора с одним или несколькими пользователями через сообщения Telegram путем управления четырьмя коллекциями других обработчиков. Пример использования данного обработчика можно посмотреть в разделе создания меню из кнопок (Пример встроенной клавиатуры с 2-мя состояниями).
- entry_points — список обработчиков сообщений, которые используются для инициирования разговора, например, с CommandHandler или MessageHandler .
- state — представляет собой словарь dict , который в качестве ключей хранит состояния/этапы разговора, а в качестве значений этих ключей один или несколько (список) связанных обработчиков сообщений, которые должны быть использованы, если пользователь отправляет сообщение, когда разговор с ними в настоящее время находится в этом состоянии/этапе. Здесь также можно определить состояние TIMEOUT для определения поведения при превышении conversation_timeout .
- fallbacks — это список обработчиков сообщений, которые используются, если пользователь в данный момент находится в разговоре, но состояние либо не имеет связанного обработчика, либо обработчик, связанный с состоянием, не подходит для обновления, например, если обновление содержит команду, но ожидается обычное текстовое сообщение. Это поведение можно использовать для отмены разговора или сообщения пользователю, что его сообщение не было распознано.
Чтобы изменить состояние разговора, функция обратного вызова обработчика должна вернуть новое состояние после ответа пользователю. Если она ничего не возвращает (по умолчанию), то состояние не изменится. Если функция обратного вызова точки входа возвращает None, разговор заканчивается сразу же после выполнения этой функции обратного вызова. Чтобы завершить разговор, функция обратного вызова должна вернуть END или -1. Для обработки тайм-аута разговора используйте TIMEOUT или -2.
Пример фрагмента кода определения обработчика разговора ConversationHandler :
conv_handler = ConversationHandler( # точка входа в разговор entry_points=[CommandHandler('start', start)], # словарь состояний разговора, возвращаемых callback функциями states= # Этап `FIRST` - т.е. функция обработчик сообщения в этом разговоре явно # вернула константу FIRST (return `FIRST`), а так же послала/ответила # на сообщение. Ответ пользователя на это сообщение будет # обрабатываться обработчиками определенными в этом списке FIRST: [ CallbackQueryHandler(one, pattern='^' + str(ONE) + '$'), CallbackQueryHandler(two, pattern='^' + str(TWO) + '$'), CallbackQueryHandler(three, pattern='^' + str(THREE) + '$'), CallbackQueryHandler(four, pattern='^' + str(FOUR) + '$'), ], # Этап `SECOND` - происходит то же самое, что и в описании этапа `FIRST` SECOND: [ CallbackQueryHandler(start_over, pattern='^' + str(ONE) + '$'), CallbackQueryHandler(end, pattern='^' + str(TWO) + '$'), ], >, # точка выхода из разговора fallbacks=[CommandHandler('start', start)], )
from telegram.ext import ChosenInlineResultHandler def result_chosen(update, _): print(update.to_dict()) # результат inline запроса result = update.chosen_inline_result # параметры результата result_id = result.result_id query = result.query user = result.from_user.id print(result_id) print(user) print(query) print(result.inline_message_id) result_chosen_handler = ChosenInlineResultHandler(result_chosen) dispatcher.add_handler(result_chosen_handler)
# сработает на команду '!test'. PrefixHandler('!', 'test', callback) # сработает на команды '!test' и '#test'. PrefixHandler(['!', '#'], 'test', callback) # сработает на команды '!test', '#test', '!help' и '#help'. PrefixHandler(['!', '#'], ['test', 'help`], callback)
В некоторых случаях полезно обрабатывать сообщения, поступающие не из Telegram. Например. можно обрабатывать уведомления от сторонней службы и пересылать их своим пользователям. Для таких случаев python-telegram-bot предоставляет следующие обработчики:
- Класс TypeHandler() предназначен для обработки обновлений пользовательских типов. Тип type — тип сообщения, которые должен обрабатывать этот обработчик, как определено isinstance() .
- Класс StringRegexHandler(pattern, callback) предназначен для обработки обновлений строк на основе регулярного выражения, которое проверяет содержимое сообщения.
- Класс StringCommandHandler(command, callback) предназначен для обработки пользовательских строковых команд. Команды представляют собой сообщения, которые начинаются с / .
Эти обработчики не используется для обработки Telegram.Update , но строки вручную помещаются в очередь. Например, чтобы отправлять сообщения с ботом, используя командную строку или API.
Обработка сообщений обработчиком MessageHandler .
Особенностью MessageHandler является то, что существует такое огромное разнообразие типов сообщений (текст, gif, изображение, документ, стикер и т. д.), что невозможно предоставить отдельный обработчик для каждого типа. Вместо этого MessageHandler сочетается с так называемыми фильтрами, которые позволяют проводить мелкие различия: MessageHandler(Filters.all, callback) будет обрабатывать все сообщения, которые содержат:
- update.message ;
- update.edited_message ;
- update.channel_post ;
- update.edited_channel_post .
Вы можно использовать различные фильтры, чтобы сузить круг сообщений, которые будет обрабатывать конкретный MessageHandler . Смотрите также раздел по использованию фильтров.
Обработка команд обработчиком CommandHandler .
Команды — это сообщения Telegram, которые начинаются с символа / , за которым могут следовать @ и имя бота и / или некоторый дополнительный текст. Обработчик добавит список в context с именем CallbackContext.args . Он будет содержать список строк, который представляет собой текст, следующий за командой, разделенной на одиночные или последовательные символы пробела.
По умолчанию обработчик прослушивает все сообщения, а также отредактированные сообщения. Чтобы изменить это поведение, используйте ~Filters.update.edited_message в аргументе фильтра.
Класс telegram.ext.CommandHandler не обрабатывает отредактированные сообщения на канале.
Для примера использования обработчика CommandHandler , расширим функцию start_callback() некоторыми аргументами, чтобы пользователь мог предоставить дополнительную информацию:
Для многопоточной версии 13.x библиотеки:
. def start_callback(update, context): # обработка аргументов, переданных с командой user_says = " ".join(context.args) update.message.reply_text("User said: " + user_says) . updater = Updater('TOKEN') dispatcher = updater.dispatcher dispatcher.add_handler(CommandHandler("start", start_callback))
Для асинхронной версии 20.x библиотеки:
. async def start_callback(update, context): # обработка аргументов, переданных с командой user_says = " ".join(context.args) await update.message.reply_text("User said:" + user_says) . application = ApplicationBuilder().token('TOKEN').build() application.add_handler(CommandHandler("start", start_callback))
Отправка команды ‘/start Hello World!’ приведет к тому, что бот разделит все, что находится после /start , на список слов по пробелам и передаст его параметру args контекста: [‘Hello’, ‘World!’] . Мы объединяем эти фрагменты вместе, вызывая ».join(context.args) , и выводим полученную строку обратно пользователю.
Старт Telegram бота с параметрами.
Описанная выше передача аргументов работает точно так же, когда пользователь нажимает на глубоко связанный начальный URL, например этот:
Щелчок по этой ссылке откроет Telegram-клиент и покажет большую кнопку СТАРТ. При ее нажатии параметры URL-адреса Hello_World! будут переданы в аргументы объекта контекста.
Обратите внимание, поскольку Telegram не поддерживает пробелы в параметрах URL для запуска ботов таким образом, то придется вручную разделить единственный аргумент Hello_World на [‘Hello’, ‘World!’] , например используя вызов context.args[0].split(‘_’) .
Также обратите внимание на максимальную длину, принимаемую самим Telegram. Как указано в документации, максимальная длина параметра start в URL составляет не более 64 символа.
Кроме того, так как это параметр URL-адреса, то необходимо правильно передавать значения, чтобы избежать зарезервированных символов URL-адреса. Рассмотрим использование base64.urlsafe_b64encode .
Соответствие шаблону: Filters.regex(pattern)
Для более сложных входных данных можно использовать telegram.ext.MessageHandler с фильтром telegram.ext.Filters.regex , который внутренне использует модуль re для сопоставления текстового ввода пользователя с предоставленным шаблоном.
Имейте в виду, что для извлечения URL-адресов, #Hashtags , @Mentions и других объектов Telegram нет необходимости, потому что Bot AP уже присылает их нам с каждым сообщением.
Сущности сообщения MessageEntity .
Для использования MessageEntity , сначала необходимо извлечь сущности и соответствующий им текст из объекта Message с помощью метода parse_entities .
Примечание. Этот метод всегда следует использовать вместо атрибута сущностей, поскольку он вычисляет правильную подстроку из текста сообщения на основе кодовых точек UTF-16, то есть извлекает правильную строку даже при работе со странными символами, такими как Emojis .
entity = message.parse_entities()
- КРАТКИЙ ОБЗОР МАТЕРИАЛА.
- Переход на асинхронный python-telegram-bot версии 20.x
- Чистый интерфейс Python для Telegram Bot API
- Команды и оповещения @BotFather в Telegram
- Обработка сообщений модулем python-telegram-bot
- Фильтры сообщений модуля python-telegram-bot
- Хранение временных данных модулем python-telegram-bot
- Настройки по умолчанию модуля python-telegram-bot
- Планировщик сообщений модуля python-telegram-bot
- Форматирование и отправка сообщений в python-telegram-bot
- Работа с файлами/media, модуль python-telegram-bot
- Меню из кнопок, модуль python-telegram-bot
- Объект CallbackContext модуля python-telegram-bot
- Подключения Telegram-бота через webhook
- Обработка исключений модуля python-telegram-bot
- Создание Inline-бота, модуль python-telegram-bot
- Работа с опросами в модуле python-telegram-bot
- Создание разговоров ConversationHandler в python-telegram-bot
- Перезапуск телеграмм-бота в случае ошибки
- Декоратор-обработчик сообщений в python-telegram-bot
- Авторизация на сайте через Telegram Passport
- Ведение публикаций в Telegram-канале с python-telegram-bot
- UTF коды emoji/эмодзи для отправки в Telegram из Python