-
-
Notifications
You must be signed in to change notification settings - Fork 105
Feature: Implement /rewrite command for message improvement using Cha… #1378
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
| * <p> | ||
| * Users can optionally specify a tone/style for the rewrite. If not provided, defaults to CLEAR. | ||
| */ | ||
| public final class RewriteMsgCommand extends SlashCommandAdapter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dont abbreviate, RewriteMsgCommand. but to avoid confusion i would try to stick to the actual slash-command name, so just RewriteCommand would be better imo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about doing that in the beginning, but I found that it may be confusing, since it's possible to be interpreted "rewrite something else, other than a message", so I found it better to write "Message" as abbreviation to avoid verbosity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but that confusion then also applies to the slashcommand. if u think its confusing then the slash command has to be renamed as well, to /rewrite-msg for example. then the class name is okay again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/rewrite is perfectly fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tj-wazei is this a requirement or an optional suggestion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is his opinion as code-reviewer. and now we come to a consensus. i am also fine with rewrite but im still proposing to call the class RewriteCommand in that case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, here's the plan:
- Rename the class to
RewriteCommand - Restore the original name of the command (
/rewrite)
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgCommand.java
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgCommand.java
Outdated
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgCommand.java
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgCommand.java
Outdated
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgService.java
Outdated
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgTone.java
Outdated
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgTone.java
Outdated
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgTone.java
Outdated
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/Features.java
Outdated
Show resolved
Hide resolved
|
tj-wazei
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see comments. There's a lot of final abuse that does nothing but add clutter to the code. It's best to use final when you need it.
|
|
||
| /** | ||
| * The implemented command is {@code /rewrite-msg}, which allows users to have their message | ||
| * rewritten in a clearer, more professional, or better structured form using ChatGPT AI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove ChatGPT from the docs as you leak too much implementation details. "using AI" is fine.
| * rewritten in a clearer, more professional, or better structured form using ChatGPT AI. | ||
| * <p> | ||
| * The rewritten message is shown as an ephemeral message visible only to the user who triggered the | ||
| * command, making it perfect for getting quick writing improvements without cluttering the channel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
making it perfect for getting quick writing improvements without cluttering the channel. is unnecessary for code documentation.
| * The rewritten message is shown as an ephemeral message visible only to the user who triggered the | ||
| * command, making it perfect for getting quick writing improvements without cluttering the channel. | ||
| * <p> | ||
| * Users can optionally specify a tone/style for the rewrite. If not provided, defaults to CLEAR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
defaults to CLEAR does not tell a developer what CLEAR is so please can you change this so it makes sense without coupling it to the enum (that isn't even linked).
| * <p> | ||
| * Users can optionally specify a tone/style for the rewrite. If not provided, defaults to CLEAR. | ||
| */ | ||
| public final class RewriteMsgCommand extends SlashCommandAdapter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/rewrite is perfectly fine
| */ | ||
| public final class RewriteMsgCommand extends SlashCommandAdapter { | ||
| private static final Logger logger = LoggerFactory.getLogger(RewriteMsgCommand.class); | ||
| public static final String COMMAND_NAME = "rewrite-msg"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
COMMAND_NAME does not need to be public
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SquidXTV it sounds like you accidently marked this as resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Damn, my bad
| final Optional<String> rewrittenMessage = this.rewrite(userMessage, tone); | ||
|
|
||
| if (rewrittenMessage.isEmpty()) { | ||
| logger.debug("Failed to obtain a response for /rewrite-msg, original message: '{}'", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not hard code the name here, instead used the constant you defined COMMAND_NAME
| logger.debug("Failed to obtain a response for /rewrite-msg, original message: '{}'", | ||
| userMessage); | ||
| event.getHook() | ||
| .editOriginal( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't good UX. If the user spent a fair bit of time trying to craft their message and an error occurs, they lose it. Instead, return back the original message - an embed might be useful here to add the fact there was an "error" but the user can still copy their original message and send that, should they wish.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI discord shows the original prompt on slash commands if u click on the "foo used /bar" that didcord shows in small blue text above the message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI discord shows the original prompt on slash commands if u click on the "foo used /bar" that didcord shows in small blue text above the message
| return; | ||
| } | ||
|
|
||
| final String response = buildResponse(userMessage, rewrittenMessage.orElseThrow(), tone); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary use of orElseThrow since it will never throw. You are doing an isEmpty check above.
Ideally, this entire block is a good candidate for rewrittenMessage.ifPresentOrElse() if you want that fluency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to be fair, if (foo.isEmpty()) ... foo.orElseThrow() is the normal way ur supposed to deal with this in case you are not able to utilize the other, better, methods of the API. (but in this case, try to put the extraction of the content right after the if-check, not 20 lines later)
| } | ||
|
|
||
| private Optional<String> rewrite(String userMessage, MsgTone tone) { | ||
| final String rewritePrompt = buildChatGptPrompt(userMessage, tone); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can inline this String
| private Optional<String> rewrite(String userMessage, MsgTone tone) { | ||
| final String rewritePrompt = buildChatGptPrompt(userMessage, tone); | ||
|
|
||
| return chatGptService.ask(rewritePrompt, tone.displayName, CHAT_GPT_MODEL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to update the ask method. The original implementor of the ChatGptService did not make this abstract enough so your request will be mixed with the following prefixed:
For code supplied for review, refer to the old code supplied rather than rewriting the code. DON'T supply a corrected version of the code.
KEEP IT CONCISE, NOT MORE THAN 280 WORDS
%s
Question: %s| %s | ||
| **Rewritten:** | ||
| %s""".formatted(toneLabel, userMessage, rewrittenMessage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dont forget to String#stripIndent when using multi-line strings
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgCommand.java
Show resolved
Hide resolved
| If the message is already well-written, provide minor improvements. | ||
| Original message: | ||
| %s""".formatted(tone.description, userMessage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dont forget to String#stripIndent when using multi-line strings
| @Override | ||
| public void onSlashCommand(SlashCommandInteractionEvent event) { | ||
| final String userMessage = | ||
| Objects.requireNonNull(event.getOption(MESSAGE_OPTION)).getAsString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for requireNonNull
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the getOption() return is Nullable based on its docs
| final OptionData toneOption = new OptionData(OptionType.STRING, TONE_OPTION, | ||
| "The tone/style for the rewritten message (default: " + MsgTone.CLEAR.displayName | ||
| + ")", | ||
| false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
y not also make it auto-completeable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgCommand.java
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgCommand.java
Show resolved
Hide resolved
application/src/main/java/org/togetherjava/tjbot/features/messages/RewriteMsgCommand.java
Show resolved
Hide resolved
| if (toneOption == null) { | ||
| logger.debug("Tone option not provided for user: {}, using default CLEAR", userId); | ||
| return MsgTone.CLEAR; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cannot be null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're confused here, the call of the method is like this this.parseTone(event.getOption(TONE_OPTION), event.getUser().getId());, where the event.getOption(TONE_OPTION) refers to toneOption argument, and the return of getOption() is marked @Nullable based on docs and source
| event.getHook().editOriginal(response).queue(); | ||
| } | ||
|
|
||
| private MsgTone parseTone(@Nullable OptionMapping toneOption, String userId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are you taking in the userId just for the logs? seems unnecessary
Zabuzard
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great stuff. Apart from what the others mentioned, im happy now 👍




New Feature: Rewrite Command
The
/rewritecommand allows users to have their messages rewritten in a clearer, more professional, or better structured form using ChatGPT AI (GPT 5 mini). The rewritten message is displayed as an ephemeral message (visible only to the user), making it perfect for getting quick writing improvements without cluttering the channel where they are.Usage
Parameters
CLEARif not providedAvailable Tones
How It Works
Example
UPDATE
/rewrite-msgfor consistency with the class in source code.