Cleaned up CommandsPlugin, added CommandMap, new parameter declaration and aliases.
This commit is contained in:
@@ -43,6 +43,9 @@
|
|||||||
<Compile Include="..\Discord.Net.Commands\CommandBuilder.cs">
|
<Compile Include="..\Discord.Net.Commands\CommandBuilder.cs">
|
||||||
<Link>CommandBuilder.cs</Link>
|
<Link>CommandBuilder.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Discord.Net.Commands\CommandMap.cs">
|
||||||
|
<Link>CommandMap.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Discord.Net.Commands\CommandParser.cs">
|
<Compile Include="..\Discord.Net.Commands\CommandParser.cs">
|
||||||
<Link>CommandParser.cs</Link>
|
<Link>CommandParser.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -1,23 +1,102 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Discord.Commands
|
namespace Discord.Commands
|
||||||
{
|
{
|
||||||
|
public sealed class CommandParameter
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
public bool IsOptional { get; }
|
||||||
|
public bool IsCatchAll { get; }
|
||||||
|
|
||||||
|
public CommandParameter(string name, bool isOptional, bool isCatchAll)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
IsOptional = isOptional;
|
||||||
|
IsCatchAll = isCatchAll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class Command
|
public sealed class Command
|
||||||
{
|
{
|
||||||
public string Text { get; }
|
public string Text { get; }
|
||||||
public int? MinArgs { get; internal set; }
|
public int? MinArgs { get; private set; }
|
||||||
public int? MaxArgs { get; internal set; }
|
public int? MaxArgs { get; private set; }
|
||||||
public int MinPerms { get; internal set; }
|
public int MinPerms { get; internal set; }
|
||||||
public bool IsHidden { get; internal set; }
|
public bool IsHidden { get; internal set; }
|
||||||
public string Description { get; internal set; }
|
public string Description { get; internal set; }
|
||||||
internal Func<CommandEventArgs, Task> Handler;
|
|
||||||
|
public IEnumerable<string> Aliases => _aliases;
|
||||||
|
private string[] _aliases;
|
||||||
|
|
||||||
|
public IEnumerable<CommandParameter> Parameters => _parameters;
|
||||||
|
private CommandParameter[] _parameters;
|
||||||
|
|
||||||
|
private Func<CommandEventArgs, Task> _handler;
|
||||||
|
|
||||||
internal Command(string text)
|
internal Command(string text)
|
||||||
{
|
{
|
||||||
Text = text;
|
Text = text;
|
||||||
IsHidden = false; // Set false by default to avoid null error
|
IsHidden = false;
|
||||||
Description = "No description set for this command.";
|
_aliases = new string[0];
|
||||||
|
_parameters = new CommandParameter[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetAliases(string[] aliases)
|
||||||
|
{
|
||||||
|
_aliases = aliases;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetParameters(CommandParameter[] parameters)
|
||||||
|
{
|
||||||
|
_parameters = parameters;
|
||||||
|
if (parameters != null)
|
||||||
|
{
|
||||||
|
if (parameters.Length == 0)
|
||||||
|
{
|
||||||
|
MinArgs = 0;
|
||||||
|
MaxArgs = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (parameters[parameters.Length - 1].IsCatchAll)
|
||||||
|
MaxArgs = null;
|
||||||
|
else
|
||||||
|
MaxArgs = parameters.Length;
|
||||||
|
|
||||||
|
int? optionalStart = null;
|
||||||
|
for (int i = parameters.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (parameters[i].IsOptional)
|
||||||
|
optionalStart = i;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (optionalStart == null)
|
||||||
|
MinArgs = MaxArgs;
|
||||||
|
else
|
||||||
|
MinArgs = optionalStart.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetHandler(Func<CommandEventArgs, Task> func)
|
||||||
|
{
|
||||||
|
_handler = func;
|
||||||
|
}
|
||||||
|
internal void SetHandler(Action<CommandEventArgs> func)
|
||||||
|
{
|
||||||
|
_handler = e => { func(e); return TaskHelper.CompletedTask; };
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Task Run(CommandEventArgs args)
|
||||||
|
{
|
||||||
|
var task = _handler(args);
|
||||||
|
if (task != null)
|
||||||
|
return task;
|
||||||
|
else
|
||||||
|
return TaskHelper.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,55 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Discord.Commands
|
namespace Discord.Commands
|
||||||
{
|
{
|
||||||
public sealed class CommandBuilder
|
public sealed class CommandBuilder
|
||||||
{
|
{
|
||||||
|
private readonly CommandsPlugin _plugin;
|
||||||
private readonly Command _command;
|
private readonly Command _command;
|
||||||
public CommandBuilder(Command command)
|
private List<CommandParameter> _params;
|
||||||
|
private bool _hasOptional, _hasCatchAll;
|
||||||
|
private string _prefix;
|
||||||
|
|
||||||
|
public CommandBuilder(CommandsPlugin plugin, Command command, string prefix)
|
||||||
{
|
{
|
||||||
|
_plugin = plugin;
|
||||||
_command = command;
|
_command = command;
|
||||||
}
|
_params = new List<CommandParameter>();
|
||||||
|
_prefix = prefix;
|
||||||
public CommandBuilder ArgsEqual(int argCount)
|
}
|
||||||
|
|
||||||
|
public CommandBuilder Alias(params string[] aliases)
|
||||||
{
|
{
|
||||||
_command.MinArgs = argCount;
|
aliases = aliases.Select(x => AppendPrefix(_prefix, x)).ToArray();
|
||||||
_command.MaxArgs = argCount;
|
_command.SetAliases(aliases);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public CommandBuilder ArgsAtLeast(int minArgCount)
|
public CommandBuilder Info(string description)
|
||||||
{
|
{
|
||||||
_command.MinArgs = minArgCount;
|
_command.Description = description;
|
||||||
_command.MaxArgs = null;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public CommandBuilder ArgsAtMost(int maxArgCount)
|
public CommandBuilder Parameter(string name, bool isOptional = false, bool isCatchAll = false)
|
||||||
{
|
{
|
||||||
_command.MinArgs = null;
|
if (_hasCatchAll)
|
||||||
_command.MaxArgs = maxArgCount;
|
throw new Exception("No parameters may be added after the catch-all");
|
||||||
|
if (_hasOptional && isOptional)
|
||||||
|
throw new Exception("Non-optional parameters may not be added after an optional one");
|
||||||
|
|
||||||
|
_params.Add(new CommandParameter(name, isOptional, isCatchAll));
|
||||||
|
|
||||||
|
if (isOptional)
|
||||||
|
_hasOptional = true;
|
||||||
|
if (isCatchAll)
|
||||||
|
_hasCatchAll = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public CommandBuilder ArgsBetween(int minArgCount, int maxArgCount)
|
public CommandBuilder IsHidden()
|
||||||
{
|
{
|
||||||
_command.MinArgs = minArgCount;
|
_command.IsHidden = true;
|
||||||
_command.MaxArgs = maxArgCount;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public CommandBuilder NoArgs()
|
|
||||||
{
|
|
||||||
_command.MinArgs = 0;
|
|
||||||
_command.MaxArgs = 0;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public CommandBuilder AnyArgs()
|
|
||||||
{
|
|
||||||
_command.MinArgs = null;
|
|
||||||
_command.MaxArgs = null;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,32 +59,45 @@ namespace Discord.Commands
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandBuilder Desc(string desc)
|
public void Do(Func<CommandEventArgs, Task> func)
|
||||||
{
|
|
||||||
_command.Description = desc;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandBuilder IsHidden()
|
|
||||||
{
|
|
||||||
_command.IsHidden = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandBuilder Do(Func<CommandEventArgs, Task> func)
|
|
||||||
{
|
{
|
||||||
_command.Handler = func;
|
_command.SetHandler(func);
|
||||||
return this;
|
Build();
|
||||||
}
|
}
|
||||||
public CommandBuilder Do(Action<CommandEventArgs> func)
|
public void Do(Action<CommandEventArgs> func)
|
||||||
{
|
{
|
||||||
_command.Handler = e => { func(e); return TaskHelper.CompletedTask; };
|
_command.SetHandler(func);
|
||||||
return this;
|
Build();
|
||||||
|
}
|
||||||
|
private void Build()
|
||||||
|
{
|
||||||
|
_command.SetParameters(_params.ToArray());
|
||||||
|
foreach (var alias in _command.Aliases)
|
||||||
|
_plugin.Map.AddCommand(alias, _command);
|
||||||
|
_plugin.AddCommand(_command);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string AppendPrefix(string prefix, string cmd)
|
||||||
|
{
|
||||||
|
if (cmd != "")
|
||||||
|
{
|
||||||
|
if (prefix != "")
|
||||||
|
return prefix + ' ' + cmd;
|
||||||
|
else
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (prefix != "")
|
||||||
|
return prefix;
|
||||||
|
else
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(cmd));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public sealed class CommandGroupBuilder
|
public sealed class CommandGroupBuilder
|
||||||
{
|
{
|
||||||
private readonly CommandsPlugin _plugin;
|
internal readonly CommandsPlugin _plugin;
|
||||||
private readonly string _prefix;
|
private readonly string _prefix;
|
||||||
private int _defaultMinPermissions;
|
private int _defaultMinPermissions;
|
||||||
|
|
||||||
@@ -104,25 +122,9 @@ namespace Discord.Commands
|
|||||||
=> CreateCommand("");
|
=> CreateCommand("");
|
||||||
public CommandBuilder CreateCommand(string cmd)
|
public CommandBuilder CreateCommand(string cmd)
|
||||||
{
|
{
|
||||||
string text;
|
var command = new Command(CommandBuilder.AppendPrefix(_prefix, cmd));
|
||||||
if (cmd != "")
|
|
||||||
{
|
|
||||||
if (_prefix != "")
|
|
||||||
text = _prefix + ' ' + cmd;
|
|
||||||
else
|
|
||||||
text = cmd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_prefix != "")
|
|
||||||
text = _prefix;
|
|
||||||
else
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(cmd));
|
|
||||||
}
|
|
||||||
var command = new Command(text);
|
|
||||||
command.MinPerms = _defaultMinPermissions;
|
command.MinPerms = _defaultMinPermissions;
|
||||||
_plugin.AddCommand(command);
|
return new CommandBuilder(_plugin, command, _prefix);
|
||||||
return new CommandBuilder(command);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
84
src/Discord.Net.Commands/CommandMap.cs
Normal file
84
src/Discord.Net.Commands/CommandMap.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Discord.Commands
|
||||||
|
{
|
||||||
|
internal class CommandMap
|
||||||
|
{
|
||||||
|
private CommandMap _parent;
|
||||||
|
private Command _command;
|
||||||
|
private readonly Dictionary<string, CommandMap> _subCommands;
|
||||||
|
|
||||||
|
public CommandMap(CommandMap parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
_subCommands = new Dictionary<string, CommandMap>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandMap GetMap(string text)
|
||||||
|
{
|
||||||
|
CommandMap map;
|
||||||
|
if (_subCommands.TryGetValue(text, out map))
|
||||||
|
return map;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Command GetCommand()
|
||||||
|
{
|
||||||
|
if (_command != null)
|
||||||
|
return _command;
|
||||||
|
else if (_parent != null)
|
||||||
|
return _parent.GetCommand();
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public Command GetCommand(string text)
|
||||||
|
{
|
||||||
|
return GetCommand(0, text.Split(' '));
|
||||||
|
}
|
||||||
|
public Command GetCommand(int index, string[] parts)
|
||||||
|
{
|
||||||
|
if (index != parts.Length)
|
||||||
|
{
|
||||||
|
string nextPart = parts[index];
|
||||||
|
CommandMap nextGroup;
|
||||||
|
if (_subCommands.TryGetValue(nextPart, out nextGroup))
|
||||||
|
{
|
||||||
|
var cmd = nextGroup.GetCommand(index + 1, parts);
|
||||||
|
if (cmd != null)
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_command != null)
|
||||||
|
return _command;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCommand(string text, Command command)
|
||||||
|
{
|
||||||
|
AddCommand(0, text.Split(' '), command);
|
||||||
|
}
|
||||||
|
public void AddCommand(int index, string[] parts, Command command)
|
||||||
|
{
|
||||||
|
if (index != parts.Length)
|
||||||
|
{
|
||||||
|
string nextPart = parts[index];
|
||||||
|
CommandMap nextGroup;
|
||||||
|
if (!_subCommands.TryGetValue(nextPart, out nextGroup))
|
||||||
|
{
|
||||||
|
nextGroup = new CommandMap(this);
|
||||||
|
_subCommands.Add(nextPart, nextGroup);
|
||||||
|
}
|
||||||
|
nextGroup.AddCommand(index + 1, parts, command);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_command != null)
|
||||||
|
throw new InvalidOperationException("A command has already been added with this path.");
|
||||||
|
_command = command;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,37 +15,69 @@ namespace Discord.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Check support for escaping
|
//TODO: Check support for escaping
|
||||||
public static class CommandParser
|
internal static class CommandParser
|
||||||
{
|
{
|
||||||
private enum CommandParserPart
|
private enum CommandParserPart
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
CommandName,
|
|
||||||
Parameter,
|
Parameter,
|
||||||
QuotedParameter,
|
QuotedParameter,
|
||||||
DoubleQuotedParameter
|
DoubleQuotedParameter
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Parse(string input, out string command, out CommandPart[] args)
|
public static bool ParseCommand(string input, CommandMap map, out Command command, out int endPos)
|
||||||
{
|
{
|
||||||
return Parse(input, out command, out args, true);
|
|
||||||
}
|
|
||||||
public static bool ParseArgs(string input, out CommandPart[] args)
|
|
||||||
{
|
|
||||||
string ignored;
|
|
||||||
return Parse(input, out ignored, out args, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool Parse(string input, out string command, out CommandPart[] args, bool parseCommand)
|
|
||||||
{
|
|
||||||
CommandParserPart currentPart = parseCommand ? CommandParserPart.CommandName : CommandParserPart.None;
|
|
||||||
int startPosition = 0;
|
int startPosition = 0;
|
||||||
int endPosition = 0;
|
int endPosition = 0;
|
||||||
|
int inputLength = input.Length;
|
||||||
|
bool isEscaped = false;
|
||||||
|
command = null;
|
||||||
|
endPos = 0;
|
||||||
|
|
||||||
|
if (input == "")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while (endPosition < inputLength)
|
||||||
|
{
|
||||||
|
char currentChar = input[endPosition++];
|
||||||
|
if (isEscaped)
|
||||||
|
isEscaped = false;
|
||||||
|
else if (currentChar == '\\')
|
||||||
|
isEscaped = true;
|
||||||
|
|
||||||
|
if ((!isEscaped && currentChar == ' ') || endPosition >= inputLength)
|
||||||
|
{
|
||||||
|
int length = (currentChar == ' ' ? endPosition - 1 : endPosition) - startPosition;
|
||||||
|
string temp = input.Substring(startPosition, length);
|
||||||
|
if (temp == "")
|
||||||
|
startPosition = endPosition;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var newMap = map.GetMap(temp);
|
||||||
|
if (newMap != null)
|
||||||
|
{
|
||||||
|
map = newMap;
|
||||||
|
endPos = endPosition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
startPosition = endPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
command = map.GetCommand(); //Work our way backwards to find a command that matches our input
|
||||||
|
return command != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ParseArgs(string input, int startPos, Command command, out CommandPart[] args)
|
||||||
|
{
|
||||||
|
CommandParserPart currentPart = CommandParserPart.None;
|
||||||
|
int startPosition = startPos;
|
||||||
|
int endPosition = startPos;
|
||||||
int inputLength = input.Length;
|
int inputLength = input.Length;
|
||||||
bool isEscaped = false;
|
bool isEscaped = false;
|
||||||
List<CommandPart> argList = new List<CommandPart>();
|
List<CommandPart> argList = new List<CommandPart>();
|
||||||
|
|
||||||
command = null;
|
|
||||||
args = null;
|
args = null;
|
||||||
|
|
||||||
if (input == "")
|
if (input == "")
|
||||||
@@ -61,21 +93,6 @@ namespace Discord.Commands
|
|||||||
|
|
||||||
switch (currentPart)
|
switch (currentPart)
|
||||||
{
|
{
|
||||||
case CommandParserPart.CommandName:
|
|
||||||
if ((!isEscaped && currentChar == ' ') || endPosition >= inputLength)
|
|
||||||
{
|
|
||||||
int length = (currentChar == ' ' ? endPosition - 1 : endPosition) - startPosition;
|
|
||||||
string temp = input.Substring(startPosition, length);
|
|
||||||
if (temp == "")
|
|
||||||
startPosition = endPosition;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
currentPart = CommandParserPart.None;
|
|
||||||
command = temp;
|
|
||||||
startPosition = endPosition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CommandParserPart.None:
|
case CommandParserPart.None:
|
||||||
if ((!isEscaped && currentChar == '\"'))
|
if ((!isEscaped && currentChar == '\"'))
|
||||||
{
|
{
|
||||||
@@ -126,9 +143,6 @@ namespace Discord.Commands
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseCommand && (command == null || command == ""))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
args = argList.ToArray();
|
args = argList.ToArray();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace Discord.Commands
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum CommandErrorType { Exception, UnknownCommand, BadPermissions, BadArgCount }
|
public enum CommandErrorType { Exception, UnknownCommand, BadPermissions, BadArgCount, InvalidInput }
|
||||||
public class CommandErrorEventArgs : CommandEventArgs
|
public class CommandErrorEventArgs : CommandEventArgs
|
||||||
{
|
{
|
||||||
public CommandErrorType ErrorType { get; }
|
public CommandErrorType ErrorType { get; }
|
||||||
|
|||||||
@@ -10,29 +10,30 @@ namespace Discord.Commands
|
|||||||
public partial class CommandsPlugin
|
public partial class CommandsPlugin
|
||||||
{
|
{
|
||||||
private readonly DiscordClient _client;
|
private readonly DiscordClient _client;
|
||||||
private Func<User, int> _getPermissions;
|
private readonly Func<User, int> _getPermissions;
|
||||||
|
|
||||||
private Dictionary<string, Command> _commands;
|
|
||||||
|
|
||||||
public Dictionary<string, Command> Commands => _commands;
|
public IEnumerable<Command> Commands => _commands;
|
||||||
|
private readonly List<Command> _commands;
|
||||||
|
|
||||||
public char CommandChar { get { return CommandChars[0]; } set { CommandChars = new List<char> { value }; } } // This could possibly be removed entirely. Not sure.
|
internal CommandMap Map => _map;
|
||||||
public List<char> CommandChars { get; set; }
|
private readonly CommandMap _map;
|
||||||
public bool UseCommandChar { get; set; }
|
|
||||||
|
public IEnumerable<char> CommandChars { get { return _commandChars; } set { _commandChars = value.ToArray(); } }
|
||||||
|
private char[] _commandChars;
|
||||||
|
|
||||||
public bool RequireCommandCharInPublic { get; set; }
|
public bool RequireCommandCharInPublic { get; set; }
|
||||||
public bool RequireCommandCharInPrivate { get; set; }
|
public bool RequireCommandCharInPrivate { get; set; }
|
||||||
public bool HelpInPublic { get; set; }
|
public bool HelpInPublic { get; set; }
|
||||||
|
|
||||||
public CommandsPlugin(DiscordClient client, Func<User, int> getPermissions = null, bool builtInHelp = false)
|
public CommandsPlugin(DiscordClient client, Func<User, int> getPermissions = null, bool builtInHelp = false)
|
||||||
{
|
{
|
||||||
_client = client; // Wait why is this even set
|
_client = client;
|
||||||
_getPermissions = getPermissions;
|
_getPermissions = getPermissions;
|
||||||
|
|
||||||
_commands = new Dictionary<string, Command>();
|
_commands = new List<Command>();
|
||||||
|
_map = new CommandMap(null);
|
||||||
|
|
||||||
CommandChar = '!'; // Kept around to keep from possibly throwing an error. Might not be necessary.
|
_commandChars = new char[] { '!' };
|
||||||
CommandChars = new List<char> { '!', '?', '/' };
|
|
||||||
UseCommandChar = true;
|
|
||||||
RequireCommandCharInPublic = true;
|
RequireCommandCharInPublic = true;
|
||||||
RequireCommandCharInPrivate = true;
|
RequireCommandCharInPrivate = true;
|
||||||
HelpInPublic = true;
|
HelpInPublic = true;
|
||||||
@@ -40,9 +41,9 @@ namespace Discord.Commands
|
|||||||
if (builtInHelp)
|
if (builtInHelp)
|
||||||
{
|
{
|
||||||
CreateCommand("help")
|
CreateCommand("help")
|
||||||
.ArgsBetween(0, 1)
|
.Parameter("command", isOptional: true)
|
||||||
.IsHidden()
|
.IsHidden()
|
||||||
.Desc("Returns information about commands.")
|
.Info("Returns information about commands.")
|
||||||
.Do(async e =>
|
.Do(async e =>
|
||||||
{
|
{
|
||||||
if (e.Command.Text != "help")
|
if (e.Command.Text != "help")
|
||||||
@@ -50,29 +51,18 @@ namespace Discord.Commands
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (e.Args == null)
|
if (e.Args == null)
|
||||||
{
|
{
|
||||||
StringBuilder output = new StringBuilder();
|
int permissions = getPermissions(e.User);
|
||||||
bool first = true;
|
StringBuilder output = new StringBuilder();
|
||||||
output.AppendLine("These are the commands you can use:");
|
output.AppendLine("These are the commands you can use:");
|
||||||
output.Append("`");
|
output.Append("`");
|
||||||
int permissions = getPermissions(e.User);
|
output.Append(string.Join(", ", _commands.Select(x => permissions >= x.MinPerms && !x.IsHidden)));
|
||||||
foreach (KeyValuePair<string, Command> k in _commands)
|
|
||||||
{
|
|
||||||
if (permissions >= k.Value.MinPerms && !k.Value.IsHidden)
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
output.Append(k.Key);
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
output.Append($", {k.Key}");
|
|
||||||
}
|
|
||||||
output.Append("`");
|
output.Append("`");
|
||||||
|
|
||||||
if (CommandChars.Count == 1)
|
if (_commandChars.Length == 1)
|
||||||
output.AppendLine($"{Environment.NewLine}You can use `{CommandChars[0]}` to call a command.");
|
output.AppendLine($"\nYou can use `{_commandChars[0]}` to call a command.");
|
||||||
else
|
else
|
||||||
output.AppendLine($"{Environment.NewLine}You can use `{String.Join(" ", CommandChars.Take(CommandChars.Count - 1))}` and `{CommandChars.Last()}` to call a command.");
|
output.AppendLine($"\nYou can use `{string.Join(" ", CommandChars.Take(_commandChars.Length - 1))}` and `{_commandChars.Last()}` to call a command.");
|
||||||
|
|
||||||
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.");
|
||||||
|
|
||||||
@@ -80,8 +70,9 @@ namespace Discord.Commands
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_commands.ContainsKey(e.Args[0]))
|
var cmd = _map.GetCommand(e.Args[0]);
|
||||||
await Reply(e, CommandDetails(_commands[e.Args[0]]));
|
if (cmd != null)
|
||||||
|
await Reply(e, CommandDetails(cmd));
|
||||||
else
|
else
|
||||||
await Reply(e, $"`{e.Args[0]}` is not a valid command.");
|
await Reply(e, $"`{e.Args[0]}` is not a valid command.");
|
||||||
}
|
}
|
||||||
@@ -99,7 +90,7 @@ namespace Discord.Commands
|
|||||||
string msg = e.Message.Text;
|
string msg = e.Message.Text;
|
||||||
if (msg.Length == 0) return;
|
if (msg.Length == 0) return;
|
||||||
|
|
||||||
if (UseCommandChar)
|
if (_commandChars.Length > 0)
|
||||||
{
|
{
|
||||||
bool isPrivate = e.Message.Channel.IsPrivate;
|
bool isPrivate = e.Message.Channel.IsPrivate;
|
||||||
bool hasCommandChar = CommandChars.Contains(msg[0]);
|
bool hasCommandChar = CommandChars.Contains(msg[0]);
|
||||||
@@ -112,44 +103,41 @@ namespace Discord.Commands
|
|||||||
return; // Same, but public.
|
return; // Same, but public.
|
||||||
}
|
}
|
||||||
|
|
||||||
string cmd;
|
//Parse command
|
||||||
CommandPart[] args;
|
Command command;
|
||||||
if (!CommandParser.Parse(msg, out cmd, out args))
|
int argPos;
|
||||||
return;
|
CommandParser.ParseCommand(msg, _map, out command, out argPos);
|
||||||
|
if (command == null)
|
||||||
if (_commands.ContainsKey(cmd))
|
{
|
||||||
{
|
CommandEventArgs errorArgs = new CommandEventArgs(e.Message, null, null, null);
|
||||||
Command comm = _commands[cmd];
|
RaiseCommandError(CommandErrorType.UnknownCommand, errorArgs);
|
||||||
|
return;
|
||||||
//Clean args
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Parse arguments
|
||||||
|
CommandPart[] args;
|
||||||
|
if (!CommandParser.ParseArgs(msg, argPos, command, out args))
|
||||||
|
{
|
||||||
|
CommandEventArgs errorArgs = new CommandEventArgs(e.Message, null, null, null);
|
||||||
|
RaiseCommandError(CommandErrorType.InvalidInput, errorArgs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int argCount = args.Length;
|
int argCount = args.Length;
|
||||||
string[] newArgs = null;
|
|
||||||
|
|
||||||
if (comm.MaxArgs != null && argCount > 0)
|
|
||||||
{
|
|
||||||
newArgs = new string[(int)comm.MaxArgs];
|
|
||||||
for (int j = 0; j < newArgs.Length; j++)
|
|
||||||
newArgs[j] = args[j].Value;
|
|
||||||
}
|
|
||||||
else if (comm.MaxArgs == null && comm.MinArgs == null)
|
|
||||||
{
|
|
||||||
newArgs = new string[argCount];
|
|
||||||
for (int j = 0; j < newArgs.Length; j++)
|
|
||||||
newArgs[j] = args[j].Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//Get information for the rest of the steps
|
||||||
int userPermissions = _getPermissions != null ? _getPermissions(e.Message.User) : 0;
|
int userPermissions = _getPermissions != null ? _getPermissions(e.Message.User) : 0;
|
||||||
var eventArgs = new CommandEventArgs(e.Message, comm, userPermissions, newArgs);
|
var eventArgs = new CommandEventArgs(e.Message, command, userPermissions, args.Select(x => x.Value).ToArray());
|
||||||
|
|
||||||
// Check permissions
|
// Check permissions
|
||||||
if (userPermissions < comm.MinPerms)
|
if (userPermissions < command.MinPerms)
|
||||||
{
|
{
|
||||||
RaiseCommandError(CommandErrorType.BadPermissions, eventArgs);
|
RaiseCommandError(CommandErrorType.BadPermissions, eventArgs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check arg count
|
//Check arg count
|
||||||
if (argCount < comm.MinArgs)
|
if (argCount < command.MinArgs)
|
||||||
{
|
{
|
||||||
RaiseCommandError(CommandErrorType.BadArgCount, eventArgs);
|
RaiseCommandError(CommandErrorType.BadArgCount, eventArgs);
|
||||||
return;
|
return;
|
||||||
@@ -159,21 +147,13 @@ namespace Discord.Commands
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
RaiseRanCommand(eventArgs);
|
RaiseRanCommand(eventArgs);
|
||||||
var task = comm.Handler(eventArgs);
|
await command.Run(eventArgs).ConfigureAwait(false);
|
||||||
if (task != null)
|
}
|
||||||
await task.ConfigureAwait(false);
|
catch (Exception ex)
|
||||||
}
|
{
|
||||||
catch (Exception ex)
|
RaiseCommandError(CommandErrorType.Exception, eventArgs, ex);
|
||||||
{
|
}
|
||||||
RaiseCommandError(CommandErrorType.Exception, eventArgs, ex);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CommandEventArgs eventArgs = new CommandEventArgs(e.Message, null, null, null);
|
|
||||||
RaiseCommandError(CommandErrorType.UnknownCommand, eventArgs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +178,7 @@ namespace Discord.Commands
|
|||||||
else if (command.MinArgs == null && command.MaxArgs != null)
|
else if (command.MinArgs == null && command.MaxArgs != null)
|
||||||
output.Append($" ≤{command.MaxArgs.ToString()} Args");
|
output.Append($" ≤{command.MaxArgs.ToString()} Args");
|
||||||
|
|
||||||
output.Append($": {command.Description}");
|
output.Append($": {command.Description ?? "No description set for this command."}");
|
||||||
|
|
||||||
return output.ToString();
|
return output.ToString();
|
||||||
}
|
}
|
||||||
@@ -216,13 +196,14 @@ namespace Discord.Commands
|
|||||||
public CommandBuilder CreateCommand(string cmd)
|
public CommandBuilder CreateCommand(string cmd)
|
||||||
{
|
{
|
||||||
var command = new Command(cmd);
|
var command = new Command(cmd);
|
||||||
_commands.Add(cmd, command);
|
_commands.Add(command);
|
||||||
return new CommandBuilder(command);
|
return new CommandBuilder(null, command, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddCommand(Command command)
|
internal void AddCommand(Command command)
|
||||||
{
|
{
|
||||||
_commands.Add(command.Text, command);
|
_commands.Add(command);
|
||||||
|
_map.AddCommand(command.Text, command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user