Browse Source

Added new permissions system, fixed more commands and module bugs.

tags/docs-0.9
RogueException 9 years ago
parent
commit
093095e410
23 changed files with 443 additions and 100 deletions
  1. +33
    -0
      src/Discord.Net.Commands.Net45/Discord.Net.Commands.csproj
  2. +21
    -12
      src/Discord.Net.Commands/Command.cs
  3. +45
    -19
      src/Discord.Net.Commands/CommandBuilder.cs
  4. +13
    -10
      src/Discord.Net.Commands/CommandMap.cs
  5. +43
    -41
      src/Discord.Net.Commands/CommandService.cs
  6. +2
    -4
      src/Discord.Net.Commands/CommandServiceConfig.cs
  7. +1
    -1
      src/Discord.Net.Commands/Discord.Net.Commands.xproj
  8. +7
    -0
      src/Discord.Net.Commands/Permissions/IPermissionChecker.cs
  9. +27
    -0
      src/Discord.Net.Commands/Permissions/Levels/PermissionLevelChecker.cs
  10. +21
    -0
      src/Discord.Net.Commands/Permissions/Levels/PermissionLevelExtensions.cs
  11. +23
    -0
      src/Discord.Net.Commands/Permissions/Levels/PermissionLevelService.cs
  12. +21
    -0
      src/Discord.Net.Commands/Permissions/Userlist/BlacklistChecker.cs
  13. +21
    -0
      src/Discord.Net.Commands/Permissions/Userlist/BlacklistExtensions.cs
  14. +17
    -0
      src/Discord.Net.Commands/Permissions/Userlist/BlacklistService.cs
  15. +52
    -0
      src/Discord.Net.Commands/Permissions/Userlist/UserlistService.cs
  16. +21
    -0
      src/Discord.Net.Commands/Permissions/Userlist/WhitelistChecker.cs
  17. +21
    -0
      src/Discord.Net.Commands/Permissions/Userlist/WhitelistExtensions.cs
  18. +17
    -0
      src/Discord.Net.Commands/Permissions/Userlist/WhitelistService.cs
  19. +4
    -1
      src/Discord.Net.Modules.Net45/Discord.Net.Modules.csproj
  20. +1
    -1
      src/Discord.Net.Modules/Discord.Net.Modules.xproj
  21. +20
    -0
      src/Discord.Net.Modules/ModuleChecker.cs
  22. +6
    -5
      src/Discord.Net.Modules/ModuleManager.cs
  23. +6
    -6
      src/Discord.Net.Modules/ModuleType.cs

+ 33
- 0
src/Discord.Net.Commands.Net45/Discord.Net.Commands.csproj View File

@@ -61,6 +61,39 @@
<Compile Include="..\Discord.Net.Commands\CommandServiceConfig.cs"> <Compile Include="..\Discord.Net.Commands\CommandServiceConfig.cs">
<Link>CommandServiceConfig.cs</Link> <Link>CommandServiceConfig.cs</Link>
</Compile> </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" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>


+ 21
- 12
src/Discord.Net.Commands/Command.cs View File

@@ -1,4 +1,5 @@
using System;
using Discord.Commands.Permissions;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;


@@ -41,8 +42,9 @@ namespace Discord.Commands


public IEnumerable<CommandParameter> Parameters => _parameters; public IEnumerable<CommandParameter> Parameters => _parameters;
internal CommandParameter[] _parameters; internal CommandParameter[] _parameters;

private Func<CommandEventArgs, Task> _handler;
private IPermissionChecker[] _checks;
private Func<CommandEventArgs, Task> _runFunc;


internal Command(string text) internal Command(string text)
{ {
@@ -56,7 +58,6 @@ namespace Discord.Commands
{ {
_aliases = aliases; _aliases = aliases;
} }

internal void SetParameters(CommandParameter[] parameters) internal void SetParameters(CommandParameter[] parameters)
{ {
_parameters = parameters; _parameters = parameters;
@@ -89,24 +90,32 @@ namespace Discord.Commands
} }
} }
} }

internal void SetHandler(Func<CommandEventArgs, Task> func)
{
_handler = func;
}
internal void SetHandler(Action<CommandEventArgs> func)
internal void SetChecks(IPermissionChecker[] checks)
{ {
_handler = e => { func(e); return TaskHelper.CompletedTask; };
_checks = checks;
} }


