package Modules; import Controll.GuildController; import Controll.SuperModule; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.MessageReaction; import net.dv8tion.jda.api.entities.PermissionOverride; import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.events.guild.GenericGuildEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent; import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionRemoveEvent; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; public class AutoSelect extends SuperModule { private static final String WAITING_FOR_REACTION_ROLE= "Okay! Please React to a Message you want to bind the Role to!"; private static final String WAITING_FOR_REACTION_TEXTCHANNEL = "Okay! Please React to a Message you want to bind the TextChannel to!"; private static final String WAITING_FOR_REACTION_CATEGORY= "Okay! Please React to a Message you want to bind the Category to!"; private static final String WAITING_FOR_REACTION_VOICECHANNEL = "Okay! Please React to a Message you want to bind the VoiceChannel to!"; private static final String WAITING_FOR_REACTION_REMOVE = "Okay, please react/unreact to a activ Connection to remove it!!"; private static final String ERROR_NO_VALID_INPUT_ID = "That is not a valid Category ID or VoiceChannel ID!"; private static final String ERROR_NO_VALID_INPUT_GENERAL = "That is not a valid input! \n Please mention exact one Role / TextChannel / CategoryID / VoiceChannelID"; private static final String ERROR_ALREADY_EXISTS = "Connection already exists! Abort."; private static final String CONFIRM_DELETE = "Connection deleted!"; private static final String CONFIRM_ADDED= "Connection Added!"; private final Logger logger = LoggerFactory.getLogger(AutoSelect.class); public static final String COMMAND = "AutoSelect"; private HashMap awatingReactionFrom; public AutoSelect(GuildController guildController, JSONObject config){ super(COMMAND, guildController, config); awatingReactionFrom = new HashMap(); if (!config.containsKey("connections")){ config.put("connections", new JSONArray()); safeConfig(getConfig()); } } @Override public String getCommand() { return COMMAND; } @Override public String getDescription(){ return "Setup Roles/Channels/Categories Members can self assign.\nFor Channels/Categories bot assigns View, Read, write, connect, speak rights. Rest have to be managed by your self.\n" + "`AutoSelect new <@ROLE | #TEXTCHANNEL | CATEGORYID | VOICECHANNELID>` add a connection" + "`AutoSelect remove` remove a connection"; } @Override public void execute(GenericEvent event) { ////////////////// // On DELETE ////////////////// if (event instanceof GuildMessageDeleteEvent){ logger.debug(COMMAND + "triggered"); GuildMessageDeleteEvent thisEvent = (GuildMessageDeleteEvent) event; JSONArray connections = (JSONArray)getConfig().get("connections"); for (Object o : connections){ // Go through every entry JSONObject connection = (JSONObject) o; if (connection.get("messageID").toString().equals(thisEvent.getMessageId())){ logger.info("Delete Connection:" + connection.get("targetID") + " | " + connection.get("messageID") + " | " + connection.get("reactionEmote")); connections.remove(o); safeConfig(); } } ////////////////// // On MESSAGE ////////////////// } else if (event instanceof GuildMessageReceivedEvent) { GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; if (!isCommand(thisEvent.getMessage())) return; logger.debug(COMMAND + "triggered"); if (checkForAdmin(thisEvent.getMember())){ ////////////////// // Init New Connection ////////////////// if (checkForCommand(thisEvent.getMessage().getContentRaw(), "new")){ if (thisEvent.getMessage().getMentionedRoles().size() == 1){ // Process for roles addWaitState(thisEvent.getMember().getIdLong(), // add to waitList new TmpData( thisEvent.getChannel().sendMessage( WAITING_FOR_REACTION_ROLE).complete(), thisEvent.getMessage().getMentionedRoles().get(0).getIdLong(), "role" ) ); } else if (thisEvent.getMessage().getMentionedChannels().size() == 1) { // Process for Channels addWaitState(thisEvent.getMember().getIdLong(), // add to waitList new TmpData( thisEvent.getChannel().sendMessage( WAITING_FOR_REACTION_TEXTCHANNEL).complete(), thisEvent.getMessage().getMentionedChannels().get(0).getIdLong(), "text-channel" ) ); } else if (thisEvent.getMessage().getContentRaw().matches("(?is:.*[0-9]+$)")) { // Process for Category Matcher m = Pattern.compile("[0-9]+$").matcher(thisEvent.getMessage().getContentRaw()); if (m.find()){ // Just to make sure, lol if (thisEvent.getGuild().getCategoryById(m.group(0)) != null){ // check if found ID is a Category ID addWaitState(thisEvent.getMember().getIdLong(), // add to waitList new TmpData( thisEvent.getChannel().sendMessage( WAITING_FOR_REACTION_CATEGORY).complete(), Long.parseLong(m.group(0)), "category" ) ); } else if (thisEvent.getGuild().getVoiceChannelById(m.group(0)) != null) { // check if found ID is a VoiceChannel ID addWaitState(thisEvent.getMember().getIdLong(), // add to waitList new TmpData( thisEvent.getChannel().sendMessage( WAITING_FOR_REACTION_VOICECHANNEL).complete(), Long.parseLong(m.group(0)), "voice-channel" ) ); } else { // If ID is not a Category ID send error thisEvent.getChannel().sendMessage(ERROR_NO_VALID_INPUT_ID).queue(msg -> msg.delete().queueAfter(1, TimeUnit.MINUTES)); } } } else { thisEvent.getChannel().sendMessage(ERROR_NO_VALID_INPUT_GENERAL).queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); } ////////////////// // Init remove Connection ////////////////// } if (checkForCommand(thisEvent.getMessage().getContentRaw(), "remove")){ // Setup wait state addWaitState(thisEvent.getMember().getIdLong(), new TmpData( thisEvent.getChannel().sendMessage(WAITING_FOR_REACTION_REMOVE).complete() ,0 ,"delete") ); } } else //delete for no spam thisEvent.getMessage().delete().queue(); ////////////////// // On REACTION ADD ////////////////// } else if (event instanceof GuildMessageReactionAddEvent) { logger.debug(COMMAND + "triggered"); GuildMessageReactionAddEvent thisEvent = (GuildMessageReactionAddEvent)event; if (awatingReactionFrom.containsKey(thisEvent.getUserIdLong())){ // check if reaction is by user we wait for if (awatingReactionFrom.get(thisEvent.getUserIdLong()).targetType.equalsIgnoreCase("delete")){ // check if we have to delete // REMOVE CONNECTION removeConnection(thisEvent.getMessageId(), thisEvent.getReactionEmote(), thisEvent.getChannel().getIdLong()); awatingReactionFrom.get(thisEvent.getUserIdLong()).message.editMessage(CONFIRM_DELETE).queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); awatingReactionFrom.remove(thisEvent.getUserIdLong()); } else { // ADD CONNECTION JSONObject newConnection = new JSONObject(); newConnection.put("targetID", awatingReactionFrom.get(thisEvent.getUserIdLong()).targetID); newConnection.put("messageID", thisEvent.getMessageIdLong()); newConnection.put("reactionEmote", thisEvent.getReactionEmote().getName()); newConnection.put("targetType", awatingReactionFrom.get(thisEvent.getUserIdLong()).targetType); //Check if reaction already connected to a role JSONArray connections = (JSONArray)getConfig().get("connections"); for (Object o : connections){ JSONObject connection = (JSONObject) o; if (connection.get("messageID").toString().equals(thisEvent.getMessageId()) && connection.get("reactionEmote").toString().equals(thisEvent.getReactionEmote().getName())){ awatingReactionFrom.get(thisEvent.getUserIdLong()).message.editMessage(ERROR_ALREADY_EXISTS).complete(); return; } } logger.info("Create Connection:" + newConnection.get("targetID") + " | " + newConnection.get("messageID") + " | " + newConnection.get("reactionEmote")); connections.add(newConnection); awatingReactionFrom.remove(thisEvent.getUserIdLong()).message.editMessage(CONFIRM_ADDED).queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); //switch for emojo or Emote if (thisEvent.getReactionEmote().isEmoji()) thisEvent.getChannel().addReactionById(thisEvent.getMessageIdLong(), thisEvent.getReactionEmote().getName()).queue(); else thisEvent.getChannel().addReactionById(thisEvent.getMessageIdLong(), thisEvent.getReactionEmote().getEmote()).queue(); safeConfig(); } } else { // CHECK IF CONNECTED REACTION AND ADD JSONArray connections = (JSONArray)getConfig().get("connections"); for (Object o : connections){ JSONObject connection = (JSONObject) o; if (connection.get("messageID").toString().equals(thisEvent.getMessageId()) && connection.get("reactionEmote").toString().equals(thisEvent.getReactionEmote().getName())){ PermissionOverride po; // Permission Override Object to avoid conflicting scopes switch (connection.get("targetType").toString()){ case "role": thisEvent.getGuild().addRoleToMember(thisEvent.getMember(), thisEvent.getGuild().getRoleById(connection.get("targetID").toString())).queue(); break; case "text-channel": thisEvent.getGuild().getTextChannelById(connection.get("targetID").toString()).upsertPermissionOverride(thisEvent.getMember()).complete() .getManager().setAllow(Permission.MESSAGE_WRITE, Permission.MESSAGE_READ, Permission.VIEW_CHANNEL).queue(); break; case "voice-channel": thisEvent.getGuild().getVoiceChannelById(connection.get("targetID").toString()).upsertPermissionOverride(thisEvent.getMember()).complete() .getManager().setAllow(Permission.VOICE_CONNECT, Permission.VIEW_CHANNEL, Permission.VOICE_SPEAK).queue(); break; case "category": thisEvent.getGuild().getCategoryById(connection.get("targetID").toString()).upsertPermissionOverride(thisEvent.getMember()).complete() .getManager().setAllow(Permission.VOICE_CONNECT, Permission.VIEW_CHANNEL, Permission.VOICE_SPEAK, Permission.MESSAGE_READ, Permission.MESSAGE_WRITE).queue(); break; } logger.info("ADDED target " + connection.get("targetID") + " to User" + thisEvent.getMember().getId()); } } } ////////////////// // On REACTION REMOVE ////////////////// } else if (event instanceof GuildMessageReactionRemoveEvent){ logger.debug(COMMAND + "triggered"); GuildMessageReactionRemoveEvent thisEvent = (GuildMessageReactionRemoveEvent) event; if (awatingReactionFrom.containsKey(thisEvent.getUserIdLong())){ if (awatingReactionFrom.get(thisEvent.getUserIdLong()).targetType.equalsIgnoreCase("delete")){ // REMOVE CONNECTION removeConnection(thisEvent.getMessageId(), thisEvent.getReactionEmote(), thisEvent.getChannel().getIdLong()); awatingReactionFrom.remove(thisEvent.getUserIdLong()).message.editMessage(CONFIRM_DELETE).queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); } } else { // CHECK IF CONNECTED REACTION AND REMOVE JSONArray connections = (JSONArray)getConfig().get("connections"); for (Object o : connections){ JSONObject connection = (JSONObject) o; if (connection.get("messageID").toString().equals(thisEvent.getMessageId()) && connection.get("reactionEmote").toString().equals(thisEvent.getReactionEmote().getName())){ PermissionOverride po; // Permission Override Object to avoid conflicting scopes Member member = thisEvent.retrieveMember().complete(); switch (connection.get("targetType").toString()){ case "role": if (thisEvent.getGuild().getRoleById(connection.get("targetID").toString()) != null) { thisEvent.getGuild().removeRoleFromMember(member, thisEvent.getGuild().getRoleById(connection.get("targetID").toString())).queue(); } else { // REMOVE DEPRECATED CONNECTION ((JSONArray)getConfig().get("connections")).remove(o); safeConfig(); } break; case "text-channel": if (thisEvent.getGuild().getTextChannelById(connection.get("targetID").toString()) != null) { thisEvent.getGuild().getTextChannelById(connection.get("targetID").toString()).getPermissionOverride(member).delete().queue(); } else { // REMOVE DEPRECATED CONNECTION ((JSONArray)getConfig().get("connections")).remove(o); safeConfig(); } break; case "voice-channel": if (thisEvent.getGuild().getVoiceChannelById(connection.get("targetID").toString()) != null) { thisEvent.getGuild().getVoiceChannelById(connection.get("targetID").toString()).getPermissionOverride(member).delete().queue(); } else { // REMOVE DEPRECATED CONNECTION ((JSONArray)getConfig().get("connections")).remove(o); safeConfig(); } break; case "category": if (thisEvent.getGuild().getCategoryById(connection.get("targetID").toString()) != null) { thisEvent.getGuild().getCategoryById(connection.get("targetID").toString()).getPermissionOverride(member).delete().queue(); } else { // REMOVE DEPRECATED CONNECTION ((JSONArray)getConfig().get("connections")).remove(o); safeConfig(); } break; } logger.info("REMOVED target " + connection.get("targetID") + " to User" + member.getUser().getId()); break; } } } } } private void removeConnection(String messageId, MessageReaction.ReactionEmote reactionEmote, long channelID) { JSONArray connections = (JSONArray)getConfig().get("connections"); for (Object o : connections) { JSONObject connection = (JSONObject) o; try { if (reactionEmote.isEmoji()) { reactionEmote.getJDA().getGuildById(getGuildController().getGUILD_ID()).getTextChannelById(channelID).clearReactionsById(messageId, reactionEmote.getName()); } else { reactionEmote.getJDA().getGuildById(getGuildController().getGUILD_ID()).getTextChannelById(channelID).clearReactionsById(messageId, reactionEmote.getEmote()); } } catch (NullPointerException e) { // } if (connection.get("messageID").toString().equalsIgnoreCase(messageId) && connection.get("reactionEmote").toString().equals(reactionEmote.getName())) { logger.info("Delete Connection:" + connection.get("targetID") + " | " + connection.get("messageID") + " | " + connection.get("reactionEmote")); connections.remove(o); safeConfig(); } } } @Override public String showSettings() { return "NUMBER OF CONNECTIONS: `" + ((JSONArray)getConfig().get("connections")).size() + "`"; } private class TmpData{ public Message message; public long targetID; public String reactionEmote; public String targetType; public TmpData(Message message, long targetID, String targetType){ this.message = message; this.targetID = targetID; this.targetType = targetType; } } private void addWaitState(long userID, TmpData tmpData){ // Setup wait state awatingReactionFrom.put(userID, tmpData); // Setup timer to remove waitstate new Timer().schedule(new TimerTask(){ public void run(){ awatingReactionFrom.remove(userID).message.editMessage("TimeOut!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); } }, TimeUnit.SECONDS.toMillis(60)); } }