|
| 1 | +package org.togetherjava.tjbot.features.messages; |
| 2 | + |
| 3 | +import net.dv8tion.jda.api.entities.MessageEmbed; |
| 4 | +import net.dv8tion.jda.api.entities.SelfUser; |
| 5 | +import net.dv8tion.jda.api.interactions.commands.OptionMapping; |
| 6 | +import org.jetbrains.annotations.Nullable; |
| 7 | +import org.slf4j.Logger; |
| 8 | +import org.slf4j.LoggerFactory; |
| 9 | + |
| 10 | +import org.togetherjava.tjbot.features.chatgpt.ChatGptModel; |
| 11 | +import org.togetherjava.tjbot.features.chatgpt.ChatGptService; |
| 12 | +import org.togetherjava.tjbot.features.help.HelpSystemHelper; |
| 13 | + |
| 14 | +import java.util.Optional; |
| 15 | + |
| 16 | +/** |
| 17 | + * Service for handling rewrite command business logic and ChatGPT integration. |
| 18 | + */ |
| 19 | +public class RewriteMsgService { |
| 20 | + private static final Logger logger = LoggerFactory.getLogger(RewriteMsgService.class); |
| 21 | + private static final ChatGptModel CHAT_GPT_MODEL = ChatGptModel.HIGH_QUALITY; |
| 22 | + |
| 23 | + private final ChatGptService chatGptService; |
| 24 | + private final HelpSystemHelper helper; |
| 25 | + |
| 26 | + /** |
| 27 | + * Creates a new RewriteMsgService. |
| 28 | + * |
| 29 | + * @param chatGptService the ChatGPT service |
| 30 | + * @param helper the help system helper for embed formatting |
| 31 | + */ |
| 32 | + public RewriteMsgService(ChatGptService chatGptService, HelpSystemHelper helper) { |
| 33 | + this.chatGptService = chatGptService; |
| 34 | + this.helper = helper; |
| 35 | + } |
| 36 | + |
| 37 | + public String validateMsg(@Nullable OptionMapping messageOption, String userId) { |
| 38 | + logger.debug("Extracting message option for user: {}", userId); |
| 39 | + logger.debug("Retrieved message option: {}", messageOption != null ? "present" : "null"); |
| 40 | + |
| 41 | + final String userMessage = messageOption != null ? messageOption.getAsString() : ""; |
| 42 | + |
| 43 | + if (userMessage.isEmpty()) { |
| 44 | + logger.warn("User {} provided an empty message", userId); |
| 45 | + } else { |
| 46 | + logger.debug("User {} provided message of length: {}", userId, userMessage.length()); |
| 47 | + logMessagePreview(userMessage); |
| 48 | + } |
| 49 | + |
| 50 | + return userMessage; |
| 51 | + } |
| 52 | + |
| 53 | + public RewriteMsgTone parseTone(@Nullable OptionMapping toneOption, String userId) { |
| 54 | + logger.debug("Extracting tone option for user: {}", userId); |
| 55 | + logger.debug("Retrieved tone option: {}", toneOption != null ? "present" : "null"); |
| 56 | + |
| 57 | + if (toneOption == null) { |
| 58 | + logger.debug("Tone option not provided, using default: {}", |
| 59 | + RewriteMsgTone.CLEAR.getDisplayName()); |
| 60 | + return RewriteMsgTone.CLEAR; |
| 61 | + } |
| 62 | + |
| 63 | + final String toneValue = toneOption.getAsString(); |
| 64 | + try { |
| 65 | + final RewriteMsgTone tone = RewriteMsgTone.valueOf(toneValue); |
| 66 | + logger.debug("Parsed tone value from option: {}", toneValue); |
| 67 | + return tone; |
| 68 | + } catch (IllegalArgumentException e) { |
| 69 | + logger.error("Invalid tone value provided: {}, using default CLEAR", toneValue, e); |
| 70 | + return RewriteMsgTone.CLEAR; |
| 71 | + } |
| 72 | + } |
| 73 | + |
| 74 | + public Optional<String> rewrite(String userMessage, RewriteMsgTone tone, String userId) { |
| 75 | + logger.debug("Rewriting message for user {} with tone: {}", userId, tone.getDisplayName()); |
| 76 | + |
| 77 | + final String rewritePrompt = buildChatGptPrompt(userMessage, tone); |
| 78 | + logger.debug("ChatGPT prompt prepared: {} characters", rewritePrompt.length()); |
| 79 | + |
| 80 | + try { |
| 81 | + final Optional<String> rewrittenMessage = chatGptService.ask(rewritePrompt, |
| 82 | + "Professional writing improvement", CHAT_GPT_MODEL); |
| 83 | + |
| 84 | + if (rewrittenMessage.isPresent()) { |
| 85 | + logger.info("Successfully rewrote message for user: {} with tone: {}", userId, |
| 86 | + tone.getDisplayName()); |
| 87 | + logMessagePreview(rewrittenMessage.get()); |
| 88 | + } else { |
| 89 | + logger.warn("ChatGPT returned empty response for user: {}", userId); |
| 90 | + } |
| 91 | + |
| 92 | + return rewrittenMessage; |
| 93 | + } catch (Exception e) { |
| 94 | + logger.error("Failed to rewrite message for user: {}", userId, e); |
| 95 | + return Optional.empty(); |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + public Optional<MessageEmbed> buildResponse(String userMessage, |
| 100 | + @Nullable String rewrittenMessage, RewriteMsgTone tone, String userId, |
| 101 | + SelfUser selfUser) { |
| 102 | + logger.debug("Building response embed for user: {}", userId); |
| 103 | + |
| 104 | + final String responseContent = rewrittenMessage != null ? rewrittenMessage |
| 105 | + : "Sorry, I couldn't rewrite your message at this time. Please try again later."; |
| 106 | + final String embedTitle = "Rewritten message (" + tone.getDisplayName() + ")"; |
| 107 | + logger.debug("Prepared embed title: {}", embedTitle); |
| 108 | + |
| 109 | + try { |
| 110 | + final MessageEmbed responseEmbed = helper.generateGptResponseEmbed( |
| 111 | + "**Original:**\n" + userMessage + "\n\n**Rewritten:**\n" + responseContent, |
| 112 | + selfUser, embedTitle, CHAT_GPT_MODEL); |
| 113 | + logger.debug("Message embed created successfully for user: {}", userId); |
| 114 | + return Optional.of(responseEmbed); |
| 115 | + } catch (Exception e) { |
| 116 | + logger.error("Failed to create message embed for user: {}", userId, e); |
| 117 | + return Optional.empty(); |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + private String buildChatGptPrompt(String userMessage, RewriteMsgTone tone) { |
| 122 | + return """ |
| 123 | + Please rewrite the following message to make it clearer, more professional, \ |
| 124 | + and better structured. Maintain the original meaning while improving the quality \ |
| 125 | + of the writing. Do NOT use em-dashes (—). %s |
| 126 | +
|
| 127 | + If the message is already well-written, provide minor improvements. |
| 128 | +
|
| 129 | + Original message: |
| 130 | + %s""".formatted(tone.getPromptInstruction(), userMessage); |
| 131 | + } |
| 132 | + |
| 133 | + private void logMessagePreview(String message) { |
| 134 | + final int previewLength = Math.min(50, message.length()); |
| 135 | + final String preview = message.substring(0, previewLength); |
| 136 | + |
| 137 | + logger.debug("Message content preview: {}", preview); |
| 138 | + } |
| 139 | +} |
0 commit comments