Fix formatting of code longer than Discord's message limit#549
Fix formatting of code longer than Discord's message limit#549Neil-Tomar wants to merge 4 commits into
Conversation
danthe1st
left a comment
There was a problem hiding this comment.
Congratulations on writing your first pull request. I commented on a few things I noticed. Please don't unnecessarily duplicate code.
| } | ||
| channel.sendMessage(messages.get(index)) | ||
| .setAllowedMentions(List.of()) | ||
| .setComponents(FormatCodeCommand.buildActionRow(event.getTarget(), event.getUser().getIdLong())) |
There was a problem hiding this comment.
The action row including the buttons for deleting and the URL for jumping back are no longer present because you removed them here. Please add them to all messages.
There was a problem hiding this comment.
There is a reason for that. The buttons only affect the message they are attached to, so adding them to each message would only allow deletion of that specific message.
Adding buttons to every message would also introduce a visual break inside the code block, which could hurt readability, as shown in the screenshots.
If you'd prefer the buttons to appear only on the last message while still affecting the entire code block, I can look into implementing that. I'm not familiar with that approach yet, but I'm happy to investigate it.
Here is with buttons:
as you can see it's hard to read through indentation.
There was a problem hiding this comment.
If it is a single message, both buttons should definitely be there.
If it consists of multiple messages, at least the View Original button should be present in the last message. There could also be a delete button that deletes all codeblock messages on the last message (and the file upload message should also have both buttons).
| this.content = content; | ||
| } | ||
|
|
||
| public String getContent() { |
There was a problem hiding this comment.
I think getContent() and setLanguage are unused. If so, please remove them.
There was a problem hiding this comment.
getContent() is still present.
There was a problem hiding this comment.
getContent() in now being used in FormatCodeDispatcher at line 34 and 44.
|
Fixes #537 |
…nto fix/format-code-long-messages # Conflicts: # src/main/java/net/discordjug/javabot/systems/user_commands/format_code/Code.java # src/main/java/net/discordjug/javabot/systems/user_commands/format_code/FormatCodeDispatcher.java # src/main/java/net/discordjug/javabot/systems/user_commands/format_code/Language.java
danthe1st
left a comment
There was a problem hiding this comment.
These are mostly minor comments. Is there any good reason why users would want a file response in addition to the codeblocks?
| */ | ||
| private static final int MAX_SIZE = 1980; | ||
|
|
||
| private Language language; |
There was a problem hiding this comment.
Do you plan on needing to mutate Language in the follow-up PR you planned? If not, you could make this final or make Code a record.
| * downloadable file, then posts it as one or more ordered code-block messages that each respect | ||
| * Discord's 2000-character limit. | ||
| */ | ||
| public class FormatCodeDispatcher { |
There was a problem hiding this comment.
This class is only used internally and could be package private.
| * @return an action row containing the delete and "View Original" buttons | ||
| */ | ||
| @Contract("_ -> new") | ||
| static @NotNull ActionRow buildActionRow(@NotNull Message target, long requesterId) { |
There was a problem hiding this comment.
I guess this could be moved to FormatCodeDispatcher as that's the place for common code but it's fine as-is.
|
|
||
| MessageChannel channel = target.getChannel(); | ||
|
|
||
| event.replyFiles(file) |
There was a problem hiding this comment.
What is the reason to reply with a file vs just using event.reply... on the first message and skipping the file?
At least if it's only a single chunk, there shouldn't be any file (but I think it's also better without a file with multiple messages).
Make sure to update the Javadoc accordingly.
There was a problem hiding this comment.
I tried dropping the file and replying with the first chunk as suggested, but it hits two problems:
Sending the chunks as plain messages with no reply leaves the interaction unacknowledged → "This application did not respond."
Replying with the first chunk does acknowledge it, but the reply renders as its own attributed block, separate from the follow-up messages, so the code gets split visually mid-block.

Replying with the file avoids both: it acknowledges the interaction, and since the reply is a file (not a chunk) the code-block messages stay uniform with no break — plus it's a clean, copyable full version that reads nicely on desktop. The file seemed like the most useful thing to put there.
So, my preference would actually be to keep the file for both the single- and multi-chunk cases — it gives a consistent experience either way. But if you'd rather it was gone, I'm happy to remove it for the single-chunk case (just reply with the one block directly), or if you have a different approach in mind, I'll gladly go with that.
| Responses.error(event.getHook(), "There is no code to format in that message.").queue(); | ||
| return; | ||
| } | ||
| // Currently we always format as Java. A language dropdown will be added in the future. |
There was a problem hiding this comment.
That comment is incorrect. The Code can have a language with /format-code.
| .setAllowedMentions(List.of()); | ||
|
|
||
| if (index == messages.size() - 1) { | ||
| action.setComponents(buildActionRow(target, event.getUser().getIdLong())); |
There was a problem hiding this comment.
Please also add the standard delete button if there is only a single message.
| if (index >= messages.size()) { | ||
| return; | ||
| } | ||
| var action = channel.sendMessage(messages.get(index)) |
There was a problem hiding this comment.
If you remove the file upload, you can do something like this:
String content = messages.get(index);
MessageRequest<?> action = index == 0 ? event.reply(content) : channel.sendMessage(content);
action.setAllowedMentions(List.of());| * syntax highlighting inside code blocks. | ||
| */ | ||
| public enum Language { | ||
| /** |
There was a problem hiding this comment.
I think you don't need Javadoc comments for the enum constants here (but please check using mvn verify).
| /** | ||
| * Fallback used when the language is unrecognised; renders as plain text. | ||
| */ | ||
| UNKNOWN("Unknown", "txt"); |
There was a problem hiding this comment.
If you are removing the replyFiles, I think you can change the "txt" to "".
Description of the Changes
The "Format Code" / "Format and Indent Code" message commands and the
/format-codeslash command failed when the target message was longer than Discord's 2000-character limit: the whole snippet was wrapped in a single code block and sent as one message, which Discord rejects — so the command silently did nothing.This PR splits the formatted output into chunks that each stay under the limit:
Codeclass splits content into ≤1980-character chunks (breaking on newlines where possible) and renders each as a code block.Languageenum +Language.fromString(...)maps the slash command'sformatoption to a code-fence tag.A follow-up PR will add the language-selection dropdown.