From 3fba69823a1f7a7b69f8c7a5ee1351118cd816cf Mon Sep 17 00:00:00 2001 From: HappyAreaBean Date: Mon, 22 Apr 2024 17:11:15 +0800 Subject: [PATCH] feat: collections can now be edited via editor --- .../happyareabean/sjm/SimpleJoinMessage.java | 2 +- .../sjm/commands/SJMCommand.java | 95 ++++++++++++++----- .../sjm/database/DatabaseManager.java | 21 +++- 3 files changed, 88 insertions(+), 30 deletions(-) diff --git a/src/main/java/cc/happyareabean/sjm/SimpleJoinMessage.java b/src/main/java/cc/happyareabean/sjm/SimpleJoinMessage.java index a022604..b16c934 100644 --- a/src/main/java/cc/happyareabean/sjm/SimpleJoinMessage.java +++ b/src/main/java/cc/happyareabean/sjm/SimpleJoinMessage.java @@ -122,7 +122,7 @@ public void loadSync() { return; } - database.getContent(collection).ifPresentOrElse(data -> { + database.getRawContent(collection).ifPresentOrElse(data -> { logger().info("Updating join message from collection [%s]...".formatted(collection)); String content = new String(Util.BASE64_DECODER.decode(data.getContent())); diff --git a/src/main/java/cc/happyareabean/sjm/commands/SJMCommand.java b/src/main/java/cc/happyareabean/sjm/commands/SJMCommand.java index eb8a781..404f7d6 100644 --- a/src/main/java/cc/happyareabean/sjm/commands/SJMCommand.java +++ b/src/main/java/cc/happyareabean/sjm/commands/SJMCommand.java @@ -20,6 +20,7 @@ import revxrsal.commands.annotation.DefaultFor; import revxrsal.commands.annotation.Description; import revxrsal.commands.annotation.Named; +import revxrsal.commands.annotation.Optional; import revxrsal.commands.annotation.Subcommand; import revxrsal.commands.bukkit.BukkitCommandActor; import revxrsal.commands.bukkit.annotation.CommandPermission; @@ -28,7 +29,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; +import java.util.concurrent.CompletableFuture; import static cc.happyareabean.sjm.SimpleJoinMessage.LEGACY_SERIALIZER; import static cc.happyareabean.sjm.SimpleJoinMessage.MINIMESSAGE; @@ -87,30 +88,60 @@ public void show(BukkitCommandActor actor) { } @Subcommand({"editor"}) - @Description("Open join message editor") - public void editor(BukkitCommandActor actor) { + @Description("Open a new join message editor session") + @AutoComplete("@sjmData") + public void editor(BukkitCommandActor actor, @Optional @Named("collection") String collection) { SJMConfig config = SimpleJoinMessage.getInstance().getSJMConfig(); - AdventureWebEditorAPI api = SimpleJoinMessage.getInstance().getAdventureWebEditorAPI(); - actor.reply(Constants.PREFIX.append(text("Preparing new editor session, please wait...", NamedTextColor.GRAY))); - api.startSession(String.join("\n", config.getJoinMessage()), "/sjm applyedits {token}", Constants.USER_AGENT) - .whenComplete((token, throwable) -> { - if (throwable != null) { - actor.reply(Constants.PREFIX.append(text("Error occurred when processing your request: " + throwable.getMessage(), NamedTextColor.RED))); - return; - } - String url = config.getAdventureWebURL() + "?token=" + token; - actor.reply(Constants.PREFIX.append(text("Click the link below to open the editor:", NamedTextColor.GREEN))); - actor.reply(text(url, NamedTextColor.AQUA).clickEvent(clickEvent(ClickEvent.Action.OPEN_URL, url))); - }); + CompletableFuture.supplyAsync(() -> { + if (collection == null) + return config.getJoinMessage(); + + return SimpleJoinMessage.getInstance().getDatabase().getContent(collection); + }).whenComplete((strings, throwable) -> { + + if (throwable != null) { + actor.reply(Constants.PREFIX.append(text("Error occurred when preparing your editor session: " + throwable.getMessage(), + NamedTextColor.RED))); + return; + } + + // Check if strings are null and a collection is entered + // Because strings will always non-null if a collection is not entered + if (strings == null && collection != null) { + actor.reply(Constants.PREFIX.append(text("The collection '%s' does not exist.".formatted(collection), NamedTextColor.RED))); + return; + } + + AdventureWebEditorAPI api = SimpleJoinMessage.getInstance().getAdventureWebEditorAPI(); + String command = collection != null ? "/sjm applyedits {token} " + collection : "/sjm applyedits {token}"; + actor.reply(Constants.PREFIX.append(text("Preparing new editor session, please wait...", NamedTextColor.GRAY))); + api.startSession(String.join("\n", strings), command, Constants.USER_AGENT) + .whenComplete((token, editorThrowable) -> { + if (editorThrowable != null) { + actor.reply(Constants.PREFIX.append(text("Error occurred when processing your request: " + editorThrowable.getMessage(), NamedTextColor.RED))); + return; + } + String url = config.getAdventureWebURL() + "?token=" + token; + + actor.reply(Constants.PREFIX.append(text("Click the link below to open the editor:", NamedTextColor.GREEN))); + actor.reply(text(url, NamedTextColor.AQUA).clickEvent(clickEvent(ClickEvent.Action.OPEN_URL, url))); + }); + }); } @Subcommand({"applyedits"}) @Description("Apply edit from editor") - public void applyEdits(BukkitCommandActor actor, @Named("token") String token) { + public void applyEdits(BukkitCommandActor actor, @Named("token") String token, @Optional @Named("collection") String collection) { SJMConfig config = SimpleJoinMessage.getInstance().getSJMConfig(); AdventureWebEditorAPI api = SimpleJoinMessage.getInstance().getAdventureWebEditorAPI(); actor.reply(Constants.PREFIX.append(text("Applying your edits...", NamedTextColor.GRAY))); + + if (collection != null && !SimpleJoinMessage.getInstance().getDatabase().getCollections().contains(collection)) { + actor.reply(Constants.PREFIX.append(text("The collection '%s' does not exist.".formatted(collection), NamedTextColor.RED))); + return; + } + api.retrieveSession(token) .whenComplete((value, throwable) -> { if (throwable != null) { @@ -118,25 +149,36 @@ public void applyEdits(BukkitCommandActor actor, @Named("token") String token) { return; } - config.setJoinMessage(Arrays.stream(value.split("\n")).collect(Collectors.toList())); - config.save(); - config.reloadAndSave(); + List messages = Arrays.stream(value.split("\n")).toList(); + SJMSync sync = SimpleJoinMessage.getInstance().getSyncConfig(); + + // Perform different action if sync enabled and collection arg are not null + // This makes sure apply edits will operate normally if sync is disabled + if (sync.isEnabled() && collection != null) { + SimpleJoinMessage.getInstance().getDatabase().updateCollection(collection, value); + } else { + config.setJoinMessage(messages); + config.save(); + config.reloadAndSave(); + } + + String command = collection != null ? "/sjm collection show " + collection : "/sjm show"; actor.reply(Constants.PREFIX .append(text("Web editor data was applied successfully.", NamedTextColor.GREEN)) .append(space()) .append(text("Click here to view join message", NamedTextColor.WHITE, TextDecoration.BOLD) - .hoverEvent(text("Click here to run /sjm show", NamedTextColor.YELLOW)) - .clickEvent(clickEvent(ClickEvent.Action.RUN_COMMAND, "/sjm show"))) + .hoverEvent(text("Click here to run " + command, NamedTextColor.YELLOW)) + .clickEvent(clickEvent(ClickEvent.Action.RUN_COMMAND, command))) ); }); } @Subcommand({"regenerate"}) - @Description("Regenerate SJM settings back to default") + @Description("Regenerate SJM settings.yml back to default") public void regenerate(BukkitCommandActor actor) { - actor.reply(Constants.PREFIX.append(text("Regenerating SJM settings..."))); + actor.reply(Constants.PREFIX.append(text("Regenerating SJM settings.yml..."))); String fileName = SimpleJoinMessage.getInstance().regenerateSettings(); - actor.reply(Constants.PREFIX.append(text("Settings has been regenerated and a backup has been saved as ")) + actor.reply(Constants.PREFIX.append(text("settings.yml has been regenerated and a backup has been saved as ")) .append(text(fileName, NamedTextColor.GRAY))); } @@ -208,7 +250,7 @@ public void collectionShow(BukkitCommandActor actor, @Named("collection") String Player player = actor.requirePlayer(); Bukkit.getScheduler().runTaskAsynchronously(SimpleJoinMessage.getInstance(), () -> SimpleJoinMessage.getInstance().getDatabase() - .getContentFuture(collectionName) + .getRawContentFuture(collectionName) .whenCompleteAsync((data, throwable) -> { if (data.isEmpty()) { @@ -255,9 +297,10 @@ public void syncSet(BukkitCommandActor actor, @Named("collection") String collec actor.reply(Constants.PREFIX.append(text("The collection has been updated to %s.".formatted(collectionName), NamedTextColor.GREEN))); actor.reply(Constants.PREFIX.append(text("It will be applied when the next server starts up.", NamedTextColor.GREEN))); + actor.reply(Constants.PREFIX.append(text("Or you can manually trigger sync by using '/sjm sync now'", NamedTextColor.GREEN))); } - @Subcommand({"sync"}) + @Subcommand({"sync now"}) @Description("Manually perform sync operation") public void sync(BukkitCommandActor actor) { Bukkit.getScheduler().runTaskAsynchronously(SimpleJoinMessage.getInstance(), () -> { diff --git a/src/main/java/cc/happyareabean/sjm/database/DatabaseManager.java b/src/main/java/cc/happyareabean/sjm/database/DatabaseManager.java index e7e8fad..fb038a9 100644 --- a/src/main/java/cc/happyareabean/sjm/database/DatabaseManager.java +++ b/src/main/java/cc/happyareabean/sjm/database/DatabaseManager.java @@ -1,6 +1,7 @@ package cc.happyareabean.sjm.database; import cc.happyareabean.sjm.SimpleJoinMessage; +import cc.happyareabean.sjm.utils.Util; import com.nivixx.ndatabase.api.NDatabase; import com.nivixx.ndatabase.api.Promise; import com.nivixx.ndatabase.api.query.NQuery; @@ -22,6 +23,7 @@ import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -126,7 +128,7 @@ public CompletableFuture updateCollection(String name, String content) { .findOne(NQuery.predicate("$.collection_name == " + name)); if (optional.isEmpty()) - throw new RuntimeException("This collection does not exist"); + return; SJMData newData = optional.get(); newData.setContent(BASE64_ENCODER.encodeToString(content.getBytes())); @@ -139,17 +141,30 @@ public Promise.AsyncEmptyResult deleteCollection(String name) { .deleteAsync(name); } - public CompletableFuture> getContentFuture(String collectionName) { + public CompletableFuture> getRawContentFuture(String collectionName) { return SimpleJoinMessage.getInstance().getDatabase().getData() .findOneAsync(NQuery.predicate("$.collection_name == " + collectionName)) .getResultFuture(); } - public Optional getContent(String collectionName) { + public Optional getRawContent(String collectionName) { return SimpleJoinMessage.getInstance().getDatabase().getData() .findOne(NQuery.predicate("$.collection_name == " + collectionName)); } + public CompletableFuture> getContentFuture(String collectionName) { + return CompletableFuture.supplyAsync(() -> getContent(collectionName)); + } + + public List getContent(String collectionName) { + Optional sjmData = getRawContent(collectionName); + + if (sjmData.isEmpty()) return null; + + String content = new String(Util.BASE64_DECODER.decode(sjmData.get().getContent())); + return Arrays.stream(content.split("\n")).toList(); + } + public void updateCollectionNames() { collections.clear(); data.streamAllValuesAsync().thenAsync(stream -> {