В одной из предыдущих статей мы делали бота для конференций, добавили возможность кика, бана и мута пользователей. Сегодня мы продолжим эту тему, реализуем систему ролей для участников беседы и настроем права доступа для каждой из них.
Шаг 1: Введение
Как я уже сказал выше - в этот раз будем использовать уже имеющую базу для бота, о написании которой я рассказывал в этой статье. Далее речь пойдёт исключительно о системе ролей: сделаем возможность добавления и удаления ролей, изменения прав доступа ролей, а также реализуем выдачу ролей юзерам.
Шаг 2: Новые таблички в БД
Пока у нас есть лишь одна таблица `black_list`, в которую записываются баны и муты участников. Однако для текущих планов и задач потребуется создать ещё две. Первая будет хранить в себе список ролей и их настройки, вторая - список пользователей с ролями.
Создаю первую таблицу roles с восьмью полями:
Вторая таблица members (4 поля):
Шаг 3: Время писать код
Итак, ищем строчку:
if ( $type == 'message_new' ) {
После неё нужно вставить запросы к базе данных, дабы получить инфу об участнике, который отправил мессагу, а также вытащить из БД права доступа его роли (если, конечно, она у него есть):
$row = $db->query( "SELECT * FROM `members` WHERE `vk_id` = ?i AND `conf_id` = ?i", $vk_id, $peer_id )->fetchAssoc();
$role = $db->query( "SELECT * FROM `roles` WHERE `id` = ?i", $row['role_id'] )->fetchAssoc();
Чуть ниже есть кусок кода, где мы проверяли, находится ли приглашённый пользователь в чёрном списке. Если находится - значит исключаем его. Теперь нам нужно добавить ещё одно условие: если у пользователя, который кого-то пригласил нет прав доступа на инвайты - значит приглашённого нужно кикнуть.
Ищем этот код:
if ( isset( $result['id'] ) and $result['id'] and $result['duration'] > time() ) // Проверяем, истёк ли срок наказания
{
$vk->request( 'messages.removeChatUser', [ 'chat_id' => $peer_id - 2000000000, 'member_id' => $data->object->action->member_id ] ); // Кикаем, если срок не истёк
$vk->sendMessage( $peer_id, 'Пользователь находится в чёрном списке беседы' ); // Уведомляем об этом участников беседы
}
И заменяем на:
if ( ( isset( $result['id'] ) and $result['id'] and $result['duration'] > time() ) or ( !$role['g_invite_users'] and !$vk->isAdmin( $vk_id, $peer_id ) ) )
{
$vk->request( 'messages.removeChatUser', [ 'chat_id' => $peer_id - 2000000000, 'member_id' => $data->object->action->member_id ] );
$vk->sendMessage( $peer_id, 'Вы не можете пригласить в беседу этого пользователя' );
}
Ранее блок с обработкой команд мы оборачивали в проверку на наличие админки в беседе (чтобы левые молодые люди не могли беспредельничать). Поскольку теперь права доступа будут зависеть от роли, то строку:
if ( $vk->isAdmin( $vk_id, $peer_id ) ) {
Заменим на:
if ( strpos( $message, '/' ) === 0 ) {
Это условие будет отсеивать все сообщения, которые не начинаются со слэша (то есть те, которые не являются командами). Это позволит скрипту не срабатывать на все подряд входящие.
Также ко всем командам (кик, мут, размут, бан, разбан) нужно дописать через оператор AND проверку на права доступа роли к действию:
and ( $role['ПРАВО_ДОСТУПА_ИЗ_БД'] or $vk->isAdmin( $vk_id, $peer_id ) )
Я решил разрешить использовать все команды тем, у кого есть системная админка в конфе. В принципе, это можно убрать при желании.
Ну, а теперь переходим к командам. И начну я с выдачи ролей (/выдатьроль). Команда будет иметь примерно такой вид: /выдатьроль *кому* *название роли*. Названия ролей, состоящие из нескольких слов, можно будет писать через нижнее подчёркивание (напомню, что все команды у нас разбиваются на массив через пробелы). То бишь, к примеру, как-то так: Старший_администратор, Создатель_беседы. С помощтю функции str_replce() нижние подчёркивании будут удаляться.
Код вставляем после остальных (уже написанных в прошлой статье) команд:
else if ( $message_data[0] == '/выдатьроль' and ( $role['g_give_roles'] or $vk->isAdmin( $vk_id, $peer_id ) ) )
{
$res = $db->query( "SELECT * FROM `members` WHERE `vk_id` = ?i", $user_info['id'] )->fetchAssoc();
if ( isset( $res['id'] ) and $res['id'] )
{
try
{
$res = $db->query( "SELECT * FROM `roles` WHERE `name` = '?s'", str_replace( '_', ' ', $message_data[2] ) )->fetchAssoc();
$db->query( "UPDATE `members` SET `role_id` = ?i WHERE `vk_id` = ?i", $res['id'], $user_info['id'] );
$vk->sendMessage( $peer_id, '@id' . $user_info['id'] . '(Пользователю) присвоена роль ' . $res['name'] );
}
catch ( \Krugozor\Database\MySqlException $e )
{
$vk->sendMessage( $peer_id, 'Ошибка' );
}
}
else
{
try
{
$res = $db->query( "SELECT * FROM `roles` WHERE `name` = '?s'", str_replace( '_', ' ', $message_data[2] ) )->fetchAssoc();
$db->query( "INSERT INTO `members` SET `vk_id` = ?i, `conf_id` = ?i, `role_id` = ?i", $user_info['id'], 2000000000 + $peer_id, $res['id'] );
$vk->sendMessage( $peer_id, '@id' . $user_info['id'] . '(Пользователю) выдана роль ' . $res['name'] );
}
catch ( \Krugozor\Database\MySqlException $e )
{
$vk->sendMessage( $peer_id, 'Ошибка' );
}
}
}
Для того, чтобы снять роль, можно будет юзать команду /снятьроль (/снятьроль *кому*). После этого пользователь удалится из таблицы members и останется без роли:
else if ( $message_data[0] == '/снятьроль' and ( $role['g_give_roles'] or $vk->isAdmin( $vk_id, $peer_id ) ) )
{
$db->query( "DELETE FROM `members` WHERE `vk_id` = ?i AND `conf_id` = ?i", $user_info['id'], $peer_id );
$vk->sendMessage( $peer_id, 'У @id' . $user_info['id'] . '(пользователя) изъята роль' );
}
Следующая команда понадобится для создания новых ролей и будет иметь вид: /создатьроль *название*:
else if ( $message_data[0] == '/создатьроль' and ( $role['g_create_roles'] or $vk->isAdmin( $vk_id, $peer_id ) ) )
{
$name = str_replace( '_', ' ', $message_data[1] );
$res = $db->query( "SELECT `name` FROM `roles` WHERE `name` = '?s'", $name )->fetchAssoc();
if ( isset( $res['name'] ) )
{
$vk->sendMessage( $peer_id, 'Роль а таким названием уже существует, придумайте другое' );
}
else
{
$db->query( "INSERT INTO `roles` SET `name` = '?s'", $name );
$vk->sendMessage( $peer_id, 'Роль успешно создана' );
}
}
Для удаления ролей также создаю отдельную команду (/удалитьроль *кому*):
else if ( $message_data[0] == '/удалитьроль' and ( $role['g_create_roles'] or $vk->isAdmin( $vk_id, $peer_id ) ) )
{
try
{
$res = $db->query( "DELETE FROM `roles` WHERE `name` = '?s'", str_replace( '_', ' ', $message_data[1] ) );
$vk->sendMessage( $peer_id, 'Роль удалена' );
}
catch ( \Krugozor\Database\MySqlException $e )
{
$vk->sendMessage( $peer_id, 'Ошибка' );
}
}
И напоследок сделаю регулировку прав доступа. Команда будет иметь следующий вид: /правароли *название роли* *право доступа из БД* *значение 1 или 0 (разрешено или нет)*:
else if ( $message_data[0] == '/правароли' and ( $role['g_create_roles'] or $vk->isAdmin( $vk_id, $peer_id ) ) )
{
$role = str_replace( '_', ' ', $message_data[1] );
$type = $message_data[2];
$value = $message_data[3] ? 1 : 0;
try
{
$db->query( "UPDATE `roles` SET `$type` = ?i WHERE `name` = '?s'", $value, $role );
$vk->sendMessage( $peer_id, 'Права (' . $type . ') роли были изменены' );
}
catch ( \Krugozor\Database\MySqlException $e )
{
$vk->sendMessage( $peer_id, 'Произошла ошибка, убедитесь в правильности введённых данных' );
}
}
Шаг 4: Работает?
Проверяем - работает:
На этом, думаю, всё. Возможно, сделаю ещё одну часть.
Архив с исходниками прикрепляю:
Нашли ошибку?
Вы можете сообщить об этом администрации.
Выделив текст нажмите CTRL+Enter