internal bool CanRun(User user, Channel channel) 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; 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) internal Task Run(CommandEventArgs args)
{ {
var task = _handler(args);
var task = _runFunc(args);
if (task != null) if (task != null)
return task; return task;
else else


+ 45
- 19
src/Discord.Net.Commands/CommandBuilder.cs View File

@@ -1,4 +1,5 @@
using System;
using Discord.Commands.Permissions;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -9,19 +10,27 @@ namespace Discord.Commands
{ {
private readonly CommandService _service; private readonly CommandService _service;
private readonly Command _command; 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;

public CommandService Service => _service;


internal CommandBuilder(CommandService service, Command command, string prefix, string category)
internal CommandBuilder(CommandService service, Command command, string prefix = "", string category = "", IEnumerable<IPermissionChecker> initialChecks = null)
{ {
_service = service; _service = service;
_command = command; _command = command;
_command.Category = category; _command.Category = category;
_params = new List<CommandParameter>(); _params = new List<CommandParameter>();
if (initialChecks != null)
_checks = new List<IPermissionChecker>(initialChecks);
else
_checks = new List<IPermissionChecker>();
_prefix = prefix; _prefix = prefix;
_allowRequired = true;
_isClosed = false;

_allowRequiredParams = true;
_areParamsClosed = false;
} }


public CommandBuilder Alias(params string[] aliases) public CommandBuilder Alias(params string[] aliases)
@@ -35,24 +44,24 @@ namespace Discord.Commands
_command.Category = category; _command.Category = category;
return this; return this;
}*/ }*/
public CommandBuilder Info(string description)
public CommandBuilder Description(string description)
{ {
_command.Description = description; _command.Description = description;
return this; return this;
} }
public CommandBuilder Parameter(string name, ParameterType type = ParameterType.Required) 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."); 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"); throw new Exception($"{nameof(ParameterType.Required)} parameters may not be added after an optional one");


_params.Add(new CommandParameter(name, type)); _params.Add(new CommandParameter(name, type));


if (type == ParameterType.Optional) if (type == ParameterType.Optional)
_allowRequired = false;
_allowRequiredParams = false;
if (type == ParameterType.Multiple || type == ParameterType.Unparsed) if (type == ParameterType.Multiple || type == ParameterType.Unparsed)
_isClosed = true;
_areParamsClosed = true;
return this; return this;
} }
public CommandBuilder Hide() public CommandBuilder Hide()
@@ -60,20 +69,26 @@ namespace Discord.Commands
_command.IsHidden = true; _command.IsHidden = true;
return this; return this;
} }
public CommandBuilder AddCheck(IPermissionChecker check)
{
_checks.Add(check);
return this;
}


public void Do(Func<CommandEventArgs, Task> func) public void Do(Func<CommandEventArgs, Task> func)
{ {
_command.SetHandler(func);
_command.SetRunFunc(func);
Build(); Build();
} }
public void Do(Action<CommandEventArgs> func) public void Do(Action<CommandEventArgs> func)
{ {
_command.SetHandler(func);
_command.SetRunFunc(func);
Build(); Build();
} }
private void Build() private void Build()
{ {
_command.SetParameters(_params.ToArray()); _command.SetParameters(_params.ToArray());
_command.SetChecks(_checks.ToArray());
_service.AddCommand(_command); _service.AddCommand(_command);
} }


@@ -97,14 +112,21 @@ namespace Discord.Commands
} }
public sealed class CommandGroupBuilder public sealed class CommandGroupBuilder
{ {
internal readonly CommandService _service;
private readonly CommandService _service;
private readonly string _prefix; private readonly string _prefix;
private readonly List<IPermissionChecker> _checks;
private string _category; 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; _service = service;
_prefix = prefix; _prefix = prefix;
if (initialChecks != null)
_checks = new List<IPermissionChecker>(initialChecks);
else
_checks = new List<IPermissionChecker>();
} }


public CommandGroupBuilder Category(string category) public CommandGroupBuilder Category(string category)
@@ -112,10 +134,14 @@ namespace Discord.Commands
_category = category; _category = category;
return this; return this;
} }
public void AddCheck(IPermissionChecker check)
{
_checks.Add(check);
}


public CommandGroupBuilder CreateGroup(string cmd, Action<CommandGroupBuilder> config = null) 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; return this;
} }
public CommandBuilder CreateCommand() public CommandBuilder CreateCommand()
@@ -123,7 +149,7 @@ namespace Discord.Commands
public CommandBuilder CreateCommand(string cmd) public CommandBuilder CreateCommand(string cmd)
{ {
var command = new Command(CommandBuilder.AppendPrefix(_prefix, cmd)); var command = new Command(CommandBuilder.AppendPrefix(_prefix, cmd));
return new CommandBuilder(_service, command, _prefix, _category);
return new CommandBuilder(_service, command, _prefix, _category, _checks);
} }
} }
} }

