Search in sources :

Example 1 with CommandWrapper

use of de.nikos410.discordbot.framework.CommandWrapper in project de-DiscordBot by DACH-Discord.

the class DiscordBot method discoverCommands.

private List<CommandWrapper> discoverCommands(final ModuleWrapper moduleWrapper) {
    LOG.debug("Registering command(s) for module '{}'.", moduleWrapper.getName());
    final List<CommandWrapper> commands = new LinkedList<>();
    final Method[] allMethods = moduleWrapper.getModuleClass().getMethods();
    final List<Method> commandMethods = Arrays.stream(allMethods).filter(module -> module.isAnnotationPresent(CommandSubscriber.class)).collect(Collectors.toList());
    for (final Method method : commandMethods) {
        // Register methods with the @CommandSubscriber as commands
        // All annotations of type CommandSubscriber declared for that Method. Should be exactly 1
        final CommandSubscriber annotation = method.getDeclaredAnnotationsByType(CommandSubscriber.class)[0];
        // Get command properties from annotation
        final String commandName = annotation.command();
        final String commandHelp = annotation.help();
        final boolean pmAllowed = annotation.pmAllowed();
        final PermissionLevel permissionLevel = annotation.permissionLevel();
        final boolean passContext = annotation.passContext();
        final boolean ignoreParameterCount = annotation.ignoreParameterCount();
        final int parameterCount = method.getParameterCount() - 1;
        if ((parameterCount >= 0 && parameterCount <= 5) || ignoreParameterCount) {
            final CommandWrapper commandWrapper = new CommandWrapper(commandName, commandHelp, moduleWrapper, method, pmAllowed, permissionLevel, parameterCount, passContext, ignoreParameterCount);
            commands.add(commandWrapper);
            LOG.debug("Saved command '{}'.", commandName);
        } else {
            LOG.warn("Method '{}' has an invalid number of arguments. Skipping", commandName);
        }
    }
    return commands;
}
Also used : java.util(java.util) Authorization(de.nikos410.discordbot.util.discord.Authorization) LoggerFactory(org.slf4j.LoggerFactory) MessageUpdateEvent(sx.blah.discord.handle.impl.events.guild.channel.message.MessageUpdateEvent) Reflections(org.reflections.Reflections) DiscordIO(de.nikos410.discordbot.util.discord.DiscordIO) ModuleWrapper(de.nikos410.discordbot.framework.ModuleWrapper) ReadyEvent(sx.blah.discord.handle.impl.events.ReadyEvent) MessageReceivedEvent(sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent) JSONObject(org.json.JSONObject) ModuleStatus(de.nikos410.discordbot.framework.ModuleWrapper.ModuleStatus) InitializationException(de.nikos410.discordbot.exception.InitializationException) CommandWrapper(de.nikos410.discordbot.framework.CommandWrapper) Method(java.lang.reflect.Method) Path(java.nio.file.Path) Logger(org.slf4j.Logger) PermissionLevel(de.nikos410.discordbot.framework.PermissionLevel) Files(java.nio.file.Files) CommandModule(de.nikos410.discordbot.framework.CommandModule) EventSubscriber(sx.blah.discord.api.events.EventSubscriber) Instant(java.time.Instant) UserUtils(de.nikos410.discordbot.util.discord.UserUtils) Collectors(java.util.stream.Collectors) InvocationTargetException(java.lang.reflect.InvocationTargetException) TimeUnit(java.util.concurrent.TimeUnit) IDiscordClient(sx.blah.discord.api.IDiscordClient) sx.blah.discord.handle.obj(sx.blah.discord.handle.obj) ChronoUnit(java.time.temporal.ChronoUnit) BotSetup(de.nikos410.discordbot.modules.BotSetup) IOUtil(de.nikos410.discordbot.util.io.IOUtil) Paths(java.nio.file.Paths) DiscordException(sx.blah.discord.util.DiscordException) EventDispatcher(sx.blah.discord.api.events.EventDispatcher) CommandSubscriber(de.nikos410.discordbot.framework.annotations.CommandSubscriber) JSONArray(org.json.JSONArray) CommandWrapper(de.nikos410.discordbot.framework.CommandWrapper) Method(java.lang.reflect.Method) PermissionLevel(de.nikos410.discordbot.framework.PermissionLevel) CommandSubscriber(de.nikos410.discordbot.framework.annotations.CommandSubscriber)

Example 2 with CommandWrapper

use of de.nikos410.discordbot.framework.CommandWrapper in project de-DiscordBot by DACH-Discord.

