Глава 5 Управление правами пользователей бота
В пятой главе нашего руководства мы сосредоточимся на управлении правами пользователей вашего Telegram-бота. Вы узнаете, как настраивать и контролировать доступ к различным функциям, чтобы сделать ваш бот более гибким и безопасным.
Мы изучим, как реализовать систему управления правами, которая позволит вам назначать разные уровни доступа для пользователей. Вы научитесь ограничивать или предоставлять доступ к определенным функциям в зависимости от их ролей, что поможет вам создать более структурированное и безопасное взаимодействие.
Эта глава предоставит вам инструменты для тонкой настройки доступа и управления пользователями, что сделает ваш бот более эффективным и удобным. Надеюсь, что эти знания помогут вам реализовать проект на новом уровне, обеспечивая лучшее взаимодействие с вашими пользователями.
5.1 Введение
Ваш бот может выполнять совершенно любые задачи, и автоматизировать как некоторые внутренние процессы, так и наладить коммуникации с клиентами.
Т.е. бот может использоваться в многопользовательском режиме. При этом, вам может понадобиться разграничить права на использование бота. Например, некоторые пользователи смогут использовать абсолютно все возможности бота, а некоторым вы предоставите ограниченные права.
Ограничить права можно не только на уровне пользователя, но и на уровне отдельных чатов.
Мы создадим простейшего бота, у которого в арсенале будет всего 2 метода:
-
say_hello
- команда приветствия -
what_time
- команда, по которой бот сообщает текущую дату и время
library(telegram.bot)
# создаём экземпляр класса Updater
updater <- Updater('ТОКЕН ВАШЕГО БОТА')
# Пишем метод для приветсвия
## команда приветствия
say_hello <- function(bot, update) {
# Имя пользователя с которым надо поздароваться
user_name <- update$effective_user()$first_name
# Отправка сообщения
bot$sendMessage(update$from_chat_id(),
text = paste0("Моё почтение, ", user_name, "!"),
parse_mode = "Markdown",
reply_to_message_id = update$effective_message()$message_id)
}
## команда по которой бот возвращает системную дату и время
what_time <- function(bot, update) {
# Запрашиваем текущее время
cur_time <- as.character(Sys.time())
# Отправка сообщения
bot$sendMessage(update$from_chat_id(),
text = paste0("Текущее время, ", cur_time),
parse_mode = "Markdown",
reply_to_message_id = update$effective_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 (о создании бота я рассказывал в первой статье).
В данной главе мы разберёмся с тем, как разными способами, и на разных уровнях ограничить использование методов этого бота.
5.2 Ограничиваем права пользователя с помощью фильтров сообщений
Из предыдущих публикаций мы уже разобрались с тем, что такое фильтры сообщений. Но ранее мы использовали их в основном для, того, что бы вызывать какие-то методы бота через обычное сообщение, а не команду и для прослушиваний сообщений в определённом состоянии чата.
В этот раз мы научимся с помощью фильтров ограничивать возможности по использованию методов бота, на разных уровнях.
5.2.1 Ограничиваем права на уровне имени пользователя
Для создания собственных фильтров вам необходимо с помощью функции 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
Более подробно описание ответа и всех его компонентов можно узнать из официальной документации:
- User - Этот объект представляет бота или пользователя Telegram.
- Chat - Этот объект представляет собой чат.
- Message - Этот объект представляет собой сообщение.
Соответственно вы можете разделять права пользователей бота, и его методов используя любую, отправляемую с сообщением информацию, т.е. любые элементы объекта message
. Для того, что бы ограничить круг пользователей которые могут использовать методы вашего бота достаточно создать фильтр:
## список пользователей, с полными правами
MessageFilters$admins <- BaseFilter(
function(message) {
# проверяем от кого отправлено сообщение
message$effective_user()$username %in% c('AlexeySeleznev', 'user1', 'user2')
}
)
Где c('AlexeySeleznev', 'user1', 'user2')
- вектор, с именами пользователей, которые могут использовать все функции бота. Далее этот фильтр мы используем при создании обработчиков.
## фильтр для вызова команды say_hello
MessageFilters$say_hello <- BaseFilter(
function(message) {
# проверяем от кого отправлено сообщение
message$text == '/say_hallo'
}
)
## фильтр для вызова команды what_time
MessageFilters$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)
# создаём экземпляр класса Updater
updater <- Updater('ТОКЕН ВАШЕГО БОТА')
# Пишем метод для приветсвия
## команда приветствия
say_hello <- function(bot, update) {
# Имя пользователя с которым надо поздароваться
user_name <- update$effective_user()$first_name
# Отправка сообщения
bot$sendMessage(update$from_chat_id(),
text = paste0("Моё почтение, ", user_name, "!"),
parse_mode = "Markdown",
reply_to_message_id = update$effective_message()$message_id)
}
## команда по которой бот возвращает системную дату и время
what_time <- function(bot, update) {
# Запрашиваем текущее время
cur_time <- as.character(Sys.time())
# Отправка сообщения
bot$sendMessage(update$from_chat_id(),
text = paste0("Текущее время, ", cur_time),
parse_mode = "Markdown",
reply_to_message_id = update$effective_message()$message_id)
}
# фильтры
## список пользователей, с полными правами
MessageFilters$admins <- BaseFilter(
function(message) {
# проверяем от кого отправлено сообщение
message$from$username %in% c('AlexeySeleznev', 'user1', 'user2')
}
)
## фильтр для вызова команды say_hello
MessageFilters$say_hello <- BaseFilter(
function(message) {
# проверяем от кого отправлено сообщение
message$text == '/say_hallo'
}
)
## фильтр для вызова команды what_time
MessageFilters$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()
5.2.2 Ограничиваем права на уровне чата
Тем же способом мы можем создать фильтр не только по списку пользователей, но и по конкретному чату. Для этого достаточно создать ещё один фильтр:
## список чатов в которых разрешено использовать бота
MessageFilters$chats <- BaseFilter(
function(message) {
# проверяем от кого отправлено сообщение
message$chat_id %in% c(194336771, 0, 1)
}
)
## фильтр для вызова команды say_hello
MessageFilters$say_hello <- BaseFilter(
function(message) {
# проверяем от кого отправлено сообщение
message$text == '/say_hallo'
}
)
## фильтр для вызова команды what_time
MessageFilters$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)
5.3 Ограничиваем права пользователя внутри кода методов
Так же вы можете ограничить использование методов не прибегая к созданию дополнительных фильтров, а прописав все условия внутри каждого метода.
5.3.1 Ограничиваем права на уровне имени пользователя
Давайте создадим функцию, которая будет принимать данные для проверки имени пользователя.
# функция для проверки прав пользователя
bot_check_usernames <-
function(admins, username) {
username %in% admins
}
В аргумент admins
далее нам надо передавать список пользователей, которым разрешено использовать данный метод, а в аргумент username
имя пользователя, которого надо проверить в списке.
Далее в каждый метод, который мы хотим защитить с помощью конструкции IF
добавляем проверку, разрешено пользователю использовать данный метод или нет. В случае если у пользователя нет таких прав бот будет сообщать об этом в чате.
Давайте, для примера, я исключу себя из списка пользователей, которым разрешено использовать метод what_time
.
library(telegram.bot)
# создаём экземпляр класса Updater
updater <- Updater('ТОКЕН ВАШЕГО БОТА')
# Пишем метод для приветсвия
## команда приветствия
say_hello <- function(bot, update) {
# Имя пользователя с которым надо поздароваться
user_name <- update$effective_user()$username
# проверяем разрешено ли использовать данному пользователю этот метод
if ( bot_check_usernames(c('AlexeySeleznev', 'user1', 'user2'), user_name) ) {
# Отправка сообщения
bot$sendMessage(update$from_chat_id(),
text = paste0("Моё почтение, ", user_name, "!"),
parse_mode = "Markdown",
reply_to_message_id = update$effective_message()$message_id)
} else {
# Отправка сообщения
bot$sendMessage(update$from_chat_id(),
text = paste0("У вас нет прав для использования этого метода!"),
parse_mode = "Markdown",
reply_to_message_id = update$effective_message()$message_id)
}
}
## команда по которой бот возвращает системную дату и время
what_time <- function(bot, update) {
# проверяем разрешено ли использовать данному пользователю этот метод
if ( bot_check_usernames(c('user1', 'user2'), update$effective_user()$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$effective_message()$message_id)
} else {
# Отправка сообщения о том что у пользователя не достаточно прав
bot$sendMessage(update$message$chat_id,
text = paste0("У вас нет прав для использования этого метода!"),
parse_mode = "Markdown",
reply_to_message_id = update$effective_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()
Результат будет следующим:
Теперь бот не просто игнорирует сообщения от обычных пользователей, а сообщает им, что у них недостаточно прав использовать какой либо метод.
5.3.2 Ограничиваем права на уровне чата
Думаю у вас уже не возникнет трудностей при доработке ваших методов, таким образом, что бы их можно было использовать только в определённых чатах, тем не менее приведу пример.
Напишем функцию, которая будет проверять входит ли текущий чат в список разрешенных.
bot_check_chat_id <-
function(allowed_chats, current_chat) {
current_chat %in% allowed_chats
}
Далее используем эту функции внутри наших методов:
library(telegram.bot)
# создаём экземпляр класса Updater
updater <- 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$from_chat_id())) {
# Отправка сообщения
bot$sendMessage(update$from_chat_id(),
text = paste0("Моё почтение, ", user_name, "!"),
parse_mode = "Markdown",
reply_to_message_id = update$effective_message()$message_id)
} else {
# Отправка сообщения
bot$sendMessage(update$from_chat_id(),
text = paste0("У вас нет прав для использования этого метода!"),
parse_mode = "Markdown",
reply_to_message_id = update$effective_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$from_chat_id(),
text = paste0("Текущее время, ", cur_time),
parse_mode = "Markdown",
reply_to_message_id = update$effective_message()$message_id)
} else {
# Отправка сообщения о том что у пользователя не достаточно прав
bot$sendMessage(update$from_chat_id(),
text = paste0("У вас нет прав для использования этого метода!"),
parse_mode = "Markdown",
reply_to_message_id = update$effective_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()
5.4 Заключение
Вы успешно освоили управление правами пользователей, что значительно расширяет возможности вашего бота. В следующей главе мы сосредоточимся на повышении стабильности работы бота, что поможет вам обеспечить надежность и эффективность его работы в различных условиях и нагрузках.
Успехов вам в ботостроении. В комментариях можете написать примеры ваших ботов, и как вы их на практике используете.