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">
<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>


+ 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.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)
{
_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)
{
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


+ 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.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;

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

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

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


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



+ 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
{
@@ -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


+ 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)' != ''" />
<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>


+ 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>
<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>


+ 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)' != ''" />
<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
- 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;
_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;



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

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


Loading…
Cancel
Save