Search in sources :

Example 1 with CommandFailure

use of net.robinfriedli.aiode.exceptions.CommandFailure in project aiode by robinfriedli.

the class ScriptCommandInterceptor method performChained.

@Override
public void performChained(Command command) {
    if (command instanceof AbstractCommand) {
        AbstractCommand abstractCommand = (AbstractCommand) command;
        if (abstractCommand.getArgumentController().argumentSet("skipInterceptors") || abstractCommand.getCommandContribution().isDisableScriptInterceptors()) {
            return;
        }
    } else {
        return;
    }
    CommandContext context = command.getContext();
    Session session = context.getSession();
    GuildSpecification specification = context.getGuildContext().getSpecification(session);
    boolean enableScripting = guildPropertyManager.getPropertyValueOptional("enableScripting", Boolean.class, specification).orElse(true);
    if (!enableScripting) {
        return;
    }
    String usageId = getUsageId();
    List<StoredScript> scriptInterceptors = queryBuilderFactory.find(StoredScript.class).where((cb, root, subQueryFactory) -> cb.and(cb.isTrue(root.get("active")), cb.equal(root.get("scriptUsage"), subQueryFactory.createUncorrelatedSubQuery(StoredScript.ScriptUsage.class, "pk").where((cb1, root1) -> cb1.equal(root1.get("uniqueId"), usageId)).build(session)))).build(session).getResultList();
    if (scriptInterceptors.isEmpty()) {
        return;
    }
    Aiode aiode = Aiode.get();
    SafeGroovyScriptRunner scriptRunner = new SafeGroovyScriptRunner(context, groovySandboxComponent, aiode.getGroovyVariableManager(), aiode.getSecurityManager(), false);
    AtomicReference<StoredScript> currentScriptReference = new AtomicReference<>();
    try {
        scriptRunner.runScripts(scriptInterceptors, currentScriptReference, 5, TimeUnit.SECONDS);
    } catch (ExecutionException e) {
        Throwable error = e.getCause() != null ? e.getCause() : e;
        if (error instanceof CommandFailure) {
            messageService.sendError(String.format("Executing command %1$ss failed due to an error in %1$s '%2$s'", usageId, currentScriptReference.get().getIdentifier()), context.getChannel());
        } else {
            EmbedBuilder embedBuilder = ExceptionUtils.buildErrorEmbed(error);
            StoredScript currentScript = currentScriptReference.get();
            embedBuilder.setTitle(String.format("Error occurred while executing custom command %s%s", usageId, currentScript.getIdentifier() != null ? ": " + currentScript.getIdentifier() : ""));
            messageService.sendTemporary(embedBuilder.build(), context.getChannel());
        }
    } catch (TimeoutException e) {
        StoredScript currentScript = currentScriptReference.get();
        messageService.sendError(String.format("Execution of script command %ss stopped because script%s has run into a timeout", usageId, currentScript != null ? String.format(" '%s'", currentScript.getIdentifier()) : ""), context.getChannel());
    }
}
Also used : CommandContext(net.robinfriedli.aiode.command.CommandContext) AbstractCommand(net.robinfriedli.aiode.command.AbstractCommand) AtomicReference(java.util.concurrent.atomic.AtomicReference) Aiode(net.robinfriedli.aiode.Aiode) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) SafeGroovyScriptRunner(net.robinfriedli.aiode.scripting.SafeGroovyScriptRunner) StoredScript(net.robinfriedli.aiode.entities.StoredScript) GuildSpecification(net.robinfriedli.aiode.entities.GuildSpecification) CommandFailure(net.robinfriedli.aiode.exceptions.CommandFailure) ExecutionException(java.util.concurrent.ExecutionException) Session(org.hibernate.Session) TimeoutException(java.util.concurrent.TimeoutException)

Example 2 with CommandFailure

use of net.robinfriedli.aiode.exceptions.CommandFailure in project aiode by robinfriedli.

the class CommandExecutionInterceptor method performChained.

