11package org .togetherjava .tjbot .features .messages ;
22
3+ import net .dv8tion .jda .api .entities .Message ;
34import net .dv8tion .jda .api .events .interaction .command .SlashCommandInteractionEvent ;
45import net .dv8tion .jda .api .interactions .commands .OptionMapping ;
56import net .dv8tion .jda .api .interactions .commands .OptionType ;
1920
2021/**
2122 * The implemented command is {@code /rewrite-msg}, which allows users to have their message
22- * rewritten in a clearer, more professional, or better structured form using ChatGPT AI.
23+ * rewritten in a clearer, more professional, or better structured form using AI.
2324 * <p>
2425 * The rewritten message is shown as an ephemeral message visible only to the user who triggered the
25- * command, making it perfect for getting quick writing improvements without cluttering the channel .
26+ * command.
2627 * <p>
27- * Users can optionally specify a tone/style for the rewrite. If not provided, defaults to CLEAR.
28+ * Users can optionally specify a tone/style for the rewrite.
2829 */
29- public final class RewriteMsgCommand extends SlashCommandAdapter {
30- private static final Logger logger = LoggerFactory .getLogger (RewriteMsgCommand .class );
31- public static final String COMMAND_NAME = "rewrite-msg " ;
30+ public final class RewriteCommand extends SlashCommandAdapter {
31+ private static final Logger logger = LoggerFactory .getLogger (RewriteCommand .class );
32+ private static final String COMMAND_NAME = "rewrite" ;
3233 private static final String MESSAGE_OPTION = "message" ;
3334 private static final String TONE_OPTION = "tone" ;
34- private static final int MAX_MESSAGE_LENGTH = 500 ;
35+
36+ private static final int MAX_MESSAGE_LENGTH = Message .MAX_CONTENT_LENGTH ;
3537 private static final int MIN_MESSAGE_LENGTH = 3 ;
36- private static final ChatGptModel CHAT_GPT_MODEL = ChatGptModel .HIGH_QUALITY ;
38+ private static final ChatGptModel CHAT_GPT_MODEL = ChatGptModel .FASTEST ;
3739
3840 private final ChatGptService chatGptService ;
3941
40- private static String buildResponse (String userMessage , String rewrittenMessage , MsgTone tone ) {
41- final String toneLabel = tone .displayName ;
42-
42+ private static String createAiPrompt (String userMessage , MessageTone tone ) {
4343 return """
44- **Rewritten message (%s)**
44+ Rewrite the following message to make it clearer, more professional, \
45+ and better structured. Maintain the original meaning while improving the quality \
46+ of the writing. Do NOT use em-dashes (—). %s
4547
46- **Original:**
47- %s
48+ IMPORTANT: The rewritten text MUST be no more than 2000 characters. \
49+ If needed, compress wording while preserving key details and intent.
50+
51+ If the message is already well-written, provide minor improvements.
4852
49- **Rewritten:**
50- %s""" .formatted (toneLabel , userMessage , rewrittenMessage );
53+ Original message:
54+ %s""" .stripIndent (). formatted (tone . description , userMessage );
5155 }
5256
53- private static String buildChatGptPrompt (String userMessage , MsgTone tone ) {
57+ private static String buildOriginalMsgResponse (String userMessage , MessageTone tone ) {
5458 return """
55- Please rewrite the following message to make it clearer, more professional, \
56- and better structured. Maintain the original meaning while improving the quality \
57- of the writing. Do NOT use em-dashes (—). %s
59+ **Original message (%s)**
5860
59- If the message is already well-written, provide minor improvements.
61+ %s
62+ """ .stripIndent ().formatted (tone .displayName , userMessage );
63+ }
6064
61- Original message:
62- %s""" .formatted (tone .description , userMessage );
65+ private static String buildRewrittenMsgResponse (String aiMessage , MessageTone tone ) {
66+ return """
67+ **Rewritten message (%s)**
68+
69+ %s
70+ """ .stripIndent ().formatted (tone .displayName , aiMessage );
6371 }
6472
6573 /**
6674 * Creates the slash command definition and configures available options for rewriting messages.
6775 *
6876 * @param chatGptService service for interacting with ChatGPT
6977 */
70- public RewriteMsgCommand (ChatGptService chatGptService ) {
78+ public RewriteCommand (ChatGptService chatGptService ) {
7179 super (COMMAND_NAME , "Let AI rephrase and improve your message" , CommandVisibility .GUILD );
7280
7381 this .chatGptService = chatGptService ;
@@ -79,64 +87,97 @@ public RewriteMsgCommand(ChatGptService chatGptService) {
7987 .setMaxLength (MAX_MESSAGE_LENGTH );
8088
8189 final OptionData toneOption = new OptionData (OptionType .STRING , TONE_OPTION ,
82- "The tone/style for the rewritten message (default: " + MsgTone . CLEAR . displayName
83- + ")" ,
90+ "The tone/style for the rewritten message (default: "
91+ + MessageTone . CLEAR . displayName + ")" ,
8492 false );
8593
86- Arrays .stream (MsgTone .values ())
94+ Arrays .stream (MessageTone .values ())
8795 .forEach (tone -> toneOption .addChoice (tone .displayName , tone .name ()));
8896
8997 getData ().addOptions (messageOption , toneOption );
9098 }
9199
92100 @ Override
93101 public void onSlashCommand (SlashCommandInteractionEvent event ) {
102+
94103 final String userMessage =
95104 Objects .requireNonNull (event .getOption (MESSAGE_OPTION )).getAsString ();
96-
97- final MsgTone tone = parseTone (event .getOption (TONE_OPTION ), event .getUser ().getId ());
105+ final MessageTone tone = parseTone (event .getOption (TONE_OPTION ));
98106
99107 event .deferReply (true ).queue ();
100108
101- final Optional <String > rewrittenMessage = this . rewrite (userMessage , tone );
109+ Optional <String > rewrittenMessage = rewrite (userMessage , tone );
102110
103111 if (rewrittenMessage .isEmpty ()) {
104- logger .debug ("Failed to obtain a response for /rewrite-msg, original message: '{}'" ,
105- userMessage );
112+ logger .debug ("Failed to obtain a response for /{}, original message: '{}'" ,
113+ COMMAND_NAME , userMessage );
114+
106115 event .getHook ()
107116 .editOriginal (
108117 "An error occurred while processing your request. Please try again later." )
109118 .queue ();
119+
110120 return ;
111121 }
112122
113- final String response = buildResponse ( userMessage , rewrittenMessage .orElseThrow (), tone );
123+ final String rewrittenText = rewrittenMessage .orElseThrow ();
114124
115- event .getHook ().editOriginal (response ).queue ();
125+ logger .debug ("Rewrite successful; rewritten message length: {}" , rewrittenText .length ());
126+
127+ event .getHook ()
128+ .sendMessage (buildOriginalMsgResponse (userMessage , tone ))
129+ .setEphemeral (true )
130+ .queue ();
131+
132+ event .getHook ()
133+ .sendMessage (buildRewrittenMsgResponse (rewrittenText , tone ))
134+ .setEphemeral (true )
135+ .queue ();
116136 }
117137
118- private MsgTone parseTone (@ Nullable OptionMapping toneOption , String userId )
138+ private MessageTone parseTone (@ Nullable OptionMapping toneOption )
119139 throws IllegalArgumentException {
140+
120141 if (toneOption == null ) {
121- logger .debug ("Tone option not provided for user: {} , using default CLEAR " , userId );
122- return MsgTone .CLEAR ;
142+ logger .debug ("Tone option not provided, using default '{}' " , MessageTone . CLEAR . name () );
143+ return MessageTone .CLEAR ;
123144 }
124145
125146 final String toneValue = toneOption .getAsString ();
126- final MsgTone tone = MsgTone .valueOf (toneValue );
127-
128- logger .debug ("Parsed tone '{}' for user: {}" , tone .displayName , userId );
129147
130- return tone ;
148+ return MessageTone . valueOf ( toneValue ) ;
131149 }
132150
133- private Optional <String > rewrite (String userMessage , MsgTone tone ) {
134- final String rewritePrompt = buildChatGptPrompt (userMessage , tone );
151+ private Optional <String > rewrite (String userMessage , MessageTone tone ) {
152+
153+ final String rewritePrompt = createAiPrompt (userMessage , tone );
154+
155+ Optional <String > attempt =
156+ chatGptService .ask (rewritePrompt , tone .displayName , CHAT_GPT_MODEL );
157+
158+ if (attempt .isEmpty ()) {
159+ return attempt ;
160+ }
161+
162+ final String response = attempt .get ();
163+
164+ if (response .length () <= Message .MAX_CONTENT_LENGTH ) {
165+ return attempt ;
166+ }
167+
168+ logger .debug ("Rewritten message exceeded {} characters; retrying with stricter constraint" ,
169+ Message .MAX_CONTENT_LENGTH );
170+
171+ final String shortenPrompt = rewritePrompt
172+ + "\n \n Constraint reminder: Your previous rewrite exceeded "
173+ + Message .MAX_CONTENT_LENGTH
174+ + " characters. Provide a revised rewrite strictly under "
175+ + Message .MAX_CONTENT_LENGTH + " characters while preserving meaning and tone." ;
135176
136- return chatGptService .ask (rewritePrompt , tone .displayName , CHAT_GPT_MODEL );
177+ return chatGptService .ask (shortenPrompt , tone .displayName , CHAT_GPT_MODEL );
137178 }
138179
139- private enum MsgTone {
180+ private enum MessageTone {
140181 CLEAR ("Clear" , "Make it clear and easy to understand." ),
141182 PRO ("Pro" , "Use a professional and polished tone." ),
142183 DETAILED ("Detailed" , "Expand with more detail and explanation." ),
@@ -145,7 +186,7 @@ private enum MsgTone {
145186 private final String displayName ;
146187 private final String description ;
147188
148- MsgTone (String displayName , String description ) {
189+ MessageTone (String displayName , String description ) {
149190 this .displayName = displayName ;
150191 this .description = description ;
151192 }
0 commit comments