private async Task ParseCommandFromMatchesAsync(CommandContext context, CommandDelegate next) { context.Features.Set <IArgumentParserFeature>(new ArgumentParserFeature()); var matchesFeature = context.Features.Get <ICommandMatchesFeature>(); var argumentParserFeature = context.Features.Get <IArgumentParserFeature>(); if (matchesFeature.HasNoContent() || matchesFeature.CommandMatches.HasNoContent()) { throw new InvalidOperationException($"Can't get command matches from feature: {nameof(ICommandMatchesFeature)}."); } var bestMatches = new List <ICommandMatch>(); var fails = new Dictionary <ICommand, IResult>(); foreach (var match in matchesFeature.CommandMatches) { var result = await ParseCommandAsync(context, match.Command, match.RemainingInput); if (result.Success) { bestMatches.Add(match); argumentParserFeature.CommandArgs.Add(match, result.Args.Values.ToArray()); } else { fails.Add(match.Command, result); } } if (bestMatches.HasNoContent()) { _logger.LogInformation("All matched commands returned fail for command parsing."); context.Result = MiddlewareUtils.GetErrorResult(fails); return; } var config = context.CommandServices.GetRequiredService <IOptions <MariCommandsOptions> >().Value; if (!config.ContinueMultiMatchAfterParser) { bestMatches = bestMatches .OrderByDescending(a => a.Command.Priority) .Take(1) .ToList(); var bestMatch = bestMatches.FirstOrDefault(); context.Command = bestMatch.Command; context.Alias = bestMatch.Alias; context.Args = argumentParserFeature.CommandArgs[bestMatch].ToList(); } matchesFeature.CommandMatches = bestMatches; await next(context); }
public async Task InvokeAsync(CommandContext context, CommandDelegate next) { context.NotNull(nameof(context)); if (context.Result.HasContent()) { await next(context); return; } var isUniqueCommand = context.Command.HasContent() && context.Args != null; if (isUniqueCommand) { var result = await ExecutePreconditionsForContextAsync(context); if (result.Success) { await next(context); } else { context.Result = result; } return; } var matchesFeature = context.Features.Get <ICommandMatchesFeature>(); if (matchesFeature.HasNoContent() || matchesFeature.CommandMatches.HasNoContent()) { throw new InvalidOperationException($"Can't get command matches from feature: {nameof(ICommandMatchesFeature)}."); } var argumentParserFeature = context.Features.Get <IArgumentParserFeature>(); if (argumentParserFeature.HasNoContent() || argumentParserFeature.CommandArgs.HasNoContent()) { throw new InvalidOperationException($"Can't get command matches parsed param values from feature: {nameof(IArgumentParserFeature)}."); } var matches = matchesFeature.CommandMatches; var parsedArgs = argumentParserFeature.CommandArgs; var fails = new Dictionary <ICommand, IResult>(); var bestMatches = new List <ICommandMatch>(); foreach (var match in matches) { var command = match.Command; var args = parsedArgs[match]; var result = await ExecutePreconditionsAsync(command, args, context); if (result.Success) { bestMatches.Add(match); } else { fails.Add(command, result); } } if (bestMatches.HasNoContent()) { _logger.LogInformation("All matched commands returned fail for input count."); context.Result = MiddlewareUtils.GetErrorResult(fails); return; } matchesFeature.CommandMatches = bestMatches; await next(context); }
public async Task InvokeAsync(CommandContext context, CommandDelegate next) { context.NotNull(nameof(context)); if (context.Result.HasContent() || context.Args != null) { await next(context); return; } var verifyCommandInputCount = context.Command.HasContent() && !string.IsNullOrWhiteSpace(context.RawArgs); if (verifyCommandInputCount) { context.Features.Set <ICommandMatchesFeature>(new CommandMatchesFeature { CommandMatches = new List <ICommandMatch> { new CommandMatch(context.Command, null, null, context.RawArgs) } }); } var matchesFeature = context.Features.Get <ICommandMatchesFeature>(); if (matchesFeature.HasNoContent() || matchesFeature.CommandMatches.HasNoContent()) { throw new InvalidOperationException($"Can't get command matches from feature: {nameof(ICommandMatchesFeature)}."); } var multiMatches = new List <ICommandMatch>(); if (matchesFeature.CommandMatches.Count > 1) { multiMatches = matchesFeature.CommandMatches .Where(a => a.Command.Module.GetMatchHandling(_config) == MultiMatchHandling.Best) .ToList(); } else { multiMatches = matchesFeature.CommandMatches.ToList(); } if (multiMatches.HasNoContent()) { _logger.LogInformation($"This input has more than one match but none of then has {MultiMatchHandling.Best} as configuration."); context.Result = MultiMatchErrorResult.FromMatches(matchesFeature.CommandMatches); return; } matchesFeature.CommandMatches = multiMatches; var bestMatches = new List <ICommandMatch>(); var fails = new Dictionary <ICommand, IResult>(); foreach (var match in matchesFeature.CommandMatches) { var inputCount = string.IsNullOrWhiteSpace(match.RemainingInput) ? 0 : match.RemainingInput.Split(_config.Separator).Count(); var command = match.Command; if (command.Parameters.Count > inputCount) { var hasAnyOptional = command.Parameters.Any(a => IsOptional(a)); if (!hasAnyOptional) { fails.Add(command, BadArgCountResult.FromCommand(command)); continue; } var optionalsCount = command.Parameters.Count(a => IsOptional(a)); var missingCount = command.Parameters.Count - inputCount; if (optionalsCount < missingCount) { fails.Add(command, BadArgCountResult.FromCommand(command)); continue; } } else if (command.Parameters.Count < inputCount) { var ignoreExtraArgs = command.GetIgnoreExtraArgs(_config); if (!ignoreExtraArgs) { fails.Add(command, BadArgCountResult.FromCommand(command)); continue; } } bestMatches.Add(match); } if (bestMatches.HasNoContent()) { _logger.LogInformation("All matched commands returned fail for input count."); context.Result = MiddlewareUtils.GetErrorResult(fails); return; } matchesFeature.CommandMatches = bestMatches; await next(context); }