如何使不和谐的机器人仅对具有特定角色的人做出反应? [C#]

时间:2019-04-04 20:09:41

标签: c# discord discord.net

我想让不和谐的机器人只对具有@Member角色的人做出响应,因此,当没有该角色的人写命令时(例如> say Hello),机器人将不响应它,但是当有人具有@Member角色的用户会这样写。

2 个答案:

答案 0 :(得分:0)

理想地,如果此命令用于一个命令或多个命令,则应使用前提条件(示例管理命令)。这使您不必在每个命令中重复检查。

此类前提条件的一个示例可以在here中找到。 您可以在preconditions here

上阅读更多内容

答案 1 :(得分:0)

您需要为每个命令添加角色验证。

快速简便的方法是执行以下操作:

[Command("test")]
public async Task TestCommand()
{
   var user as Context.User as IGuildUser;
   var roleToValidate = Context.Guild.Roles.First(r => r.Name == "SomeRoleName");

   if (!user.RoleIDs.Any(r => r == roleToValidate.Id))
      return;

   // the rest of the code
}

另一种方法(我建议)是使用PreconditionAttribute

/// CheckRole.cs

using Discord;
using Discord.Commands;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Example.Attributes
{
    public class CheckRole : PreconditionAttribute
    {
        private List<string> _roles;

        public CheckRole(params string[] roles)
        {
            _roles = roles.ToList();
        }

        public async override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command)
        {
            var user = context.User as IGuildUser;
            var discordRoles = context.Guild.Roles.Where(gr => _roles.Any(r => gr.Name == r));

            foreach (var role in discordRoles)
            {
                var userInRole = user.RoleIds.Any(ri => ri == role.Id);

                if (userInRole)
                {
                    return await Task.FromResult(PreconditionResult.FromSuccess());
                }
            }

            return await Task.FromResult(PreconditionResult.FromError("You do not have permission to use this role."));
        }
    }
}
/// WhateverClassThatYouWriteCommandsIn.cs 

[Command("test")]
[CheckRole("AdminRoleName", "ModeratorRole", "NormalRole")]
public async Task TestCommandForMostRoles()
{
   var user as Context.User as IGuildUser;
   var roleToValidate = Context.Guild.Roles.First(r => r.Name == "Some Role Name");

   if (!user.RoleIDs.Any(r => r == roleToValidate.Id))
      return;

   // the rest of the code
}

[Command("test")]
[CheckRole("AdminRoleName", "ModeratorRole")]
public async Task TestCommandForAdmins()
{
   var user as Context.User as IGuildUser;
   var roleToValidate = Context.Guild.Roles.First(r => r.Name == "Some Role Name");

   if (!user.RoleIDs.Any(r => r == roleToValidate.Id))
      return;

   // the rest of the code
}

此文字代码可能无法运行,因为我尚未对其进行测试,但是它基于我自己对角色前提条件授权的有效实现。

要分解代码:

  1. 我有一个变量来存储多个角色名称,并在构造函数中使用params []来允许提供任意数量的角色名称。它们存储在变量中。

    private List<string> _roles;
    
    public CheckRole(params string[] roles)
    {
        _roles = roles.ToList();
    }
    
  2. 每次调用特定命令时,都会自动调用
  3. CheckPermissionsAsync

public async override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command)
  1. 从名称中的上下文中获取实际的Role对象,对其进行循环,然后检查用户是否具有该权限。第一次在用户上找到角色时,它将返回成功,并且将运行原始命令功能中的命令代码。如果返回FromError,则命令代码不会运行。
var user = context.User as IGuildUser;
            var discordRoles = context.Guild.Roles.Where(gr => _roles.Any(r => gr.Name == r));

            foreach (var role in discordRoles)
            {
                var userInRole = user.RoleIds.Any(ri => ri == role.Id);

                if (userInRole)
                {
                    return await Task.FromResult(PreconditionResult.FromSuccess());
                }
            }

            return await Task.FromResult(PreconditionResult.FromError("You do not have permission to use this role."));

这似乎很多,但是您无需再次重新编写角色授权代码,您只需将此属性添加到所需的任何命令中即可。如果您希望该类中的每个命令都由角色授权,则也可以将此属性添加到类中:

[CheckRoles("Moderator", "LowLevelModerator")]
public class ModeratorCommands : ModuleBase<SocketCommandContext>
{
   [Command("CheckStats")]
   public async Task ModeratorCommandForCheckStats()
   {
      // the code
   }

   [Command("BanUser")]
   public async Task ModeratorCommandForBanUser()
   {
      // the code
   }

   [CheckRole("Admin")]
   [Command("BanUser")]
   public async Task ModeratorCommandOnlyForAdminsForBanModerator()
   {
      // the code
   }
}