+ 13
- 10
src/Discord.Net.Commands/CommandMap.cs View File

@@ -7,24 +7,26 @@ namespace Discord.Commands
internal class CommandMap internal class CommandMap
{ {
private readonly CommandMap _parent; private readonly CommandMap _parent;
private readonly string _text;
private readonly string _name, _fullName;


private Command _command; private Command _command;
private readonly Dictionary<string, CommandMap> _items; private readonly Dictionary<string, CommandMap> _items;
private bool _isHidden; private bool _isHidden;


public string Text => _text;
public string Name => _name;
public string FullName => _fullName;
public bool IsHidden => _isHidden; public bool IsHidden => _isHidden;
public Command Command => _command; public Command Command => _command;
public IEnumerable<CommandMap> SubGroups => _items.Values; public IEnumerable<CommandMap> SubGroups => _items.Values;
/*public IEnumerable<Command> SubCommands => _items.Select(x => x.Value._command).Where(x => x != null); /*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 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; _parent = parent;
_text = text;
_items = new Dictionary<string, CommandMap>();
_name = name;
_fullName = fullName;
_items = new Dictionary<string, CommandMap>();
_isHidden = true; _isHidden = true;
} }
@@ -82,19 +84,20 @@ namespace Discord.Commands
{ {
AddCommand(0, text.Split(' '), command); 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) if (!command.IsHidden && _isHidden)
_isHidden = false; _isHidden = false;


if (index != parts.Length) if (index != parts.Length)
{ {
string nextPart = parts[index];
CommandMap nextGroup; 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); nextGroup.AddCommand(index + 1, parts, command);
} }


+ 43
- 41
src/Discord.Net.Commands/CommandService.cs View File

@@ -9,8 +9,12 @@ namespace Discord.Commands
/// <summary> A Discord.Net client with extensions for handling common bot operations like text commands. </summary> /// <summary> A Discord.Net client with extensions for handling common bot operations like text commands. </summary>
public partial class CommandService : IService public partial class CommandService : IService
{ {
private readonly CommandServiceConfig _config;
private readonly CommandGroupBuilder _root;
private DiscordClient _client; private DiscordClient _client;
public CommandServiceConfig Config { get; }

public DiscordClient Client => _client;
public CommandGroupBuilder Root => _root;


//AllCommands store a flattened collection of all commands //AllCommands store a flattened collection of all commands
public IEnumerable<Command> AllCommands => _allCommands; public IEnumerable<Command> AllCommands => _allCommands;
@@ -23,40 +27,47 @@ namespace Discord.Commands
internal IEnumerable<CommandMap> Categories => _categories.Values; internal IEnumerable<CommandMap> Categories => _categories.Values;
private readonly Dictionary<string, CommandMap> _categories; private readonly Dictionary<string, CommandMap> _categories;



public CommandService(CommandServiceConfig config) public CommandService(CommandServiceConfig config)
{ {
Config = config;
_config = config;
_allCommands = new List<Command>(); _allCommands = new List<Command>();
_map = new CommandMap(null, null);
_map = new CommandMap(null, "", "");
_categories = new Dictionary<string, CommandMap>(); _categories = new Dictionary<string, CommandMap>();
}
_root = new CommandGroupBuilder(this, "", null);
}


void IService.Install(DiscordClient client) void IService.Install(DiscordClient client)
{ {
_client = 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) .Parameter("command", ParameterType.Multiple)
.Hide() .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 if (e.Args.Length > 0) //Show command help
{ {
var map = _map.GetItem(string.Join(" ", e.Args)); var map = _map.GetItem(string.Join(" ", e.Args));
if (map != null) if (map != null)
await ShowHelp(map, e.User, channel);
await ShowCommandHelp(map, e.User, e.Channel, replyChannel);
else 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 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) => client.MessageReceived += async (s, e) =>
@@ -68,7 +79,7 @@ namespace Discord.Commands
if (msg.Length == 0) return; if (msg.Length == 0) return;


//Check for command char if one is provided //Check for command char if one is provided
var chars = Config.CommandChars;
var chars = _config.CommandChars;
if (chars.Length > 0) if (chars.Length > 0)
{ {
if (!chars.Contains(msg[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(); StringBuilder output = new StringBuilder();
/*output.AppendLine("These are the commands you can use:"); /*output.AppendLine("These are the commands you can use:");
@@ -163,7 +174,7 @@ namespace Discord.Commands
else else
output.Append(", "); output.Append(", ");
output.Append('`'); output.Append('`');
output.Append(group.Text);
output.Append(group.Name);
if (group.SubGroups.Any()) if (group.SubGroups.Any())
output.Append("*"); output.Append("*");
output.Append('`'); output.Append('`');
@@ -177,7 +188,7 @@ namespace Discord.Commands
{ {
output.Append("\n\n"); output.Append("\n\n");


var chars = Config.CommandChars;
var chars = _config.CommandChars;
if (chars.Length > 0) if (chars.Length > 0)
{ {
if (chars.Length == 1) 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."); 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(); StringBuilder output = new StringBuilder();


Command cmd = map.Command; Command cmd = map.Command;
if (cmd != null) if (cmd != null)
ShowHelpInternal(cmd, user, channel, output);
ShowCommandHelpInternal(cmd, user, channel, output);
else else
{ {
output.Append('`'); output.Append('`');
output.Append(map.Text);
output.Append(map.FullName);
output.Append("`\n"); output.Append("`\n");
} }


@@ -218,21 +229,21 @@ namespace Discord.Commands
else else
output.Append(", "); output.Append(", ");
output.Append('`'); output.Append('`');
output.Append(subCmd.Text);
output.Append(subCmd.Name);
if (subCmd.SubGroups.Any()) if (subCmd.SubGroups.Any())
output.Append("*"); output.Append("*");
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(); 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('`');
output.Append(command.Text); output.Append(command.Text);
@@ -261,17 +272,8 @@ namespace Discord.Commands
output.AppendLine($"Aliases: `" + string.Join("`, `", command.Aliases) + '`'); 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) internal void AddCommand(Command command)
{ {
@@ -282,7 +284,7 @@ namespace Discord.Commands
string categoryName = command.Category ?? ""; string categoryName = command.Category ?? "";
if (!_categories.TryGetValue(categoryName, out category)) if (!_categories.TryGetValue(categoryName, out category))
{ {
category = new CommandMap(null, "");
category = new CommandMap(null, "", "");
_categories.Add(categoryName, category); _categories.Add(categoryName, category);
} }




+ 2
- 4
src/Discord.Net.Commands/CommandServiceConfig.cs View File

@@ -1,4 +1,5 @@
using System;
using Discord.Commands.Permissions;
using System;


namespace Discord.Commands namespace Discord.Commands
{ {
@@ -13,9 +14,6 @@ namespace Discord.Commands
} }
public class CommandServiceConfig public class CommandServiceConfig
{ {
/*public Func<User, int> PermissionResolver { get { return _permissionsResolver; } set { SetValue(ref _permissionsResolver, value); } }
private Func<User, int> _permissionsResolver;*/

public char? CommandChar public char? CommandChar
{ {
get get


+ 1
- 1
src/Discord.Net.Commands/Discord.Net.Commands.xproj View File

@@ -7,7 +7,7 @@
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>19793545-ef89-48f4-8100-3ebaad0a9141</ProjectGuid> <ProjectGuid>19793545-ef89-48f4-8100-3ebaad0a9141</ProjectGuid>
<RootNamespace>Discord</RootNamespace>
<RootNamespace>Discord.Commands</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> <OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup> </PropertyGroup>


+ 7
- 0
src/Discord.Net.Commands/Permissions/IPermissionChecker.cs View File

@@ -0,0 +1,7 @@
namespace Discord.Commands.Permissions
{
public interface IPermissionChecker
{
bool CanRun(Command command, User user, Channel channel);
}
}

+ 27
- 0
src/Discord.Net.Commands/Permissions/Levels/PermissionLevelChecker.cs View File

@@ -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;
}
}
}

+ 21
- 0
src/Discord.Net.Commands/Permissions/Levels/PermissionLevelExtensions.cs View File

@@ -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;
}
}
}