@Override
public void performChained(Command command) {
    boolean completedSuccessfully = false;
    boolean failedManually = false;
    String errorMessage = null;
    boolean unexpectedException = false;
    boolean aborted = false;
    try {
        try {
            if (command.isAborted()) {
                aborted = true;
                return;
            }
            command.doRun();
        } catch (Exception e) {
            if ((command.getTask() != null && command.getTask().isTerminated()) || Thread.currentThread().isInterrupted()) {
                logger.warn(String.format("Suppressed '%s' because command execution was interrupted.", e));
                return;
            }
            try {
                command.onFailure();
            } catch (Exception e1) {
                logger.error("Exception thrown in onFailure of command, logging this error and throwing the exception that caused the command to fail.", e1);
            }
            throw e;
        }
        if (!command.isFailed()) {
            command.onSuccess();
            completedSuccessfully = true;
        } else {
            command.onFailure();
            failedManually = true;
        }
    } catch (AmbiguousCommandException e) {
        if (command instanceof AbstractCommand) {
            ((AbstractCommand) command).askQuestion(e.getOptions(), e.getDisplayFunc());
        } else {
            throw e;
        }
    } catch (CommandFailure e) {
        throw e;
    } catch (NoLoginException e) {
        MessageChannel channel = command.getContext().getChannel();
        User user = command.getContext().getUser();
        String message = "User " + user.getName() + " is not logged in to Spotify";
        messageService.sendError(message, channel);
        errorMessage = message;
        throw new CommandFailure(e);
    } catch (UserException e) {
        messageService.sendTemporary(e.buildEmbed().build(), command.getContext().getChannel());
        errorMessage = e.getMessage();
        throw new CommandFailure(e);
    } catch (FriendlyException e) {
        EmbedBuilder embedBuilder = new EmbedBuilder();
        embedBuilder.setTitle("Could not load track");
        if (e.getMessage() != null) {
            embedBuilder.setDescription("Message returned by source: " + e.getMessage());
        }
        embedBuilder.setColor(Color.RED);
        messageService.sendTemporary(embedBuilder.build(), command.getContext().getChannel());
        throw new CommandFailure(e);
    } catch (UnauthorizedException e) {
        String message = "Unauthorized: " + e.getMessage();
        messageService.sendException(message, command.getContext().getChannel());
        logger.warn("Unauthorized Spotify API operation", e);
        errorMessage = message;
        unexpectedException = true;
        throw new CommandFailure(e);
    } catch (TooManyRequestsException e) {
        String message = "Executing too many Spotify requests at the moment, please try again later.";
        messageService.sendException(message, command.getContext().getChannel());
        logger.warn("Executing too many Spotify requests", e);
        errorMessage = message;
        unexpectedException = true;
        throw new CommandFailure(e);
    } catch (GoogleJsonResponseException e) {
        String message = e.getDetails().getMessage();
        StringBuilder responseBuilder = new StringBuilder("Error occurred when requesting data from YouTube.");
        if (!Strings.isNullOrEmpty(message)) {
            responseBuilder.append(" Error response: ").append(message);
        }
        messageService.sendException(responseBuilder.toString(), command.getContext().getChannel());
        logger.error("Exception during YouTube request", e);
        errorMessage = message;
        unexpectedException = true;
        throw new CommandFailure(e);
    } catch (ErrorResponseException e) {
        messageService.sendException(String.format("Discord returned error (code: %d): %s", e.getErrorCode(), e.getMeaning()), command.getContext().getChannel());
        logger.error("Blocking Discord request returned error", e);
        throw new CommandFailure(e);
    } catch (CommandRuntimeException e) {
        if (e.getCause() != null) {
            errorMessage = e.getCause().getClass().getSimpleName() + ": " + e.getCause().getMessage();
        } else {
            errorMessage = e.getClass().getSimpleName() + ": " + e.getMessage();
        }
        unexpectedException = true;
        throw e;
    } catch (Exception e) {
        errorMessage = e.getClass().getSimpleName() + ": " + e.getMessage();
        unexpectedException = true;
        throw new CommandRuntimeException(e);
    } finally {
        postCommand(command, completedSuccessfully, failedManually, errorMessage, unexpectedException, aborted);
    }
}
Also used : AmbiguousCommandException(net.robinfriedli.aiode.exceptions.AmbiguousCommandException) User(net.dv8tion.jda.api.entities.User) AbstractCommand(net.robinfriedli.aiode.command.AbstractCommand) UnauthorizedException(se.michaelthelin.spotify.exceptions.detailed.UnauthorizedException) GoogleJsonResponseException(com.google.api.client.googleapis.json.GoogleJsonResponseException) UserException(net.robinfriedli.aiode.exceptions.UserException) NoLoginException(net.robinfriedli.aiode.exceptions.NoLoginException) FriendlyException(com.sedmelluq.discord.lavaplayer.tools.FriendlyException) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) AmbiguousCommandException(net.robinfriedli.aiode.exceptions.AmbiguousCommandException) CommandRuntimeException(net.robinfriedli.aiode.exceptions.CommandRuntimeException) TooManyRequestsException(se.michaelthelin.spotify.exceptions.detailed.TooManyRequestsException) FriendlyException(com.sedmelluq.discord.lavaplayer.tools.FriendlyException) GoogleJsonResponseException(com.google.api.client.googleapis.json.GoogleJsonResponseException) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) TooManyRequestsException(se.michaelthelin.spotify.exceptions.detailed.TooManyRequestsException) NoLoginException(net.robinfriedli.aiode.exceptions.NoLoginException) MessageChannel(net.dv8tion.jda.api.entities.MessageChannel) UnauthorizedException(se.michaelthelin.spotify.exceptions.detailed.UnauthorizedException) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) CommandFailure(net.robinfriedli.aiode.exceptions.CommandFailure) UserException(net.robinfriedli.aiode.exceptions.UserException) CommandRuntimeException(net.robinfriedli.aiode.exceptions.CommandRuntimeException)

