From 92e6242b7a309df048a0f79930700a71b682fb75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Pani=C4=87?= Date: Wed, 17 Jul 2019 22:07:59 +0200 Subject: [PATCH] Added role adding by reaction --- build.gradle | 2 + .../java/com/redstoner/redstonerBot/Main.java | 6 +- .../redstonerBot/ReactionHandler.java | 8 + .../listeners/MessageReaction.java | 67 +++++++ .../redstonerBot/managers/DataManager.java | 99 ++++++++- .../redstonerBot/managers/DiscordManager.java | 22 +- .../redstonerBot/managers/InfoManager.java | 55 +++++ .../managers/ReactionManager.java | 49 +++++ .../InfoReactableMessageHandler.java | 146 ++++++++++++++ .../OptInReactableMessageHandler.java | 188 ++++++++++++++++++ .../ReactableMessageHandler.java | 88 ++++++++ 11 files changed, 718 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/redstoner/redstonerBot/ReactionHandler.java create mode 100644 src/main/java/com/redstoner/redstonerBot/listeners/MessageReaction.java create mode 100644 src/main/java/com/redstoner/redstonerBot/managers/InfoManager.java create mode 100644 src/main/java/com/redstoner/redstonerBot/managers/ReactionManager.java create mode 100644 src/main/java/com/redstoner/redstonerBot/reactableMessages/InfoReactableMessageHandler.java create mode 100644 src/main/java/com/redstoner/redstonerBot/reactableMessages/OptInReactableMessageHandler.java create mode 100644 src/main/java/com/redstoner/redstonerBot/reactableMessages/ReactableMessageHandler.java diff --git a/build.gradle b/build.gradle index ed9d538..715411a 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,8 @@ dependencies { compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.26' compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.16' + + compile 'com.vdurmont:emoji-java:4.0.0' } jar { diff --git a/src/main/java/com/redstoner/redstonerBot/Main.java b/src/main/java/com/redstoner/redstonerBot/Main.java index f43d357..bcae298 100644 --- a/src/main/java/com/redstoner/redstonerBot/Main.java +++ b/src/main/java/com/redstoner/redstonerBot/Main.java @@ -1,8 +1,6 @@ package com.redstoner.redstonerBot; -import com.redstoner.redstonerBot.managers.CommandManager; -import com.redstoner.redstonerBot.managers.DataManager; -import com.redstoner.redstonerBot.managers.DiscordManager; +import com.redstoner.redstonerBot.managers.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,8 +16,10 @@ public class Main { static { managers.add(new DataManager()); + managers.add(new ReactionManager()); managers.add(new DiscordManager()); managers.add(new CommandManager()); + managers.add(new InfoManager()); } public static void main(final String... args) { diff --git a/src/main/java/com/redstoner/redstonerBot/ReactionHandler.java b/src/main/java/com/redstoner/redstonerBot/ReactionHandler.java new file mode 100644 index 0000000..4a95c18 --- /dev/null +++ b/src/main/java/com/redstoner/redstonerBot/ReactionHandler.java @@ -0,0 +1,8 @@ +package com.redstoner.redstonerBot; + +import net.dv8tion.jda.core.entities.MessageReaction; +import net.dv8tion.jda.core.entities.User; + +public interface ReactionHandler { + void handle(String messageId, MessageReaction reaction, User author, boolean added); +} diff --git a/src/main/java/com/redstoner/redstonerBot/listeners/MessageReaction.java b/src/main/java/com/redstoner/redstonerBot/listeners/MessageReaction.java new file mode 100644 index 0000000..0cf7013 --- /dev/null +++ b/src/main/java/com/redstoner/redstonerBot/listeners/MessageReaction.java @@ -0,0 +1,67 @@ +package com.redstoner.redstonerBot.listeners; + +import com.redstoner.redstonerBot.managers.DataManager; +import com.redstoner.redstonerBot.managers.ReactionManager; +import net.dv8tion.jda.core.Permission; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.Member; +import net.dv8tion.jda.core.entities.TextChannel; +import net.dv8tion.jda.core.entities.User; +import net.dv8tion.jda.core.events.message.guild.react.GuildMessageReactionAddEvent; +import net.dv8tion.jda.core.events.message.guild.react.GuildMessageReactionRemoveEvent; +import net.dv8tion.jda.core.hooks.ListenerAdapter; +import net.dv8tion.jda.core.utils.Checks; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Objects; + +public class MessageReaction extends ListenerAdapter { + private static final Logger logger = LoggerFactory.getLogger(MessageReaction.class); + + @Override + public final void onGuildMessageReactionAdd(GuildMessageReactionAddEvent event) { + Checks.notNull(event, "Event"); + + final Guild guild = event.getGuild(); + final TextChannel channel = event.getChannel(); + final User author = event.getUser(); + final net.dv8tion.jda.core.entities.MessageReaction reaction = event.getReaction(); + + final String messageId = event.getMessageId(); + + final Member self = guild.getSelfMember(); + + if (!Objects.equals(guild.getId(), DataManager.getConfigValue("guild_id"))) return; + if (author.isBot()) return; + if (!self.hasPermission(channel, Permission.MESSAGE_WRITE)) return; + if (!self.hasPermission(channel, Permission.MESSAGE_EMBED_LINKS)) return; + + logger.info("[" + messageId + "] " + author.getAsTag() + " -> + " + reaction.getReactionEmote().getName()); + + ReactionManager.handle(messageId, reaction, author, true); + } + + @Override + public final void onGuildMessageReactionRemove(GuildMessageReactionRemoveEvent event) { + Checks.notNull(event, "Event"); + + final Guild guild = event.getGuild(); + final TextChannel channel = event.getChannel(); + final User author = event.getUser(); + final net.dv8tion.jda.core.entities.MessageReaction reaction = event.getReaction(); + + final String messageId = event.getMessageId(); + + final Member self = guild.getSelfMember(); + + if (!Objects.equals(guild.getId(), DataManager.getConfigValue("guild_id"))) return; + if (author.isBot()) return; + if (!self.hasPermission(channel, Permission.MESSAGE_WRITE)) return; + if (!self.hasPermission(channel, Permission.MESSAGE_EMBED_LINKS)) return; + + logger.info("[" + messageId + "] " + author.getAsTag() + " -> - " + reaction.getReactionEmote().getName()); + + ReactionManager.handle(messageId, reaction, author, false); + } +} \ No newline at end of file diff --git a/src/main/java/com/redstoner/redstonerBot/managers/DataManager.java b/src/main/java/com/redstoner/redstonerBot/managers/DataManager.java index e88a711..56c6081 100644 --- a/src/main/java/com/redstoner/redstonerBot/managers/DataManager.java +++ b/src/main/java/com/redstoner/redstonerBot/managers/DataManager.java @@ -5,10 +5,7 @@ import com.redstoner.redstonerBot.Manager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; +import java.sql.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -95,16 +92,42 @@ public class DataManager implements Manager { return config.get(name); } - public boolean loadConfig() { - config.clear(); + public static boolean setConfigValue(String name, String value) { + String existing = getConfigValue(name); + if (existing != null && existing.equals(value)) return true; + + try { + Connection conn = getConnection(); + PreparedStatement ps = conn.prepareStatement("INSERT INTO config (name, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value=?"); + + ps.setString(1, name); + ps.setString(2, value); + ps.setString(3, value); + + boolean succ = ps.execute(); + + if (succ) { + config.put(name, value); + } + + return succ; + } catch (SQLException e) { + logger.error("SQL error:", e); + return false; + } + } + + public static boolean loadConfig() { try { Connection conn = getConnection(); ResultSet rs = conn.prepareStatement("SELECT * FROM config").executeQuery(); + config.clear(); + while (rs.next()) { - String name = rs.getString(2); - String value = rs.getString(3); + String name = rs.getString(1); + String value = rs.getString(2); config.put(name, value); } @@ -115,4 +138,64 @@ public class DataManager implements Manager { return false; } } + + public static List getRules() { + try { + Connection conn = getConnection(); + ResultSet rs = conn.prepareStatement("SELECT * FROM rules").executeQuery(); + + List rules = new ArrayList<>(); + + while (rs.next()) { + rules.add(rs.getString(2)); + } + + return rules; + } catch (SQLException e) { + logger.error("SQL error:", e); + return null; + } + } + + public static Map getruleAgreeReactions() { + try { + Connection conn = getConnection(); + ResultSet rs = conn.prepareStatement("SELECT * FROM rule_agree_reactions").executeQuery(); + + Map reactions = new HashMap<>(); + + while (rs.next()) { + reactions.put(rs.getString(3), rs.getString(2)); + } + + return reactions; + } catch (SQLException e) { + logger.error("SQL error:", e); + return null; + } + } + + public static List> getOptins() { + try { + Connection conn = getConnection(); + ResultSet rs = conn.prepareStatement("SELECT * FROM opt_in").executeQuery(); + + List> optins = new ArrayList<>(); + + while (rs.next()) { + Map optin = new HashMap<>(); + + optin.put("role_id", rs.getString(3)); + optin.put("channel_id", rs.getString(4)); + optin.put("emoji", rs.getString(5)); + + optins.add(optin); + } + + return optins; + } catch (SQLException e) { + logger.error("SQL error:", e); + return null; + } + } } diff --git a/src/main/java/com/redstoner/redstonerBot/managers/DiscordManager.java b/src/main/java/com/redstoner/redstonerBot/managers/DiscordManager.java index 1d737fb..9eda447 100644 --- a/src/main/java/com/redstoner/redstonerBot/managers/DiscordManager.java +++ b/src/main/java/com/redstoner/redstonerBot/managers/DiscordManager.java @@ -2,22 +2,27 @@ package com.redstoner.redstonerBot.managers; import com.redstoner.redstonerBot.Env; import com.redstoner.redstonerBot.Manager; +import com.redstoner.redstonerBot.listeners.MessageReaction; import com.redstoner.redstonerBot.listeners.MessageReceived; +import com.vdurmont.emoji.Emoji; +import com.vdurmont.emoji.EmojiManager; import net.dv8tion.jda.core.AccountType; import net.dv8tion.jda.core.JDA; import net.dv8tion.jda.core.JDABuilder; +import net.dv8tion.jda.core.entities.Emote; import net.dv8tion.jda.core.entities.Guild; import net.dv8tion.jda.core.entities.Message; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.security.auth.login.LoginException; +import java.util.List; import java.util.concurrent.TimeUnit; public class DiscordManager implements Manager { private static final Logger logger = LoggerFactory.getLogger(DiscordManager.class); - private JDA jda; + private static JDA jda; public boolean start() { logger.info("Discord Manager starting..."); @@ -31,6 +36,7 @@ public class DiscordManager implements Manager { builder.setToken(Env.TOKEN); builder.addEventListener(new MessageReceived()); + builder.addEventListener(new MessageReaction()); jda = builder.build().awaitReady(); } catch (LoginException e) { @@ -66,4 +72,18 @@ public class DiscordManager implements Manager { public static void expireMessage(Message message) { message.delete().reason("Redstoner Bot message expiry").queueAfter(5, TimeUnit.SECONDS); } + + public static JDA getJda() { + return jda; + } + + public static Object getEmoteByName(String name) { + Emoji e = EmojiManager.getForAlias(name); + if (e != null) return e.getUnicode(); + + List emotes = jda.getEmotesByName(name, true); + if (emotes.size() > 0) return emotes.get(0); + + return null; + } } diff --git a/src/main/java/com/redstoner/redstonerBot/managers/InfoManager.java b/src/main/java/com/redstoner/redstonerBot/managers/InfoManager.java new file mode 100644 index 0000000..6ceae60 --- /dev/null +++ b/src/main/java/com/redstoner/redstonerBot/managers/InfoManager.java @@ -0,0 +1,55 @@ +package com.redstoner.redstonerBot.managers; + +import com.redstoner.redstonerBot.Manager; +import com.redstoner.redstonerBot.reactableMessages.InfoReactableMessageHandler; +import com.redstoner.redstonerBot.reactableMessages.OptInReactableMessageHandler; +import com.redstoner.redstonerBot.reactableMessages.ReactableMessageHandler; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.TextChannel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public class InfoManager implements Manager { + private static final Logger logger = LoggerFactory.getLogger(InfoManager.class); + + private List messageHandlers = new ArrayList<>(); + + @Override + public boolean start() { + logger.info("Info Manager starting..."); + + JDA jda = DiscordManager.getJda(); + Guild guild = jda.getGuildById(DataManager.getConfigValue("guild_id")); + TextChannel channel = guild.getTextChannelById(DataManager.getConfigValue("info_channel_id")); + + messageHandlers.add(new InfoReactableMessageHandler(jda, guild, channel)); + messageHandlers.add(new OptInReactableMessageHandler(jda, guild, channel)); + + new Thread(() -> { + for (ReactableMessageHandler handler : messageHandlers) { + handler.checkMessage(); + } + }).start(); + + logger.info("Info Manager started!"); + return true; + } + + @Override + public boolean stop() { + logger.info("Info Manager stopping..."); + + for (ReactableMessageHandler handler : messageHandlers) { + ReactionManager.removeHandler(handler.msgId); + } + + messageHandlers.clear(); + + logger.info("Info Manager stopped!"); + return true; + } +} diff --git a/src/main/java/com/redstoner/redstonerBot/managers/ReactionManager.java b/src/main/java/com/redstoner/redstonerBot/managers/ReactionManager.java new file mode 100644 index 0000000..54ecae6 --- /dev/null +++ b/src/main/java/com/redstoner/redstonerBot/managers/ReactionManager.java @@ -0,0 +1,49 @@ +package com.redstoner.redstonerBot.managers; + +import com.redstoner.redstonerBot.Manager; +import com.redstoner.redstonerBot.ReactionHandler; +import net.dv8tion.jda.core.entities.MessageReaction; +import net.dv8tion.jda.core.entities.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +public class ReactionManager implements Manager { + private static final Logger logger = LoggerFactory.getLogger(ReactionManager.class); + + private static final Map handlers = new HashMap<>(); + + @Override + public boolean start() { + logger.info("Reaction Manager starting..."); + + logger.info("Reaction Manager started!"); + return true; + } + + @Override + public boolean stop() { + logger.info("Reaction Manager stopping..."); + + logger.info("Reaction Manager stopped!"); + return true; + } + + public static void setHandler(String messageId, ReactionHandler handler) { + handlers.put(messageId, handler); + } + + public static void removeHandler(String messageId) { + handlers.remove(messageId); + } + + public static void handle(String messageId, MessageReaction reaction, User author, boolean added) { + ReactionHandler handler = handlers.get(messageId); + + if (handler == null) return; + + handler.handle(messageId, reaction, author, added); + } +} diff --git a/src/main/java/com/redstoner/redstonerBot/reactableMessages/InfoReactableMessageHandler.java b/src/main/java/com/redstoner/redstonerBot/reactableMessages/InfoReactableMessageHandler.java new file mode 100644 index 0000000..ff59796 --- /dev/null +++ b/src/main/java/com/redstoner/redstonerBot/reactableMessages/InfoReactableMessageHandler.java @@ -0,0 +1,146 @@ +package com.redstoner.redstonerBot.reactableMessages; + +import com.redstoner.redstonerBot.ReactionHandler; +import com.redstoner.redstonerBot.managers.DataManager; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.MessageBuilder; +import net.dv8tion.jda.core.entities.*; +import net.dv8tion.jda.core.managers.GuildController; + +import java.util.*; +import java.util.function.Consumer; + +public class InfoReactableMessageHandler extends ReactableMessageHandler { + static Map configNames = new HashMap<>(); + + static { + configNames.put("msg_id", "info_msg_id"); + + configNames.put("prefix", "info_prefix"); + configNames.put("suffix", "info_suffix"); + + configNames.put("format", "info_format"); + } + + public InfoReactableMessageHandler(JDA jda, Guild guild, TextChannel channel) { + super(jda, guild, channel); + } + + @Override + Map getConfigNames() { + return configNames; + } + + @Override + public void send(Consumer onSent) { + String prefix = DataManager.getConfigValue(configNames.get("prefix")); + String suffix = DataManager.getConfigValue(configNames.get("suffix")); + + String format = DataManager.getConfigValue(configNames.get("format")); + + MessageBuilder msg = new MessageBuilder(prefix + "\n"); + + List rules = DataManager.getRules(); + + if (rules != null) { + for (int i = 0; i < rules.size(); i++) { + msg.append(i + 1); + msg.append(". "); + msg.append(rules.get(i)); + msg.append("\n"); + } + msg.append("\n"); + } + + Map reactions = DataManager.getruleAgreeReactions(); + + if (reactions != null) { + for (String emojiName : reactions.keySet()) { + String why = reactions.get(emojiName); + + String reactionMsg = format; + + reactionMsg = reactionMsg.replaceAll("%emoji", ":" + emojiName + ":"); + reactionMsg = reactionMsg.replaceAll("%why", why); + + msg.append(reactionMsg); + msg.append("\n"); + } + } + + msg.append("\n"); + + msg.append(suffix); + + channel.sendMessage(msg.build()).queue(onSent); + } + + @Override + public ReactionHandler getReactionHandler() { + return (messageId, reaction, author, added) -> { + String emoteName = reaction.getReactionEmote().getName(); + String authorTag = author.getAsTag(); + + if (added) { + logger.info("Info reaction " + emoteName + " by user " + authorTag + " added!"); + } else { + logger.info("Info reaction " + emoteName + " by user " + authorTag + " removed!"); + } + + switch (emoteName) { + case "\uD83D\uDC4C": + case "\uD83D\uDC4D": + case "\u270B": + channel.getMessageById(messageId).queue(message -> { + List reactions = message.getReactions(); + + new Thread(() -> { + int count = 0; + + for (MessageReaction mr : reactions) { + List users = mr.getUsers().complete(); + + if (users.contains(author)) { + count++; + } + } + + logger.info("User " + author.getAsTag() + " has " + count + " reactions!"); + + GuildController guildController = guild.getController(); + Member authorMember = guild.getMember(author); + Role rule_agree_role = guild.getRoleById(DataManager.getConfigValue("rule_agree_role_id")); + + int requiredReactions = Integer.parseInt(DataManager.getConfigValue("rule_agree_required_reactions")); + + if (count >= requiredReactions) { + logger.info("Adding role " + rule_agree_role.getName() + " to user " + authorTag); + guildController.addSingleRoleToMember(authorMember, rule_agree_role).queue(); + } else { + logger.info("Removing role " + rule_agree_role.getName() + " from user " + authorTag); + guildController.removeSingleRoleFromMember(authorMember, rule_agree_role).queue(); + } + }).start(); + }); + + break; + default: + if (added) { + logger.info("Removing rogue reaction " + emoteName + " by user " + authorTag); + reaction.removeReaction(author).queue(); + } + } + }; + } + + @Override + public Set getReactions() { + Map r = DataManager.getruleAgreeReactions(); + + if (r != null) { + return r.keySet(); + } else { + return new HashSet<>(); + } + } +} diff --git a/src/main/java/com/redstoner/redstonerBot/reactableMessages/OptInReactableMessageHandler.java b/src/main/java/com/redstoner/redstonerBot/reactableMessages/OptInReactableMessageHandler.java new file mode 100644 index 0000000..31a1240 --- /dev/null +++ b/src/main/java/com/redstoner/redstonerBot/reactableMessages/OptInReactableMessageHandler.java @@ -0,0 +1,188 @@ +package com.redstoner.redstonerBot.reactableMessages; + +import com.redstoner.redstonerBot.ReactionHandler; +import com.redstoner.redstonerBot.managers.DataManager; +import com.redstoner.redstonerBot.managers.DiscordManager; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.MessageBuilder; +import net.dv8tion.jda.core.entities.*; +import net.dv8tion.jda.core.managers.GuildController; + +import java.util.*; +import java.util.function.Consumer; + +public class OptInReactableMessageHandler extends ReactableMessageHandler { + static Map configNames = new HashMap<>(); + + static { + configNames.put("msg_id", "opt_in_msg_id"); + + configNames.put("prefix", "opt_in_prefix"); + configNames.put("suffix", "opt_in_suffix"); + + configNames.put("channel_format", "opt_in_channel_format"); + configNames.put("role_format", "opt_in_role_format"); + } + + public OptInReactableMessageHandler(JDA jda, Guild guild, TextChannel channel) { + super(jda, guild, channel); + } + + @Override + Map getConfigNames() { + return configNames; + } + + @Override + public void send(Consumer onSent) { + String prefix = DataManager.getConfigValue(configNames.get("prefix")); + String suffix = DataManager.getConfigValue(configNames.get("suffix")); + + String channelFormat = DataManager.getConfigValue(configNames.get("channel_format")); + String roleFormat = DataManager.getConfigValue(configNames.get("role_format")); + + MessageBuilder msg = new MessageBuilder(prefix + "\n"); + + List> optIns = DataManager.getOptins(); + + if (optIns != null) { + List> channelOptIns = new ArrayList<>(); + List> roleOptIns = new ArrayList<>(); + + for (Map optIn : optIns) { + if (optIn.get("channel_id") != null) { + channelOptIns.add(optIn); + } else { + roleOptIns.add(optIn); + } + } + + if (channelOptIns.size() > 0) { + for (Map optIn : channelOptIns) { + TextChannel optinChannel = guild.getTextChannelById(optIn.get("channel_id")); + String channelMention = optinChannel.getAsMention(); + + String emoji = optIn.get("emoji"); + Object resolvedEmoji = DiscordManager.getEmoteByName(emoji); + + if (resolvedEmoji instanceof String) emoji = (String) resolvedEmoji; + if (resolvedEmoji instanceof Emote) emoji = ((Emote) resolvedEmoji).getAsMention(); + + String reactionMsg = channelFormat; + + reactionMsg = reactionMsg.replaceAll("%emoji", emoji); + reactionMsg = reactionMsg.replaceAll("%channel", channelMention); + + msg.append(reactionMsg); + msg.append("\n"); + } + + msg.append("\n"); + } + + if (roleOptIns.size() > 0) { + for (Map optIn : roleOptIns) { + Role optinRole = guild.getRoleById(optIn.get("role_id")); + String roleMention = optinRole.getAsMention(); + + String emoji = optIn.get("emoji"); + Object resolvedEmoji = DiscordManager.getEmoteByName(emoji); + + if (resolvedEmoji instanceof String) emoji = (String) resolvedEmoji; + if (resolvedEmoji instanceof Emote) emoji = ((Emote) resolvedEmoji).getAsMention(); + + String reactionMsg = roleFormat; + + reactionMsg = reactionMsg.replaceAll("%emoji", emoji); + reactionMsg = reactionMsg.replaceAll("%role", roleMention); + + msg.append(reactionMsg); + msg.append("\n"); + } + + msg.append("\n"); + } + } + + msg.append(suffix); + + channel.sendMessage(msg.build()).queue(onSent); + } + + @Override + public ReactionHandler getReactionHandler() { + return (messageId, reaction, author, added) -> { + String emoteName = reaction.getReactionEmote().getName(); + String authorTag = author.getAsTag(); + + if (added) { + logger.info("Opt in reaction " + emoteName + " by user " + authorTag + " added!"); + } else { + logger.info("Opt in reaction " + emoteName + " by user " + authorTag + " removed!"); + } + + List> optIns = DataManager.getOptins(); + if (optIns == null) return; + + String roleId = null; + + for (Map optIn : optIns) { + String rId = optIn.get("role_id"); + String e = optIn.get("emoji"); + + if (rId != null && e != null) { + if (reaction.getReactionEmote().isEmote()) { + if (e.equals(emoteName)) { + roleId = rId; + break; + } + } else { + Object discordEmote = DiscordManager.getEmoteByName(e); + + if (discordEmote != null) { + if (discordEmote instanceof String && discordEmote.equals(emoteName)) { + roleId = rId; + break; + } else if (discordEmote instanceof Emote && ((Emote) discordEmote).getName().equals(emoteName)) { + roleId = rId; + break; + } + } + } + } + } + + if (roleId != null) { + GuildController guildController = guild.getController(); + Member authorMember = guild.getMember(author); + Role optInRole = guild.getRoleById(roleId); + + if (added) { + logger.info("Adding role " + optInRole.getName() + " to user " + authorTag); + guildController.addSingleRoleToMember(authorMember, optInRole).queue(); + } else { + logger.info("Removing role " + optInRole.getName() + " from user " + authorTag); + guildController.removeSingleRoleFromMember(authorMember, optInRole).queue(); + } + } else if (added) { + logger.info("Removing rogue reaction " + emoteName + " by user " + authorTag); + reaction.removeReaction(author).queue(); + } + }; + } + + @Override + public Set getReactions() { + Set reactions = new HashSet<>(); + + List> optIns = DataManager.getOptins(); + + if (optIns != null) { + for (Map optIn : optIns) { + reactions.add(optIn.get("emoji")); + } + } + + return reactions; + } +} diff --git a/src/main/java/com/redstoner/redstonerBot/reactableMessages/ReactableMessageHandler.java b/src/main/java/com/redstoner/redstonerBot/reactableMessages/ReactableMessageHandler.java new file mode 100644 index 0000000..71330ca --- /dev/null +++ b/src/main/java/com/redstoner/redstonerBot/reactableMessages/ReactableMessageHandler.java @@ -0,0 +1,88 @@ +package com.redstoner.redstonerBot.reactableMessages; + +import com.redstoner.redstonerBot.ReactionHandler; +import com.redstoner.redstonerBot.managers.DataManager; +import com.redstoner.redstonerBot.managers.DiscordManager; +import com.redstoner.redstonerBot.managers.ReactionManager; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.entities.Emote; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.Message; +import net.dv8tion.jda.core.entities.TextChannel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; + +public abstract class ReactableMessageHandler { + static final Logger logger = LoggerFactory.getLogger(ReactableMessageHandler.class); + + public String msgId; + + final JDA jda; + final Guild guild; + final TextChannel channel; + + ReactableMessageHandler(JDA jda, Guild guild, TextChannel channel) { + this.jda = jda; + this.guild = guild; + this.channel = channel; + + this.msgId = DataManager.getConfigValue(getConfigNames().get("msg_id")); + } + + abstract Map getConfigNames(); + + public abstract void send(Consumer onSent); + + public abstract ReactionHandler getReactionHandler(); + + public abstract Set getReactions(); + + public void checkMessage() { + logger.info("[Check] Checking message ID: " + msgId); + + try { + checkAfterMessageFound(channel.getMessageById(msgId).complete()); + } catch (Exception e) { + logger.info("[Check] Message with ID " + msgId + " does not exist, sending new one!"); + send(this::checkAfterMessageFound); + } + } + + private void checkAfterMessageFound(Message message) { + msgId = message.getId(); + DataManager.setConfigValue(getConfigNames().get("msg_id"), msgId); + + logger.info("[Check] Found message with ID: " + msgId); + + checkReactions(message, getReactions()); + ReactionManager.setHandler(msgId, getReactionHandler()); + + logger.info("[Check] Set reaction handler for message ID " + msgId); + } + + private void checkReactions(Message message, Set reactions) { + if (reactions != null) { + for (String emojiName : reactions) { + try { + logger.info("Adding reaction emote: " + emojiName); + + Object reactionEmoji = DiscordManager.getEmoteByName(emojiName); + + if (reactionEmoji instanceof Emote) { + message.addReaction((Emote) reactionEmoji).queue(); + } else if (reactionEmoji instanceof String) { + message.addReaction((String) reactionEmoji).queue(); + } else { + logger.error("Could not find emote for name '" + emojiName + "'"); + } + } catch (Exception e) { + logger.error("Error adding reaction: ", e); + } + } + } + } +}