-
-
Notifications
You must be signed in to change notification settings - Fork 104
Implement Quotes Board #1029
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
Open
christolis
wants to merge
8
commits into
Together-Java:develop
Choose a base branch
from
christolis:feature/cool-messages
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+208
−0
Open
Implement Quotes Board #1029
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
e1dcd79
feat(cool-messages): add configuration files
christolis 26e7811
feat(cool-messages): add primary logic
christolis fb4fb5d
feat(cool-message): forward messages instead of using embed
christolis 1ade409
refactor: code review addressed by Zabuzard
suryatejess a6085db
doc(QuoteBoardForwarder.java): improve JavaDoc
christolis 0a53bbc
refactor: code review addressed by zabuzard
suryatejess 5db7cff
Resolve merge conflicts
christolis d2c1b29
fix: more renaming to quoteMessageConfig
christolis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
application/src/main/java/org/togetherjava/tjbot/config/QuoteBoardConfig.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package org.togetherjava.tjbot.config; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
| import com.fasterxml.jackson.annotation.JsonRootName; | ||
|
|
||
| import org.togetherjava.tjbot.features.basic.QuoteBoardForwarder; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| /** | ||
| * Configuration for the quote board feature, see {@link QuoteBoardForwarder}. | ||
| */ | ||
| @JsonRootName("coolMessagesConfig") | ||
| public record QuoteBoardConfig( | ||
| @JsonProperty(value = "minimumReactions", required = true) int minimumReactions, | ||
| @JsonProperty(value = "boardChannelPattern", required = true) String boardChannelPattern, | ||
| @JsonProperty(value = "reactionEmoji", required = true) String reactionEmoji) { | ||
|
|
||
| /** | ||
| * Creates a QuoteBoardConfig. | ||
| * | ||
| * @param minimumReactions the minimum amount of reactions | ||
| * @param boardChannelPattern the pattern for the board channel | ||
| * @param reactionEmoji the emoji with which users should react to | ||
| */ | ||
| public QuoteBoardConfig { | ||
| Objects.requireNonNull(boardChannelPattern); | ||
| Objects.requireNonNull(reactionEmoji); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
application/src/main/java/org/togetherjava/tjbot/features/basic/QuoteBoardForwarder.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| package org.togetherjava.tjbot.features.basic; | ||
|
|
||
| import net.dv8tion.jda.api.JDA; | ||
| import net.dv8tion.jda.api.entities.Message; | ||
| import net.dv8tion.jda.api.entities.MessageReaction; | ||
| import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; | ||
| import net.dv8tion.jda.api.entities.emoji.Emoji; | ||
| import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; | ||
| import net.dv8tion.jda.api.requests.RestAction; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| import org.togetherjava.tjbot.config.Config; | ||
| import org.togetherjava.tjbot.config.QuoteBoardConfig; | ||
| import org.togetherjava.tjbot.features.MessageReceiverAdapter; | ||
|
|
||
| import java.util.Optional; | ||
| import java.util.function.Predicate; | ||
| import java.util.regex.Pattern; | ||
|
|
||
| /** | ||
| * Listens for reaction-add events and turns popular messages into "quotes". | ||
| * <p> | ||
| * When someone reacts to a message with the configured emoji, the listener counts how many users | ||
| * have used that same emoji. If the total meets or exceeds the minimum threshold and the bot has | ||
| * not processed the message before, it copies (forwards) the message to the first text channel | ||
| * whose name matches the configured quote-board pattern, then reacts to the original message itself | ||
| * to mark it as handled (and to not let people spam react a message and give a way to the bot to | ||
| * know that a message has been quoted before). | ||
| * <p> | ||
| * Key points: - Trigger emoji, minimum vote count and quote-board channel pattern are supplied via | ||
| * {@code QuoteBoardConfig}. | ||
| */ | ||
| public final class QuoteBoardForwarder extends MessageReceiverAdapter { | ||
|
|
||
| private static final Logger logger = LoggerFactory.getLogger(QuoteBoardForwarder.class); | ||
| private final Emoji triggerReaction; | ||
| private final Predicate<String> isQuoteBoardChannelName; | ||
| private final QuoteBoardConfig config; | ||
|
|
||
| /** | ||
| * Constructs a new instance of QuoteBoardForwarder. | ||
| * | ||
| * @param config the configuration containing settings specific to the cool messages board, | ||
| * including the reaction emoji and the pattern to match board channel names | ||
| */ | ||
| public QuoteBoardForwarder(Config config) { | ||
| this.config = config.getCoolMessagesConfig(); | ||
| this.triggerReaction = Emoji.fromUnicode(this.config.reactionEmoji()); | ||
|
|
||
| isQuoteBoardChannelName = | ||
| Pattern.compile(this.config.boardChannelPattern()).asMatchPredicate(); | ||
| } | ||
|
|
||
| @Override | ||
| public void onMessageReactionAdd(MessageReactionAddEvent event) { | ||
| final MessageReaction messageReaction = event.getReaction(); | ||
| boolean isTriggerEmoji = messageReaction.getEmoji().equals(triggerReaction); | ||
| long guildId = event.getGuild().getIdLong(); | ||
|
|
||
| if (!isTriggerEmoji) { | ||
| return; | ||
| } | ||
|
|
||
| if (hasAlreadyForwardedMessage(event.getJDA(), messageReaction)) { | ||
| return; | ||
| } | ||
|
|
||
| final int reactionsCount = (int) messageReaction.retrieveUsers().stream().count(); | ||
|
|
||
| if (reactionsCount < config.minimumReactions()) { | ||
| return; | ||
| } | ||
|
|
||
| Optional<TextChannel> boardChannel = findQuoteBoardChannel(event.getJDA(), guildId); | ||
|
|
||
| if (boardChannel.isEmpty()) { | ||
| logger.warn( | ||
| "Could not find board channel with pattern '{}' in server with ID '{}'. Skipping reaction handling...", | ||
| this.config.boardChannelPattern(), guildId); | ||
| return; | ||
| } | ||
|
|
||
| event.retrieveMessage() | ||
| .queue(message -> markAsProcessed(message).flatMap(v -> message | ||
| .forwardTo(boardChannel.orElseThrow())).queue(), e -> logger.warn( | ||
| "Unknown error while attempting to retrieve and forward message for quote-board, message is ignored.", | ||
| e)); | ||
|
|
||
| } | ||
|
|
||
| private RestAction<Void> markAsProcessed(Message message) { | ||
| return message.addReaction(triggerReaction); | ||
| } | ||
|
|
||
| /** | ||
| * Gets the board text channel where the quotes go to, wrapped in an optional. | ||
| * | ||
| * @param jda the JDA | ||
| * @param guildId the guild ID | ||
| * @return the board text channel | ||
| */ | ||
| private Optional<TextChannel> findQuoteBoardChannel(JDA jda, long guildId) { | ||
| return jda.getGuildById(guildId) | ||
| .getTextChannelCache() | ||
| .stream() | ||
| .filter(channel -> isQuoteBoardChannelName.test(channel.getName())) | ||
| .findAny(); | ||
| } | ||
|
|
||
| /** | ||
| * Inserts a message to the specified text channel | ||
| * | ||
| * @return a {@link MessageCreateAction} of the call to make | ||
| */ | ||
|
|
||
| /** | ||
| * Checks a {@link MessageReaction} to see if the bot has reacted to it. | ||
| */ | ||
| private boolean hasAlreadyForwardedMessage(JDA jda, MessageReaction messageReaction) { | ||
| if (!triggerReaction.equals(messageReaction.getEmoji())) { | ||
| return false; | ||
| } | ||
|
|
||
| return messageReaction.retrieveUsers() | ||
| .parallelStream() | ||
| .anyMatch(user -> jda.getSelfUser().getIdLong() == user.getIdLong()); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.