В предыдущих статьях мы достаточно подробно разобрали тему ботостроения, от отправки первого сообщения до программирования логического диалога с ботом.
Это последняя статья из данной серии, в которой мы разберёмся с тем, как управлять правами использования отдельных методов бота на различных уровнях.
Все статьи из серии "Пишем telegram бота на языке R"
- Создаём бота, и отправляем с его помощью сообщения в telegram
- Добавляем боту поддержку команд и фильтры сообщений
- Как добавить боту поддержку клавиатуры
- Построение последовательного, логического диалога с ботом
- Управление правами пользователей бота
Содержание
Если вы интересуетесь анализом данных возможно вам будут интересны мои telegram и youtube каналы. Большая часть контента которых посвящены языку R.
- Введение
-
Ограничиваем права пользователя с помощью фильтров
сообщений
2.1. Ограничиваем права на уровне имени пользователя
2.2. Ограничиваем права на уровне чата -
Ограничиваем
права пользователя внутри кода методов
3.1. Ограничиваем права на уровне имени пользователя
3.2. Ограничиваем права на уровне чата - Заключение
Введение
Ваш бот может выполнять совершенно любые задачи, и автоматизировать как некоторые внутренние процессы, так и наладить коммуникации с клиентами.
Т.е. бот может использоваться в многопользовательском режиме. При этом, вам может понадобиться разграничить права на использование бота. Например, некоторые пользователи смогут использовать абсолютно все возможности бота, а некоторым вы предоставите ограниченные права.
Ограничить права можно не только на уровне пользователя, но и на уровне отдельных чатов.
Мы создадим простейшего бота, у которого в арсенале будет всего 2 метода:
-
say_hello
команда приветствия -
what_time
команда, по которой бот сообщает текущую дату и время
library(telegram.bot)# создаём экземпляр класса Updaterupdater <- Updater('ТОКЕН ВАШЕГО БОТА')# Пишем метод для приветсвия## команда приветствияsay_hello <- function(bot, update) { # Имя пользователя с которым надо поздароваться user_name <- update$message$from$first_name # Отправка сообщения bot$sendMessage(update$message$chat_id, text = paste0("Моё почтение, ", user_name, "!"), parse_mode = "Markdown", reply_to_message_id = update$message$message_id)}## команда по которой бот возвращает системную дату и времяwhat_time <- function(bot, update) { # Запрашиваем текущее время cur_time <- as.character(Sys.time()) # Отправка сообщения bot$sendMessage(update$message$chat_id, text = paste0("Текущее время, ", cur_time), parse_mode = "Markdown", reply_to_message_id = update$message$message_id)}# обработчикиh_hello <- CommandHandler('say_hello', say_hello)h_time <- CommandHandler('what_time', what_time)# добавляем обработчики в диспетчерupdater <- updater + h_hello + h_time# запускаем бота updater$start_polling()
Запустите приведённый выше пример кода, предварительно заменив 'ТОКЕН ВАШЕГО БОТА' на реальный токен, который вы получили при создании бота через BotFather (о создании бота я рассказывал в первой статье).
В статье мы разберёмся с тем, как разными способами, и на разных уровнях ограничить использование методов этого бота.
Ограничиваем права пользователя с помощью фильтров сообщений
Из предыдущих публикаций мы уже разобрались с тем, что такое фильтры сообщений. Но ранее мы использовали их в основном для, того, что бы вызывать какие-то методы бота через обычное сообщение, а не команду и для прослушиваний сообщений в определённом состоянии чата.
В этот раз мы научимся с помощью фильтров ограничивать возможности по использованию методов бота, на разных уровнях.
Ограничиваем права на уровне имени пользователя
Для создания собственных фильтров вам необходимо с помощью
функции BaseFilter()
добавить новый элемент в объект
MessageFilters
. Более подробно об этом я рассказывал
во второй статье из данной серии.
В анонимную функцию, которую вы прописываете внутри
BaseFilter()
передаётся всего один аргумент
message
. Это сообщение которое вы, или другой
пользователей отправляет боту, со всеми его метаданными. Данный
объект имеет следующую структуру:
$message_id[1] 1174$from$from$id[1] 194336771$from$is_bot[1] FALSE$from$first_name[1] "Alexey"$from$last_name[1] "Seleznev"$from$username[1] "AlexeySeleznev"$from$language_code[1] "ru"$chat$chat$id[1] 194336771$chat$first_name[1] "Alexey"$chat$last_name[1] "Seleznev"$chat$username[1] "AlexeySeleznev"$chat$type[1] "private"$date[1] 1601295189$text[1] "отправленный пользователем текст"$chat_id[1] 194336771$from_user[1] 194336771
Соответственно вы можете разделять права пользователей бота, и его методов используя любую, отправляемую с сообщением информацию. Для того, что бы ограничить круг пользователей которые могут использовать методы вашего бота достаточно создать фильтр:
## список пользователей, с полными правамиMessageFilters$admins <- BaseFilter( function(message) { # проверяем от кого отправлено сообщение message$from$username %in% c('AlexeySeleznev', 'user1', 'user2') })
Где c('AlexeySeleznev', 'user1', 'user2')
вектор, с
именами пользователей, которые могут использовать все функции бота.
Далее этот фильтр мы используем при создании обработчиков.
## фильтр для вызова команды say_helloMessageFilters$say_hello <- BaseFilter( function(message) { # проверяем от кого отправлено сообщение message$text == '/say_hallo' })## фильтр для вызова команды what_timeMessageFilters$what_time <- BaseFilter( function(message) { # проверяем от кого отправлено сообщение message$text == '/what_time' })# обработчикиh_hello <- MessageHandler(say_hello, MessageFilters$admins & MessageFilters$say_hello)h_time <- MessageHandler(what_time, MessageFilters$admins & MessageFilters$what_time)
Теперь нашего бота могут использовать пользователи с логинами AlexeySeleznev, user1, user2. На сообщения отправленные боту другими пользователями он никак не будет реагировать.
Изменённый код нашего бота на данный момент выглядит вот так:
library(telegram.bot)# создаём экземпляр класса Updaterupdater <- Updater('ТОКЕН ВАШЕГО БОТА')# Пишем метод для приветсвия## команда приветствияsay_hello <- function(bot, update) { # Имя пользователя с которым надо поздароваться user_name <- update$message$from$first_name # Отправка сообщения bot$sendMessage(update$message$chat_id, text = paste0("Моё почтение, ", user_name, "!"), parse_mode = "Markdown", reply_to_message_id = update$message$message_id)}## команда по которой бот возвращает системную дату и времяwhat_time <- function(bot, update) { # Запрашиваем текущее время cur_time <- as.character(Sys.time()) # Отправка сообщения bot$sendMessage(update$message$chat_id, text = paste0("Текущее время, ", cur_time), parse_mode = "Markdown", reply_to_message_id = update$message$message_id)}# фильтры## список пользователей, с полными правамиMessageFilters$admins <- BaseFilter( function(message) { # проверяем от кого отправлено сообщение message$from$username %in% c('AlexeySeleznev', 'user1', 'user2') })## фильтр для вызова команды say_helloMessageFilters$say_hello <- BaseFilter( function(message) { # проверяем от кого отправлено сообщение message$text == '/say_hallo' })## фильтр для вызова команды what_timeMessageFilters$what_time <- BaseFilter( function(message) { # проверяем от кого отправлено сообщение message$text == '/what_time' })# обработчикиh_hello <- MessageHandler(say_hello, MessageFilters$admins & MessageFilters$say_hello)h_time <- MessageHandler(what_time, MessageFilters$admins & MessageFilters$what_time)# добавляем обработчики в диспетчерupdater <- updater + h_hello + h_time# запускаем бота updater$start_polling()
Ограничиваем права на уровне чата
Тем же способом мы можем создать фильтр не только по списку пользователей, но и по конкретному чату. Для этого достаточно создать ещё один фильтр:
## список чатов в которых разрешено использовать ботаMessageFilters$chats <- BaseFilter( function(message) { # проверяем от кого отправлено сообщение message$chat_id %in% c(194336771, 0, 1) })## фильтр для вызова команды say_helloMessageFilters$say_hello <- BaseFilter( function(message) { # проверяем от кого отправлено сообщение message$text == '/say_hallo' })## фильтр для вызова команды what_timeMessageFilters$what_time <- BaseFilter( function(message) { # проверяем от кого отправлено сообщение message$text == '/what_time' })# обработчикиh_hello <- MessageHandler(say_hello, MessageFilters$admins & MessageFilters$chats & MessageFilters$say_hello)h_time <- MessageHandler(what_time, MessageFilters$admins & MessageFilters$chats & MessageFilters$what_time)
Ограничиваем права пользователя внутри кода методов
Так же вы можете ограничить использование методов не прибегая к созданию дополнительных фильтров, а прописав все условия внутри каждого метода.
Ограничиваем права на уровне имени пользователя
Давайте создадим функцию, которая будет принимать данные для проверки имени пользователя.
# функция для проверки прав пользователяbot_check_usernames <- function(admins, username) { username %in% admins }
В аргумент admins
далее нам надо передавать список
пользователей, которым разрешено использовать данный метод, а в
аргумент username
имя пользователя, которого надо
проверить в списке.
Далее в каждый метод, который мы хотим защитить с помощью
конструкции IF
добавляем проверку, разрешено
пользователю использовать данный метод или нет. В случае если у
пользователя нет таких прав бот будет сообщать об этом в чате.
Давайте, для примера, я исключу себя из списка пользователей,
которым разрешено использовать метод what_time
.
library(telegram.bot)# создаём экземпляр класса Updaterupdater <- Updater('ТОКЕН ВАШЕГО БОТА')# Пишем метод для приветсвия## команда приветствияsay_hello <- function(bot, update) { # Имя пользователя с которым надо поздароваться user_name <- update$message$from$username # проверяем разрешено ли использовать данному пользователю этот метод if ( bot_check_usernames(c('AlexeySeleznev', 'user1', 'user2'), user_name) ) { # Отправка сообщения bot$sendMessage(update$message$chat_id, text = paste0("Моё почтение, ", user_name, "!"), parse_mode = "Markdown", reply_to_message_id = update$message$message_id) } else { # Отправка сообщения bot$sendMessage(update$message$chat_id, text = paste0("У вас нет прав для использования этого метода!"), parse_mode = "Markdown", reply_to_message_id = update$message$message_id) }}## команда по которой бот возвращает системную дату и времяwhat_time <- function(bot, update) { # проверяем разрешено ли использовать данному пользователю этот метод if ( bot_check_usernames(c('user1', 'user2'), update$message$from$username) ) { # Запрашиваем текущее время cur_time <- as.character(Sys.time()) # Отправка сообщения о том что у пользователя не достаточно прав bot$sendMessage(update$message$chat_id, text = paste0("Текущее время, ", cur_time), parse_mode = "Markdown", reply_to_message_id = update$message$message_id) } else { # Отправка сообщения о том что у пользователя не достаточно прав bot$sendMessage(update$message$chat_id, text = paste0("У вас нет прав для использования этого метода!"), parse_mode = "Markdown", reply_to_message_id = update$message$message_id) }}# обработчикиh_hello <- CommandHandler('say_hello', say_hello)h_time <- CommandHandler('what_time', what_time)# добавляем обработчики в диспетчерupdater <- updater + h_hello + h_time# запускаем бота updater$start_polling()
Результат будет следующим:
Теперь бот не просто игнорирует сообщения от обычных пользователей, а сообщает им, что у них недостаточно прав использовать какой либо метод.
Ограничиваем права на уровне чата
Думаю у вас уже не возникнет трудностей при доработке ваших методов, таким образом, что бы их можно было использовать только в определённых чатах, тем не менее приведу пример.
Напишем функцию, которая будет проверять входит ли текущий чат в список разрешенных.
bot_check_chat_id <- function(allowed_chats, current_chat) { current_chat %in% allowed_chats }
Далее используем эту функции внутри наших методов:
library(telegram.bot)# создаём экземпляр класса Updaterupdater <- Updater('ТОКЕН ВАШЕГО БОТА')# Пишем метод для приветсвия## команда приветствияsay_hello <- function(bot, update) { # Имя пользователя с которым надо поздароваться user_name <- update$message$from$username # проверяем разрешено ли использовать данному пользователю этот метод if ( bot_check_usernames(c('AlexeySeleznev', 'user1', 'user2'), user_name) & bot_check_chat_id(c(194336771, 1, 2), update$message$chat_id)) { # Отправка сообщения bot$sendMessage(update$message$chat_id, text = paste0("Моё почтение, ", user_name, "!"), parse_mode = "Markdown", reply_to_message_id = update$message$message_id) } else { # Отправка сообщения bot$sendMessage(update$message$chat_id, text = paste0("У вас нет прав для использования этого метода!"), parse_mode = "Markdown", reply_to_message_id = update$message$message_id) }}## команда по которой бот возвращает системную дату и времяwhat_time <- function(bot, update) { # проверяем разрешено ли использовать данному пользователю этот метод if ( bot_check_usernames(c('AlexeySeleznev', 'user1', 'user2'), update$message$from$username) & bot_check_chat_id(c(194336771, 1, 2), update$message$chat_id)) { # Запрашиваем текущее время cur_time <- as.character(Sys.time()) # Отправка сообщения о том что у пользователя не достаточно прав bot$sendMessage(update$message$chat_id, text = paste0("Текущее время, ", cur_time), parse_mode = "Markdown", reply_to_message_id = update$message$message_id) } else { # Отправка сообщения о том что у пользователя не достаточно прав bot$sendMessage(update$message$chat_id, text = paste0("У вас нет прав для использования этого метода!"), parse_mode = "Markdown", reply_to_message_id = update$message$message_id) }}# обработчикиh_hello <- CommandHandler('say_hello', say_hello)h_time <- CommandHandler('what_time', what_time)# добавляем обработчики в диспетчерupdater <- updater + h_hello + h_time# запускаем бота updater$start_polling()
Заключение
На этом серия статей о построении telegram ботов завершается. Я старался структурировать и подавать материал достаточно сжато, убрав всю воду, но при этом сделать так, что бы материал был вам понятен. Очень надеюсь на то, что мне это удалось.
Успехов вам в ботостроении. В комментариях можете написать примеры ваших ботов, и как вы их на практике используете.