the class BotSetup method command_help.

@CommandSubscriber(command = "help", help = "Zeigt diese Hilfe an")
public void command_help(final IMessage message) {
    final EmbedBuilder helpEmbedBuilder = new EmbedBuilder();
    final List<ModuleWrapper> loadedModules = bot.getLoadedModules();
    for (ModuleWrapper module : loadedModules) {
        final StringBuilder moduleHelpBuilder = new StringBuilder();
        for (CommandWrapper command : module.getCommands()) {
            // Only list commands that are available to that user
            if (bot.getUserPermissionLevel(message.getAuthor(), message.getGuild()).getLevel() >= command.getPermissionLevel().getLevel()) {
                moduleHelpBuilder.append(String.format("`%s` - %s%n", command.getName(), command.getHelp()));
            }
        }
        final String helpString = moduleHelpBuilder.toString();
        if (moduleHelpBuilder.length() > 0) {
            helpEmbedBuilder.appendField(module.getDisplayName(), helpString, false);
        }
    }
    final EmbedObject embedObject = helpEmbedBuilder.build();
    DiscordIO.sendEmbed(message.getAuthor().getOrCreatePMChannel(), embedObject);
    if (!message.getChannel().isPrivate()) {
        DiscordIO.sendMessage(message.getChannel(), ":mailbox_with_mail:");
    }
}
Also used : EmbedBuilder(sx.blah.discord.util.EmbedBuilder) ModuleWrapper(de.nikos410.discordbot.framework.ModuleWrapper) CommandWrapper(de.nikos410.discordbot.framework.CommandWrapper) EmbedObject(sx.blah.discord.api.internal.json.objects.EmbedObject) CommandSubscriber(de.nikos410.discordbot.framework.annotations.CommandSubscriber)

Example 3 with CommandWrapper

use of de.nikos410.discordbot.framework.CommandWrapper in project de-DiscordBot by DACH-Discord.

the class DiscordBot method makeCommandMap.

/**
 * Populates global command map, maps a 'CommandWrapper' instance, containing a commands attributes, to each command.
 */
private void makeCommandMap() {
    LOG.debug("Creating command map.");
    LOG.debug("Clearing old commands.");
    this.commands.clear();
    final List<ModuleWrapper> loadedModules = getLoadedModules();
    for (final ModuleWrapper moduleWrapper : loadedModules) {
        for (final CommandWrapper commandWrapper : moduleWrapper.getCommands()) {
            this.commands.put(commandWrapper.getName().toLowerCase(), commandWrapper);
        }
    }
}
Also used : ModuleWrapper(de.nikos410.discordbot.framework.ModuleWrapper) CommandWrapper(de.nikos410.discordbot.framework.CommandWrapper)

Example 4 with CommandWrapper

use of de.nikos410.discordbot.framework.CommandWrapper in project de-DiscordBot by DACH-Discord.

the class DiscordBot method handleMessage.

/**
 * Process a received or edited message. Check if it contains a command and execute the corresponding method.
 *
 * @param message The received/edited message
 */
private void handleMessage(final IMessage message) {
    final String messageContent = message.getContent();
    // Check if the message starts with the configured prefix
    if (!messageContent.startsWith(this.prefix)) {
        return;
    }
    // Get only the command in lower case without prefix/parameters
    final String commandName = (messageContent.contains(" ") ? // Message contains parameters
    messageContent.substring(this.prefix.length(), messageContent.indexOf(' ')) : // Message doesn't contain parameters
    messageContent.substring(this.prefix.length())).toLowerCase();
    // Check if a command with that name is known
    if (!commands.containsKey(commandName)) {
        return;
    }
    final CommandWrapper command = commands.get(commandName);
    LOG.info("User {} used command {}", UserUtils.makeUserString(message.getAuthor(), message.getGuild()), commandName);
    // The command was received in a PM but is only available on guilds
    if (message.getChannel().isPrivate() && !command.isPmAllowed()) {
        DiscordIO.sendMessage(message.getChannel(), "Dieser Befehl ist nicht in Privatnachrichten verfügbar!");
        LOG.info("CommandWrapper {} is not available in PMs.", commandName);
        return;
    }
    // Check if the user is allowed to use that command
    final PermissionLevel userPermissionLevel = this.getUserPermissionLevel(message.getAuthor(), message.getGuild());
    LOG.debug("Checking permissions. User: {} | Required: {}", userPermissionLevel, command.getPermissionLevel());
    if (userPermissionLevel.getLevel() < command.getPermissionLevel().getLevel()) {
        DiscordIO.sendMessage(message.getChannel(), String.format("Dieser Befehl ist für deine Gruppe (%s) nicht verfügbar.", userPermissionLevel.getName()));
        LOG.info("User {} doesn't have the required permissions for using the command {}.", UserUtils.makeUserString(message.getAuthor(), message.getGuild()), commandName);
        return;
    }
    final int expectedParameterCount = command.getExpectedParameterCount();
    final List<String> parameters = parseParameters(messageContent, commandName, expectedParameterCount, command.isPassContext());
    // Check if the user used the correct number of parameters
    if (parameters.size() < expectedParameterCount) {
        if (command.isIgnoreParameterCount()) {
            while (parameters.size() < expectedParameterCount) {
                parameters.add(null);
            }
        } else {
            DiscordIO.sendMessage(message.getChannel(), String.format("Dieser Befehl benötigt mindestens %s Parameter! (Gegeben: %s)", expectedParameterCount, parameters.size()));
            LOG.info("Wrong number of arguments. Expected number: {} Actual number: {}", expectedParameterCount, parameters.size());
            return;
        }
    }
    executeCommand(command, parameters, message);
}
Also used : CommandWrapper(de.nikos410.discordbot.framework.CommandWrapper) PermissionLevel(de.nikos410.discordbot.framework.PermissionLevel)

