【问题标题】:How do I make a discord bot respond only to people with a certain role? [C#]如何让 Discord 机器人只响应具有特定角色的人? [C#]
【发布时间】:2019-08-26 16:39:23
【问题描述】:

我想让我的不和谐机器人只响应具有@Member 角色的人,所以当没有该角色的人写命令(例如>say Hello)时,机器人不会响应它,但是当一个人@Member 角色写道,它会。

【问题讨论】:

标签: c# discord discord.net


【解决方案1】:

理想情况下,如果这用于一个命令或更确切地说是多个命令,则应使用前置条件(例如管理命令)。这使您不必在每个命令中重复检查。

可以在here 找到此类前提条件的示例。 你可以阅读更多preconditions here

【讨论】:

    【解决方案2】:

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

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

    [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. 每次调用特定命令时都会自动调用CheckPermissionsAsync

    public async override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command)
    
    1. 从名称的上下文中获取实际的角色对象,遍历它们并检查用户是否具有该权限。第一次在用户上找到角色时,它将返回成功,并且将运行原始命令函数中的命令代码。如果返回 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
       }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-09-22
      • 2021-04-09
      • 1970-01-01
      • 2021-04-30
      • 2021-03-14
      • 2021-05-25
      • 2023-03-22
      • 2022-10-30
      • 2023-02-10
      相关资源
      最近更新 更多