use of alexh.weak.Dynamic in project DiscordSRV by Scarsz.
the class DebugUtil method getActiveConfig.
private static String getActiveConfig() {
try {
Dynamic activeConfig = DiscordSRV.config().getProvider("config").getValues();
StringBuilder stringBuilder = new StringBuilder(500);
Iterator<Dynamic> iterator = activeConfig.allChildren().iterator();
while (iterator.hasNext()) {
Dynamic child = iterator.next();
if (child.allChildren().count() == 0) {
stringBuilder.append(child.key().asObject()).append(": ").append(child.asObject());
} else {
StringJoiner childJoiner = new StringJoiner(", ");
Iterator<Dynamic> childIterator = child.allChildren().iterator();
while (childIterator.hasNext()) {
Dynamic grandchild = childIterator.next();
childJoiner.add("- " + grandchild.asObject());
}
stringBuilder.append(child.key().asString()).append(": ").append(childJoiner);
}
stringBuilder.append("\n");
}
return stringBuilder.toString();
} catch (Exception e) {
return "Failed to get parsed config: " + e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e);
}
}
use of alexh.weak.Dynamic in project DiscordSRV by Scarsz.
the class AllConfigsHaveKeysTest method test.
// @Test
public void test() {
List<File> configs = Arrays.asList(new File(resources, "config"));
for (File parent : configs) {
try {
Dynamic english = Dynamic.from(yaml.loadAs(FileUtils.readFileToString(new File(parent, "en.yml"), "UTF-8"), Map.class));
english.allChildren().filter(d -> d.getClass().getSimpleName().equals("Child")).filter(d -> d.children().count() == 0).map(d -> {
String almostClean = d.key().toString().substring(6).replace("->", ".");
do {
almostClean = almostClean.substring(0, almostClean.lastIndexOf('.'));
} while (almostClean.matches(".+\\.\\d+$"));
return almostClean;
}).distinct().filter(StringUtils::isNotBlank).forEach(System.out::println);
for (Language language : Language.values()) {
if (language == Language.EN)
continue;
File file = new File(parent, language.getCode().toLowerCase() + ".yml");
if (!file.exists())
continue;
Map<String, Object> other = yaml.loadAs(FileUtils.readFileToString(file, "UTF-8"), Map.class);
// for (String key : english.keySet()) {
// Assert.assertTrue(String.format("%s %s config (%s/%s.yml) does not contain key %s",
// language.getName(), parent.getName(), parent.getName(), language.getCode().toLowerCase(), key),
// other.containsKey(key)
// );
// }
//
// other.keySet().removeAll(english.keySet());
// for (String key : other.keySet()) {
// Assert.fail(String.format("%s %s config (%s/%s.yml) has unused key %s",
// language.getName(), parent.getName(), parent.getName(), language.getCode().toLowerCase(), key)
// );
// }
}
} catch (IOException e) {
System.out.println("Failed to read file " + parent.getPath() + ": " + e.getMessage());
}
}
}
use of alexh.weak.Dynamic in project DiscordSRV by Scarsz.
the class AlertListener method process.
private void process(Object event, Dynamic alert, Set<String> triggers, int alertIndex) {
Player player = event instanceof PlayerEvent ? ((PlayerEvent) event).getPlayer() : null;
if (player == null) {
// this will check to see if a #getPlayer() method exists on events coming through
try {
Method getPlayerMethod = event.getClass().getMethod("getPlayer");
if (getPlayerMethod.getReturnType().equals(Player.class)) {
player = (Player) getPlayerMethod.invoke(event);
}
} catch (Exception ignored) {
// we tried ¯\_(ツ)_/¯
}
}
CommandSender sender = null;
String command = null;
List<String> args = new LinkedList<>();
if (event instanceof PlayerCommandPreprocessEvent) {
sender = player;
command = ((PlayerCommandPreprocessEvent) event).getMessage().substring(1);
} else if (event instanceof ServerCommandEvent) {
sender = ((ServerCommandEvent) event).getSender();
command = ((ServerCommandEvent) event).getCommand();
}
if (StringUtils.isNotBlank(command)) {
String[] split = command.split(" ", 2);
String commandBase = split[0];
if (split.length == 2)
args.addAll(Arrays.asList(split[1].split(" ")));
// transform "discordsrv:discord" to just "discord" for example
if (commandBase.contains(":"))
commandBase = commandBase.substring(commandBase.lastIndexOf(":") + 1);
command = commandBase + (split.length == 2 ? (" " + split[1]) : "");
}
MessageFormat messageFormat = DiscordSRV.getPlugin().getMessageFromConfiguration("Alerts." + alertIndex);
for (String trigger : triggers) {
String eventName = getEventName(event);
if (trigger.startsWith("/")) {
if (StringUtils.isBlank(command) || !command.toLowerCase().split("\\s+|$", 2)[0].equals(trigger.substring(1)))
continue;
} else {
// make sure the called event matches what this alert is supposed to trigger on
if (!eventName.equalsIgnoreCase(trigger))
continue;
}
// make sure alert should run even if event is cancelled
if (event instanceof Cancellable && ((Cancellable) event).isCancelled()) {
Dynamic ignoreCancelledDynamic = alert.get("IgnoreCancelled");
boolean ignoreCancelled = ignoreCancelledDynamic.isPresent() ? ignoreCancelledDynamic.as(Boolean.class) : true;
if (ignoreCancelled) {
DiscordSRV.debug(Debug.ALERTS, "Not running alert for event " + eventName + ": event was cancelled");
return;
}
}
Dynamic textChannelsDynamic = alert.get("Channel");
if (textChannelsDynamic == null) {
DiscordSRV.debug(Debug.ALERTS, "Not running alert for trigger " + trigger + ": no target channel was defined");
return;
}
Set<String> channels = new HashSet<>();
if (textChannelsDynamic.isList()) {
textChannelsDynamic.children().map(Weak::asString).filter(Objects::nonNull).forEach(channels::add);
} else if (textChannelsDynamic.isString()) {
channels.add(textChannelsDynamic.asString());
}
Function<Function<String, Collection<TextChannel>>, Set<TextChannel>> channelResolver = converter -> {
Set<TextChannel> textChannels = new HashSet<>();
channels.forEach(channel -> textChannels.addAll(converter.apply(channel)));
textChannels.removeIf(Objects::isNull);
return textChannels;
};
Set<TextChannel> textChannels = channelResolver.apply(s -> {
TextChannel target = DiscordSRV.getPlugin().getDestinationTextChannelForGameChannelName(s);
return Collections.singleton(target);
});
if (textChannels.isEmpty()) {
textChannels.addAll(channelResolver.apply(s -> DiscordUtil.getJda().getTextChannelsByName(s, false)));
}
if (textChannels.isEmpty()) {
textChannels.addAll(channelResolver.apply(s -> NumberUtils.isDigits(s) ? Collections.singleton(DiscordUtil.getJda().getTextChannelById(s)) : Collections.emptyList()));
}
if (textChannels.size() == 0) {
DiscordSRV.debug(Debug.ALERTS, "Not running alert for trigger " + trigger + ": no target channel was defined/found (channels: " + channels + ")");
return;
}
for (TextChannel textChannel : textChannels) {
// check alert conditions
boolean allConditionsMet = true;
Dynamic conditionsDynamic = alert.dget("Conditions");
if (conditionsDynamic.isPresent()) {
Iterator<Dynamic> conditions = conditionsDynamic.children().iterator();
while (conditions.hasNext()) {
Dynamic dynamic = conditions.next();
String expression = dynamic.convert().intoString();
try {
Boolean value = new SpELExpressionBuilder(expression).withPluginVariables().withVariable("event", event).withVariable("server", Bukkit.getServer()).withVariable("discordsrv", DiscordSRV.getPlugin()).withVariable("player", player).withVariable("sender", sender).withVariable("command", command).withVariable("args", args).withVariable("allArgs", String.join(" ", args)).withVariable("channel", textChannel).withVariable("jda", DiscordUtil.getJda()).evaluate(event, Boolean.class);
DiscordSRV.debug(Debug.ALERTS, "Condition \"" + expression + "\" -> " + value);
if (value != null && !value) {
allConditionsMet = false;
break;
}
} catch (ParseException e) {
DiscordSRV.error("Error while parsing expression \"" + expression + "\" for trigger \"" + trigger + "\" -> " + e.getMessage());
} catch (SpelEvaluationException e) {
DiscordSRV.error("Error while evaluating expression \"" + expression + "\" for trigger \"" + trigger + "\" -> " + e.getMessage());
}
}
if (!allConditionsMet)
continue;
}
CommandSender finalSender = sender;
String finalCommand = command;
Player finalPlayer = player;
BiFunction<String, Boolean, String> translator = (content, needsEscape) -> {
if (content == null)
return null;
// evaluate any SpEL expressions
Map<String, Object> variables = new HashMap<>();
variables.put("event", event);
variables.put("server", Bukkit.getServer());
variables.put("discordsrv", DiscordSRV.getPlugin());
variables.put("player", finalPlayer);
variables.put("sender", finalSender);
variables.put("command", finalCommand);
variables.put("args", args);
variables.put("allArgs", String.join(" ", args));
variables.put("channel", textChannel);
variables.put("jda", DiscordUtil.getJda());
content = NamedValueFormatter.formatExpressions(content, event, variables);
// replace any normal placeholders
content = NamedValueFormatter.format(content, key -> {
switch(key) {
case "tps":
return Lag.getTPSString();
case "time":
case "date":
return TimeUtil.timeStamp();
case "ping":
return finalPlayer != null ? PlayerUtil.getPing(finalPlayer) : "-1";
case "name":
case "username":
return finalPlayer != null ? finalPlayer.getName() : "";
case "displayname":
return finalPlayer != null ? MessageUtil.strip(needsEscape ? DiscordUtil.escapeMarkdown(finalPlayer.getDisplayName()) : finalPlayer.getDisplayName()) : "";
case "world":
return finalPlayer != null ? finalPlayer.getWorld().getName() : "";
case "embedavatarurl":
return finalPlayer != null ? DiscordSRV.getAvatarUrl(finalPlayer) : DiscordUtil.getJda().getSelfUser().getEffectiveAvatarUrl();
case "botavatarurl":
return DiscordUtil.getJda().getSelfUser().getEffectiveAvatarUrl();
case "botname":
return DiscordSRV.getPlugin().getMainGuild() != null ? DiscordSRV.getPlugin().getMainGuild().getSelfMember().getEffectiveName() : DiscordUtil.getJda().getSelfUser().getName();
default:
return "{" + key + "}";
}
});
content = DiscordUtil.translateEmotes(content, textChannel.getGuild());
content = PlaceholderUtil.replacePlaceholdersToDiscord(content, finalPlayer);
return content;
};
Message message = DiscordSRV.translateMessage(messageFormat, translator);
if (message == null) {
DiscordSRV.debug(Debug.ALERTS, "Not sending alert because it is configured to have no message content");
return;
}
if (messageFormat.isUseWebhooks()) {
WebhookUtil.deliverMessage(textChannel, translator.apply(messageFormat.getWebhookName(), false), translator.apply(messageFormat.getWebhookAvatarUrl(), false), message.getContentRaw(), message.getEmbeds().stream().findFirst().orElse(null));
} else {
DiscordUtil.queueMessage(textChannel, message);
}
}
}
}
use of alexh.weak.Dynamic in project DiscordSRV by Scarsz.
the class AlertListener method getTriggers.
private Set<String> getTriggers(Dynamic alert) {
Set<String> triggers = new HashSet<>();
Dynamic triggerDynamic = alert.get("Trigger");
if (triggerDynamic.isList()) {
triggers.addAll(triggerDynamic.children().map(Weak::asString).map(String::toLowerCase).collect(Collectors.toSet()));
} else if (triggerDynamic.isString()) {
triggers.add(triggerDynamic.asString().toLowerCase());
}
Set<String> finalTriggers = new HashSet<>();
for (String trigger : triggers) {
if (!trigger.startsWith("/")) {
String className = validClassNameCache.get(trigger);
if (className == null) {
// event trigger, make sure it's a valid class name
Matcher matcher = VALID_CLASS_NAME_PATTERN.matcher(trigger);
if (matcher.find()) {
// valid class name found
className = matcher.group();
}
validClassNameCache.put(trigger, className);
}
finalTriggers.add(className);
continue;
}
finalTriggers.add(trigger);
}
return finalTriggers;
}
use of alexh.weak.Dynamic in project DiscordSRV by Scarsz.
the class AlertListener method reloadAlerts.
public void reloadAlerts() {
validClassNameCache.clear();
activeTriggers.clear();
alerts.clear();
Optional<List<Map<?, ?>>> optionalAlerts = DiscordSRV.config().getOptional("Alerts");
boolean any = optionalAlerts.isPresent() && !optionalAlerts.get().isEmpty();
if (registered)
unregister();
if (any) {
register();
long count = optionalAlerts.get().size();
DiscordSRV.info(optionalAlerts.get().size() + " alert" + (count > 1 ? "s" : "") + " registered");
for (Map<?, ?> map : optionalAlerts.get()) {
Dynamic alert = Dynamic.from(map);
alerts.add(alert);
activeTriggers.addAll(getTriggers(alert));
}
}
}
Aggregations