Example 5 with CommandWrapper

use of de.nikos410.discordbot.framework.CommandWrapper in project de-DiscordBot by DACH-Discord.

the class DiscordBot method executeCommand.

/**
 * Invoke the method specified in a CommandWrapper with the parameters in a List
 *
 * @param command The instance containing the attributes of the command, specifically the method to invoke
 * @param parameters The parameters to use while invoking the method
 * @param message The message that triggered the command
 */
private void executeCommand(final CommandWrapper command, final List<String> parameters, final IMessage message) {
    LOG.debug("Executing command {} with {} parameters.", command.getName(), parameters.size());
    final Method method = command.getMethod();
    final CommandModule instance = command.getModule().getInstance();
    try {
        switch(parameters.size()) {
            case 0:
                method.invoke(instance, message);
                break;
            case 1:
                method.invoke(instance, message, parameters.get(0));
                break;
            case 2:
                method.invoke(instance, message, parameters.get(0), parameters.get(1));
                break;
            case 3:
                method.invoke(instance, message, parameters.get(0), parameters.get(1), parameters.get(2));
                break;
            case 4:
                method.invoke(instance, message, parameters.get(0), parameters.get(1), parameters.get(2), parameters.get(3));
                break;
            case 5:
                method.invoke(instance, message, parameters.get(0), parameters.get(1), parameters.get(2), parameters.get(3), parameters.get(4));
                break;
            default:
                throw new IllegalArgumentException("Command has an invalid number of arguments. This should never happen.");
        }
    } catch (IllegalAccessException | InvocationTargetException e) {
        final Throwable cause = e.getCause();
        LOG.error("Command '{}' could not be executed.", command.getName(), e.getCause());
        DiscordIO.errorNotify(cause.toString(), message.getChannel());
    }
}
Also used : CommandModule(de.nikos410.discordbot.framework.CommandModule) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException)

Aggregations

CommandWrapper (de.nikos410.discordbot.framework.CommandWrapper)4 ModuleWrapper (de.nikos410.discordbot.framework.ModuleWrapper)3 CommandModule (de.nikos410.discordbot.framework.CommandModule)2 PermissionLevel (de.nikos410.discordbot.framework.PermissionLevel)2 CommandSubscriber (de.nikos410.discordbot.framework.annotations.CommandSubscriber)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 Method (java.lang.reflect.Method)2 InitializationException (de.nikos410.discordbot.exception.InitializationException)1 ModuleStatus (de.nikos410.discordbot.framework.ModuleWrapper.ModuleStatus)1 BotSetup (de.nikos410.discordbot.modules.BotSetup)1 Authorization (de.nikos410.discordbot.util.discord.Authorization)1 DiscordIO (de.nikos410.discordbot.util.discord.DiscordIO)1 UserUtils (de.nikos410.discordbot.util.discord.UserUtils)1 IOUtil (de.nikos410.discordbot.util.io.IOUtil)1 Files (java.nio.file.Files)1 Path (java.nio.file.Path)1 Paths (java.nio.file.Paths)1 Instant (java.time.Instant)1 ChronoUnit (java.time.temporal.ChronoUnit)1 java.util (java.util)1