+ 23
- 0
src/Discord.Net.Commands/Permissions/Levels/PermissionLevelService.cs View File

@@ -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);
}
}

+ 21
- 0
src/Discord.Net.Commands/Permissions/Userlist/BlacklistChecker.cs View File

@@ -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);
}
}
}

+ 21
- 0
src/Discord.Net.Commands/Permissions/Userlist/BlacklistExtensions.cs View File

@@ -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;
}
}
}

+ 17
- 0
src/Discord.Net.Commands/Permissions/Userlist/BlacklistService.cs View File

@@ -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);
}
}
}

+ 52
- 0
src/Discord.Net.Commands/Permissions/Userlist/UserlistService.cs View File

@@ -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;
}
}
}

+ 21
- 0
src/Discord.Net.Commands/Permissions/Userlist/WhitelistChecker.cs View File

@@ -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);
}
}
}

+ 21
- 0
src/Discord.Net.Commands/Permissions/Userlist/WhitelistExtensions.cs View File

@@ -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;
}
}
}

+ 17
- 0
src/Discord.Net.Commands/Permissions/Userlist/WhitelistService.cs View File

@@ -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);
}
}
}

+ 4
- 1
src/Discord.Net.Modules.Net45/Discord.Net.Modules.csproj View File

@@ -7,7 +7,7 @@
<ProjectGuid>{3091164F-66AE-4543-A63D-167C1116241D}</ProjectGuid> <ProjectGuid>{3091164F-66AE-4543-A63D-167C1116241D}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Discord</RootNamespace>
<RootNamespace>Discord.Modules</RootNamespace>
<AssemblyName>Discord.Net.Commands</AssemblyName> <AssemblyName>Discord.Net.Commands</AssemblyName>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
@@ -40,6 +40,9 @@
<Compile Include="..\Discord.Net.Modules\IModule.cs"> <Compile Include="..\Discord.Net.Modules\IModule.cs">
<Link>IModule.cs</Link> <Link>IModule.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net.Modules\ModuleChecker.cs">
<Link>ModuleChecker.cs</Link>
</Compile>
<Compile Include="..\Discord.Net.Modules\ModuleExtensions.cs"> <Compile Include="..\Discord.Net.Modules\ModuleExtensions.cs">
<Link>ModuleExtensions.cs</Link> <Link>ModuleExtensions.cs</Link>
</Compile> </Compile>


