From c42529cbf869f5798c82c83caa8ddb0f74790c6e Mon Sep 17 00:00:00 2001 From: Neil Tomar Date: Sat, 4 Jul 2026 20:58:04 +0530 Subject: [PATCH 1/3] feat: link multi-message code blocks for delete-all and language switching Delete-all button removes every message of a block; ephemeral language dropdown re-colors every chunk. Only the bot's own messages are touched. --- .../FormatAndIndentCodeMessageContext.java | 2 +- .../format_code/FormatCodeCommand.java | 4 +- .../format_code/FormatCodeDispatcher.java | 38 ++--- .../FormatCodeInteractionHandler.java | 131 ++++++++++++++++++ .../format_code/FormatCodeMessageContext.java | 2 +- .../format_code/LinkedMessages.java | 60 ++++++++ 6 files changed, 204 insertions(+), 33 deletions(-) create mode 100644 src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java create mode 100644 src/main/java/net/discordjug/javabot/systems/user_commands/format_code/LinkedMessages.java diff --git a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatAndIndentCodeMessageContext.java b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatAndIndentCodeMessageContext.java index 4c3bbc7c4..f355fdc01 100644 --- a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatAndIndentCodeMessageContext.java +++ b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatAndIndentCodeMessageContext.java @@ -30,6 +30,6 @@ public void execute(@NotNull MessageContextInteractionEvent event) { Code code = new Code(Language.JAVA, indented); - event.deferReply().queue(_ -> FormatCodeDispatcher.sendCode(code, event, event.getTarget())); + event.deferReply(true).queue(_ -> FormatCodeDispatcher.sendCode(code, event, event.getTarget())); } } diff --git a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeCommand.java b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeCommand.java index 10744eab6..ebbfecceb 100644 --- a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeCommand.java +++ b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeCommand.java @@ -56,7 +56,7 @@ public void execute(@NotNull SlashCommandInteractionEvent event) { String indentation = event.getOption("auto-indent","NULL",OptionMapping::getAsString); if (idOption == null) { - event.deferReply().queue(_ -> { + event.deferReply(true).queue(_ -> { event.getChannel().getHistory() .retrievePast(10) .queue(messages -> { @@ -78,7 +78,7 @@ public void execute(@NotNull SlashCommandInteractionEvent event) { return; } long messageId = idOption.getAsLong(); - event.deferReply().queue(_ -> { + event.deferReply(true).queue(_ -> { event.getChannel().retrieveMessageById(messageId).queue( target -> sendFormattedCode(event, target, language, indentation), error -> Responses.errorWithTitle(event.getHook(), "Message Not Found", "Could not retrieve the message with ID `" + messageId + "`. Make sure the message exists and is accessible.").queue()); diff --git a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeDispatcher.java b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeDispatcher.java index 4fc1215ac..f0b04375f 100644 --- a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeDispatcher.java +++ b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeDispatcher.java @@ -49,7 +49,9 @@ public static void sendCode(Code code, @Nonnull CommandInteraction event, Messag return; } - Responses.success(event.getHook(), "Success", "The formatted message is being sent to this channel.") + event.getHook().sendMessage("Your message has been formatted. If needed, you can change the language used for syntax highlighting below.") + .setEphemeral(true) + .setComponents(FormatCodeInteractionHandler.buildLanguageMenu(event.getUser().getIdLong(),messages.size())) .queue(success -> sendChunksInOrder(channel, messages, 0, target,event)); } @@ -62,38 +64,16 @@ private static void sendChunksInOrder(MessageChannel channel, List messa .setAllowedMentions(List.of()); if (index == messages.size() - 1) { - if(index == 0){ - action.setComponents(buildActionRow(target, event.getUser().getIdLong())); - } else { - action.setComponents(buildActionRow(target)); - } + action.setComponents(buildActionRow(target, event.getUser().getIdLong(), messages.size())); } - action.queue(success -> - sendChunksInOrder(channel, messages, index + 1, target, event)); + action.queue(sent -> sendChunksInOrder(channel, messages, index + 1, target, event)); } - /** - * Builds the action row placed on the last code-block message. - * - * @param target the original message linked by the "View Original" button - * @return an action row containing the "View Original" link button - */ - @Contract("_ -> new") - static @NotNull ActionRow buildActionRow(@NotNull Message target) { - return ActionRow.of(Button.link(target.getJumpUrl(), "View Original")); - } - - /** - * Builds the action row placed on the file-upload message: a delete button and a "View Original" link. - * - * @param target the original message linked by the "View Original" button - * @param requesterId the id of the user permitted to delete the message - * @return an action row containing the delete and "View Original" buttons - */ - @Contract("_,_ -> new") - static @NotNull ActionRow buildActionRow(@NotNull Message target, long requesterId) { - return ActionRow.of(InteractionUtils.createDeleteButton(requesterId), + @Contract("_,_,_ -> new") + static @NotNull ActionRow buildActionRow(@NotNull Message target, long requesterId, int total) { + return ActionRow.of( + FormatCodeInteractionHandler.createDeleteAllButton(requesterId, total), Button.link(target.getJumpUrl(), "View Original")); } } diff --git a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java new file mode 100644 index 000000000..fb4e1fba4 --- /dev/null +++ b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java @@ -0,0 +1,131 @@ +package net.discordjug.javabot.systems.user_commands.format_code; + +import lombok.RequiredArgsConstructor; +import net.discordjug.javabot.annotations.AutoDetectableComponentHandler; +import net.discordjug.javabot.data.config.BotConfig; +import net.discordjug.javabot.util.Checks; +import net.discordjug.javabot.util.Responses; +import net.dv8tion.jda.api.components.actionrow.ActionRow; +import net.dv8tion.jda.api.components.buttons.Button; +import net.dv8tion.jda.api.components.selections.SelectOption; +import net.dv8tion.jda.api.components.selections.StringSelectMenu; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent; +import org.jspecify.annotations.NonNull; +import xyz.dynxsty.dih4jda.interactions.components.ButtonHandler; +import xyz.dynxsty.dih4jda.interactions.components.StringSelectMenuHandler; +import xyz.dynxsty.dih4jda.util.ComponentIdBuilder; + +import java.util.Arrays; +import java.util.List; + +/** + * Handles the interactive components on formatted code blocks: the delete-all button and the + * language-selection dropdown. Both act on every message of a (possibly multi-message) block, + * which is resolved via {@link LinkedMessages}. + */ +@AutoDetectableComponentHandler(FormatCodeInteractionHandler.COMPONENT_ID) +@RequiredArgsConstructor +public class FormatCodeInteractionHandler implements ButtonHandler, StringSelectMenuHandler { + static final String COMPONENT_ID = "format-code-delete"; + private final BotConfig botConfig; + + /** + * Builds the delete-all button placed on the last message of a code block. + * + * @param requesterID the id of the user allowed to delete the block + * @param total the number of messages making up the block + * @return the delete-all button + */ + public static Button createDeleteAllButton(long requesterID, int total){ + return Button.secondary(ComponentIdBuilder.build(COMPONENT_ID,requesterID,total),"\uD83D\uDDD1️"); + } + + private static StringSelectMenu languageMenu(String customId) { + return StringSelectMenu.create(customId) + .setPlaceholder("Change language") + .addOptions(Arrays.stream(Language.values()) + .filter(language -> language != Language.UNKNOWN) + .map(language -> SelectOption.of(language.getDisplayName(), language.name())) + .toList()) + .build(); + } + + /** + * Builds the language-selection dropdown row for a code block. + * + * @param requesterId the id of the user allowed to change the language + * @param total the number of messages making up the block + * @return an action row containing the language dropdown + */ + public static ActionRow buildLanguageMenu(long requesterId, int total) { + return ActionRow.of(languageMenu(ComponentIdBuilder.build(COMPONENT_ID, requesterId, total))); + } + + @Override + public void handleButton(ButtonInteractionEvent event, Button button) { + String[] id = ComponentIdBuilder.split(event.getComponentId()); + long requesterId = Long.parseLong(id[1]); + + + Member member = event.getMember(); + if (member == null) { + Responses.error(event, "This button may only be used inside a server.").queue(); + return; + } + if (!canManage(member, requesterId)) { + Responses.errorWithTitle(event, "Access Denied", "You are not authorized to perform this action.").queue(); + return; + } + + event.deferEdit().queue(); + var channel = event.getChannel(); + LinkedMessages.resolve(channel, event.getMessage(), Integer.parseInt(id[2]), + messages -> messages.forEach(message -> message.delete().queue())); + } + + @Override + public void handleStringSelectMenu(@NonNull StringSelectInteractionEvent event, @NonNull List values) { + String[] id = ComponentIdBuilder.split(event.getComponentId()); + long requesterId = Long.parseLong(id[1]); + + Member member = event.getMember(); + if (member == null) { + Responses.error(event, "This menu may only be used inside a server.").queue(); + return; + } + if (!canManage(member, requesterId)) { + Responses.errorWithTitle(event, "Access Denied", "You are not authorized to perform this action.").queue(); + return; + } + + Language language = Language.fromString(values.getFirst()); + event.deferEdit().queue(); + + LinkedMessages.resolveForward(event.getChannel(), event.getMessage(), Integer.parseInt(id[2]), + messages -> messages.forEach(message -> + message.editMessage(withLanguage(message.getContentRaw(), language)).queue())); + } + + private boolean canManage(Member member, long requesterId) { + return member.getIdLong() == requesterId + || Checks.hasStaffRole(botConfig, member) + || member.isOwner() ; + } + + /** + * Re-wraps a code-block message in a different language by swapping the tag on its opening fence, + * leaving the code itself untouched. + * + * @param content the raw message content, expected to start with a fenced code block + * @param language the language to switch to + * @return the message content with its opening fence set to {@code language} + */ + private static String withLanguage(String content, Language language) { + int firstLineEnd = content.indexOf('\n'); + return firstLineEnd < 0 + ? content + : "```" + language.getDiscordName() + content.substring(firstLineEnd); + } +} diff --git a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeMessageContext.java b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeMessageContext.java index ce1033702..835fa72cf 100644 --- a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeMessageContext.java +++ b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeMessageContext.java @@ -27,6 +27,6 @@ public void execute(@NotNull MessageContextInteractionEvent event) { Code code = new Code(Language.JAVA, content); - event.deferReply().queue(_ -> FormatCodeDispatcher.sendCode(code, event, event.getTarget())); + event.deferReply(true).queue(_ -> FormatCodeDispatcher.sendCode(code, event, event.getTarget())); } } diff --git a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/LinkedMessages.java b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/LinkedMessages.java new file mode 100644 index 000000000..04956161f --- /dev/null +++ b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/LinkedMessages.java @@ -0,0 +1,60 @@ +package net.discordjug.javabot.systems.user_commands.format_code; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + + +/** + * Helper for acting on a block of related messages sent as a group — such as a piece of code split + * across several Discord messages. Given one message of the block and the total count, it resolves + * the whole block (only the bot's own messages) so a single interaction can delete or edit it. + */ +public class LinkedMessages { + private LinkedMessages(){} + + /** + * Resolves the block ending at {@code triggerMessage} (walking back {@code total} messages) and + * passes the bot's own messages among them to {@code onResolved}. + * + * @param channel the channel the block is in + * @param triggerMessage the last message of the block (carries the component) + * @param total the number of messages in the block + * @param onResolved receives the bot's messages that make up the block + */ + static void resolve(MessageChannel channel, Message triggerMessage, int total, Consumer> onResolved) { + if (total <= 1) { + onResolved.accept(List.of(triggerMessage)); + return; + } + channel.getHistoryBefore(triggerMessage.getIdLong(), total - 1).queue(history -> { + List block = new ArrayList<>(history.getRetrievedHistory()); + block.add(triggerMessage); + onResolved.accept(onlyOwn(channel, block)); + }); + } + + /** + * Resolves the block of {@code total} messages sent after {@code anchorMessage} and passes the + * bot's own messages among them to {@code onResolved}. + * + * @param channel the channel the block is in + * @param anchorMessage the message just before the block (carries the component) + * @param total the number of messages in the block + * @param onResolved receives the bot's messages that make up the block + */ + static void resolveForward(MessageChannel channel, Message anchorMessage, int total, Consumer> onResolved) { + channel.getHistoryAfter(anchorMessage.getIdLong(), total).queue(history -> + onResolved.accept(onlyOwn(channel, history.getRetrievedHistory()))); + } + + private static List onlyOwn(MessageChannel channel, List messages) { + long selfId = channel.getJDA().getSelfUser().getIdLong(); + return messages.stream() + .filter(message -> message.getAuthor().getIdLong() == selfId) + .toList(); + } +} From 50e3fdfb05a57beb745efe76a699f51b12c0a34a Mon Sep 17 00:00:00 2001 From: Neil Tomar Date: Sun, 5 Jul 2026 18:42:11 +0530 Subject: [PATCH 2/3] refactor: address review feedback --- .../FormatCodeInteractionHandler.java | 20 +++++---- .../format_code/LinkedMessages.java | 43 +++++++++++-------- .../javabot/util/InteractionUtils.java | 2 +- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java index fb4e1fba4..3119242e4 100644 --- a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java +++ b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java @@ -28,7 +28,7 @@ @AutoDetectableComponentHandler(FormatCodeInteractionHandler.COMPONENT_ID) @RequiredArgsConstructor public class FormatCodeInteractionHandler implements ButtonHandler, StringSelectMenuHandler { - static final String COMPONENT_ID = "format-code-delete"; + static final String COMPONENT_ID = "format-code"; private final BotConfig botConfig; /** @@ -39,7 +39,7 @@ public class FormatCodeInteractionHandler implements ButtonHandler, StringSelect * @return the delete-all button */ public static Button createDeleteAllButton(long requesterID, int total){ - return Button.secondary(ComponentIdBuilder.build(COMPONENT_ID,requesterID,total),"\uD83D\uDDD1️"); + return Button.secondary(ComponentIdBuilder.build(COMPONENT_ID,requesterID,total),"\uD83D\uDDD1\uFE0F"); } private static StringSelectMenu languageMenu(String customId) { @@ -64,7 +64,7 @@ public static ActionRow buildLanguageMenu(long requesterId, int total) { } @Override - public void handleButton(ButtonInteractionEvent event, Button button) { + public void handleButton(ButtonInteractionEvent event, @NonNull Button button) { String[] id = ComponentIdBuilder.split(event.getComponentId()); long requesterId = Long.parseLong(id[1]); @@ -80,13 +80,14 @@ public void handleButton(ButtonInteractionEvent event, Button button) { } event.deferEdit().queue(); - var channel = event.getChannel(); - LinkedMessages.resolve(channel, event.getMessage(), Integer.parseInt(id[2]), - messages -> messages.forEach(message -> message.delete().queue())); + + LinkedMessages.resolveBefore(event.getMessage(), Integer.parseInt(id[2]), + messages -> event.getChannel().purgeMessages(messages), + () -> Responses.error(event.getHook(),"Could not delete the code block")); } @Override - public void handleStringSelectMenu(@NonNull StringSelectInteractionEvent event, @NonNull List values) { + public void handleStringSelectMenu(@NonNull StringSelectInteractionEvent event, @NonNull List values) { String[] id = ComponentIdBuilder.split(event.getComponentId()); long requesterId = Long.parseLong(id[1]); @@ -103,9 +104,10 @@ public void handleStringSelectMenu(@NonNull StringSelectInteractionEvent event, Language language = Language.fromString(values.getFirst()); event.deferEdit().queue(); - LinkedMessages.resolveForward(event.getChannel(), event.getMessage(), Integer.parseInt(id[2]), + LinkedMessages.resolveAfter(event.getMessage(), Integer.parseInt(id[2]), messages -> messages.forEach(message -> - message.editMessage(withLanguage(message.getContentRaw(), language)).queue())); + message.editMessage(withLanguage(message.getContentRaw(), language)).queue()), + () -> Responses.error(event.getHook(),"Could not update the code block")); } private boolean canManage(Member member, long requesterId) { diff --git a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/LinkedMessages.java b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/LinkedMessages.java index 04956161f..54d0e8e63 100644 --- a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/LinkedMessages.java +++ b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/LinkedMessages.java @@ -1,7 +1,6 @@ package net.discordjug.javabot.systems.user_commands.format_code; import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import java.util.ArrayList; import java.util.List; @@ -18,43 +17,53 @@ private LinkedMessages(){} /** * Resolves the block ending at {@code triggerMessage} (walking back {@code total} messages) and - * passes the bot's own messages among them to {@code onResolved}. + * passes the bot's own messages to {@code onResolved}, or runs {@code onError} if it can't be + * safely resolved. * - * @param channel the channel the block is in * @param triggerMessage the last message of the block (carries the component) * @param total the number of messages in the block - * @param onResolved receives the bot's messages that make up the block + * @param onResolved receives the bot's messages that make up the block + * @param onError runs if the block can't be safely resolved */ - static void resolve(MessageChannel channel, Message triggerMessage, int total, Consumer> onResolved) { + static void resolveBefore(Message triggerMessage, int total, Consumer> onResolved, Runnable onError) { if (total <= 1) { - onResolved.accept(List.of(triggerMessage)); + verify(List.of(triggerMessage), total, onResolved, onError); return; } - channel.getHistoryBefore(triggerMessage.getIdLong(), total - 1).queue(history -> { + triggerMessage.getChannel().getHistoryBefore(triggerMessage.getIdLong(), total - 1).queue(history -> { List block = new ArrayList<>(history.getRetrievedHistory()); block.add(triggerMessage); - onResolved.accept(onlyOwn(channel, block)); + verify(block, total, onResolved, onError); }); } /** * Resolves the block of {@code total} messages sent after {@code anchorMessage} and passes the - * bot's own messages among them to {@code onResolved}. + * bot's own messages to {@code onResolved}, or runs {@code onError} if it can't be safely resolved. * - * @param channel the channel the block is in * @param anchorMessage the message just before the block (carries the component) * @param total the number of messages in the block - * @param onResolved receives the bot's messages that make up the block + * @param onResolved receives the bot's messages that make up the block + * @param onError runs if the block can't be safely resolved */ - static void resolveForward(MessageChannel channel, Message anchorMessage, int total, Consumer> onResolved) { - channel.getHistoryAfter(anchorMessage.getIdLong(), total).queue(history -> - onResolved.accept(onlyOwn(channel, history.getRetrievedHistory()))); + static void resolveAfter(Message anchorMessage, int total, Consumer> onResolved, Runnable onError) { + anchorMessage.getChannel().getHistoryAfter(anchorMessage.getIdLong(), total).queue(history -> + verify(history.getRetrievedHistory(), total, onResolved, onError)); + } + + private static void verify(List messages, int total, Consumer> onResolved, Runnable onError) { + List own = onlyOwn(messages); + boolean allCodeBlocks = own.stream().allMatch(message -> message.getContentRaw().startsWith("```")); + if (own.size() != total || !allCodeBlocks) { + onError.run(); + return; + } + onResolved.accept(own); } - private static List onlyOwn(MessageChannel channel, List messages) { - long selfId = channel.getJDA().getSelfUser().getIdLong(); + private static List onlyOwn(List messages) { return messages.stream() - .filter(message -> message.getAuthor().getIdLong() == selfId) + .filter(message -> message.getAuthor().getIdLong() == message.getJDA().getSelfUser().getIdLong()) .toList(); } } diff --git a/src/main/java/net/discordjug/javabot/util/InteractionUtils.java b/src/main/java/net/discordjug/javabot/util/InteractionUtils.java index 41c057b3d..b91f2cb10 100644 --- a/src/main/java/net/discordjug/javabot/util/InteractionUtils.java +++ b/src/main/java/net/discordjug/javabot/util/InteractionUtils.java @@ -116,7 +116,7 @@ private boolean canDeleteUsingButton(Member member, String[] componentId) { } public static Button createDeleteButton(long senderId) { - return Button.secondary(createDeleteInteractionId(senderId), "\uD83D\uDDD1️"); + return Button.secondary(createDeleteInteractionId(senderId), "\uD83D\uDDD1\uFE0F"); } public static String createDeleteInteractionId(long senderId) { From 87a95527a76fc6a763ea275d3c631d0c460e4e82 Mon Sep 17 00:00:00 2001 From: Neil Tomar Date: Sun, 5 Jul 2026 22:03:59 +0530 Subject: [PATCH 3/3] fixed small mistakes. --- .../format_code/FormatCodeInteractionHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java index 3119242e4..56472a08e 100644 --- a/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java +++ b/src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeInteractionHandler.java @@ -83,7 +83,7 @@ public void handleButton(ButtonInteractionEvent event, @NonNull Button button) { LinkedMessages.resolveBefore(event.getMessage(), Integer.parseInt(id[2]), messages -> event.getChannel().purgeMessages(messages), - () -> Responses.error(event.getHook(),"Could not delete the code block")); + () -> Responses.error(event.getHook(),"Could not delete the code block").queue()); } @Override @@ -107,7 +107,7 @@ public void handleStringSelectMenu(@NonNull StringSelectInteractionEvent event, LinkedMessages.resolveAfter(event.getMessage(), Integer.parseInt(id[2]), messages -> messages.forEach(message -> message.editMessage(withLanguage(message.getContentRaw(), language)).queue()), - () -> Responses.error(event.getHook(),"Could not update the code block")); + () -> Responses.error(event.getHook(),"Could not update the code block").queue()); } private boolean canManage(Member member, long requesterId) {