Added support for unparsed parameters, more cleanup
This commit is contained in:
@@ -32,7 +32,7 @@ namespace Discord.Commands
|
|||||||
public string Text { get; }
|
public string Text { get; }
|
||||||
public int? MinArgs { get; private set; }
|
public int? MinArgs { get; private set; }
|
||||||
public int? MaxArgs { get; private set; }
|
public int? MaxArgs { get; private set; }
|
||||||
public int MinPerms { get; internal set; }
|
public int MinPermissions { 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; }
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ namespace Discord.Commands
|
|||||||
private string[] _aliases;
|
private string[] _aliases;
|
||||||
|
|
||||||
public IEnumerable<CommandParameter> Parameters => _parameters;
|
public IEnumerable<CommandParameter> Parameters => _parameters;
|
||||||
private CommandParameter[] _parameters;
|
internal CommandParameter[] _parameters;
|
||||||
|
|
||||||
private Func<CommandEventArgs, Task> _handler;
|
private Func<CommandEventArgs, Task> _handler;
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Discord.Commands
|
|||||||
{
|
{
|
||||||
if (_isClosed)
|
if (_isClosed)
|
||||||
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 (!_allowRequired && 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));
|
||||||
@@ -57,7 +57,7 @@ namespace Discord.Commands
|
|||||||
|
|
||||||
public CommandBuilder MinPermissions(int level)
|
public CommandBuilder MinPermissions(int level)
|
||||||
{
|
{
|
||||||
_command.MinPerms = level;
|
_command.MinPermissions = level;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +125,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));
|
||||||
command.MinPerms = _defaultMinPermissions;
|
command.MinPermissions = _defaultMinPermissions;
|
||||||
return new CommandBuilder(_plugin, command, _prefix);
|
return new CommandBuilder(_plugin, command, _prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,6 @@
|
|||||||
|
|
||||||
namespace Discord.Commands
|
namespace Discord.Commands
|
||||||
{
|
{
|
||||||
public class CommandPart
|
|
||||||
{
|
|
||||||
public string Value { get; }
|
|
||||||
public int Index { get; }
|
|
||||||
|
|
||||||
internal CommandPart(string value, int index)
|
|
||||||
{
|
|
||||||
Value = value;
|
|
||||||
Index = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Check support for escaping
|
|
||||||
internal static class CommandParser
|
internal static class CommandParser
|
||||||
{
|
{
|
||||||
private enum CommandParserPart
|
private enum CommandParserPart
|
||||||
@@ -69,23 +56,40 @@ namespace Discord.Commands
|
|||||||
return command != null;
|
return command != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ParseArgs(string input, int startPos, Command command, out CommandPart[] args)
|
//TODO: Check support for escaping
|
||||||
|
public static CommandErrorType? ParseArgs(string input, int startPos, Command command, out string[] args)
|
||||||
{
|
{
|
||||||
CommandParserPart currentPart = CommandParserPart.None;
|
CommandParserPart currentPart = CommandParserPart.None;
|
||||||
int startPosition = startPos;
|
int startPosition = startPos;
|
||||||
int endPosition = startPos;
|
int endPosition = startPos;
|
||||||
int inputLength = input.Length;
|
int inputLength = input.Length;
|
||||||
bool isEscaped = false;
|
bool isEscaped = false;
|
||||||
List<CommandPart> argList = new List<CommandPart>();
|
|
||||||
|
var expectedArgs = command._parameters;
|
||||||
|
List<string> argList = new List<string>();
|
||||||
|
CommandParameter parameter = null;
|
||||||
|
|
||||||
args = null;
|
args = null;
|
||||||
|
|
||||||
if (input == "")
|
if (input == "")
|
||||||
return false;
|
return CommandErrorType.InvalidInput;
|
||||||
|
|
||||||
while (endPosition < inputLength)
|
while (endPosition < inputLength)
|
||||||
{
|
{
|
||||||
char currentChar = input[endPosition++];
|
if (startPosition == endPosition && (parameter == null || parameter.Type != ParameterType.Multiple)) //Is first char of a new arg
|
||||||
|
{
|
||||||
|
if (argList.Count == command.MaxArgs)
|
||||||
|
return CommandErrorType.BadArgCount;
|
||||||
|
|
||||||
|
parameter = command._parameters[argList.Count];
|
||||||
|
if (parameter.Type == ParameterType.Unparsed)
|
||||||
|
{
|
||||||
|
argList.Add(input.Substring(startPosition));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char currentChar = input[endPosition++];
|
||||||
if (isEscaped)
|
if (isEscaped)
|
||||||
isEscaped = false;
|
isEscaped = false;
|
||||||
else if (currentChar == '\\')
|
else if (currentChar == '\\')
|
||||||
@@ -113,7 +117,7 @@ namespace Discord.Commands
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentPart = CommandParserPart.None;
|
currentPart = CommandParserPart.None;
|
||||||
argList.Add(new CommandPart(temp, startPosition));
|
argList.Add(temp);
|
||||||
startPosition = endPosition;
|
startPosition = endPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,28 +127,31 @@ namespace Discord.Commands
|
|||||||
{
|
{
|
||||||
string temp = input.Substring(startPosition, endPosition - startPosition - 1);
|
string temp = input.Substring(startPosition, endPosition - startPosition - 1);
|
||||||
currentPart = CommandParserPart.None;
|
currentPart = CommandParserPart.None;
|
||||||
argList.Add(new CommandPart(temp, startPosition));
|
argList.Add(temp);
|
||||||
startPosition = endPosition;
|
startPosition = endPosition;
|
||||||
}
|
}
|
||||||
else if (endPosition >= inputLength)
|
else if (endPosition >= inputLength)
|
||||||
return false;
|
return CommandErrorType.InvalidInput;
|
||||||
break;
|
break;
|
||||||
case CommandParserPart.DoubleQuotedParameter:
|
case CommandParserPart.DoubleQuotedParameter:
|
||||||
if ((!isEscaped && currentChar == '\"'))
|
if ((!isEscaped && currentChar == '\"'))
|
||||||
{
|
{
|
||||||
string temp = input.Substring(startPosition, endPosition - startPosition - 1);
|
string temp = input.Substring(startPosition, endPosition - startPosition - 1);
|
||||||
currentPart = CommandParserPart.None;
|
currentPart = CommandParserPart.None;
|
||||||
argList.Add(new CommandPart(temp, startPosition));
|
argList.Add(temp);
|
||||||
startPosition = endPosition;
|
startPosition = endPosition;
|
||||||
}
|
}
|
||||||
else if (endPosition >= inputLength)
|
else if (endPosition >= inputLength)
|
||||||
return false;
|
return CommandErrorType.InvalidInput;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argList.Count < command.MinArgs)
|
||||||
|
return CommandErrorType.BadArgCount;
|
||||||
|
|
||||||
args = argList.ToArray();
|
args = argList.ToArray();
|
||||||
return true;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ namespace Discord.Commands
|
|||||||
internal CommandMap Map => _map;
|
internal CommandMap Map => _map;
|
||||||
private readonly CommandMap _map;
|
private readonly CommandMap _map;
|
||||||
|
|
||||||
public char ComamndChar { get { return _commandChars[0]; } set { _commandChars = new char[] { value }; } }
|
public char? ComamndChar
|
||||||
|
{
|
||||||
|
get { return _commandChars.Length > 0 ? _commandChars[0] : (char?)null; }
|
||||||
|
set { _commandChars = value != null ? new char[] { value.Value } : new char[0]; }
|
||||||
|
}
|
||||||
public IEnumerable<char> CommandChars { get { return _commandChars; } set { _commandChars = value.ToArray(); } }
|
public IEnumerable<char> CommandChars { get { return _commandChars; } set { _commandChars = value.ToArray(); } }
|
||||||
private char[] _commandChars;
|
private char[] _commandChars;
|
||||||
|
|
||||||
@@ -54,16 +58,20 @@ namespace Discord.Commands
|
|||||||
if (e.Args == null)
|
if (e.Args == null)
|
||||||
{
|
{
|
||||||
int permissions = getPermissions(e.User);
|
int permissions = getPermissions(e.User);
|
||||||
|
|
||||||
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:");
|
||||||
output.Append("`");
|
output.Append("`");
|
||||||
output.Append(string.Join(", ", _commands.Select(x => permissions >= x.MinPerms && !x.IsHidden)));
|
output.Append(string.Join(", ", _commands.Select(x => permissions >= x.MinPermissions && !x.IsHidden)));
|
||||||
output.Append("`");
|
output.Append("`");
|
||||||
|
|
||||||
if (_commandChars.Length == 1)
|
if (_commandChars.Length > 0)
|
||||||
output.AppendLine($"\nYou can use `{_commandChars[0]}` to call a command.");
|
{
|
||||||
else
|
if (_commandChars.Length == 1)
|
||||||
output.AppendLine($"\nYou can use `{string.Join(" ", CommandChars.Take(_commandChars.Length - 1))}` and `{_commandChars.Last()}` to call a command.");
|
output.AppendLine($"\nYou can use `{_commandChars[0]}` to call a command.");
|
||||||
|
else
|
||||||
|
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.");
|
||||||
|
|
||||||
@@ -84,17 +92,17 @@ namespace Discord.Commands
|
|||||||
|
|
||||||
client.MessageReceived += async (s, e) =>
|
client.MessageReceived += async (s, e) =>
|
||||||
{
|
{
|
||||||
// This will need to be changed once a built in help command is made
|
|
||||||
if (_commands.Count == 0) return;
|
if (_commands.Count == 0) return;
|
||||||
if (e.Message.IsAuthor) return;
|
if (e.Message.IsAuthor) return;
|
||||||
|
|
||||||
string msg = e.Message.Text;
|
string msg = e.Message.Text;
|
||||||
if (msg.Length == 0) return;
|
if (msg.Length == 0) return;
|
||||||
|
|
||||||
|
//Check for command char if one is provided
|
||||||
if (_commandChars.Length > 0)
|
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]);
|
||||||
if (hasCommandChar)
|
if (hasCommandChar)
|
||||||
msg = msg.Substring(1);
|
msg = msg.Substring(1);
|
||||||
|
|
||||||
@@ -116,34 +124,27 @@ namespace Discord.Commands
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
int userPermissions = _getPermissions != null ? _getPermissions(e.Message.User) : 0;
|
||||||
|
|
||||||
//Parse arguments
|
//Parse arguments
|
||||||
CommandPart[] args;
|
string[] args;
|
||||||
if (!CommandParser.ParseArgs(msg, argPos, command, out args))
|
var error = CommandParser.ParseArgs(msg, argPos, command, out args);
|
||||||
|
if (error != null)
|
||||||
{
|
{
|
||||||
CommandEventArgs errorArgs = new CommandEventArgs(e.Message, null, null, null);
|
var errorArgs = new CommandEventArgs(e.Message, command, userPermissions, null);
|
||||||
RaiseCommandError(CommandErrorType.InvalidInput, errorArgs);
|
RaiseCommandError(error.Value, errorArgs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int argCount = args.Length;
|
|
||||||
|
var eventArgs = new CommandEventArgs(e.Message, command, userPermissions, args);
|
||||||
//Get information for the rest of the steps
|
|
||||||
int userPermissions = _getPermissions != null ? _getPermissions(e.Message.User) : 0;
|
|
||||||
var eventArgs = new CommandEventArgs(e.Message, command, userPermissions, args.Select(x => x.Value).ToArray());
|
|
||||||
|
|
||||||
// Check permissions
|
// Check permissions
|
||||||
if (userPermissions < command.MinPerms)
|
if (userPermissions < command.MinPermissions)
|
||||||
{
|
{
|
||||||
RaiseCommandError(CommandErrorType.BadPermissions, eventArgs);
|
RaiseCommandError(CommandErrorType.BadPermissions, eventArgs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check arg count
|
|
||||||
if (argCount < command.MinArgs)
|
|
||||||
{
|
|
||||||
RaiseCommandError(CommandErrorType.BadArgCount, eventArgs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the command
|
// Run the command
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user