+ 1
- 1
src/Discord.Net.Modules/Discord.Net.Modules.xproj View File

@@ -7,7 +7,7 @@
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>01584e8a-78da-486f-9ef9-a894e435841b</ProjectGuid> <ProjectGuid>01584e8a-78da-486f-9ef9-a894e435841b</ProjectGuid>
<RootNamespace>Discord</RootNamespace>
<RootNamespace>Discord.Modules</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> <OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup> </PropertyGroup>


+ 20
- 0
src/Discord.Net.Modules/ModuleChecker.cs View 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);
}
}
}

+ 6
- 5
src/Discord.Net.Modules/ModuleManager.cs View File

@@ -64,8 +64,8 @@ namespace Discord.Modules
_name = name; _name = name;
_id = name.ToLowerInvariant(); _id = name.ToLowerInvariant();
_filterType = filterType; _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); _allowPrivate = filterType.HasFlag(FilterType.AllowPrivate);


_enabledServers = new ConcurrentDictionary<string, Server>(); _enabledServers = new ConcurrentDictionary<string, Server>();
@@ -115,6 +115,7 @@ namespace Discord.Modules
commandService.CreateGroup(prefix, x => commandService.CreateGroup(prefix, x =>
{ {
x.Category(_name); x.Category(_name);
x.AddCheck(new ModuleChecker(this));
config(x); config(x);
}); });


@@ -244,12 +245,12 @@ namespace Discord.Modules
DisableAllChannels(); DisableAllChannels();
} }


private bool HasServer(Server server) =>
internal bool HasServer(Server server) =>
_allowServerWhitelist && _enabledServers.ContainsKey(server.Id); _allowServerWhitelist && _enabledServers.ContainsKey(server.Id);
private bool HasIndirectServer(Server server) =>
internal bool HasIndirectServer(Server server) =>
(_allowServerWhitelist && _enabledServers.ContainsKey(server.Id)) || (_allowServerWhitelist && _enabledServers.ContainsKey(server.Id)) ||
(_allowChannelWhitelist && _indirectServers.ContainsKey(server.Id)); (_allowChannelWhitelist && _indirectServers.ContainsKey(server.Id));
private bool HasChannel(Channel channel)
internal bool HasChannel(Channel channel)
{ {
if (channel.IsPrivate) return _allowPrivate; if (channel.IsPrivate) return _allowPrivate;




+ 6
- 6
src/Discord.Net.Modules/ModuleType.cs View File

@@ -5,12 +5,12 @@ namespace Discord.Modules
[Flags] [Flags]
public enum FilterType 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> /// <summary> Enables this module in all private messages. </summary>
AllowPrivate = 0x4 AllowPrivate = 0x4
} }


Loading…
Cancel
Save