Example 3 with CommandFailure

use of net.robinfriedli.aiode.exceptions.CommandFailure in project aiode by robinfriedli.

the class SafeGroovyScriptRunner method runAndSendResult.

/**
 * Run a groovy script and send its result, returned object or thrown exception, to the channel of the {@link ExecutionContext}
 * this instance was set up with. This method calls {@link #evaluateScript(String, long, TimeUnit)} and handles the
 * result by sending the string representation of the result or an error message should an error occur. If the script
 * returns null this method sends nothing.
 *
 * @param script   the groovy code to run
 * @param timeout  the timeout, ignored if isPrivileged is true
 * @param timeUnit the time unit for the timout parameter
 */
public void runAndSendResult(String script, long timeout, TimeUnit timeUnit) {
    MessageService messageService = Aiode.get().getMessageService();
    MessageChannel channel = context.getChannel();
    try {
        Object result = evaluateScript(script, timeout, timeUnit);
        if (result != null) {
            String resultString = result.toString();
            if (resultString.length() < 1000) {
                EmbedBuilder embedBuilder = new EmbedBuilder();
                embedBuilder.setTitle("Output");
                embedBuilder.setDescription("```" + resultString + "```");
                messageService.send(embedBuilder, channel);
            } else {
                EmbedBuilder embedBuilder = new EmbedBuilder().setTitle("Output too long, attaching as file");
                embedBuilder.setColor(ColorSchemeProperty.getColor());
                byte[] bytes = resultString.getBytes();
                if (bytes.length > 1000000) {
                    messageService.sendError("Output too long", channel);
                    return;
                }
                ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
                messageService.executeMessageAction(channel, c -> c.sendMessage(embedBuilder.build()).addFile(inputStream, "output.txt"));
            }
        }
    } catch (TimeoutException e) {
        messageService.sendError(e.getMessage(), channel);
    } catch (ExecutionException e) {
        Throwable error = e.getCause() != null ? e.getCause() : e;
        if (error instanceof SecurityException) {
            messageService.sendError(error.getMessage(), channel);
            throw new CommandFailure(error);
        } else if (error instanceof MultipleCompilationErrorsException) {
            MultipleCompilationErrorsException compilationErrorsException = (MultipleCompilationErrorsException) error;
            EmbedBuilder embedBuilder = new EmbedBuilder();
            embedBuilder.setColor(Color.RED);
            embedBuilder.setTitle("Could not compile script");
            embedBuilder.setDescription(ExceptionUtils.formatScriptCompilationError(compilationErrorsException));
            messageService.sendTemporary(embedBuilder.build(), channel);
            throw new CommandFailure(error);
        } else if (!(error instanceof CommandFailure)) {
            EmbedBuilder embedBuilder = ExceptionUtils.buildErrorEmbed(error);
            embedBuilder.setTitle("Error occurred while executing script");
            messageService.sendTemporary(embedBuilder.build(), channel);
            throw new CommandFailure(error);
        }
    }
}
Also used : MessageService(net.robinfriedli.aiode.discord.MessageService) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) MessageChannel(net.dv8tion.jda.api.entities.MessageChannel) ByteArrayInputStream(java.io.ByteArrayInputStream) CommandFailure(net.robinfriedli.aiode.exceptions.CommandFailure) ExecutionException(java.util.concurrent.ExecutionException) MultipleCompilationErrorsException(org.codehaus.groovy.control.MultipleCompilationErrorsException) TimeoutException(java.util.concurrent.TimeoutException)

Aggregations

EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)3 CommandFailure (net.robinfriedli.aiode.exceptions.CommandFailure)3 ExecutionException (java.util.concurrent.ExecutionException)2 TimeoutException (java.util.concurrent.TimeoutException)2 MessageChannel (net.dv8tion.jda.api.entities.MessageChannel)2 AbstractCommand (net.robinfriedli.aiode.command.AbstractCommand)2 GoogleJsonResponseException (com.google.api.client.googleapis.json.GoogleJsonResponseException)1 FriendlyException (com.sedmelluq.discord.lavaplayer.tools.FriendlyException)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 User (net.dv8tion.jda.api.entities.User)1 ErrorResponseException (net.dv8tion.jda.api.exceptions.ErrorResponseException)1 Aiode (net.robinfriedli.aiode.Aiode)1 CommandContext (net.robinfriedli.aiode.command.CommandContext)1 MessageService (net.robinfriedli.aiode.discord.MessageService)1 GuildSpecification (net.robinfriedli.aiode.entities.GuildSpecification)1 StoredScript (net.robinfriedli.aiode.entities.StoredScript)1 AmbiguousCommandException (net.robinfriedli.aiode.exceptions.AmbiguousCommandException)1 CommandRuntimeException (net.robinfriedli.aiode.exceptions.CommandRuntimeException)1 NoLoginException (net.robinfriedli.aiode.exceptions.NoLoginException)1