Search in sources :

Example 1 with Dynamic

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);
    }
}
Also used : Dynamic(alexh.weak.Dynamic) InvocationTargetException(java.lang.reflect.InvocationTargetException) InvalidKeyException(java.security.InvalidKeyException)

Example 2 with Dynamic

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());
        }
    }
}
Also used : Dynamic(alexh.weak.Dynamic) Arrays(java.util.Arrays) List(java.util.List) Language(github.scarsz.configuralize.Language) Map(java.util.Map) FileUtils(org.apache.commons.io.FileUtils) IOException(java.io.IOException) StringUtils(org.apache.commons.lang3.StringUtils) File(java.io.File) Yaml(org.yaml.snakeyaml.Yaml) Dynamic(alexh.weak.Dynamic) Language(github.scarsz.configuralize.Language) IOException(java.io.IOException) File(java.io.File) Map(java.util.Map)

Example 3 with Dynamic

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);
            }
        }
    }
}
Also used : SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) Dynamic(alexh.weak.Dynamic) java.util(java.util) MessageFormat(github.scarsz.discordsrv.objects.MessageFormat) BiFunction(java.util.function.BiFunction) TextChannel(net.dv8tion.jda.api.entities.TextChannel) Player(org.bukkit.entity.Player) StringUtils(org.apache.commons.lang3.StringUtils) Function(java.util.function.Function) ServerCommandEvent(org.bukkit.event.server.ServerCommandEvent) Matcher(java.util.regex.Matcher) DiscordSRV(github.scarsz.discordsrv.DiscordSRV) org.bukkit.event(org.bukkit.event) PlayerCommandPreprocessEvent(org.bukkit.event.player.PlayerCommandPreprocessEvent) Weak(alexh.weak.Weak) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) github.scarsz.discordsrv.util(github.scarsz.discordsrv.util) Method(java.lang.reflect.Method) ParseException(org.springframework.expression.ParseException) Bukkit(org.bukkit.Bukkit) Message(net.dv8tion.jda.api.entities.Message) Lag(github.scarsz.discordsrv.objects.Lag) CommandSender(org.bukkit.command.CommandSender) Field(java.lang.reflect.Field) Collectors(java.util.stream.Collectors) InvocationTargetException(java.lang.reflect.InvocationTargetException) Debug(github.scarsz.discordsrv.Debug) Subscribe(github.scarsz.discordsrv.api.Subscribe) RegisteredListener(org.bukkit.plugin.RegisteredListener) TimeUnit(java.util.concurrent.TimeUnit) EventListener(net.dv8tion.jda.api.hooks.EventListener) Modifier(java.lang.reflect.Modifier) NumberUtils(org.apache.commons.lang3.math.NumberUtils) PlayerEvent(org.bukkit.event.player.PlayerEvent) ExpiringDualHashBidiMap(github.scarsz.discordsrv.objects.ExpiringDualHashBidiMap) Pattern(java.util.regex.Pattern) NotNull(org.jetbrains.annotations.NotNull) Dynamic(alexh.weak.Dynamic) Message(net.dv8tion.jda.api.entities.Message) BiFunction(java.util.function.BiFunction) Function(java.util.function.Function) TextChannel(net.dv8tion.jda.api.entities.TextChannel) Player(org.bukkit.entity.Player) SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) MessageFormat(github.scarsz.discordsrv.objects.MessageFormat) PlayerEvent(org.bukkit.event.player.PlayerEvent) Method(java.lang.reflect.Method) ServerCommandEvent(org.bukkit.event.server.ServerCommandEvent) SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) ParseException(org.springframework.expression.ParseException) InvocationTargetException(java.lang.reflect.InvocationTargetException) PlayerCommandPreprocessEvent(org.bukkit.event.player.PlayerCommandPreprocessEvent) Weak(alexh.weak.Weak) CommandSender(org.bukkit.command.CommandSender) ParseException(org.springframework.expression.ParseException) ExpiringDualHashBidiMap(github.scarsz.discordsrv.objects.ExpiringDualHashBidiMap)

Example 4 with Dynamic

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;
}
Also used : Dynamic(alexh.weak.Dynamic) Matcher(java.util.regex.Matcher)

Example 5 with Dynamic

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));
        }
    }
}
Also used : Dynamic(alexh.weak.Dynamic)

Aggregations

Dynamic (alexh.weak.Dynamic)8 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 Matcher (java.util.regex.Matcher)2 GenericEvent (net.dv8tion.jda.api.events.GenericEvent)2 StringUtils (org.apache.commons.lang3.StringUtils)2 PlayerCommandPreprocessEvent (org.bukkit.event.player.PlayerCommandPreprocessEvent)2 PlayerEvent (org.bukkit.event.player.PlayerEvent)2 Weak (alexh.weak.Weak)1 Language (github.scarsz.configuralize.Language)1 Debug (github.scarsz.discordsrv.Debug)1 DiscordSRV (github.scarsz.discordsrv.DiscordSRV)1 Subscribe (github.scarsz.discordsrv.api.Subscribe)1 ExpiringDualHashBidiMap (github.scarsz.discordsrv.objects.ExpiringDualHashBidiMap)1 Lag (github.scarsz.discordsrv.objects.Lag)1 MessageFormat (github.scarsz.discordsrv.objects.MessageFormat)1 github.scarsz.discordsrv.util (github.scarsz.discordsrv.util)1 File (java.io.File)1 IOException (java.io.IOException)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1