public static List <CommandHelpInfo> GetCommands() { List <CommandHelpInfo> _commands = new List <CommandHelpInfo>(); foreach (var _class in _commandLibraries.Keys) { foreach (var _command in _commandLibraries[_class].Keys) { CommandHelpInfo _chi = new CommandHelpInfo { Name = string.Format("{0}.{1}", _class, _command) }; IEnumerable <ParameterInfo> _params = _commandLibraries[_class][_command].ToList(); foreach (var _param in _params) { if (_param.IsOptional) { _chi.OptionalArgs.Add(string.Format("[{0}]", _param.ToString())); } else { _chi.RequiredArgs.Add(string.Format("<{0}>", _param.ToString())); } } _commands.Add(_chi); } } return(_commands); }
private async Task SendAllHelp(bool expanded) { var embed = new EmbedBuilder() { Title = $"{CustomEmoji.PacMan} __**Bot Commands**__", Description = (Prefix == "" ? "No prefix is needed in this channel!" : $"Prefix for this server is '{Prefix}'") + $"\nYou can do **{Prefix}help command** for more information about a command.\n\n" + $"Parameters: [optional] <needed>".If(expanded), Color = Colors.PacManYellow }; foreach (var module in Commands.Modules.OrderBy(m => m.Remarks)) { var moduleText = new StringBuilder(); foreach (var command in module.Commands.OrderBy(c => c.Priority)) { var helpInfo = new CommandHelpInfo(command); if (!helpInfo.Hidden) { var conditions = await command.CheckPreconditionsAsync(Context); if (!conditions.IsSuccess) { continue; } if (expanded) { moduleText.Append($"**{command.Name} {helpInfo.Parameters}**"); if (helpInfo.Remarks != "") { moduleText.Append($" — *{helpInfo.Remarks}*"); } moduleText.Append("\n"); } else { moduleText.Append($"**{command.Name}**, "); } } } if (!expanded && module.Name.Contains("Pac-Man")) { moduleText.Append("**bump**, **cancel**"); } if (moduleText.Length > 0) { embed.AddField(module.Name, moduleText.ToString().Trim(' ', ',', '\n')); } } await ReplyAsync(embed); }
public async Task SendCommandHelp([Remainder] string commandName) { CommandInfo command = Commands.Commands.FirstOrDefault(c => c.Aliases.Contains(commandName)); if (command == null) { await ReplyAsync($"Can't find a command with that name. Use `{Prefix}help` for a list of commands."); return; } var helpInfo = new CommandHelpInfo(command); const string pad = "\nᅠ"; var embed = new EmbedBuilder { Title = $"__Command__: {Prefix}{command.Name}", Color = Colors.PacManYellow }; if (helpInfo.Hidden) { embed.AddField("Hidden command", "*Are you a wizard?*" + pad, true); } if (helpInfo.Parameters != "") { embed.AddField("Parameters", helpInfo.Parameters + pad, true); } if (command.Aliases.Count > 1) { string aliases = command.Aliases.Skip(1).Select(x => $"{Prefix}{x}").JoinString(", "); embed.AddField("Aliases", aliases + pad, true); } if (helpInfo.Summary != "") { var summarySections = helpInfo.Summary.Replace("{prefix}", Prefix).Split("\n\n\n").ToArray(); for (int i = 0; i < summarySections.Length; i++) { embed.AddField("Summary" + $" #{i+1}".If(summarySections.Length > 1), summarySections[i] + pad); } } if (helpInfo.ExampleUsage != "") { embed.AddField("Example Usage", helpInfo.ExampleUsage.Replace("{prefix}", Prefix) + pad); } // I like padding between the fields, but not on the last one embed.Fields.Last().Value = embed.Fields.Last().Value.ToString().Replace(pad, ""); await ReplyAsync(embed); }
private async Task <bool> _executeCommand(SocketUserMessage message) { // If the message is just the bot's prefix, don't attempt to respond to it (this reduces "Unknown command" spam). if (message.Content == Config.Prefix) { return(false); } int pos = _getCommandArgumentsPosition(message); var context = new CommandContext(_discord_client, message); var result = await CommandService.ExecuteAsync(context, pos, ServiceProvider); if (result.IsSuccess) { return(true); } bool show_error_message = true; if (result.Error == CommandError.BadArgCount) { // Get the name of the command that the user attempted to use. System.Text.RegularExpressions.Match command_m = System.Text.RegularExpressions.Regex.Match(message.Content.Substring(pos), @"^[^\s]+", System.Text.RegularExpressions.RegexOptions.IgnoreCase); // If help documentation exists for this command, display it. CommandHelpInfo command_info = HelpUtils.GetCommandInfo(command_m.Value); if (!(command_info is null)) { EmbedBuilder embed = new EmbedBuilder(); embed.WithColor(Color.Red); embed.WithTitle(string.Format("Incorrect usage of \"{0}\" command", command_m.Value)); embed.WithDescription("❌ " + result.ErrorReason); embed.AddField("Example(s) of correct usage:", command_info.ExamplesToString(Config.Prefix)); await context.Channel.SendMessageAsync("", false, embed.Build()); show_error_message = false; } } if (show_error_message) { await BotUtils.ReplyAsync_Error(context, result.ErrorReason); } return(false); }
/// <summary> /// Extract command-level information from the MAML contents. /// </summary> /// <param name="command">The command XML element.</param> /// <param name="descriptor">A command info record.</param> private static void FillInDetails(XElement command, CommandHelpInfo descriptor) { var details = GetChildrenMatching(command, "details").FirstOrDefault(); if (details != null) { descriptor.Name = GetChildrenMatching(details, "name").FirstOrDefault().Value; descriptor.Brief = GetChildrenMatching(details, "description").FirstOrDefault().Value; } FillInDescriptionRecords(GetChildrenMatching(command, "description").FirstOrDefault(), descriptor); }
/// <summary> /// Process a helpInfo forwarded from other providers (normally commandHelpProvider) /// </summary> /// <remarks> /// For command help info, this will /// 1. check whether provider-specific commandlet help exists. /// 2. merge found provider-specific help with commandlet help provided. /// </remarks> /// <param name="helpInfo">helpInfo forwarded in</param> /// <param name="helpRequest">help request object</param> /// <returns>The help info object after processing</returns> override internal HelpInfo ProcessForwardedHelp(HelpInfo helpInfo, HelpRequest helpRequest) { if (helpInfo == null) { return(null); } if (helpInfo.HelpCategory != HelpCategory.Command) { return(helpInfo); } string providerName = helpRequest.Provider; if (String.IsNullOrEmpty(providerName)) { providerName = this._sessionState.Path.CurrentLocation.Provider.Name; } HelpRequest providerHelpRequest = helpRequest.Clone(); providerHelpRequest.Target = providerName; ProviderHelpInfo providerHelpInfo = (ProviderHelpInfo)this.ExactMatchHelp(providerHelpRequest); if (providerHelpInfo == null) { return(null); } CommandHelpInfo commandHelpInfo = (CommandHelpInfo)helpInfo; CommandHelpInfo result = commandHelpInfo.MergeProviderSpecificHelp(providerHelpInfo.GetCmdletHelp(commandHelpInfo.Name), providerHelpInfo.GetDynamicParameterHelp(helpRequest.DynamicParameters)); // Reset ForwardHelpCategory for the helpinfo to be returned so that it will not be forwarded back again. result.ForwardHelpCategory = HelpCategory.None; return(result); }
/// <summary> /// Reads a help file for a given assembly in a given package for a given set of commands. /// Any content that is found is attached to the command record. /// /// </summary> /// <param name="contentRootPath">Absolute path to the content folder containing MAML file</param> /// <param name="assembly">The specific command assembly in which the commands are found.</param> /// <param name="commands">A sequence of command records to look for.</param> internal static void ReadMAMLFile(string contentRootPath, string assembly, IEnumerable<InstalledCmdletInfo> commands) { Debug.Assert(!string.IsNullOrEmpty(contentRootPath)); Debug.Assert(!string.IsNullOrEmpty(assembly)); Debug.Assert(commands != null); var nameSet = commands.ToDictionary(desc => desc.CommandName); var path = Path.Combine(contentRootPath, assembly + "-help.xml"); if (File.Exists(path)) { var doc = XDocument.Load(path); var helpItems = doc.Root; foreach (var command in GetChildrenMatching(helpItems, "command")) { var info = new CommandHelpInfo(); FillInDetails(command, info); InstalledCmdletInfo cmdlet = null; if (string.IsNullOrEmpty(info.Name) || !nameSet.TryGetValue(info.Name, out cmdlet)) { continue; } info.Keys = cmdlet.Keys; cmdlet.Info = info; FillInParameterSets(command, info); } } }
public static async Task ShowHelp(ICommandContext context, string command, string nestedCommand) { // Load the .json files containing command information. // If there is a subdirectory in the help directory with the same name as the command, load files in that subdirectory instead. string help_directory = HelpUtils.HELP_DIRECTORY; if (!string.IsNullOrEmpty(nestedCommand) && System.IO.Directory.Exists(System.IO.Path.Combine(help_directory, command))) { help_directory = System.IO.Path.Combine(help_directory, command); } if (System.IO.Directory.Exists(help_directory)) { CommandHelpInfoCollection commands = HelpUtils.GetCommandInfoFromDirectory(help_directory); if (!string.IsNullOrEmpty(command)) { // If the user provided a specific command name, show information about that command. CommandHelpInfo info = commands.FindCommandByName(string.IsNullOrEmpty(nestedCommand) ? command : nestedCommand); if (info is null) { await context.Channel.SendMessageAsync("The given command does not exist, or is not yet documented."); } else { // Prefix the command with is parent if applicable. if (!string.IsNullOrEmpty(nestedCommand)) { info.Name = command.Trim() + " " + info.Name; } EmbedBuilder builder = new EmbedBuilder(); builder.WithTitle(string.Format("Help: {0}", info.Name)); builder.AddField("Description", info.Description.Replace("\\prefix", OurFoodChainBot.Instance.Config.Prefix)); if (info.Aliases.Count() > 0) { builder.AddField("Aliases", string.Join(", ", info.Aliases.OrderBy(x => x))); } if (info.Examples.Count() > 0) { for (int i = 0; i < info.Examples.Count(); ++i) { info.Examples[i] = "`" + OurFoodChainBot.Instance.Config.Prefix + (string.IsNullOrEmpty(nestedCommand) ? "" : command.Trim() + " ") + info.Examples[i] + "`"; } builder.AddField("Example(s)", string.Join(Environment.NewLine, info.Examples)); } await context.Channel.SendMessageAsync("", false, builder.Build()); } } else { await _showHelpCategory(context, commands, ""); } } else { await BotUtils.ReplyAsync_Error(context, string.Format("Help information cannot be displayed, because the help directory \"{0}\" does not exist.", help_directory)); } }
/// <summary> /// Fill in information for parameter sets and parameters. /// </summary> /// <param name="command">The command XML element.</param> /// <param name="descriptor">A command info record.</param> private static void FillInParameterSets(XElement command, CommandHelpInfo descriptor) { var syntax = GetChildrenMatching(command, "syntax").FirstOrDefault(); if (syntax != null) { foreach (var syntaxItem in GetChildrenMatching(syntax, "syntaxItem")) { var pset = new ParameterSetHelpInfo(); descriptor.ParameterSets.Add(pset); foreach (var param in GetChildrenMatching(syntaxItem, "parameter")) { var p = new ParameterHelpInfo(); pset.Parameters.Add(p); var name = GetChildrenMatching(param, "name").FirstOrDefault(); if (name != null) p.Name = name.Value; var type = GetChildrenMatching(param, "parameterValue").FirstOrDefault(); if (type != null) p.Type = type.Value; var required = GetAttributeMatching(param, "required").FirstOrDefault(); if (required != null) p.IsMandatory = bool.Parse(required.Value); var position = GetAttributeMatching(param, "position").FirstOrDefault(); if (position != null) { int pos = int.MaxValue; if (int.TryParse(position.Value, out pos)) p.Position = pos; } FillInDescriptionRecords(GetChildrenMatching(param, "description").FirstOrDefault(), p); } pset.Parameters.Sort((x, y) => x.Position.CompareTo(y.Position)); } } }