Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
for(Class<?> cl : getClass().getClassLoader().loadClass("sun.font.FontConfigManager").getDeclaredClasses()) {
hints.jni().registerType(cl, MemberCategory.ACCESS_DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException _) {
// FontConfigManager is only supported on Linux
}

for (Class<?> cl : WebhookEmbed.class.getClasses()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package net.discordjug.javabot.data.config;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import lombok.extern.slf4j.Slf4j;
import net.discordjug.javabot.util.ExceptionLogger;
import net.discordjug.javabot.util.GsonUtils;
import net.dv8tion.jda.api.entities.Guild;

import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -64,11 +63,10 @@ public BotConfig(Path dir) {
}
}
this.guilds = new ConcurrentHashMap<>();
Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
Path systemsFile = dir.resolve(SYSTEMS_FILE);
if (Files.exists(systemsFile)) {
try (BufferedReader reader = Files.newBufferedReader(systemsFile)) {
this.systemsConfig = gson.fromJson(reader, SystemsConfig.class);
this.systemsConfig = GsonUtils.fromJson(reader, SystemsConfig.class);
log.info("Loaded systems config from {}", systemsFile);
} catch (JsonSyntaxException e) {
ExceptionLogger.capture(e, getClass().getSimpleName());
Expand Down Expand Up @@ -133,10 +131,9 @@ public SystemsConfig getSystems() {
* Flushes all configuration to the disk.
*/
public void flush() {
Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
Path systemsFile = this.dir.resolve(SYSTEMS_FILE);
try (BufferedWriter writer = Files.newBufferedWriter(systemsFile)) {
gson.toJson(this.systemsConfig, writer);
GsonUtils.toJson(this.systemsConfig, writer);
writer.flush();
} catch (IOException e) {
ExceptionLogger.capture(e, getClass().getSimpleName());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package net.discordjug.javabot.data.config;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.discordjug.javabot.data.config.guild.*;
import net.discordjug.javabot.util.ExceptionLogger;
import net.discordjug.javabot.util.GsonUtils;
import net.discordjug.javabot.util.Pair;
import net.dv8tion.jda.api.entities.Guild;

Expand All @@ -20,7 +19,6 @@
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

/**
* A collection of guild-specific configuration items, each of which represents
Expand Down Expand Up @@ -71,13 +69,10 @@ public GuildConfig(Guild guild, Path file) {
* @throws UncheckedIOException if an IO error occurs.
*/
public static GuildConfig loadOrCreate(Guild guild, Path file) {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Pattern.class, new PatternTypeAdapter())
.create();
GuildConfig config;
if (Files.exists(file)) {
try (BufferedReader reader = Files.newBufferedReader(file)) {
config = gson.fromJson(reader, GuildConfig.class);
config = GsonUtils.fromJson(reader, GuildConfig.class);
config.setFile(file);
config.setGuild(guild);
log.info("Loaded config from {}", file);
Expand Down Expand Up @@ -118,13 +113,8 @@ private void setGuild(Guild guild) {
* Saves this config to its file path.
*/
public synchronized void flush() {
Gson gson = new GsonBuilder()
.serializeNulls()
.setPrettyPrinting()
.registerTypeAdapter(Pattern.class, new PatternTypeAdapter())
.create();
try (BufferedWriter writer = Files.newBufferedWriter(this.file)) {
gson.toJson(this, writer);
GsonUtils.toJson(this, writer);
writer.flush();
} catch (IOException e) {
ExceptionLogger.capture(e, getClass().getSimpleName());
Expand Down Expand Up @@ -167,7 +157,10 @@ public void set(String propertyName, String value) throws UnknownPropertyExcepti
Optional<Pair<Field, Object>> result = ReflectionUtils.resolveField(propertyName, this);
result.ifPresent(pair -> {
try {
ReflectionUtils.set(pair.first(), pair.second(), value);
Object updatedField = ReflectionUtils.set(pair.first(), pair.second(), value);
if (updatedField instanceof GuildConfigItem item) {
item.setGuildConfig(this);
}
this.flush();
} catch (IllegalAccessException e) {
ExceptionLogger.capture(e, getClass().getSimpleName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.extern.slf4j.Slf4j;
import net.discordjug.javabot.util.ExceptionLogger;
import net.discordjug.javabot.util.GsonUtils;
import net.discordjug.javabot.util.Pair;

import org.jetbrains.annotations.NotNull;
Expand All @@ -22,19 +23,6 @@
public class ReflectionUtils {
private static final Map<Class<?>, Function<String, Object>> propertyTypeParsers = new HashMap<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line can be removed as well.


static {
propertyTypeParsers.put(Integer.class, Integer::parseInt);
propertyTypeParsers.put(int.class, Integer::parseInt);
propertyTypeParsers.put(Long.class, Long::parseLong);
propertyTypeParsers.put(long.class, Long::parseLong);
propertyTypeParsers.put(Float.class, Float::parseFloat);
propertyTypeParsers.put(float.class, Float::parseFloat);
propertyTypeParsers.put(Double.class, Double::parseDouble);
propertyTypeParsers.put(double.class, Double::parseDouble);
propertyTypeParsers.put(Boolean.class, Boolean::parseBoolean);
propertyTypeParsers.put(String.class, s -> s);
}

private ReflectionUtils() {
}

Expand Down Expand Up @@ -126,13 +114,12 @@ private static Field findDeclaredField(Class<?> cl, String name) throws NoSuchFi
* @param field The field to set.
* @param parent The object whose property value to set.
* @param s The string representation of the value.
* @return Returns the new value.
* @throws IllegalAccessException If the field cannot be set.
*/
public static void set(@NotNull Field field, @NotNull Object parent, @NotNull String s) throws IllegalAccessException {
Function<String, Object> parser = propertyTypeParsers.get(field.getType());
if (parser == null) {
throw new IllegalArgumentException("No supported property type parser for the type " + field.getType().getSimpleName());
}
field.set(parent, parser.apply(s));
public static Object set(@NotNull Field field, @NotNull Object parent, @NotNull String s) throws IllegalAccessException {
Object value = GsonUtils.fromJson(s, field.getGenericType());
field.set(parent, value);
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,18 @@
import java.time.Duration;
import java.util.Base64;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.RequiredArgsConstructor;
import net.discordjug.javabot.data.config.BotConfig;
import net.discordjug.javabot.data.config.PatternTypeAdapter;
import net.discordjug.javabot.data.config.guild.MessageRule;
import net.discordjug.javabot.data.config.guild.MessageRule.MessageAction;
import net.discordjug.javabot.data.config.guild.ModerationConfig;
import net.discordjug.javabot.data.h2db.message_cache.MessageCache;
import net.discordjug.javabot.data.h2db.message_cache.model.CachedMessage;
import net.discordjug.javabot.util.Checks;
import net.discordjug.javabot.util.ExceptionLogger;
import net.discordjug.javabot.util.GsonUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message.Attachment;
import net.dv8tion.jda.api.entities.Message;
Expand Down Expand Up @@ -73,17 +70,12 @@ public MessageModificationStatus processMessage(MessageContent content) {
}

private void log(MessageContent content, MessageRule ruleToExecute, ModerationConfig moderationConfig) {
Gson gson = new GsonBuilder()
.serializeNulls()
.setPrettyPrinting()
.registerTypeAdapter(Pattern.class, new PatternTypeAdapter())
.create();
EmbedBuilder embed = messageCache.buildMessageCacheEmbed(
content.event().getMessage().getChannel(),
content.event().getMessage().getAuthor(),
CachedMessage.of(content.event().getMessage()), "Message content")
.setTitle("Message rule triggered")
.addField("Rule description", "```\n" + gson.toJson(ruleToExecute) + "\n```", false);
.addField("Rule description", "```\n" + GsonUtils.toJson(ruleToExecute) + "\n```", false);
if (!content.attachments().isEmpty()) {
embed.addField("Attachment hashes", computeAttachmentDescription(content.attachments()), false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.discordjug.javabot.data.config.BotConfig;
import net.discordjug.javabot.data.config.GuildConfig;
import net.discordjug.javabot.data.config.UnknownPropertyException;
import net.discordjug.javabot.util.GsonUtils;
import net.discordjug.javabot.util.Responses;
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
Expand Down Expand Up @@ -38,7 +39,8 @@ public ReplyCallbackAction handleConfigSubcommand(@Nonnull SlashCommandInteracti
}
String property = propertyOption.getAsString().trim();
Object value = config.resolve(property);
return Responses.info(event, "Configuration Property", "The value of the property `%s` is:\n```\n%s\n```", property, value);
String json = GsonUtils.toJson(value);
return Responses.info(event, "Configuration Property", "The value of the property `%s` is:\n```\n%s\n```", property, json);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package net.discordjug.javabot.systems.configuration;

import com.google.gson.JsonSyntaxException;
import net.discordjug.javabot.annotations.AutoDetectableComponentHandler;
import net.discordjug.javabot.data.config.BotConfig;
import net.discordjug.javabot.data.config.GuildConfig;
import net.discordjug.javabot.data.config.UnknownPropertyException;
import net.discordjug.javabot.util.GsonUtils;
import net.discordjug.javabot.util.Responses;
import net.dv8tion.jda.api.components.label.Label;
import net.dv8tion.jda.api.components.textinput.TextInput;
Expand Down Expand Up @@ -57,10 +59,11 @@ public InteractionCallbackAction<?> handleConfigSubcommand(@Nonnull SlashCommand
if (resolved == null) {
return Responses.error(event, "Config `%s` not found", property);
}
String json = GsonUtils.toJson(resolved);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When setting the config to invalid JSON, I am getting the following exception:

com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Expected ':' at line 7 column 4 path $.sdfdfsdfs
See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json
	at com.google.gson.Gson.fromJson(Gson.java:1385)
	at com.google.gson.Gson.fromJson(Gson.java:1260)
	at com.google.gson.Gson.fromJson(Gson.java:1170)
	at com.google.gson.Gson.fromJson(Gson.java:1107)
	at net.discordjug.javabot.util.GsonUtils.fromJson(GsonUtils.java:24)
	at net.discordjug.javabot.data.config.ReflectionUtils.set(ReflectionUtils.java:121)
	at net.discordjug.javabot.data.config.GuildConfig.lambda$1(GuildConfig.java:160)
	at java.base/java.util.Optional.ifPresent(Optional.java:178)
	at net.discordjug.javabot.data.config.GuildConfig.set(GuildConfig.java:158)
	at net.discordjug.javabot.systems.configuration.SetConfigSubcommand.handleModal(SetConfigSubcommand.java:81)
	at xyz.dynxsty.dih4jda.InteractionHandler.lambda$onModalInteraction$27(InteractionHandler.java:788)
	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1825)
	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1817)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187)
Caused by: com.google.gson.stream.MalformedJsonException: Expected ':' at line 7 column 4 path $.sdfdfsdfs
See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json
	at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1817)
	at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:659)
	at com.google.gson.stream.JsonReader.skipValue(JsonReader.java:1396)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:517)
	at com.google.gson.Gson.fromJson(Gson.java:1359)
	... 16 more

return event.replyModal(
Modal.create(ComponentIdBuilder.build("config-set", property), "Change configuration value")
.addComponents(Label.of("new value", TextInput.create("value", TextInputStyle.PARAGRAPH)
.setValue(String.valueOf(resolved))
.setValue(json)
.build()))
.build());
}
Expand All @@ -78,8 +81,8 @@ public void handleModal(ModalInteractionEvent event, List<ModalMapping> values)
try {
guildConfig.set(property, valueString);
Responses.success(event, "Configuration Updated", "The property `%s` has been set to `%s`.", property, valueString).queue();
} catch (UnknownPropertyException e) {
Responses.error(event, "Property not found: %s", property).queue();
} catch (UnknownPropertyException | JsonSyntaxException e) {
Responses.error(event, "Error while setting new value").queue();
}
}

Expand Down
39 changes: 39 additions & 0 deletions src/main/java/net/discordjug/javabot/util/GsonUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package net.discordjug.javabot.util;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.discordjug.javabot.data.config.PatternTypeAdapter;

import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Type;
import java.util.regex.Pattern;

/**
* Utility class that contains several methods for using Gson.
*/
public class GsonUtils {

private static final Gson gson = new GsonBuilder()
.serializeNulls()
.setPrettyPrinting()
.registerTypeAdapter(Pattern.class, new PatternTypeAdapter())
.enableComplexMapKeySerialization()
.create();

public static <T> T fromJson(Reader json, Class<T> type) {
return gson.fromJson(json, type);
}

public static String fromJson(String json, Type type) {
return gson.fromJson(json, type);
}

public static String toJson(Object object) {
return gson.toJson(object);
}

public static void toJson(Object object, Writer writer) {
gson.toJson(object, writer);
}
}