package io.shockah.skylark.groovy; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; import groovy.lang.GroovyShell; import groovy.lang.Tuple; import io.shockah.json.JSONObject; import io.shockah.json.JSONPrinter; import io.shockah.skylark.commands.CommandCall; import io.shockah.skylark.commands.CommandParseException; import io.shockah.skylark.commands.CommandResult; import io.shockah.skylark.event.GenericUserMessageEvent; import io.shockah.skylark.factoids.AbstractFactoidCommand; import io.shockah.skylark.factoids.db.Factoid; public class GroovyFactoidCommand<T, R> extends AbstractFactoidCommand<T, R> { public final GroovyPlugin plugin; public GroovyFactoidCommand(GroovyPlugin plugin, Factoid factoid) { super(factoid); this.plugin = plugin; } @SuppressWarnings("unchecked") @Override public T convertToInput(GenericUserMessageEvent e, Object input) throws CommandParseException { return (T)input; } @SuppressWarnings("unchecked") @Override public T parseInput(GenericUserMessageEvent e, String input) throws CommandParseException { return (T)input; } @SuppressWarnings("unchecked") @Override public CommandResult<R> call(CommandCall call, T input) { try { JSONObject storeData = factoid.getStoreData(); JSONPrinter printer = new JSONPrinter(); String jsonOld = storeData == null ? null : printer.toString(storeData); Map<String, Object> variables = new LinkedHashMap<>(); variables.put("call", call); variables.put("user", call.event.getUser()); variables.put("channel", call.event.getChannel()); variables.put("input", input); variables.put("store", storeData); GroovyShell shell = plugin.getShell(variables, new UserGroovySandboxImpl(), call.event); Object result = shell.evaluate(factoid.raw); if (result instanceof CommandResult<?>) return (CommandResult<R>)result; if (result instanceof Tuple) { Tuple tuple = (Tuple)result; if (tuple.size() == 2) return (CommandResult<R>)CommandResult.of(tuple.get(0), tuple.get(1).toString()); } CommandResult<R> ret = (CommandResult<R>)CommandResult.of(result); JSONObject newStoreData = (JSONObject)plugin.turnIntoJSONValue(shell.getVariable("store")); String jsonNew = newStoreData == null ? null : printer.toString(newStoreData); if (!Objects.equals(jsonOld, jsonNew)) factoid.setStoreData(newStoreData); return ret; } catch (Exception e) { return CommandResult.error(e.getMessage()); } } }