コード例 #1
0
        /// <summary>
        /// Gathers the data for all commands found in the command modules.
        /// </summary>
        private IEnumerable <HelpDataAttribute> GetCommandDataCollection(UserType userType)
        {
            var commandList = new List <HelpDataAttribute>();

            // Iterate over every installed command
            foreach (ModuleInfo module in _commands.Modules)
            {
                foreach (CommandInfo command in module.Commands)
                {
                    PermissionRestrictionAttribute pra = command.Attributes.FirstOrDefault(a => a is PermissionRestrictionAttribute) as PermissionRestrictionAttribute;
                    // If the command is permission restricted, check if the user is allowed to see it
                    if (pra != null)
                    {
                        // If the user isn't allowed to see the command, go to the next one
                        if (!pra.AllowedRoles.HasFlag(userType))
                        {
                            continue;
                        }
                    }
                    else if (userType.HasFlag(UserType.Staff))
                    {
                        // Make sure normal commands don't show up in the staff menu
                        continue;
                    }

                    HelpDataAttribute helpData = command.Attributes.FirstOrDefault(a => a is HelpDataAttribute) as HelpDataAttribute;
                    // If the command has a help data attribute, include it in the collection
                    if (helpData != null)
                    {
                        commandList.Add(helpData);
                    }
                }
            }

            return(commandList
                   .OrderBy(data => data.ListOrder)
                   .ThenBy(data => data.Usage));
        }
