From fa9e0ae6d5e06bf617e4d4eda178d64239034e07 Mon Sep 17 00:00:00 2001 From: Derek Date: Wed, 11 Nov 2026 14:31:55 -0500 Subject: [PATCH 1/3] DINO-1162: send winners discord message --- .../common/components/DiscordClubManager.java | 40 +++++++++++++++++ .../codebloom/jda/client/JDAClient.java | 18 ++++++++ .../options/EmbeddedDirectMessageOptions.java | 15 +++++++ .../components/DiscordClubManagerTest.java | 44 ++++++++++++++----- 4 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/patinanetwork/codebloom/jda/client/options/EmbeddedDirectMessageOptions.java diff --git a/src/main/java/org/patinanetwork/codebloom/common/components/DiscordClubManager.java b/src/main/java/org/patinanetwork/codebloom/common/components/DiscordClubManager.java index d76478f46..f6803e348 100644 --- a/src/main/java/org/patinanetwork/codebloom/common/components/DiscordClubManager.java +++ b/src/main/java/org/patinanetwork/codebloom/common/components/DiscordClubManager.java @@ -26,6 +26,7 @@ import org.patinanetwork.codebloom.common.url.ServerUrlUtils; import org.patinanetwork.codebloom.common.utils.leaderboard.LeaderboardUtils; import org.patinanetwork.codebloom.jda.client.JDAClient; +import org.patinanetwork.codebloom.jda.client.options.EmbeddedDirectMessageOptions; import org.patinanetwork.codebloom.jda.client.options.EmbeddedImagesMessageOptions; import org.springframework.stereotype.Component; @@ -79,6 +80,44 @@ private String buildTopUsersSection(final List users, final boole return sb.toString(); } + private void sendWinnerDiscordMessage( + final DiscordClub club, final Leaderboard leaderboard, final List winners) { + for (int i = 0; i < Math.min(winners.size(), 3); i++) { + final UserWithScore winner = winners.get(i); + String description = """ + Dear %s, + + Congratulations! You finished #%d on the %s leaderboard for %s users! + + Your final score is: %d points. + + Keep up the great work and continue solving problems to maintain your position or climb even higher! + + View the full leaderboard at %s/leaderboard/%s?%s=true + + Best regards, + The Codebloom Team + """.formatted( + winner.getDiscordName(), + i + 1, + leaderboard.getName(), + club.getName(), + winner.getTotalScore(), + serverUrlUtils.getUrl(), + leaderboard.getId(), + club.getTag().name().toLowerCase()); + jdaClient.sendDirectMessageEmbed( + winner.getDiscordId(), + EmbeddedDirectMessageOptions.builder() + .title("%s You placed #%d on %s!".formatted(MEDAL_EMOJIS[i], i + 1, leaderboard.getName())) + .description(description) + .footerText("Codebloom - LeetCode Leaderboard for %s".formatted(club.getName())) + .footerIcon("%s/favicon.ico".formatted(serverUrlUtils.getUrl())) + .color(new Color(69, 129, 103)) + .build()); + } + } + /** * Loads the page for each discord club's tag, takes a screenshot, and sends a final Discord message with the * winners of the leaderboard. @@ -153,6 +192,7 @@ private void sendLeaderboardCompletedDiscordMessage(final DiscordClub club) { .footerIcon("%s/favicon.ico".formatted(serverUrlUtils.getUrl())) .color(new Color(69, 129, 103)) .build()); + sendWinnerDiscordMessage(club, currentLeaderboard.get(), users); } catch (Exception e) { log.error("Exception thrown in DiscordClubManager", e); } diff --git a/src/main/java/org/patinanetwork/codebloom/jda/client/JDAClient.java b/src/main/java/org/patinanetwork/codebloom/jda/client/JDAClient.java index 059ba9b28..e34fed040 100644 --- a/src/main/java/org/patinanetwork/codebloom/jda/client/JDAClient.java +++ b/src/main/java/org/patinanetwork/codebloom/jda/client/JDAClient.java @@ -14,6 +14,7 @@ import net.dv8tion.jda.api.exceptions.ErrorResponseException; import net.dv8tion.jda.api.utils.FileUpload; import org.patinanetwork.codebloom.jda.JDAClientManager; +import org.patinanetwork.codebloom.jda.client.options.EmbeddedDirectMessageOptions; import org.patinanetwork.codebloom.jda.client.options.EmbeddedImagesMessageOptions; import org.patinanetwork.codebloom.jda.client.options.EmbeddedMessageOptions; import org.patinanetwork.codebloom.jda.properties.patina.JDAPatinaProperties; @@ -187,4 +188,21 @@ public boolean deleteMessageById(long channelId, long messageId) { return false; } } + + public void sendDirectMessageEmbed(final String userId, final EmbeddedDirectMessageOptions options) { + EmbedBuilder embed = new EmbedBuilder() + .setColor(options.getColor()) + .setTitle(options.getTitle()) + .setUrl("https://codebloom.patinanetwork.org") + .setDescription(options.getDescription()) + .setFooter(options.getFooterText(), options.getFooterIcon()); + + jda.retrieveUserById(userId) + .flatMap(user -> user.openPrivateChannel()) + .flatMap(channel -> channel.sendMessageEmbeds(embed.build())) + .queue( + msg -> log.info("DM sent to user {}", userId), + // User may have DMs disabled + throwable -> log.warn("Failed to DM user {}", userId, throwable)); + } } diff --git a/src/main/java/org/patinanetwork/codebloom/jda/client/options/EmbeddedDirectMessageOptions.java b/src/main/java/org/patinanetwork/codebloom/jda/client/options/EmbeddedDirectMessageOptions.java new file mode 100644 index 000000000..7ad556643 --- /dev/null +++ b/src/main/java/org/patinanetwork/codebloom/jda/client/options/EmbeddedDirectMessageOptions.java @@ -0,0 +1,15 @@ +package org.patinanetwork.codebloom.jda.client.options; + +import java.awt.Color; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class EmbeddedDirectMessageOptions { + private String title; + private String description; + private String footerText; + private String footerIcon; + private Color color; +} diff --git a/src/test/java/org/patinanetwork/codebloom/common/components/DiscordClubManagerTest.java b/src/test/java/org/patinanetwork/codebloom/common/components/DiscordClubManagerTest.java index 7ffc67f91..cce3632b3 100644 --- a/src/test/java/org/patinanetwork/codebloom/common/components/DiscordClubManagerTest.java +++ b/src/test/java/org/patinanetwork/codebloom/common/components/DiscordClubManagerTest.java @@ -33,6 +33,7 @@ import org.patinanetwork.codebloom.common.page.Indexed; import org.patinanetwork.codebloom.common.url.ServerUrlUtils; import org.patinanetwork.codebloom.jda.client.JDAClient; +import org.patinanetwork.codebloom.jda.client.options.EmbeddedDirectMessageOptions; import org.patinanetwork.codebloom.jda.client.options.EmbeddedImagesMessageOptions; import org.slf4j.LoggerFactory; @@ -193,6 +194,7 @@ void testSendLeaderboardCompletedDiscordMessageAllUsersHaveZeroPoints() { ArgumentCaptor captor = ArgumentCaptor.forClass(EmbeddedImagesMessageOptions.class); verify(jdaClient).sendEmbedWithImages(captor.capture()); + verify(jdaClient, never()).sendDirectMessageEmbed(anyString(), any(EmbeddedDirectMessageOptions.class)); String description = captor.getValue().getDescription(); assertTrue(description.contains("No one claimed a spot on this leaderboard")); @@ -214,6 +216,7 @@ void testSendWeeklyLeaderboardUpdateDiscordMessageFiltersZeroPointUsers() { verify(discordClubRepository).getAllActiveDiscordClubs(); verify(jdaClient).sendEmbedWithImages(any(EmbeddedImagesMessageOptions.class)); + verify(jdaClient, never()).sendDirectMessageEmbed(any(String.class), any(EmbeddedDirectMessageOptions.class)); } @Test @@ -229,6 +232,7 @@ void testSendWeeklyLeaderboardUpdateDiscordMessageAllUsersHaveZeroPoints() { ArgumentCaptor captor = ArgumentCaptor.forClass(EmbeddedImagesMessageOptions.class); verify(jdaClient).sendEmbedWithImages(captor.capture()); + verify(jdaClient, never()).sendDirectMessageEmbed(anyString(), any(EmbeddedDirectMessageOptions.class)); String description = captor.getValue().getDescription(); assertTrue(description.contains("no scores yet")); @@ -246,14 +250,21 @@ void testSendLeaderboardCompletedDiscordMessageOnlyOneUserWithPoints() { discordClubManager.sendLeaderboardCompletedDiscordMessageToAllClubs(); - ArgumentCaptor captor = + ArgumentCaptor leaderboardCaptor = ArgumentCaptor.forClass(EmbeddedImagesMessageOptions.class); - verify(jdaClient).sendEmbedWithImages(captor.capture()); + ArgumentCaptor idCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor embedCaptor = + ArgumentCaptor.forClass(EmbeddedDirectMessageOptions.class); + verify(jdaClient).sendEmbedWithImages(leaderboardCaptor.capture()); + verify(jdaClient).sendDirectMessageEmbed(idCaptor.capture(), embedCaptor.capture()); - String description = captor.getValue().getDescription(); - assertTrue(description.contains("🥇")); - assertFalse(description.contains("🥈")); - assertFalse(description.contains("🥉")); + String leaderboardDescription = leaderboardCaptor.getValue().getDescription(); + assertTrue(leaderboardDescription.contains("🥇")); + assertFalse(leaderboardDescription.contains("🥈")); + assertFalse(leaderboardDescription.contains("🥉")); + + assertEquals("discord1", idCaptor.getValue()); + assertTrue(embedCaptor.getValue().getTitle().contains("🥇")); } @Test @@ -265,14 +276,23 @@ void testSendLeaderboardCompletedDiscordMessageOnlyTwoUsersWithPoints() { discordClubManager.sendLeaderboardCompletedDiscordMessageToAllClubs(); - ArgumentCaptor captor = + ArgumentCaptor leaderboardCaptor = ArgumentCaptor.forClass(EmbeddedImagesMessageOptions.class); - verify(jdaClient).sendEmbedWithImages(captor.capture()); + ArgumentCaptor idCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor embedCaptor = + ArgumentCaptor.forClass(EmbeddedDirectMessageOptions.class); - String description = captor.getValue().getDescription(); - assertTrue(description.contains("🥇")); - assertTrue(description.contains("🥈")); - assertFalse(description.contains("🥉")); + verify(jdaClient).sendEmbedWithImages(leaderboardCaptor.capture()); + verify(jdaClient, times(2)).sendDirectMessageEmbed(idCaptor.capture(), embedCaptor.capture()); + + String leaderboardDescription = leaderboardCaptor.getValue().getDescription(); + assertTrue(leaderboardDescription.contains("🥇")); + assertTrue(leaderboardDescription.contains("🥈")); + assertFalse(leaderboardDescription.contains("🥉")); + + assertEquals(List.of("discord1", "discord2"), idCaptor.getAllValues()); + assertTrue(embedCaptor.getAllValues().get(0).getTitle().contains("🥇")); + assertTrue(embedCaptor.getAllValues().get(1).getTitle().contains("🥈")); } @Test From 8f8ba8803409ab7d9cbf429df48a8345fa6ba8ff Mon Sep 17 00:00:00 2001 From: Derek Date: Thu, 12 Nov 2026 23:44:14 -0500 Subject: [PATCH 2/3] DINO-1162: add direct message jda test --- .../codebloom/jda/JDAClientTest.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/test/java/org/patinanetwork/codebloom/jda/JDAClientTest.java b/src/test/java/org/patinanetwork/codebloom/jda/JDAClientTest.java index 8772c6598..b5efdfb11 100644 --- a/src/test/java/org/patinanetwork/codebloom/jda/JDAClientTest.java +++ b/src/test/java/org/patinanetwork/codebloom/jda/JDAClientTest.java @@ -7,25 +7,33 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import java.awt.Color; import java.util.List; +import java.util.function.Function; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.requests.restaction.AuditableRestAction; +import net.dv8tion.jda.api.requests.restaction.CacheRestAction; import net.dv8tion.jda.api.requests.restaction.MessageCreateAction; import net.dv8tion.jda.api.utils.FileUpload; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.patinanetwork.codebloom.jda.client.JDAClient; +import org.patinanetwork.codebloom.jda.client.options.EmbeddedDirectMessageOptions; import org.patinanetwork.codebloom.jda.client.options.EmbeddedImagesMessageOptions; import org.patinanetwork.codebloom.jda.client.options.EmbeddedMessageOptions; import org.patinanetwork.codebloom.jda.properties.patina.JDAPatinaProperties; @@ -40,6 +48,9 @@ public class JDAClientTest { private JDAClientManager jdaClientManager = mock(JDAClientManager.class); private EmbeddedMessageOptions options = mock(EmbeddedMessageOptions.class); private EmbeddedImagesMessageOptions imagesOptions = mock(EmbeddedImagesMessageOptions.class); + private EmbeddedDirectMessageOptions directOptions = mock(EmbeddedDirectMessageOptions.class); + private User user = mock(User.class); + private PrivateChannel privateChannel = mock(PrivateChannel.class); private JDAClient client; @@ -211,6 +222,42 @@ void testDeleteMessageId() { verify(mockChannel).deleteMessageById(1223334444L); } + @Test + @SuppressWarnings("unchecked") + void testDirectMessageWithEmbedSuccess() { + setupDirectOptions(); + + CacheRestAction action = mock(CacheRestAction.class); + when(jda.retrieveUserById("user123")).thenReturn(action); + doReturn(action).when(action).flatMap(any()); + + client.sendDirectMessageEmbed("user123", directOptions); + + verify(action).queue(any(), any()); + runFlatMapSteps(action, user, privateChannel); + verify(user).openPrivateChannel(); + + ArgumentCaptor embedCaptor = ArgumentCaptor.forClass(MessageEmbed.class); + verify(privateChannel).sendMessageEmbeds(embedCaptor.capture()); + MessageEmbed embed = embedCaptor.getValue(); + + assertEquals("Title", embed.getTitle()); + assertEquals("Desc", embed.getDescription()); + assertEquals("https://codebloom.patinanetwork.org", embed.getUrl()); + assertEquals(Color.BLACK, embed.getColor()); + assertEquals("Footer", embed.getFooter().getText()); + assertEquals("https://example.com/icon.png", embed.getFooter().getIconUrl()); + } + + @SuppressWarnings("unchecked") + private static void runFlatMapSteps(RestAction action, Object... inputs) { + ArgumentCaptor>> steps = ArgumentCaptor.forClass(Function.class); + verify(action, times(inputs.length)).flatMap(steps.capture()); + for (int i = 0; i < inputs.length; i++) { + steps.getAllValues().get(i).apply(inputs[i]); + } + } + private void setupOptions() { when(options.getGuildId()).thenReturn(123456789L); when(options.getChannelId()).thenReturn(987654321L); @@ -236,4 +283,12 @@ private void setupImagesOptions() { when(imagesOptions.getFilesBytes()).thenReturn(List.of(new byte[] {1}, new byte[] {2})); when(imagesOptions.getFileNames()).thenReturn(List.of("a.png", "b.png")); } + + private void setupDirectOptions() { + when(directOptions.getTitle()).thenReturn("Title"); + when(directOptions.getDescription()).thenReturn("Desc"); + when(directOptions.getFooterText()).thenReturn("Footer"); + when(directOptions.getFooterIcon()).thenReturn("https://example.com/icon.png"); + when(directOptions.getColor()).thenReturn(Color.BLACK); + } } From e42c224d54e34aaf0d40485c3a2fe315f1a44362 Mon Sep 17 00:00:00 2001 From: Derek Date: Fri, 13 Nov 2026 00:13:51 -0500 Subject: [PATCH 3/3] DINO-1162: add message winners to ff --- .../common/components/DiscordClubManager.java | 10 ++++++-- .../properties/FeatureFlagConfiguration.java | 2 ++ src/main/resources/application-ci.yaml | 1 + src/main/resources/application-dev.yaml | 1 + src/main/resources/application.yml | 1 + .../components/DiscordClubManagerTest.java | 23 +++++++++++++++++-- .../common/ff/FeatureFlagManagerTest.java | 4 +++- 7 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/patinanetwork/codebloom/common/components/DiscordClubManager.java b/src/main/java/org/patinanetwork/codebloom/common/components/DiscordClubManager.java index f6803e348..844d3771a 100644 --- a/src/main/java/org/patinanetwork/codebloom/common/components/DiscordClubManager.java +++ b/src/main/java/org/patinanetwork/codebloom/common/components/DiscordClubManager.java @@ -28,6 +28,7 @@ import org.patinanetwork.codebloom.jda.client.JDAClient; import org.patinanetwork.codebloom.jda.client.options.EmbeddedDirectMessageOptions; import org.patinanetwork.codebloom.jda.client.options.EmbeddedImagesMessageOptions; +import org.patinanetwork.codebloom.jda.properties.FeatureFlagConfiguration; import org.springframework.stereotype.Component; @Component @@ -40,6 +41,7 @@ public class DiscordClubManager { private final UserRepository userRepository; private final ServerUrlUtils serverUrlUtils; private final LeaderboardManager leaderboardManager; + private final FeatureFlagConfiguration featureFlagConfiguration; public DiscordClubManager( final ServerUrlUtils serverUrlUtils, @@ -47,13 +49,15 @@ public DiscordClubManager( final LeaderboardRepository leaderboardRepository, final DiscordClubRepository discordClubRepository, final UserRepository userRepository, - final LeaderboardManager leaderboardManager) { + final LeaderboardManager leaderboardManager, + final FeatureFlagConfiguration featureFlagConfiguration) { this.serverUrlUtils = serverUrlUtils; this.jdaClient = jdaClient; this.leaderboardRepository = leaderboardRepository; this.discordClubRepository = discordClubRepository; this.userRepository = userRepository; this.leaderboardManager = leaderboardManager; + this.featureFlagConfiguration = featureFlagConfiguration; } private static final String[] MEDAL_EMOJIS = {"🥇", "🥈", "🥉"}; @@ -192,7 +196,9 @@ private void sendLeaderboardCompletedDiscordMessage(final DiscordClub club) { .footerIcon("%s/favicon.ico".formatted(serverUrlUtils.getUrl())) .color(new Color(69, 129, 103)) .build()); - sendWinnerDiscordMessage(club, currentLeaderboard.get(), users); + if (featureFlagConfiguration.isMessageWinners()) { + sendWinnerDiscordMessage(club, currentLeaderboard.get(), users); + } } catch (Exception e) { log.error("Exception thrown in DiscordClubManager", e); } diff --git a/src/main/java/org/patinanetwork/codebloom/jda/properties/FeatureFlagConfiguration.java b/src/main/java/org/patinanetwork/codebloom/jda/properties/FeatureFlagConfiguration.java index 8eaad0e39..f586c070a 100644 --- a/src/main/java/org/patinanetwork/codebloom/jda/properties/FeatureFlagConfiguration.java +++ b/src/main/java/org/patinanetwork/codebloom/jda/properties/FeatureFlagConfiguration.java @@ -17,6 +17,8 @@ public class FeatureFlagConfiguration { private boolean userMetrics; + private boolean messageWinners; + /** no need to track the object, backend just writes this directly to the index.html file */ private Map ui = new HashMap<>(); } diff --git a/src/main/resources/application-ci.yaml b/src/main/resources/application-ci.yaml index 02ee9207e..550e999e7 100644 --- a/src/main/resources/application-ci.yaml +++ b/src/main/resources/application-ci.yaml @@ -6,6 +6,7 @@ codebloom: ff: duels: true user-metrics: false + message-winners: true ui: duels: true userMetrics: false diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index 92cc2294d..796418c30 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -6,6 +6,7 @@ codebloom: ff: duels: true user-metrics: true + message-winners: true ui: duels: true userMetrics: true diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9ab11c43a..f218c05fc 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -124,6 +124,7 @@ ff: # override per environment as needed duels: false user-metrics: false + message-winners: false # Passed straight through to the UI: keys must be camelCase since they are copied straight to the UI as is. ui: duels: false diff --git a/src/test/java/org/patinanetwork/codebloom/common/components/DiscordClubManagerTest.java b/src/test/java/org/patinanetwork/codebloom/common/components/DiscordClubManagerTest.java index cce3632b3..c40bbdfc4 100644 --- a/src/test/java/org/patinanetwork/codebloom/common/components/DiscordClubManagerTest.java +++ b/src/test/java/org/patinanetwork/codebloom/common/components/DiscordClubManagerTest.java @@ -35,6 +35,7 @@ import org.patinanetwork.codebloom.jda.client.JDAClient; import org.patinanetwork.codebloom.jda.client.options.EmbeddedDirectMessageOptions; import org.patinanetwork.codebloom.jda.client.options.EmbeddedImagesMessageOptions; +import org.patinanetwork.codebloom.jda.properties.FeatureFlagConfiguration; import org.slf4j.LoggerFactory; public class DiscordClubManagerTest { @@ -45,7 +46,7 @@ public class DiscordClubManagerTest { private ServerUrlUtils serverUrlUtils = mock(ServerUrlUtils.class); private UserRepository userRepository = mock(UserRepository.class); private LeaderboardManager leaderboardManager = mock(LeaderboardManager.class); - + private FeatureFlagConfiguration featureFlagConfiguration = mock(FeatureFlagConfiguration.class); private DiscordClubManager discordClubManager; private ListAppender logWatcher; @@ -58,7 +59,8 @@ void setUp() { leaderboardRepository, discordClubRepository, userRepository, - leaderboardManager); + leaderboardManager, + featureFlagConfiguration); logWatcher = new ListAppender<>(); logWatcher.start(); @@ -186,6 +188,7 @@ void testSendLeaderboardCompletedDiscordMessageFiltersZeroPointUsers() { void testSendLeaderboardCompletedDiscordMessageAllUsersHaveZeroPoints() { DiscordClub mockClub = createMockDiscordClub("Test Club", Tag.Rpi); when(discordClubRepository.getAllActiveDiscordClubs()).thenReturn(Arrays.asList(mockClub)); + when(featureFlagConfiguration.isMessageWinners()).thenReturn(true); setupMockLeaderboardDataWithAllZeroScoreUsers(); @@ -245,6 +248,7 @@ void testSendWeeklyLeaderboardUpdateDiscordMessageAllUsersHaveZeroPoints() { void testSendLeaderboardCompletedDiscordMessageOnlyOneUserWithPoints() { DiscordClub mockClub = createMockDiscordClub("Test Club", Tag.Rpi); when(discordClubRepository.getAllActiveDiscordClubs()).thenReturn(Arrays.asList(mockClub)); + when(featureFlagConfiguration.isMessageWinners()).thenReturn(true); setupMockLeaderboardDataWithOneUser(); @@ -267,10 +271,25 @@ void testSendLeaderboardCompletedDiscordMessageOnlyOneUserWithPoints() { assertTrue(embedCaptor.getValue().getTitle().contains("🥇")); } + @Test + void testSendLeaderboardCompletedDiscordMessageMessageWinnersFlagOffSkipsDirectMessages() { + DiscordClub mockClub = createMockDiscordClub("Test Club", Tag.Rpi); + when(discordClubRepository.getAllActiveDiscordClubs()).thenReturn(Arrays.asList(mockClub)); + when(featureFlagConfiguration.isMessageWinners()).thenReturn(false); + + setupMockLeaderboardDataWithOneUser(); + + discordClubManager.sendLeaderboardCompletedDiscordMessageToAllClubs(); + + verify(jdaClient).sendEmbedWithImages(any(EmbeddedImagesMessageOptions.class)); + verify(jdaClient, never()).sendDirectMessageEmbed(anyString(), any(EmbeddedDirectMessageOptions.class)); + } + @Test void testSendLeaderboardCompletedDiscordMessageOnlyTwoUsersWithPoints() { DiscordClub mockClub = createMockDiscordClub("Test Club", Tag.Rpi); when(discordClubRepository.getAllActiveDiscordClubs()).thenReturn(Arrays.asList(mockClub)); + when(featureFlagConfiguration.isMessageWinners()).thenReturn(true); setupMockLeaderboardDataWithTwoUsers(); diff --git a/src/test/java/org/patinanetwork/codebloom/common/ff/FeatureFlagManagerTest.java b/src/test/java/org/patinanetwork/codebloom/common/ff/FeatureFlagManagerTest.java index f7bb765b5..639af83bf 100644 --- a/src/test/java/org/patinanetwork/codebloom/common/ff/FeatureFlagManagerTest.java +++ b/src/test/java/org/patinanetwork/codebloom/common/ff/FeatureFlagManagerTest.java @@ -17,6 +17,7 @@ void setUp() { FeatureFlagConfiguration ff = new FeatureFlagConfiguration(); ff.setDuels(true); ff.setUserMetrics(false); + ff.setMessageWinners(true); featureFlagManager = new FeatureFlagManager(ff); } @@ -24,9 +25,10 @@ void setUp() { void getAllFlagsReturnsValuesFromConfiguration() { var flags = featureFlagManager.getFlags(); - assertEquals(2, flags.size()); + assertEquals(3, flags.size()); assertEquals(Boolean.TRUE, flags.get("duels")); assertEquals(Boolean.FALSE, flags.get("userMetrics")); + assertEquals(Boolean.TRUE, flags.get("messageWinners")); } @Test