/// <summary> /// Returns whether or not the text is formatted as a command. /// </summary> /// <param name="text">The message text.</param> /// <returns>Whether or not the text is formatted as a command.</returns> public static bool IsCommand(string text) { if (text.Length <= CommandPrefix.Length) { return(false); } if (!text.ToLower().StartsWith(CommandPrefix.ToLower())) { return(false); } return(true); }
/// <summary> /// Handles a command issued via a Discord message. This does not test if it is a command. Please test with <see cref="IsCommand(string)"/> before running this. /// </summary> /// <param name="originalMessage">The Discord message sent by the command.</param> public static async Task HandleMessageCommand(DiscordMessage originalMessage) { DiscordUser author = originalMessage.Author; BotContext commandContext = BotContextRegistry.GetContext(originalMessage.Channel.Guild); XanBotLogger.WriteDebugLine("Executing command in bot context. Info:"); XanBotLogger.WriteLine(commandContext.ToConsoleString(), isDebugModeOnly: true); XanBotMember member = XanBotMember.GetMemberFromUser(commandContext, author); string text = originalMessage.Content; if (text.ToLower().StartsWith(CommandPrefix.ToLower())) { text = text.Substring(CommandPrefix.Length); } while (AllowSpacesAfterPrefix && text.StartsWith(" ")) { text = text.Substring(1); } string[] allArgs = ArgumentSplitter.SplitArgs(text); string command = allArgs[0]; string[] args = new string[0]; if (allArgs.Length > 1) { args = allArgs.Skip(1).ToArray(); } // Catch case: Prevent excessive command length. if (command.Length > 32) { await ResponseUtil.RespondToAsync(originalMessage, "The command you input is too long."); XanBotLogger.WriteLine(string.Format("§aUser \"§6{0}§a\" issued a command that was considered too long to parse.", member.FullName)); return; } // Catch case: Strip color formatting command.Replace(XanBotLogger.COLOR_CODE_SYM.ToString(), ""); XanBotLogger.WriteDebugLine("Searching for command..."); Command execCommand = null; string cmdLower = command.ToLower(); // Search the context FIRST. That ensures that context commands can override stock commands. foreach (Command cmd in commandContext.Commands) { if (cmd.Name.ToLower() == cmdLower) { execCommand = cmd; XanBotLogger.WriteDebugLine($"Found command [{cmd.Name}] in context."); break; } else { if (cmd.AlternateNames != null) { foreach (string altName in cmd.AlternateNames) { if (altName.ToLower() == cmdLower) { execCommand = cmd; break; } } } } } if (execCommand == null) { foreach (Command cmd in Commands) { if (cmd.Name.ToLower() == command.ToLower()) { execCommand = cmd; XanBotLogger.WriteDebugLine($"Found command [{cmd.Name}] globally."); break; } } } if (execCommand != null) { UsagePermissionPacket usagePerms = execCommand.CanUseCommand(member); if (usagePerms.CanUse) { if (execCommand.CanUseCommandInThisChannel(member, originalMessage.Channel, out DiscordChannel optimalTargetChannel)) { try { string allArgsText = ""; if (args.Length > 0) { allArgsText = text.Substring(command.Length + 1); } originalMessage.Channel.TriggerTypingAsync().GetAwaiter().GetResult(); await execCommand.ExecuteCommandAsync(commandContext, member, originalMessage, args, allArgsText); XanBotLogger.WriteLine(string.Format("§aUser \"§6{0}§a\" issued command \"§6{1}§a\" with args {2}", member.FullName, command, ArrayToText(args))); } catch (CommandException commandErr) { string message = string.Format("§cFailed to issue command `{0}`: §1{1}", commandErr.Command.Name, commandErr.Message); await ResponseUtil.RespondToAsync(originalMessage, message); XanBotLogger.WriteLine(string.Format("§aUser \"§6{0}§a\" attempted to issue command \"§6{1}§a\" but it failed. The command gave the reason: §2{2}", member.FullName, commandErr.Command.Name, commandErr.Message)); } catch (ArchonCommandException commandErr) { string message = string.Format("§cFailed to issue Archon Command `{0}`: §1{1}", commandErr.Command.Name, commandErr.Message); await ResponseUtil.RespondToAsync(originalMessage, message); XanBotLogger.WriteLine(string.Format("§aUser \"§6{0}§a\" attempted to issue Archon Command \"§6{1}§a\" but it failed. The command gave the reason: §2{2}", member.FullName, commandErr.Command.Name, commandErr.Message)); } catch (TaskCanceledException taskCancel) { XanBotLogger.WriteException(taskCancel); } } else { string message = string.Format($"You can't use this command here. Go to <#{optimalTargetChannel.Id}> instead."); await ResponseUtil.RespondToAsync(originalMessage, message); } } else { //string message = string.Format("You are not authorized to use `{0}`. It is only available to permission level `{1}` and above (You are at `{2}`)", execCommand.Name, execCommand.RequiredPermissionLevel, member.PermissionLevel); await ResponseUtil.RespondToAsync(originalMessage, usagePerms.ErrorMessage); XanBotLogger.WriteLine(string.Format("§aUser \"§6{0}§a\" attempted to issue command \"§6{1}§a\" but it failed because they don't have a high enough permission level or because the command's CanUseCommand method returned false.", member.FullName, execCommand.Name)); } } else { await ResponseUtil.RespondToAsync(originalMessage, "The command `" + command + "` does not exist."); XanBotLogger.WriteLine(string.Format("§aUser \"§6{0}§a\" attempted to issue command \"§6{1}§a\" but it failed because it doesn't exist.", member.FullName, command)); } }