From f06a1d72780a8d038e0867b67008385de9dfc45c Mon Sep 17 00:00:00 2001 From: RogueException Date: Tue, 10 Nov 2015 15:37:32 -0400 Subject: [PATCH] Added support for custom errors from permission checkers --- src/Discord.Net.Commands/Command.cs | 5 ++- src/Discord.Net.Commands/CommandMap.cs | 13 ++++--- src/Discord.Net.Commands/CommandService.cs | 37 ++++++++++++------- .../Permissions/IPermissionChecker.cs | 2 +- .../Levels/PermissionLevelChecker.cs | 3 +- .../Permissions/Userlist/BlacklistChecker.cs | 3 +- .../Permissions/Userlist/WhitelistChecker.cs | 3 +- src/Discord.Net.Modules/ModuleChecker.cs | 13 ++++++- 8 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/Discord.Net.Commands/Command.cs b/src/Discord.Net.Commands/Command.cs index 777a8424d..81bce6a47 100644 --- a/src/Discord.Net.Commands/Command.cs +++ b/src/Discord.Net.Commands/Command.cs @@ -95,13 +95,14 @@ namespace Discord.Commands _checks = checks; } - internal bool CanRun(User user, Channel channel) + internal bool CanRun(User user, Channel channel, out string error) { for (int i = 0; i < _checks.Length; i++) { - if (!_checks[i].CanRun(this, user, channel)) + if (!_checks[i].CanRun(this, user, channel, out error)) return false; } + error = null; return true; } diff --git a/src/Discord.Net.Commands/CommandMap.cs b/src/Discord.Net.Commands/CommandMap.cs index 76dbd95d3..dab55d600 100644 --- a/src/Discord.Net.Commands/CommandMap.cs +++ b/src/Discord.Net.Commands/CommandMap.cs @@ -106,25 +106,26 @@ namespace Discord.Commands _commands.Add(command); } - public bool CanRun(User user, Channel channel) + public bool CanRun(User user, Channel channel, out string error) { if (_commands.Count > 0) { foreach (var cmd in _commands) { - if (cmd.CanRun(user, channel)) - return true; + if (!cmd.CanRun(user, channel, out error)) + return false; } } if (_items.Count > 0) { foreach (var item in _items) { - if (item.Value.CanRun(user, channel)) - return true; + if (!item.Value.CanRun(user, channel, out error)) + return false; } } - return false; + error = null; + return true; } } } diff --git a/src/Discord.Net.Commands/CommandService.cs b/src/Discord.Net.Commands/CommandService.cs index 4340e27a4..dfef9b401 100644 --- a/src/Discord.Net.Commands/CommandService.cs +++ b/src/Discord.Net.Commands/CommandService.cs @@ -9,7 +9,9 @@ namespace Discord.Commands /// A Discord.Net client with extensions for handling common bot operations like text commands. public partial class CommandService : IService { - private readonly CommandServiceConfig _config; + private const string DefaultPermissionError = "You do not have permission to access this command."; + + private readonly CommandServiceConfig _config; private readonly CommandGroupBuilder _root; private DiscordClient _client; @@ -119,9 +121,10 @@ After: var eventArgs = new CommandEventArgs(e.Message, command, args); // Check permissions - if (!command.CanRun(eventArgs.User, eventArgs.Channel)) + string errorText; + if (!command.CanRun(eventArgs.User, eventArgs.Channel, out errorText)) { - RaiseCommandError(CommandErrorType.BadPermissions, eventArgs); + RaiseCommandError(CommandErrorType.BadPermissions, eventArgs, new Exception(errorText ?? DefaultPermissionError)); return; } @@ -162,7 +165,8 @@ After: bool isFirstItem = true; foreach (var group in category.Value.SubGroups) { - if (!group.IsHidden && group.CanRun(user, channel)) + string error; + if (!group.IsHidden && group.CanRun(user, channel, out error)) { if (isFirstItem) { @@ -221,15 +225,21 @@ After: IEnumerable cmds = map.Commands; bool isFirstCmd = true; + string error; if (cmds != null) { foreach (var cmd in cmds) { - if (isFirstCmd) - isFirstCmd = false; - /*else - output.AppendLine();*/ - ShowCommandHelpInternal(cmd, user, channel, output); + if (!cmd.CanRun(user, channel, out error)) { } + //output.AppendLine(error ?? DefaultPermissionError); + else + { + if (isFirstCmd) + isFirstCmd = false; + else + output.AppendLine(); + ShowCommandHelpInternal(cmd, user, channel, output); + } } } else @@ -240,7 +250,7 @@ After: } bool isFirstSubCmd = true; - foreach (var subCmd in map.SubGroups.Where(x => x.CanRun(user, channel) && !x.IsHidden)) + foreach (var subCmd in map.SubGroups.Where(x => x.CanRun(user, channel, out error) && !x.IsHidden)) { if (isFirstSubCmd) { @@ -259,7 +269,7 @@ After: if (isFirstCmd && isFirstSubCmd) //Had no commands and no subcommands { output.Clear(); - output.AppendLine("You do not have permission to access this command."); + output.AppendLine("There are no commands you have permission to run."); } return _client.SendMessage(replyChannel ?? channel, output.ToString()); @@ -267,8 +277,9 @@ After: public Task ShowCommandHelp(Command command, User user, Channel channel, Channel replyChannel = null) { StringBuilder output = new StringBuilder(); - if (!command.CanRun(user, channel)) - output.AppendLine("You do not have permission to access this command."); + string error; + if (!command.CanRun(user, channel, out error)) + output.AppendLine(error ?? DefaultPermissionError); else ShowCommandHelpInternal(command, user, channel, output); return _client.SendMessage(replyChannel ?? channel, output.ToString()); diff --git a/src/Discord.Net.Commands/Permissions/IPermissionChecker.cs b/src/Discord.Net.Commands/Permissions/IPermissionChecker.cs index 6df6c6ea0..f400c3420 100644 --- a/src/Discord.Net.Commands/Permissions/IPermissionChecker.cs +++ b/src/Discord.Net.Commands/Permissions/IPermissionChecker.cs @@ -2,6 +2,6 @@ { public interface IPermissionChecker { - bool CanRun(Command command, User user, Channel channel); + bool CanRun(Command command, User user, Channel channel, out string error); } } diff --git a/src/Discord.Net.Commands/Permissions/Levels/PermissionLevelChecker.cs b/src/Discord.Net.Commands/Permissions/Levels/PermissionLevelChecker.cs index f64cc37a0..0092c4edf 100644 --- a/src/Discord.Net.Commands/Permissions/Levels/PermissionLevelChecker.cs +++ b/src/Discord.Net.Commands/Permissions/Levels/PermissionLevelChecker.cs @@ -14,8 +14,9 @@ _minPermissions = minPermissions; } - public bool CanRun(Command command, User user, Channel channel) + public bool CanRun(Command command, User user, Channel channel, out string error) { + error = null; //Use default error text. int permissions = _service.GetPermissionLevel(user, channel); return permissions >= _minPermissions; } diff --git a/src/Discord.Net.Commands/Permissions/Userlist/BlacklistChecker.cs b/src/Discord.Net.Commands/Permissions/Userlist/BlacklistChecker.cs index 6a4133ccc..23c48cba9 100644 --- a/src/Discord.Net.Commands/Permissions/Userlist/BlacklistChecker.cs +++ b/src/Discord.Net.Commands/Permissions/Userlist/BlacklistChecker.cs @@ -9,8 +9,9 @@ _service = client.GetService(true); } - public bool CanRun(Command command, User user, Channel channel) + public bool CanRun(Command command, User user, Channel channel, out string error) { + error = null; //Use default error text. return _service.CanRun(user); } } diff --git a/src/Discord.Net.Commands/Permissions/Userlist/WhitelistChecker.cs b/src/Discord.Net.Commands/Permissions/Userlist/WhitelistChecker.cs index e6a8ddc5f..fa441644f 100644 --- a/src/Discord.Net.Commands/Permissions/Userlist/WhitelistChecker.cs +++ b/src/Discord.Net.Commands/Permissions/Userlist/WhitelistChecker.cs @@ -9,8 +9,9 @@ _service = client.GetService(true); } - public bool CanRun(Command command, User user, Channel channel) + public bool CanRun(Command command, User user, Channel channel, out string error) { + error = null; //Use default error text. return _service.CanRun(user); } } diff --git a/src/Discord.Net.Modules/ModuleChecker.cs b/src/Discord.Net.Modules/ModuleChecker.cs index 98bcf5b05..dfc7970d1 100644 --- a/src/Discord.Net.Modules/ModuleChecker.cs +++ b/src/Discord.Net.Modules/ModuleChecker.cs @@ -14,9 +14,18 @@ namespace Discord.Modules _filterType = manager.FilterType; } - public bool CanRun(Command command, User user, Channel channel) + public bool CanRun(Command command, User user, Channel channel, out string error) { - return _filterType == FilterType.Unrestricted || _filterType == FilterType.AllowPrivate || _manager.HasChannel(channel); + if (_filterType == FilterType.Unrestricted || _filterType == FilterType.AllowPrivate || _manager.HasChannel(channel)) + { + error = null; + return true; + } + else + { + error = "This module is currently disabled."; + return false; + } } } }