Beispiel #1
0
        /// <summary>
        /// Create a <see cref="XanBotMember"/> from a <seealso cref="DiscordUser"/> and a <seealso cref="DiscordGuild"/>
        /// </summary>
        /// <param name="server">The server that this <see cref="XanBotMember"/> exists in.</param>
        /// <param name="user">The <seealso cref="DiscordUser"/> to create the member from.</param>
        /// <returns></returns>
        public static XanBotMember GetMemberFromUser(DiscordGuild server, DiscordUser user)
        {
            if (user == null)
            {
                return(null);
            }
            BotContext ctxForServer = BotContextRegistry.GetContext(server);

            return(GetMemberFromUser(ctxForServer, user));
        }
Beispiel #2
0
        /// <summary>
        /// Runs the <see cref="PassiveHandler"/>s for the server that <paramref name="originalMessage"/> was sent in based on the content from the message.
        /// </summary>
        /// <param name="originalMessage">The chat message.</param>
        public static async Task RunPassiveHandlersForMessage(DiscordMessage originalMessage)
        {
            BotContext   targetContext = BotContextRegistry.GetContext(originalMessage.Channel.Guild);
            XanBotMember sender        = XanBotMember.GetMemberFromUser(targetContext, originalMessage.Author);

            if (!targetContext.Virtual)
            {
                foreach (PassiveHandler handler in targetContext.Handlers)
                {
                    XanBotLogger.WriteDebugLine(handler.Name);
                    if (await handler.RunHandlerAsync(targetContext, sender, originalMessage))
                    {
                        XanBotLogger.WriteDebugLine("... returned true");
                        return;
                    }
                    XanBotLogger.WriteDebugLine("... returned false");
                }
            }
            else
            {
                XanBotLogger.WriteDebugLine("Target context is virtual. Skipping passive handlers.");
            }
        }
Beispiel #3
0
        /// <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));
            }
        }