diff --git a/application/config.json.template b/application/config.json.template index e2e1963c80..7c10c30880 100644 --- a/application/config.json.template +++ b/application/config.json.template @@ -195,9 +195,34 @@ "pollIntervalInMinutes": 10 }, "quoteBoardConfig": { - "minimumReactionsToTrigger": 5, + "minimumScoreToTrigger": 5.0, "channel": "quotes", - "reactionEmoji": "โญ" + "botEmoji": "โญ", + "defaultEmojiScore": 0.5, + "emojiScores": { + "๐Ÿ˜ฌ": -0.5, + "๐Ÿ’”": -0.5, + "๐Ÿ˜": -0.5, + "๐Ÿ˜Š": -0.5, + "๐Ÿ–•": -0.5, + "๐Ÿ‘Ž": -0.5, + "๐Ÿ’ฉ": -0.5, + "๐Ÿคข": -0.5, + "๐Ÿคฎ": -0.5, + "๐Ÿคฌ": -0.5, + "๐Ÿ˜ก": -0.5, + "๐Ÿ˜’": -0.5, + "๐Ÿคจ": -0.5, + + "๐Ÿ‡ท๐Ÿ‡บ": 0.0, + "๐Ÿ‡ต๐Ÿ‡ธ": 0.0, + "๐Ÿ‡ฎ๐Ÿ‡ฑ": 0.0, + "๐Ÿณ๏ธโ€๐ŸŒˆ": 0.0, + + "โญ": 1.0, + + "youtube:1464573182206804010": 0.0 + } }, "memberCountCategoryPattern": "Info", "topHelpers": { diff --git a/application/src/main/java/org/togetherjava/tjbot/config/QuoteBoardConfig.java b/application/src/main/java/org/togetherjava/tjbot/config/QuoteBoardConfig.java index faf756b4a8..767af2c16d 100644 --- a/application/src/main/java/org/togetherjava/tjbot/config/QuoteBoardConfig.java +++ b/application/src/main/java/org/togetherjava/tjbot/config/QuoteBoardConfig.java @@ -6,6 +6,7 @@ import org.togetherjava.tjbot.features.basic.QuoteBoardForwarder; +import java.util.Map; import java.util.Objects; /** @@ -13,31 +14,36 @@ */ @JsonRootName("quoteBoardConfig") public record QuoteBoardConfig( - @JsonProperty(value = "minimumReactionsToTrigger", required = true) int minimumReactions, - @JsonProperty(required = true) String channel, - @JsonProperty(value = "reactionEmoji", required = true) String reactionEmoji) { + @JsonProperty(value = "minimumScoreToTrigger", required = true) float minimumScoreToTrigger, + @JsonProperty(value = "channel", required = true) String channel, + @JsonProperty(value = "botEmoji", required = true) String botEmoji, + @JsonProperty(value = "defaultEmojiScore", required = true) float defaultEmojiScore, + @JsonProperty(value = "emojiScores", required = true) Map emojiScores) { /** * Creates a QuoteBoardConfig. * - * @param minimumReactions the minimum amount of reactions + * @param minimumScoreToTrigger the minimum amount of reaction score for a message to be quoted * @param channel the pattern for the board channel - * @param reactionEmoji the emoji with which users should react to + * @param botEmoji the emoji with which the bot will mark quoted messages + * @param defaultEmojiScore the default score of an emoji if it's not in the emojiScores map + * @param emojiScores a map of each emoji's custom score */ public QuoteBoardConfig { - if (minimumReactions <= 0) { - throw new IllegalArgumentException("minimumReactions must be greater than zero"); + if (minimumScoreToTrigger <= 0) { + throw new IllegalArgumentException("minimumScoreToTrigger must be greater than zero"); } Objects.requireNonNull(channel); if (channel.isBlank()) { throw new IllegalArgumentException("channel must not be empty or blank"); } - Objects.requireNonNull(reactionEmoji); - if (reactionEmoji.isBlank()) { + Objects.requireNonNull(botEmoji); + if (botEmoji.isBlank()) { throw new IllegalArgumentException("reactionEmoji must not be empty or blank"); } + Objects.requireNonNull(emojiScores); LogManager.getLogger(QuoteBoardConfig.class) .debug("Quote-Board configs loaded: minimumReactions={}, channel='{}', reactionEmoji='{}'", - minimumReactions, channel, reactionEmoji); + minimumScoreToTrigger, channel, botEmoji); } } diff --git a/application/src/main/java/org/togetherjava/tjbot/features/basic/QuoteBoardForwarder.java b/application/src/main/java/org/togetherjava/tjbot/features/basic/QuoteBoardForwarder.java index a6d067e16e..8121ccf037 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/basic/QuoteBoardForwarder.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/basic/QuoteBoardForwarder.java @@ -6,6 +6,7 @@ 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.entities.emoji.EmojiUnion; import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; import net.dv8tion.jda.api.requests.RestAction; import org.slf4j.Logger; @@ -36,7 +37,7 @@ public final class QuoteBoardForwarder extends MessageReceiverAdapter { private static final Logger logger = LoggerFactory.getLogger(QuoteBoardForwarder.class); - private final Emoji triggerReaction; + private final Emoji botEmoji; private final Predicate isQuoteBoardChannelName; private final QuoteBoardConfig config; @@ -48,7 +49,7 @@ public final class QuoteBoardForwarder extends MessageReceiverAdapter { */ public QuoteBoardForwarder(Config config) { this.config = config.getQuoteBoardConfig(); - this.triggerReaction = Emoji.fromUnicode(this.config.reactionEmoji()); + this.botEmoji = Emoji.fromUnicode(this.config.botEmoji()); this.isQuoteBoardChannelName = Pattern.compile(this.config.channel()).asMatchPredicate(); } @@ -60,24 +61,11 @@ public void onMessageReactionAdd(MessageReactionAddEvent event) { final MessageReaction messageReaction = event.getReaction(); - if (!messageReaction.getEmoji().equals(triggerReaction)) { - logger.debug("Reaction emoji '{}' does not match trigger emoji '{}'. Ignoring.", - messageReaction.getEmoji(), triggerReaction); - return; - } - if (hasAlreadyForwardedMessage(event.getJDA(), messageReaction)) { logger.debug("Message has already been forwarded by the bot. Skipping."); return; } - long reactionCount = messageReaction.retrieveUsers().stream().count(); - if (reactionCount < config.minimumReactions()) { - logger.debug("Reaction count {} is less than minimum required {}. Skipping.", - reactionCount, config.minimumReactions()); - return; - } - final long guildId = event.getGuild().getIdLong(); Optional boardChannelOptional = findQuoteBoardChannel(event.getJDA(), guildId); @@ -96,21 +84,27 @@ public void onMessageReactionAdd(MessageReactionAddEvent event) { return; } - logger.debug("Forwarding message to quote board channel: {}", boardChannel.getName()); + event.retrieveMessage().queue(message -> { + float emojiScore = calculateMessageScore(message.getReactions()); - event.retrieveMessage() - .queue(message -> markAsProcessed(message).flatMap(v -> message.forwardTo(boardChannel)) - .queue(_ -> logger.debug("Message forwarded to quote board channel: {}", - boardChannel.getName())), + if (emojiScore < config.minimumScoreToTrigger()) { + return; + } - e -> logger.warn( - "Unknown error while attempting to retrieve and forward message for quote-board, message is ignored.", - e)); + logger.debug("Attempting to forward message to quote board channel: {}", + boardChannel.getName()); + markAsProcessed(message).flatMap(_ -> message.forwardTo(boardChannel)) + .queue(_ -> logger.debug("Message forwarded to quote board channel: {}", + boardChannel.getName()), + e -> logger.warn( + "Unknown error while attempting to retrieve and forward message for quote-board, message is ignored.", + e)); + }); } private RestAction markAsProcessed(Message message) { - return message.addReaction(triggerReaction); + return message.addReaction(botEmoji); } /** @@ -146,7 +140,7 @@ private Optional findQuoteBoardChannel(JDA jda, long guildId) { * 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())) { + if (!botEmoji.equals(messageReaction.getEmoji())) { return false; } @@ -154,4 +148,17 @@ private boolean hasAlreadyForwardedMessage(JDA jda, MessageReaction messageReact .parallelStream() .anyMatch(user -> jda.getSelfUser().getIdLong() == user.getIdLong()); } + + private float calculateMessageScore(List reactions) { + return (float) reactions.stream() + .mapToDouble(reaction -> reaction.getCount() * getEmojiScore(reaction.getEmoji())) + .sum(); + } + + private float getEmojiScore(EmojiUnion emoji) { + float defaultScore = config.defaultEmojiScore(); + String reactionCode = emoji.getAsReactionCode(); + + return config.emojiScores().getOrDefault(reactionCode, defaultScore); + } }