Skip to content

Fix formatting of code longer than Discord's message limit#549

Open
Neil-Tomar wants to merge 8 commits into
Java-Discord:mainfrom
Neil-Tomar:fix/format-code-long-messages
Open

Fix formatting of code longer than Discord's message limit#549
Neil-Tomar wants to merge 8 commits into
Java-Discord:mainfrom
Neil-Tomar:fix/format-code-long-messages

Conversation

@Neil-Tomar

Copy link
Copy Markdown

Description of the Changes

The "Format Code" / "Format and Indent Code" message commands and the /format-code slash 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:

  • New Code class splits content into ≤1980-character chunks (breaking on newlines where possible) and renders each as a code block.
  • The commands acknowledge the interaction by replying with the full, unsplit code as an attached file, then post the chunks in order.
  • New Language enum + Language.fromString(...) maps the slash command's format option to a code-fence tag.

A follow-up PR will add the language-selection dropdown.

@Neil-Tomar Neil-Tomar requested a review from a team as a code owner June 20, 2026 15:17

@danthe1st danthe1st left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Congratulations on writing your first pull request. I commented on a few things I noticed. Please don't unnecessarily duplicate code.

Comment thread src/main/java/net/discordjug/javabot/systems/user_commands/format_code/Code.java Outdated
}
channel.sendMessage(messages.get(index))
.setAllowedMentions(List.of())
.setComponents(FormatCodeCommand.buildActionRow(event.getTarget(), event.getUser().getIdLong()))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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.

image

Here is with buttons:

image

as you can see it's hard to read through indentation.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think getContent() and setLanguage are unused. If so, please remove them.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

getContent() is still present.

@Neil-Tomar Neil-Tomar Jun 24, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

getContent() in now being used in FormatCodeDispatcher at line 34 and 44.

@danthe1st

Copy link
Copy Markdown
Member

Fixes #537

@danthe1st danthe1st linked an issue Jun 20, 2026 that may be closed by this pull request
@Neil-Tomar Neil-Tomar requested a review from danthe1st June 23, 2026 15:30
…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 danthe1st left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These are mostly minor comments. Is there any good reason why users would want a file response in addition to the codeblocks?

Comment thread src/main/java/net/discordjug/javabot/systems/user_commands/format_code/Code.java Outdated

MessageChannel channel = target.getChannel();

event.replyFiles(file)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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.
image

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.

@danthe1st danthe1st Jun 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In that case, please replace it with an ephemeral response:

Responses.success(event, "Success", "The formatted message is being sent to this channel.").queue();

(or similar)

There is no reason to clutter the public channel with the file.

/**
* Fallback used when the language is unrecognised; renders as plain text.
*/
UNKNOWN("Unknown", "txt");

@danthe1st danthe1st Jun 23, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If you are removing the replyFiles, I think you can change the "txt" to "" but it's fine if you don't.

@Neil-Tomar Neil-Tomar requested a review from danthe1st June 24, 2026 07:59

@danthe1st danthe1st left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall, your PR looks pretty good.

During testing, I noticed that it's possible to send a single message that can result in a lot of individual (and big). As an example, you can generate the content of such a message with the following code:

System.out.println("{".repeat(30)+"\n"+"a\n".repeat(1000)+"}".repeat(30));

Please add a limit to this. I don't want to have to clean that up without knowing the exact number (I think it is possible to trigger more than 500 messages with a single message that way). See the second review comment here for how to fix it.

* human-readable {@link #displayName} to the {@link #discordName} tag Discord uses for
* syntax highlighting inside code blocks.
*/
public enum Language {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If you want to, you can also add JSON there but you don't need to by any means.

return;
}

List<String> messages = code.toDiscordMessages();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please show an error if messages.size() > 5 instead of sending the code.

@danthe1st danthe1st Jun 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I forgot to mention the following: If you are already at it, could you please also remove the Collections.reverse(messages); statement? That shouldn't be there (unrelated to your PR) and results in formatting the wrong message.

@Neil-Tomar Neil-Tomar requested a review from danthe1st June 24, 2026 16:41
class FormatCodeDispatcher {

/**
* The maximum number of code-block messages to post inline; longer code is sent only as a file.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please update the Javadoc to say it shows an error in that situation.

@Neil-Tomar Neil-Tomar requested a review from danthe1st June 25, 2026 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exception formatting code >2k characters

2 participants