Added new permissions system, fixed more commands and module bugs.
This commit is contained in:
@@ -61,6 +61,39 @@
|
||||
<Compile Include="..\Discord.Net.Commands\CommandServiceConfig.cs">
|
||||
<Link>CommandServiceConfig.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\IPermissionChecker.cs">
|
||||
<Link>Permissions\IPermissionChecker.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Levels\PermissionLevelChecker.cs">
|
||||
<Link>Permissions\Levels\PermissionLevelChecker.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Levels\PermissionLevelExtensions.cs">
|
||||
<Link>Permissions\Levels\PermissionLevelExtensions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Levels\PermissionLevelService.cs">
|
||||
<Link>Permissions\Levels\PermissionLevelService.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Userlist\BlacklistChecker.cs">
|
||||
<Link>Permissions\Userlist\BlacklistChecker.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Userlist\BlacklistExtensions.cs">
|
||||
<Link>Permissions\Userlist\BlacklistExtensions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Userlist\BlacklistService.cs">
|
||||
<Link>Permissions\Userlist\BlacklistService.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Userlist\UserlistService.cs">
|
||||
<Link>Permissions\Userlist\UserlistService.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Userlist\WhitelistChecker.cs">
|
||||
<Link>Permissions\Userlist\WhitelistChecker.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Userlist\WhitelistExtensions.cs">
|
||||
<Link>Permissions\Userlist\WhitelistExtensions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Commands\Permissions\Userlist\WhitelistService.cs">
|
||||
<Link>Permissions\Userlist\WhitelistService.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Discord.Commands.Permissions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -41,8 +42,9 @@ namespace Discord.Commands
|
||||
|
||||
public IEnumerable<CommandParameter> Parameters => _parameters;
|
||||
internal CommandParameter[] _parameters;
|
||||
|
||||
private Func<CommandEventArgs, Task> _handler;
|
||||
|
||||
private IPermissionChecker[] _checks;
|
||||
private Func<CommandEventArgs, Task> _runFunc;
|
||||
|
||||
internal Command(string text)
|
||||
{
|
||||
@@ -56,7 +58,6 @@ namespace Discord.Commands
|
||||
{
|
||||
_aliases = aliases;
|
||||
}
|
||||
|
||||
internal void SetParameters(CommandParameter[] parameters)
|
||||
{
|
||||
_parameters = parameters;
|
||||
@@ -89,24 +90,32 @@ namespace Discord.Commands
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetHandler(Func<CommandEventArgs, Task> func)
|
||||
internal void SetChecks(IPermissionChecker[] checks)
|
||||
{
|
||||
_handler = func;
|
||||
}
|
||||
internal void SetHandler(Action<CommandEventArgs> func)
|
||||
{
|
||||
_handler = e => { func(e); return TaskHelper.CompletedTask; };
|
||||
_checks = checks;
|
||||
}
|
||||
|
||||
internal bool CanRun(User user, Channel channel)
|
||||
{
|
||||
for (int i = 0; i < _checks.Length; i++)
|
||||
{
|
||||
if (!_checks[i].CanRun(this, user, channel))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void SetRunFunc(Func<CommandEventArgs, Task> func)
|
||||
{
|
||||
_runFunc = func;
|
||||
}
|
||||
internal void SetRunFunc(Action<CommandEventArgs> func)
|
||||
{
|
||||
_runFunc = e => { func(e); return TaskHelper.CompletedTask; };
|
||||
}
|
||||
internal Task Run(CommandEventArgs args)
|
||||
{
|
||||
var task = _handler(args);
|
||||
var task = _runFunc(args);
|
||||
if (task != null)
|
||||
return task;
|
||||
else
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Discord.Commands.Permissions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -9,19 +10,27 @@ namespace Discord.Commands
|
||||
{
|
||||
private readonly CommandService _service;
|
||||
private readonly Command _command;
|
||||
private List<CommandParameter> _params;
|
||||
private bool _allowRequired, _isClosed;
|
||||
private string _prefix;
|
||||
private readonly List<CommandParameter> _params;
|
||||
private readonly List<IPermissionChecker> _checks;
|
||||
private readonly string _prefix;
|
||||
private bool _allowRequiredParams, _areParamsClosed;
|
||||
|
||||
internal CommandBuilder(CommandService service, Command command, string prefix, string category)
|
||||
public CommandService Service => _service;
|
||||
|
||||
internal CommandBuilder(CommandService service, Command command, string prefix = "", string category = "", IEnumerable<IPermissionChecker> initialChecks = null)
|
||||
{
|
||||
_service = service;
|
||||
_command = command;
|
||||
_command.Category = category;
|
||||
_params = new List<CommandParameter>();
|
||||
if (initialChecks != null)
|
||||
_checks = new List<IPermissionChecker>(initialChecks);
|
||||
else
|
||||
_checks = new List<IPermissionChecker>();
|
||||
_prefix = prefix;
|
||||
_allowRequired = true;
|
||||
_isClosed = false;
|
||||
|
||||
_allowRequiredParams = true;
|
||||
_areParamsClosed = false;
|
||||
}
|
||||
|
||||
public CommandBuilder Alias(params string[] aliases)
|
||||
@@ -35,24 +44,24 @@ namespace Discord.Commands
|
||||
_command.Category = category;
|
||||
return this;
|
||||
}*/
|
||||
public CommandBuilder Info(string description)
|
||||
public CommandBuilder Description(string description)
|
||||
{
|
||||
_command.Description = description;
|
||||
return this;
|
||||
}
|
||||
public CommandBuilder Parameter(string name, ParameterType type = ParameterType.Required)
|
||||
{
|
||||
if (_isClosed)
|
||||
if (_areParamsClosed)
|
||||
throw new Exception($"No parameters may be added after a {nameof(ParameterType.Multiple)} or {nameof(ParameterType.Unparsed)} parameter.");
|
||||
if (!_allowRequired && type == ParameterType.Required)
|
||||
if (!_allowRequiredParams && type == ParameterType.Required)
|
||||
throw new Exception($"{nameof(ParameterType.Required)} parameters may not be added after an optional one");
|
||||
|
||||
_params.Add(new CommandParameter(name, type));
|
||||
|
||||
if (type == ParameterType.Optional)
|
||||
_allowRequired = false;
|
||||
_allowRequiredParams = false;
|
||||
if (type == ParameterType.Multiple || type == ParameterType.Unparsed)
|
||||
_isClosed = true;
|
||||
_areParamsClosed = true;
|
||||
return this;
|
||||
}
|
||||
public CommandBuilder Hide()
|
||||
@@ -60,20 +69,26 @@ namespace Discord.Commands
|
||||
_command.IsHidden = true;
|
||||
return this;
|
||||
}
|
||||
public CommandBuilder AddCheck(IPermissionChecker check)
|
||||
{
|
||||
_checks.Add(check);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Do(Func<CommandEventArgs, Task> func)
|
||||
{
|
||||
_command.SetHandler(func);
|
||||
_command.SetRunFunc(func);
|
||||
Build();
|
||||
}
|
||||
public void Do(Action<CommandEventArgs> func)
|
||||
{
|
||||
_command.SetHandler(func);
|
||||
_command.SetRunFunc(func);
|
||||
Build();
|
||||
}
|
||||
private void Build()
|
||||
{
|
||||
_command.SetParameters(_params.ToArray());
|
||||
_command.SetChecks(_checks.ToArray());
|
||||
_service.AddCommand(_command);
|
||||
}
|
||||
|
||||
@@ -97,14 +112,21 @@ namespace Discord.Commands
|
||||
}
|
||||
public sealed class CommandGroupBuilder
|
||||
{
|
||||
internal readonly CommandService _service;
|
||||
private readonly CommandService _service;
|
||||
private readonly string _prefix;
|
||||
private readonly List<IPermissionChecker> _checks;
|
||||
private string _category;
|
||||
|
||||
internal CommandGroupBuilder(CommandService service, string prefix)
|
||||
public CommandService Service => _service;
|
||||
|
||||
internal CommandGroupBuilder(CommandService service, string prefix, IEnumerable<IPermissionChecker> initialChecks = null)
|
||||
{
|
||||
_service = service;
|
||||
_prefix = prefix;
|
||||
if (initialChecks != null)
|
||||
_checks = new List<IPermissionChecker>(initialChecks);
|
||||
else
|
||||
_checks = new List<IPermissionChecker>();
|
||||
}
|
||||
|
||||
public CommandGroupBuilder Category(string category)
|
||||
@@ -112,10 +134,14 @@ namespace Discord.Commands
|
||||
_category = category;
|
||||
return this;
|
||||
}
|
||||
public void AddCheck(IPermissionChecker check)
|
||||
{
|
||||
_checks.Add(check);
|
||||
}
|
||||
|
||||
public CommandGroupBuilder CreateGroup(string cmd, Action<CommandGroupBuilder> config = null)
|
||||
{
|
||||
config(new CommandGroupBuilder(_service, _prefix + ' ' + cmd));
|
||||
{
|
||||
config(new CommandGroupBuilder(_service, CommandBuilder.AppendPrefix(_prefix, cmd), _checks));
|
||||
return this;
|
||||
}
|
||||
public CommandBuilder CreateCommand()
|
||||
@@ -123,7 +149,7 @@ namespace Discord.Commands
|
||||
public CommandBuilder CreateCommand(string cmd)
|
||||
{
|
||||
var command = new Command(CommandBuilder.AppendPrefix(_prefix, cmd));
|
||||
return new CommandBuilder(_service, command, _prefix, _category);
|
||||
return new CommandBuilder(_service, command, _prefix, _category, _checks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,24 +7,26 @@ namespace Discord.Commands
|
||||
internal class CommandMap
|
||||
{
|
||||
private readonly CommandMap _parent;
|
||||
private readonly string _text;
|
||||
private readonly string _name, _fullName;
|
||||
|
||||
private Command _command;
|
||||
private readonly Dictionary<string, CommandMap> _items;
|
||||
private bool _isHidden;
|
||||
|
||||
public string Text => _text;
|
||||
public string Name => _name;
|
||||
public string FullName => _fullName;
|
||||
public bool IsHidden => _isHidden;
|
||||
public Command Command => _command;
|
||||
public IEnumerable<CommandMap> SubGroups => _items.Values;
|
||||
/*public IEnumerable<Command> SubCommands => _items.Select(x => x.Value._command).Where(x => x != null);
|
||||
public IEnumerable<CommandMap> SubGroups => _items.Select(x => x.Value).Where(x => x._items.Count > 0);*/
|
||||
|
||||
public CommandMap(CommandMap parent, string text)
|
||||
public CommandMap(CommandMap parent, string name, string fullName)
|
||||
{
|
||||
_parent = parent;
|
||||
_text = text;
|
||||
_items = new Dictionary<string, CommandMap>();
|
||||
_name = name;
|
||||
_fullName = fullName;
|
||||
_items = new Dictionary<string, CommandMap>();
|
||||
_isHidden = true;
|
||||
}
|
||||
|
||||
@@ -82,19 +84,20 @@ namespace Discord.Commands
|
||||
{
|
||||
AddCommand(0, text.Split(' '), command);
|
||||
}
|
||||
public void AddCommand(int index, string[] parts, Command command)
|
||||
private void AddCommand(int index, string[] parts, Command command)
|
||||
{
|
||||
if (!command.IsHidden && _isHidden)
|
||||
_isHidden = false;
|
||||
|
||||
if (index != parts.Length)
|
||||
{
|
||||
string nextPart = parts[index];
|
||||
CommandMap nextGroup;
|
||||
if (!_items.TryGetValue(nextPart, out nextGroup))
|
||||
string name = parts[index];
|
||||
string fullName = string.Join(" ", parts, 0, index + 1);
|
||||
if (!_items.TryGetValue(name, out nextGroup))
|
||||
{
|
||||
nextGroup = new CommandMap(this, nextPart);
|
||||
_items.Add(nextPart, nextGroup);
|
||||
nextGroup = new CommandMap(this, name, fullName);
|
||||
_items.Add(name, nextGroup);
|
||||
}
|
||||
nextGroup.AddCommand(index + 1, parts, command);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,12 @@ namespace Discord.Commands
|
||||
/// <summary> A Discord.Net client with extensions for handling common bot operations like text commands. </summary>
|
||||
public partial class CommandService : IService
|
||||
{
|
||||
private readonly CommandServiceConfig _config;
|
||||
private readonly CommandGroupBuilder _root;
|
||||
private DiscordClient _client;
|
||||
public CommandServiceConfig Config { get; }
|
||||
|
||||
public DiscordClient Client => _client;
|
||||
public CommandGroupBuilder Root => _root;
|
||||
|
||||
//AllCommands store a flattened collection of all commands
|
||||
public IEnumerable<Command> AllCommands => _allCommands;
|
||||
@@ -23,40 +27,47 @@ namespace Discord.Commands
|
||||
internal IEnumerable<CommandMap> Categories => _categories.Values;
|
||||
private readonly Dictionary<string, CommandMap> _categories;
|
||||
|
||||
|
||||
public CommandService(CommandServiceConfig config)
|
||||
{
|
||||
Config = config;
|
||||
_config = config;
|
||||
_allCommands = new List<Command>();
|
||||
_map = new CommandMap(null, null);
|
||||
_map = new CommandMap(null, "", "");
|
||||
_categories = new Dictionary<string, CommandMap>();
|
||||
}
|
||||
_root = new CommandGroupBuilder(this, "", null);
|
||||
}
|
||||
|
||||
void IService.Install(DiscordClient client)
|
||||
{
|
||||
_client = client;
|
||||
Config.Lock();
|
||||
_config.Lock();
|
||||
|
||||
if (Config.HelpMode != HelpMode.Disable)
|
||||
if (_config.HelpMode != HelpMode.Disable)
|
||||
{
|
||||
CreateCommand("help")
|
||||
CreateCommand("help")
|
||||
.Parameter("command", ParameterType.Multiple)
|
||||
.Hide()
|
||||
.Info("Returns information about commands.")
|
||||
.Do(async e =>
|
||||
.Description("Returns information about commands.")
|
||||
.Do((Func<CommandEventArgs, Task>)(async e =>
|
||||
{
|
||||
Channel channel = Config.HelpMode == HelpMode.Public ? e.Channel : await client.CreatePMChannel(e.User);
|
||||
Channel replyChannel = _config.HelpMode == HelpMode.Public ? e.Channel : await client.CreatePMChannel(e.User);
|
||||
if (e.Args.Length > 0) //Show command help
|
||||
{
|
||||
var map = _map.GetItem(string.Join(" ", e.Args));
|
||||
if (map != null)
|
||||
await ShowHelp(map, e.User, channel);
|
||||
await ShowCommandHelp(map, e.User, e.Channel, replyChannel);
|
||||
else
|
||||
await client.SendMessage(channel, "Unable to display help: Unknown command.");
|
||||
await client.SendMessage(replyChannel, "Unable to display help: Unknown command.");
|
||||
}
|
||||
else //Show general help
|
||||
await ShowHelp(e.User, channel);
|
||||
});
|
||||
|
||||
/* Unmerged change from project 'Discord.Net.Commands'
|
||||
Before:
|
||||
await ShowHelp(e.User, e.Channel, replyChannel);
|
||||
After:
|
||||
await this.ShowHelp((User)e.User, e.Channel, replyChannel);
|
||||
*/
|
||||
await this.ShowGeneralHelp(e.User, (Channel)e.Channel, (Channel)replyChannel);
|
||||
}));
|
||||
}
|
||||
|
||||
client.MessageReceived += async (s, e) =>
|
||||
@@ -68,7 +79,7 @@ namespace Discord.Commands
|
||||
if (msg.Length == 0) return;
|
||||
|
||||
//Check for command char if one is provided
|
||||
var chars = Config.CommandChars;
|
||||
var chars = _config.CommandChars;
|
||||
if (chars.Length > 0)
|
||||
{
|
||||
if (!chars.Contains(msg[0]))
|
||||
@@ -121,7 +132,7 @@ namespace Discord.Commands
|
||||
};
|
||||
}
|
||||
|
||||
public Task ShowHelp(User user, Channel channel)
|
||||
public Task ShowGeneralHelp(User user, Channel channel, Channel replyChannel = null)
|
||||
{
|
||||
StringBuilder output = new StringBuilder();
|
||||
/*output.AppendLine("These are the commands you can use:");
|
||||
@@ -163,7 +174,7 @@ namespace Discord.Commands
|
||||
else
|
||||
output.Append(", ");
|
||||
output.Append('`');
|
||||
output.Append(group.Text);
|
||||
output.Append(group.Name);
|
||||
if (group.SubGroups.Any())
|
||||
output.Append("*");
|
||||
output.Append('`');
|
||||
@@ -177,7 +188,7 @@ namespace Discord.Commands
|
||||
{
|
||||
output.Append("\n\n");
|
||||
|
||||
var chars = Config.CommandChars;
|
||||
var chars = _config.CommandChars;
|
||||
if (chars.Length > 0)
|
||||
{
|
||||
if (chars.Length == 1)
|
||||
@@ -190,20 +201,20 @@ namespace Discord.Commands
|
||||
output.AppendLine($"`help <command>` can tell you more about how to use a command.");
|
||||
}
|
||||
|
||||
return _client.SendMessage(channel, output.ToString());
|
||||
return _client.SendMessage(replyChannel ?? channel, output.ToString());
|
||||
}
|
||||
|
||||
private Task ShowHelp(CommandMap map, User user, Channel channel)
|
||||
private Task ShowCommandHelp(CommandMap map, User user, Channel channel, Channel replyChannel = null)
|
||||
{
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
Command cmd = map.Command;
|
||||
if (cmd != null)
|
||||
ShowHelpInternal(cmd, user, channel, output);
|
||||
ShowCommandHelpInternal(cmd, user, channel, output);
|
||||
else
|
||||
{
|
||||
output.Append('`');
|
||||
output.Append(map.Text);
|
||||
output.Append(map.FullName);
|
||||
output.Append("`\n");
|
||||
}
|
||||
|
||||
@@ -218,21 +229,21 @@ namespace Discord.Commands
|
||||
else
|
||||
output.Append(", ");
|
||||
output.Append('`');
|
||||
output.Append(subCmd.Text);
|
||||
output.Append(subCmd.Name);
|
||||
if (subCmd.SubGroups.Any())
|
||||
output.Append("*");
|
||||
output.Append('`');
|
||||
}
|
||||
|
||||
return _client.SendMessage(channel, output.ToString());
|
||||
return _client.SendMessage(replyChannel ?? channel, output.ToString());
|
||||
}
|
||||
public Task ShowHelp(Command command, User user, Channel channel)
|
||||
public Task ShowCommandHelp(Command command, User user, Channel channel, Channel replyChannel = null)
|
||||
{
|
||||
StringBuilder output = new StringBuilder();
|
||||
ShowHelpInternal(command, user, channel, output);
|
||||
return _client.SendMessage(channel, output.ToString());
|
||||
ShowCommandHelpInternal(command, user, channel, output);
|
||||
return _client.SendMessage(replyChannel ?? channel, output.ToString());
|
||||
}
|
||||
private void ShowHelpInternal(Command command, User user, Channel channel, StringBuilder output)
|
||||
private void ShowCommandHelpInternal(Command command, User user, Channel channel, StringBuilder output)
|
||||
{
|
||||
output.Append('`');
|
||||
output.Append(command.Text);
|
||||
@@ -261,17 +272,8 @@ namespace Discord.Commands
|
||||
output.AppendLine($"Aliases: `" + string.Join("`, `", command.Aliases) + '`');
|
||||
}
|
||||
|
||||
public void CreateGroup(string cmd, Action<CommandGroupBuilder> config = null)
|
||||
{
|
||||
var builder = new CommandGroupBuilder(this, cmd);
|
||||
if (config != null)
|
||||
config(builder);
|
||||
}
|
||||
public CommandBuilder CreateCommand(string cmd)
|
||||
{
|
||||
var command = new Command(cmd);
|
||||
return new CommandBuilder(this, command, "", "");
|
||||
}
|
||||
public void CreateGroup(string cmd, Action<CommandGroupBuilder> config = null) => _root.CreateGroup(cmd, config);
|
||||
public CommandBuilder CreateCommand(string cmd) => _root.CreateCommand(cmd);
|
||||
|
||||
internal void AddCommand(Command command)
|
||||
{
|
||||
@@ -282,7 +284,7 @@ namespace Discord.Commands
|
||||
string categoryName = command.Category ?? "";
|
||||
if (!_categories.TryGetValue(categoryName, out category))
|
||||
{
|
||||
category = new CommandMap(null, "");
|
||||
category = new CommandMap(null, "", "");
|
||||
_categories.Add(categoryName, category);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Discord.Commands.Permissions;
|
||||
using System;
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
@@ -13,9 +14,6 @@ namespace Discord.Commands
|
||||
}
|
||||
public class CommandServiceConfig
|
||||
{
|
||||
/*public Func<User, int> PermissionResolver { get { return _permissionsResolver; } set { SetValue(ref _permissionsResolver, value); } }
|
||||
private Func<User, int> _permissionsResolver;*/
|
||||
|
||||
public char? CommandChar
|
||||
{
|
||||
get
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>19793545-ef89-48f4-8100-3ebaad0a9141</ProjectGuid>
|
||||
<RootNamespace>Discord</RootNamespace>
|
||||
<RootNamespace>Discord.Commands</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Discord.Commands.Permissions
|
||||
{
|
||||
public interface IPermissionChecker
|
||||
{
|
||||
bool CanRun(Command command, User user, Channel channel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Discord.Commands.Permissions.Levels
|
||||
{
|
||||
public class PermissionLevelChecker : IPermissionChecker
|
||||
{
|
||||
private readonly PermissionLevelService _service;
|
||||
private readonly int _minPermissions;
|
||||
|
||||
public PermissionLevelService Service => _service;
|
||||
public int MinPermissions => _minPermissions;
|
||||
|
||||
internal PermissionLevelChecker(DiscordClient client, int minPermissions)
|
||||
{
|
||||
_service = client.GetService<PermissionLevelService>();
|
||||
_minPermissions = minPermissions;
|
||||
if (_service == null)
|
||||
throw new InvalidOperationException($"{nameof(PermissionLevelService)} must be added to {nameof(DiscordClient)} before this function is called.");
|
||||
}
|
||||
|
||||
public bool CanRun(Command command, User user, Channel channel)
|
||||
{
|
||||
int permissions = _service.GetPermissionLevel(user, channel);
|
||||
return permissions >= _minPermissions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Discord.Commands.Permissions.Levels
|
||||
{
|
||||
public static class PermissionLevelExtensions
|
||||
{
|
||||
public static CommandBuilder MinPermissions(this CommandBuilder builder, int minPermissions)
|
||||
{
|
||||
builder.AddCheck(new PermissionLevelChecker(builder.Service.Client, minPermissions));
|
||||
return builder;
|
||||
}
|
||||
public static CommandGroupBuilder MinPermissions(this CommandGroupBuilder builder, int minPermissions)
|
||||
{
|
||||
builder.AddCheck(new PermissionLevelChecker(builder.Service.Client, minPermissions));
|
||||
return builder;
|
||||
}
|
||||
public static CommandService MinPermissions(this CommandService service, int minPermissions)
|
||||
{
|
||||
service.Root.AddCheck(new PermissionLevelChecker(service.Client, minPermissions));
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
|
||||
namespace Discord.Commands.Permissions.Levels
|
||||
{
|
||||
public class PermissionLevelService : IService
|
||||
{
|
||||
private readonly Func<User, Channel, int> _getPermissionsFunc;
|
||||
|
||||
private DiscordClient _client;
|
||||
public DiscordClient Client => _client;
|
||||
|
||||
public PermissionLevelService(Func<User, Channel, int> getPermissionsFunc)
|
||||
{
|
||||
_getPermissionsFunc = getPermissionsFunc;
|
||||
}
|
||||
|
||||
public void Install(DiscordClient client)
|
||||
{
|
||||
_client = client;
|
||||
}
|
||||
public int GetPermissionLevel(User user, Channel channel) => _getPermissionsFunc(user, channel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace Discord.Commands.Permissions.Userlist
|
||||
{
|
||||
public class BlacklistChecker : IPermissionChecker
|
||||
{
|
||||
private readonly BlacklistService _service;
|
||||
|
||||
internal BlacklistChecker(DiscordClient client)
|
||||
{
|
||||
_service = client.GetService<BlacklistService>();
|
||||
if (_service == null)
|
||||
throw new InvalidOperationException($"{nameof(BlacklistService)} must be added to {nameof(DiscordClient)} before this function is called.");
|
||||
}
|
||||
|
||||
public bool CanRun(Command command, User user, Channel channel)
|
||||
{
|
||||
return _service.CanRun(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Discord.Commands.Permissions.Userlist
|
||||
{
|
||||
public static class BlacklistExtensions
|
||||
{
|
||||
public static CommandBuilder UseGlobalBlacklist(this CommandBuilder builder)
|
||||
{
|
||||
builder.AddCheck(new BlacklistChecker(builder.Service.Client));
|
||||
return builder;
|
||||
}
|
||||
public static CommandGroupBuilder UseGlobalBlacklist(this CommandGroupBuilder builder)
|
||||
{
|
||||
builder.AddCheck(new BlacklistChecker(builder.Service.Client));
|
||||
return builder;
|
||||
}
|
||||
public static CommandService UseGlobalBlacklist(this CommandService service)
|
||||
{
|
||||
service.Root.AddCheck(new BlacklistChecker(service.Client));
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord.Commands.Permissions.Userlist
|
||||
{
|
||||
public class BlacklistService : UserlistService
|
||||
{
|
||||
public BlacklistService(IEnumerable<string> initialList = null)
|
||||
: base(initialList)
|
||||
{
|
||||
}
|
||||
|
||||
public bool CanRun(User user)
|
||||
{
|
||||
return !_userList.ContainsKey(user.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord.Commands.Permissions.Userlist
|
||||
{
|
||||
public class UserlistService : IService
|
||||
{
|
||||
protected readonly ConcurrentDictionary<string, bool> _userList;
|
||||
private DiscordClient _client;
|
||||
|
||||
public DiscordClient Client => _client;
|
||||
public IEnumerable<string> UserIds => _userList.Select(x => x.Key);
|
||||
|
||||
public UserlistService(IEnumerable<string> initialList = null)
|
||||
{
|
||||
if (initialList != null)
|
||||
_userList = new ConcurrentDictionary<string, bool>(initialList.Select(x => new KeyValuePair<string, bool>(x, true)));
|
||||
else
|
||||
_userList = new ConcurrentDictionary<string, bool>();
|
||||
}
|
||||
|
||||
public void Add(User user)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||
_userList[user.Id] = true;
|
||||
}
|
||||
public void Add(string userId)
|
||||
{
|
||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
||||
_userList[userId] = true;
|
||||
}
|
||||
public bool Remove(User user)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||
bool ignored;
|
||||
return _userList.TryRemove(user.Id, out ignored);
|
||||
}
|
||||
public bool Remove(string userId)
|
||||
{
|
||||
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
||||
bool ignored;
|
||||
return _userList.TryRemove(userId, out ignored);
|
||||
}
|
||||
|
||||
public void Install(DiscordClient client)
|
||||
{
|
||||
_client = client;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace Discord.Commands.Permissions.Userlist
|
||||
{
|
||||
public class WhitelistChecker : IPermissionChecker
|
||||
{
|
||||
private readonly WhitelistService _service;
|
||||
|
||||
internal WhitelistChecker(DiscordClient client)
|
||||
{
|
||||
_service = client.GetService<WhitelistService>();
|
||||
if (_service == null)
|
||||
throw new InvalidOperationException($"{nameof(WhitelistService)} must be added to {nameof(DiscordClient)} before this function is called.");
|
||||
}
|
||||
|
||||
public bool CanRun(Command command, User user, Channel channel)
|
||||
{
|
||||
return _service.CanRun(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Discord.Commands.Permissions.Userlist
|
||||
{
|
||||
public static class WhitelistExtensions
|
||||
{
|
||||
public static CommandBuilder UseGlobalWhitelist(this CommandBuilder builder)
|
||||
{
|
||||
builder.AddCheck(new WhitelistChecker(builder.Service.Client));
|
||||
return builder;
|
||||
}
|
||||
public static CommandGroupBuilder UseGlobalWhitelist(this CommandGroupBuilder builder)
|
||||
{
|
||||
builder.AddCheck(new WhitelistChecker(builder.Service.Client));
|
||||
return builder;
|
||||
}
|
||||
public static CommandService UseGlobalWhitelist(this CommandService service)
|
||||
{
|
||||
service.Root.AddCheck(new BlacklistChecker(service.Client));
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord.Commands.Permissions.Userlist
|
||||
{
|
||||
public class WhitelistService : UserlistService
|
||||
{
|
||||
public WhitelistService(IEnumerable<string> initialList = null)
|
||||
: base(initialList)
|
||||
{
|
||||
}
|
||||
|
||||
public bool CanRun(User user)
|
||||
{
|
||||
return _userList.ContainsKey(user.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
<ProjectGuid>{3091164F-66AE-4543-A63D-167C1116241D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Discord</RootNamespace>
|
||||
<RootNamespace>Discord.Modules</RootNamespace>
|
||||
<AssemblyName>Discord.Net.Commands</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
@@ -40,6 +40,9 @@
|
||||
<Compile Include="..\Discord.Net.Modules\IModule.cs">
|
||||
<Link>IModule.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Modules\ModuleChecker.cs">
|
||||
<Link>ModuleChecker.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net.Modules\ModuleExtensions.cs">
|
||||
<Link>ModuleExtensions.cs</Link>
|
||||
</Compile>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>01584e8a-78da-486f-9ef9-a894e435841b</ProjectGuid>
|
||||
<RootNamespace>Discord</RootNamespace>
|
||||
<RootNamespace>Discord.Modules</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
20
src/Discord.Net.Modules/ModuleChecker.cs
Normal file
20
src/Discord.Net.Modules/ModuleChecker.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Discord.Commands;
|
||||
using Discord.Commands.Permissions;
|
||||
|
||||
namespace Discord.Modules
|
||||
{
|
||||
public class ModuleChecker : IPermissionChecker
|
||||
{
|
||||
private readonly ModuleManager _manager;
|
||||
|
||||
internal ModuleChecker(ModuleManager manager)
|
||||
{
|
||||
_manager = manager;
|
||||
}
|
||||
|
||||
public bool CanRun(Command command, User user, Channel channel)
|
||||
{
|
||||
return _manager.FilterType.HasFlag(FilterType.Unrestricted) || _manager.HasChannel(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,8 +64,8 @@ namespace Discord.Modules
|
||||
_name = name;
|
||||
_id = name.ToLowerInvariant();
|
||||
_filterType = filterType;
|
||||
_allowServerWhitelist = filterType.HasFlag(FilterType.Server);
|
||||
_allowChannelWhitelist = filterType.HasFlag(FilterType.Channel);
|
||||
_allowServerWhitelist = filterType.HasFlag(FilterType.ServerWhitelist);
|
||||
_allowChannelWhitelist = filterType.HasFlag(FilterType.ChannelWhitelist);
|
||||
_allowPrivate = filterType.HasFlag(FilterType.AllowPrivate);
|
||||
|
||||
_enabledServers = new ConcurrentDictionary<string, Server>();
|
||||
@@ -115,6 +115,7 @@ namespace Discord.Modules
|
||||
commandService.CreateGroup(prefix, x =>
|
||||
{
|
||||
x.Category(_name);
|
||||
x.AddCheck(new ModuleChecker(this));
|
||||
config(x);
|
||||
});
|
||||
|
||||
@@ -244,12 +245,12 @@ namespace Discord.Modules
|
||||
DisableAllChannels();
|
||||
}
|
||||
|
||||
private bool HasServer(Server server) =>
|
||||
internal bool HasServer(Server server) =>
|
||||
_allowServerWhitelist && _enabledServers.ContainsKey(server.Id);
|
||||
private bool HasIndirectServer(Server server) =>
|
||||
internal bool HasIndirectServer(Server server) =>
|
||||
(_allowServerWhitelist && _enabledServers.ContainsKey(server.Id)) ||
|
||||
(_allowChannelWhitelist && _indirectServers.ContainsKey(server.Id));
|
||||
private bool HasChannel(Channel channel)
|
||||
internal bool HasChannel(Channel channel)
|
||||
{
|
||||
if (channel.IsPrivate) return _allowPrivate;
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ namespace Discord.Modules
|
||||
[Flags]
|
||||
public enum FilterType
|
||||
{
|
||||
/// <summary> Disables the event filter. </summary>
|
||||
Disabled = 0x0,
|
||||
/// <summary> Uses the server whitelist to filter events. </summary>
|
||||
Server = 0x1,
|
||||
/// <summary> Uses the channel whitelist to filter events. </summary>
|
||||
Channel = 0x2,
|
||||
/// <summary> Disables the event and command filtesr. </summary>
|
||||
Unrestricted = 0x0,
|
||||
/// <summary> Uses the server whitelist to filter events and commands. </summary>
|
||||
ServerWhitelist = 0x1,
|
||||
/// <summary> Uses the channel whitelist to filter events and commands. </summary>
|
||||
ChannelWhitelist = 0x2,
|
||||
/// <summary> Enables this module in all private messages. </summary>
|
||||
AllowPrivate = 0x4
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user