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());
}
}
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);
}
}
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);
}
}
}
Aggregations