コード例 #2
0
        /// <summary>
        /// Handles a command, represented in the given message.
        /// </summary>
        private async Task HandleCommand(SocketMessage s, DiscordSocketClient client)
        {
            if (!(s is SocketUserMessage msg))
            {
                return;
            }

            int argPos = 0;

            if (!msg.HasStringPrefix(CommandPrefix, ref argPos))
            {
                return;
            }

            IGuildUser     author  = s.Author as IGuildUser;
            CommandContext context = new CommandContext(client, msg);

            Log.WriteLine($"{msg.Author} attempted to invoke \"{msg.Content}\".");

            if (context.IsPrivate)
            {
                // Don't allow bot usage in private messages
                await context.Channel.SendMessageAsync("I'm sorry but you can't use commands here since they don't work in DMs (not my fault, I swear :eyes:). Please run the commands in our server! :smile:");

                return;
            }

            CommandInfo executedCommand = null;

            try
            {
                executedCommand = _commandService.Search(context, argPos).Commands.First().Command;
            }
            catch
            {
                // The executed command wasnt found in the modules, therefore look if any custom commands are registered.

                string command = msg.Content.Substring(argPos).Split(' ')[0].ToLowerInvariant();
                if (_data.CustomCommands.Has(command))
                {
                    string message = _data.CustomCommands.Get(command);
                    await context.Channel.SendMessageAsync(message);
                }
                else
                {
                    // Also no custom command was found? Check all commands and custom commands if there was a close match somewhere

                    const int LEVENSHTEIN_TOLERANCE = 2;

                    IEnumerable <string> commandNames = _commandService.Commands
                                                        .Where(c => // Make sure that only commands that can be used by the user get listed
                    {
                        PermissionRestrictionAttribute pra = c.Attributes.FirstOrDefault(a => a is PermissionRestrictionAttribute) as PermissionRestrictionAttribute;
                        if (pra != null)
                        {
                            UserType roles = pra.AllowedRoles;

                            // Allow the command usage if anyone can use it, or the user is a staff member
                            if (roles.HasFlag(UserType.Everyone) || author.HasStaffRole())
                            {
                                return(true);
                            }
                            // If the command is for gurus, check if the user has the guru role
                            if (roles.HasFlag(UserType.Guru))
                            {
                                return(author.HasGuruRole());
                            }

                            return(false);
                        }
                        return(true);
                    })
                                                        .Select(c => c.Name)
                                                        .Concat(_data.CustomCommands.CommandNames)
                                                        .Distinct();

                    string closeMatch = commandNames
                                        .ToDictionary(l => l, l => command.ToLowerInvariant().ComputeLevenshtein(l.ToLowerInvariant())) // Use lower casing to avoid too high intolerance
                                        .Where(l => l.Value <= LEVENSHTEIN_TOLERANCE)
                                        .OrderBy(l => l.Value)
                                        .FirstOrDefault().Key;

                    if (closeMatch != null)
                    {
                        // A close match was found! Notify the user.
                        EmbedBuilder eb = new EmbedBuilder()
                                          .WithColor(Color.Red)
                                          .WithTitle("Error")
                                          .WithDescription($"The command \"{command}\" could not be found. Did you mean \"{closeMatch}\"?");

                        await context.Channel.SendMessageAsync(string.Empty, false, eb);

                        return;
                    }
                    else
                    {
                        // The entered command was just nonsense. Just ignore it.
                        return;
                    }
                }
                return;
            }

            PermissionRestrictionAttribute restriction = executedCommand.Attributes.FirstOrDefault(a => a is PermissionRestrictionAttribute) as PermissionRestrictionAttribute;

            if (restriction != null)
            {
                EmbedBuilder eb = new EmbedBuilder()
                                  .WithTitle("Insufficient permissions")
                                  .WithDescription("You don't have the required permissions to run that command.")
                                  .WithColor(Color.Red);

                bool     denyInvokation = true;
                UserType roles          = restriction.AllowedRoles;

                // Allow the command usage if anyone can use it, or the user is a staff member
                if (roles.HasFlag(UserType.Everyone) || author.HasStaffRole())
                {
                    denyInvokation = false;
                }
                // If the command is for gurus, check if the user has the guru role
                if (roles.HasFlag(UserType.Guru) && author.HasGuruRole())
                {
                    denyInvokation = false;
                }

                if (denyInvokation)
                {
                    var message = await context.Channel.SendMessageAsync(string.Empty, false, eb);

                    _ = message.TimedDeletion(5000);
                    Log.WriteLine($"The command \"{msg.Content}\" failed with the reason InsufficientPermissions.");
                    return;
                }
            }

            bool   cooldownCommand  = CheckIfCommandHasCooldown(executedCommand.Name.ToLower());
            bool   sameParamCommand = false;
            bool   cooldownExpired  = false;
            string parameters       = "";

            if (cooldownCommand && !UserHelper.HasStaffRole(s.Author as IGuildUser))
            {
                sameParamCommand = CheckIfSameParameterCommand(executedCommand.Name.ToLower());
                parameters       = s.ToString().Remove(0, s.ToString().IndexOf(' ') + 1);
                cooldownExpired  = HasCooldownExpired(executedCommand.Name, s.Author as IGuildUser, sameParamCommand, parameters);
                if (!cooldownExpired)
                {
                    TimeSpan ts = GetTimeUntilCooldownHasExpired(executedCommand.Name.ToLower(), s.Author as IGuildUser, sameParamCommand, parameters);

                    Embed eb = new EmbedBuilder()
                               .WithTitle("Cooldown hasn't expired yet")
                               .WithDescription($"{s.Author.Mention}, you can't run this command yet. Please wait {ts.Hours} hours, {ts.Minutes} minutes and {ts.Seconds} seconds.")
                               .WithColor(Color.Orange);

                    await context.Channel.SendMessageAsync(string.Empty, false, eb);

                    return;
                }
            }

            IResult result = await _commandService.ExecuteAsync(context, argPos, ServiceProvider);

            if (!result.IsSuccess)
            {
                Log.WriteLine($"The command \"{msg.Content}\" failed with the reason {result.Error.Value}: \"{result.ErrorReason}\"");

                if (result.Error == CommandError.UnknownCommand ||
                    result.Error == CommandError.BadArgCount ||
                    result.Error == CommandError.ParseFailed)
                {
                    return;
                }

                EmbedBuilder builder = new EmbedBuilder()
                                       .WithTitle("Error")
                                       .WithDescription(result.ErrorReason)
                                       .WithColor(Color.Red);

                IMessage errorMsg = await context.Channel.SendMessageAsync(string.Empty, false, builder.Build());
            }
            else
            {
                if (cooldownCommand && !UserHelper.HasStaffRole(s.Author as IGuildUser))
                {
                    AddUserToCooldown(executedCommand.Name, s.Author as IGuildUser, sameParamCommand, parameters);
                }
                string command = executedCommand.Name;
                if (_data.Statistics.Has(command))
                {
                    _data.Statistics.Set(command, _data.Statistics.Get(command) + 1);
                }
                else
                {
                    _data.Statistics.Add(command, 1);
                }
            }
        }