From 482eef7a82a94de981ef13b97f9dbcd8094e4471 Mon Sep 17 00:00:00 2001 From: billpapat <50835814+billpapat@users.noreply.github.com> Date: Sat, 28 Jun 2025 18:22:02 +0300 Subject: [PATCH 1/7] fix: handle empty message content for thread titles Ensures a fallback thread title is provided when the original message content is empty. The thread title will now default to the message author's name in such cases, preventing empty or uninformative thread titles. Co-authored-by: billpapat <50835814+billpapat@users.noreply.github.com> Co-authored-by: Chris Sdogkos Mentored-by: Chris Sdogkos --- .../features/basic/SuggestionsUpDownVoter.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java index 0a5add113b..f978798cbf 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java @@ -55,19 +55,26 @@ public void onMessageReceived(MessageReceivedEvent event) { } private static void createThread(Message message) { - String title = message.getContentRaw(); - if (title.length() >= TITLE_MAX_LENGTH) { - int lastWordEnd = title.lastIndexOf(' ', TITLE_MAX_LENGTH); + String threadTitle; + String messageContent = message.getContentRaw(); + + if (messageContent.isEmpty()){ + threadTitle = message.getAuthor().getName(); + } else if (messageContent.length() >= TITLE_MAX_LENGTH) { + int lastWordEnd = messageContent.lastIndexOf(' ', TITLE_MAX_LENGTH); if (lastWordEnd == -1) { lastWordEnd = TITLE_MAX_LENGTH; } - title = title.substring(0, lastWordEnd); + threadTitle = messageContent.substring(0, lastWordEnd); + } else { + + threadTitle = messageContent; } - message.createThreadChannel(title).queue(); + message.createThreadChannel(threadTitle).queue(); } private static void reactWith(String emojiName, Emoji fallbackEmoji, Guild guild, From 629ac8c8b80d8624b14b20fe1d965eba08005abe Mon Sep 17 00:00:00 2001 From: billpapat <50835814+billpapat@users.noreply.github.com> Date: Sat, 28 Jun 2025 18:34:35 +0300 Subject: [PATCH 2/7] style: apply gradle task `spotlessApply` CI/CD is failing without this commit. Co-authored-by: billpapat <50835814+billpapat@users.noreply.github.com> Co-authored-by: Chris Sdogkos Mentored-by: Chris Sdogkos --- .../tjbot/features/basic/SuggestionsUpDownVoter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java index f978798cbf..4deff229d9 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java @@ -59,7 +59,7 @@ private static void createThread(Message message) { String threadTitle; String messageContent = message.getContentRaw(); - if (messageContent.isEmpty()){ + if (messageContent.isEmpty()) { threadTitle = message.getAuthor().getName(); } else if (messageContent.length() >= TITLE_MAX_LENGTH) { int lastWordEnd = messageContent.lastIndexOf(' ', TITLE_MAX_LENGTH); From 08da7949fb5a9da1844d3a0fce960bf8f33059b7 Mon Sep 17 00:00:00 2001 From: billpapat <50835814+billpapat@users.noreply.github.com> Date: Sun, 29 Jun 2025 21:50:59 +0300 Subject: [PATCH 3/7] fix: thread titles #1265 1) Created channels without title will default to "username's suggestions" 2) Change String threadTitle to final 3) ThreadTitle logic implemented in a helper method Co-authored-by: Ethan McCue <5004262+bowbahdoe@users.noreply.github.com> --- .../basic/SuggestionsUpDownVoter.java | 23 ++--------- .../tjbot/features/basic/ThreadTitle.java | 38 +++++++++++++++++++ 2 files changed, 41 insertions(+), 20 deletions(-) create mode 100644 application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java index 4deff229d9..681d0af202 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java @@ -23,7 +23,6 @@ */ public final class SuggestionsUpDownVoter extends MessageReceiverAdapter { private static final Logger logger = LoggerFactory.getLogger(SuggestionsUpDownVoter.class); - private static final int TITLE_MAX_LENGTH = 60; private static final Emoji FALLBACK_UP_VOTE = Emoji.fromUnicode("👍"); private static final Emoji FALLBACK_DOWN_VOTE = Emoji.fromUnicode("👎"); @@ -55,26 +54,10 @@ public void onMessageReceived(MessageReceivedEvent event) { } private static void createThread(Message message) { + ThreadTitle threadTitle = ThreadTitle.withFallback(message.getContentRaw(), + message.getAuthor().getName() + "'s suggestions"); - String threadTitle; - String messageContent = message.getContentRaw(); - - if (messageContent.isEmpty()) { - threadTitle = message.getAuthor().getName(); - } else if (messageContent.length() >= TITLE_MAX_LENGTH) { - int lastWordEnd = messageContent.lastIndexOf(' ', TITLE_MAX_LENGTH); - - if (lastWordEnd == -1) { - lastWordEnd = TITLE_MAX_LENGTH; - } - - threadTitle = messageContent.substring(0, lastWordEnd); - } else { - - threadTitle = messageContent; - } - - message.createThreadChannel(threadTitle).queue(); + message.createThreadChannel(threadTitle.value()).queue(); } private static void reactWith(String emojiName, Emoji fallbackEmoji, Guild guild, diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java new file mode 100644 index 0000000000..1cb02a0aa4 --- /dev/null +++ b/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java @@ -0,0 +1,38 @@ + +package org.togetherjava.tjbot.features.basic; + +public record ThreadTitle(String value) { + + private static final int TITLE_MAX_LENGTH = 60; + + public ThreadTitle(String value) { + String threadTitle; + if (value.length() >= TITLE_MAX_LENGTH) { + int lastWordEnd = value.lastIndexOf(' ', TITLE_MAX_LENGTH); + + if (lastWordEnd == -1) { + lastWordEnd = TITLE_MAX_LENGTH; + } + + threadTitle = value.substring(0, lastWordEnd); + } else { + threadTitle = value; + } + + this.value = threadTitle; + } + + public static ThreadTitle withFallback(String threadtitle, String fallback) { + if (!threadtitle.isEmpty()) { + return new ThreadTitle(threadtitle); + } else { + return new ThreadTitle(fallback); + } + } + + @Override + public String toString() { + return value; + } + +} From 6b6b883ed88501504b03faa54a09ed9cf327e4de Mon Sep 17 00:00:00 2001 From: billpapat <50835814+billpapat@users.noreply.github.com> Date: Sun, 29 Jun 2025 22:35:56 +0300 Subject: [PATCH 4/7] docs(ThreadTitle): add JavaDocs and rename param Addresses code review by @christolis. Co-authorized-by: Chris Sdogkos Signed-off-by: Chris Sdogkos Signed-off-by: billpapat <50835814+billpapat@users.noreply.github.com> --- .../tjbot/features/basic/ThreadTitle.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java index 1cb02a0aa4..ec5b0e6c9a 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java @@ -1,6 +1,12 @@ - package org.togetherjava.tjbot.features.basic; +/** + * Represents a thread title, enforcing a maximum length of 60 characters. If an initial title + * exceeds this limit, it's truncated at the last word boundary before or at the 60-character mark + * to prevent cutting words mid-sentence. If no space is found, it truncates at 60 characters. + * Provides a static factory method `withFallback` to create a ThreadTitle, using a fallback title + * if the primary title is empty. + */ public record ThreadTitle(String value) { private static final int TITLE_MAX_LENGTH = 60; @@ -22,9 +28,9 @@ public ThreadTitle(String value) { this.value = threadTitle; } - public static ThreadTitle withFallback(String threadtitle, String fallback) { - if (!threadtitle.isEmpty()) { - return new ThreadTitle(threadtitle); + public static ThreadTitle withFallback(String primary, String fallback) { + if (!primary.isEmpty()) { + return new ThreadTitle(primary); } else { return new ThreadTitle(fallback); } From 71112b044bd17c755bb1562b3233f096445844fb Mon Sep 17 00:00:00 2001 From: billpapat <50835814+billpapat@users.noreply.github.com> Date: Mon, 30 Jun 2025 17:18:53 +0300 Subject: [PATCH 5/7] Changes as per requested by Zabuzard --- .../basic/SuggestionsUpDownVoter.java | 32 ++++++++++++-- .../tjbot/features/basic/ThreadTitle.java | 44 ------------------- 2 files changed, 29 insertions(+), 47 deletions(-) delete mode 100644 application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java index 681d0af202..56199e92fc 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java @@ -25,6 +25,7 @@ public final class SuggestionsUpDownVoter extends MessageReceiverAdapter { private static final Logger logger = LoggerFactory.getLogger(SuggestionsUpDownVoter.class); private static final Emoji FALLBACK_UP_VOTE = Emoji.fromUnicode("👍"); private static final Emoji FALLBACK_DOWN_VOTE = Emoji.fromUnicode("👎"); + private static final int THREAD_TITLE_MAX_LENGTH = 60; // Define the max length private final SuggestionsConfig config; @@ -54,10 +55,35 @@ public void onMessageReceived(MessageReceivedEvent event) { } private static void createThread(Message message) { - ThreadTitle threadTitle = ThreadTitle.withFallback(message.getContentRaw(), - message.getAuthor().getName() + "'s suggestions"); + String threadTitle = generateThreadTitle(message.getContentRaw(), + message.getAuthor().getName() + "'s suggestion"); + message.createThreadChannel(threadTitle).queue(); + } + + /** + * Generates a thread title, enforcing a maximum length of 60 characters. If an initial title + * exceeds this limit, it's truncated at the last word boundary before or at the 60-character + * mark to prevent cutting words mid-sentence. If no space is found, it truncates at 60 + * characters. Uses a fallback title if the primary title is empty. + * + * @param primaryTitle The primary title to use. + * @param fallbackTitle The fallback title to use if the primary title is empty. + * @return The generated and truncated thread title. + */ + private static String generateThreadTitle(String primaryTitle, String fallbackTitle) { + String title = primaryTitle.isEmpty() ? fallbackTitle : primaryTitle; + + if (title.length() < THREAD_TITLE_MAX_LENGTH) { + return title; + } + + int lastWordEnd = title.lastIndexOf(' ', THREAD_TITLE_MAX_LENGTH); + + if (lastWordEnd == -1) { + return title.substring(0, THREAD_TITLE_MAX_LENGTH); + } - message.createThreadChannel(threadTitle.value()).queue(); + return title.substring(0, lastWordEnd); } private static void reactWith(String emojiName, Emoji fallbackEmoji, Guild guild, diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java deleted file mode 100644 index ec5b0e6c9a..0000000000 --- a/application/src/main/java/org/togetherjava/tjbot/features/basic/ThreadTitle.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.togetherjava.tjbot.features.basic; - -/** - * Represents a thread title, enforcing a maximum length of 60 characters. If an initial title - * exceeds this limit, it's truncated at the last word boundary before or at the 60-character mark - * to prevent cutting words mid-sentence. If no space is found, it truncates at 60 characters. - * Provides a static factory method `withFallback` to create a ThreadTitle, using a fallback title - * if the primary title is empty. - */ -public record ThreadTitle(String value) { - - private static final int TITLE_MAX_LENGTH = 60; - - public ThreadTitle(String value) { - String threadTitle; - if (value.length() >= TITLE_MAX_LENGTH) { - int lastWordEnd = value.lastIndexOf(' ', TITLE_MAX_LENGTH); - - if (lastWordEnd == -1) { - lastWordEnd = TITLE_MAX_LENGTH; - } - - threadTitle = value.substring(0, lastWordEnd); - } else { - threadTitle = value; - } - - this.value = threadTitle; - } - - public static ThreadTitle withFallback(String primary, String fallback) { - if (!primary.isEmpty()) { - return new ThreadTitle(primary); - } else { - return new ThreadTitle(fallback); - } - } - - @Override - public String toString() { - return value; - } - -} From d2892b383aad01e6c3c887745f5787b12c9ff638 Mon Sep 17 00:00:00 2001 From: billpapat <50835814+billpapat@users.noreply.github.com> Date: Mon, 30 Jun 2025 22:53:12 +0300 Subject: [PATCH 6/7] Changes as per requested by Zabuzard --- .../features/basic/SuggestionsUpDownVoter.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java index 56199e92fc..8c799e8aca 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java @@ -25,7 +25,7 @@ public final class SuggestionsUpDownVoter extends MessageReceiverAdapter { private static final Logger logger = LoggerFactory.getLogger(SuggestionsUpDownVoter.class); private static final Emoji FALLBACK_UP_VOTE = Emoji.fromUnicode("👍"); private static final Emoji FALLBACK_DOWN_VOTE = Emoji.fromUnicode("👎"); - private static final int THREAD_TITLE_MAX_LENGTH = 60; // Define the max length + private static final int THREAD_TITLE_MAX_LENGTH = 60; private final SuggestionsConfig config; @@ -55,22 +55,20 @@ public void onMessageReceived(MessageReceivedEvent event) { } private static void createThread(Message message) { - String threadTitle = generateThreadTitle(message.getContentRaw(), - message.getAuthor().getName() + "'s suggestion"); + String threadTitle = generateThreadTitle(message); message.createThreadChannel(threadTitle).queue(); } /** - * Generates a thread title, enforcing a maximum length of 60 characters. If an initial title - * exceeds this limit, it's truncated at the last word boundary before or at the 60-character - * mark to prevent cutting words mid-sentence. If no space is found, it truncates at 60 - * characters. Uses a fallback title if the primary title is empty. + * Generates a title for the given message. The maximum length of the title is + * {@value #THREAD_TITLE_MAX_LENGTH}. * - * @param primaryTitle The primary title to use. - * @param fallbackTitle The fallback title to use if the primary title is empty. + * @param message The message for which to generate the title. * @return The generated and truncated thread title. */ - private static String generateThreadTitle(String primaryTitle, String fallbackTitle) { + private static String generateThreadTitle(Message message) { + String primaryTitle = message.getContentRaw(); + String fallbackTitle = message.getAuthor().getName() + "'s suggestion"; String title = primaryTitle.isEmpty() ? fallbackTitle : primaryTitle; if (title.length() < THREAD_TITLE_MAX_LENGTH) { From 006a3eee87ae17ab5a683aa076e12665279203df Mon Sep 17 00:00:00 2001 From: billpapat <50835814+billpapat@users.noreply.github.com> Date: Tue, 1 Jul 2025 18:17:36 +0300 Subject: [PATCH 7/7] Changes as per requested by Taz03 --- .../tjbot/features/basic/SuggestionsUpDownVoter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java index 8c799e8aca..5dbbdbf8b2 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/basic/SuggestionsUpDownVoter.java @@ -67,11 +67,11 @@ private static void createThread(Message message) { * @return The generated and truncated thread title. */ private static String generateThreadTitle(Message message) { - String primaryTitle = message.getContentRaw(); - String fallbackTitle = message.getAuthor().getName() + "'s suggestion"; + String primaryTitle = message.getContentStripped(); + String fallbackTitle = message.getAuthor().getEffectiveName() + "'s suggestion"; String title = primaryTitle.isEmpty() ? fallbackTitle : primaryTitle; - if (title.length() < THREAD_TITLE_MAX_LENGTH) { + if (title.length() <= THREAD_TITLE_MAX_LENGTH) { return title; }