Skip to content

Fix dead links in ChatGPT responses (#1276)#1471

Open
vlaym wants to merge 2 commits into
Together-Java:developfrom
vlaym:fix/replace-dead-links-in-chatgpt-response
Open

Fix dead links in ChatGPT responses (#1276)#1471
vlaym wants to merge 2 commits into
Together-Java:developfrom
vlaym:fix/replace-dead-links-in-chatgpt-response

Conversation

@vlaym
Copy link
Copy Markdown
Contributor

@vlaym vlaym commented Apr 29, 2026

Closes #1276

What was done

  • Integrated LinkDetection.replaceDeadLinks() (added in Add utilities to detect and replace broken links. #1366) into HelpSystemHelper#generateGptResponseEmbed(). The replacement runs before the embed is built, so both the auto-AI response in help threads and /chatgpt command are covered since they share the same embed builder.
  • If the link check fails (e.g. network error), the original answer is kept as-is - no broken behavior.
  • Added two unit tests in HelpSystemHelperTest: one verifying dead link replacement, one verifying fallback when replacement fails.

Approach

The issue proposes two options: ideally sending the response immediately and then editing it after async link checking, or as a fallback - replacing links before sending.

Current (fallback) flow:

post created → ChatGPT generates answer → dead links replaced → embed built → embed sent to Discord

Ideal flow (not implemented):

post created → ChatGPT generates answer → embed sent immediately → links checked in the background → already-sent message edited with clean links

The fallback was chosen because it keeps the change in one place (HelpSystemHelper) and is easy to test. The ideal flow would require mixing two different async mechanisms: checking links uses Java's CompletableFuture (because it makes plain HTTP requests to external sites — JDA is not involved here at all), while sending and editing Discord messages uses JDA's RestAction. These two do not compose directly, so some extra glue code is needed to chain them together correctly.

@vlaym vlaym requested a review from a team as a code owner April 29, 2026 14:52
surajkumar
surajkumar previously approved these changes Jun 5, 2026

private String sanitizeBrokenLinks(String answer) {
try {
return brokenLinkReplacer.apply(answer).join();
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.

join without timeout isnt good

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you. Added a 10-second timeout via orTimeout() so the thread cannot block indefinitely.

+private static final int LINK_CHECK_TIMEOUT_SECONDS = 10;

 private String sanitizeBrokenLinks(String answer) {
     try {
-        return brokenLinkReplacer.apply(answer).join();
+        return brokenLinkReplacer.apply(answer)
+            .orTimeout(LINK_CHECK_TIMEOUT_SECONDS, TimeUnit.SECONDS)
+            .join();
     } catch (RuntimeException runtimeException) {
         logger.debug("Failed to replace broken links in ChatGPT response", runtimeException);
         return answer;
     }
 }

If the check does not finish in time, join() throws a CompletionException (wrapping TimeoutException), which is caught by the existing RuntimeException catch block — so the original answer is returned as a fallback. Since replaceDeadLinks checks all links in parallel, the timeout applies to the slowest single request, not the sum of all of them.

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.

Replace broken links send by ChatGpt

3 participants