Skip to content

Commit 2b6f6e7

Browse files
author
Dynxsty
authored
Merge pull request #75 from Java-Discord/dynxsty/help-role
Added "permanent Role" functionality to Reaction Roles
2 parents 7cd2027 + b78e16a commit 2b6f6e7

File tree

8 files changed

+156
-177
lines changed

8 files changed

+156
-177
lines changed

src/main/java/com/javadiscord/javabot/Bot.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ private static void addEventListeners(JDA jda) {
9292
new AutoMod(),
9393
new SubmissionListener(),
9494
new StarboardListener(),
95-
new ButtonClickListener()
95+
new InteractionListener()
9696
);
9797
}
9898
}

src/main/java/com/javadiscord/javabot/commands/configuation/config/Config.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ public Config() {
3737
@Override
3838
public ReplyAction handle(SlashCommandEvent event) {
3939

40-
try { return super.handle(event);
41-
} catch (Exception e) { return Responses.error(event, "```" + e.getMessage() + "```"); }
40+
return Responses.error(event, "This command is currently not available.");
41+
42+
//try { return super.handle(event);
43+
//} catch (Exception e) { return Responses.error(event, "```" + e.getMessage() + "```"); }
4244
}
4345

4446
public MessageEmbed configEmbed (String configName, String newValue) {
Lines changed: 12 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,152 +1,25 @@
11
package com.javadiscord.javabot.commands.reaction_roles;
22

3-
import com.google.gson.JsonObject;
4-
import com.google.gson.JsonParser;
3+
import com.javadiscord.javabot.commands.DelegatingCommandHandler;
54
import com.javadiscord.javabot.commands.Responses;
6-
import com.javadiscord.javabot.commands.SlashCommandHandler;
7-
import com.javadiscord.javabot.other.Constants;
8-
import com.javadiscord.javabot.other.Misc;
9-
import com.mongodb.BasicDBObject;
10-
import com.mongodb.client.MongoCollection;
11-
import com.mongodb.client.MongoCursor;
12-
import com.mongodb.client.MongoDatabase;
13-
import net.dv8tion.jda.api.EmbedBuilder;
14-
import net.dv8tion.jda.api.entities.Emoji;
15-
import net.dv8tion.jda.api.entities.Message;
16-
import net.dv8tion.jda.api.entities.MessageChannel;
17-
import net.dv8tion.jda.api.entities.Role;
5+
import com.javadiscord.javabot.commands.reaction_roles.subcommands.CreateReactionRole;
6+
import com.javadiscord.javabot.commands.reaction_roles.subcommands.DeleteReactionRole;
7+
import com.javadiscord.javabot.commands.reaction_roles.subcommands.ListReactionRoles;
188
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
19-
import net.dv8tion.jda.api.interactions.components.Button;
20-
import net.dv8tion.jda.api.interactions.components.ButtonStyle;
219
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction;
22-
import org.bson.Document;
2310

24-
import java.util.ArrayList;
25-
import java.util.Date;
26-
import java.util.List;
11+
public class ReactionRoles extends DelegatingCommandHandler {
2712

28-
import static com.javadiscord.javabot.events.Startup.mongoClient;
29-
import static com.mongodb.client.model.Filters.eq;
13+
public ReactionRoles() {
14+
addSubcommand("create", new CreateReactionRole());
15+
addSubcommand("delete", new DeleteReactionRole());
16+
}
3017

31-
// TODO: Redo implementation of this to be much cleaner.
32-
@Deprecated(forRemoval = true)
33-
public class ReactionRoles implements SlashCommandHandler {
3418
@Override
3519
public ReplyAction handle(SlashCommandEvent event) {
36-
return switch (event.getSubcommandName()) {
37-
case "create" -> create(event,
38-
event.getOption("channel").getAsMessageChannel(),
39-
event.getOption("messageid").getAsString(),
40-
event.getOption("emote").getAsString(),
41-
event.getOption("button-label").getAsString(),
42-
event.getOption("role").getAsRole());
43-
case "delete" -> delete(event,
44-
event.getOption("messageid").getAsString(),
45-
event.getOption("button-label").getAsString(),
46-
event.getOption("emote").getAsString());
47-
default -> Responses.warning(event, "Unknown subcommand.");
48-
};
49-
}
50-
51-
private ReplyAction create(SlashCommandEvent event, MessageChannel channel, String mID, String emote, String buttonLabel, Role role) {
52-
53-
MongoDatabase database = mongoClient.getDatabase("other");
54-
MongoCollection<Document> collection = database.getCollection("reactionroles");
55-
56-
BasicDBObject criteria = new BasicDBObject()
57-
.append("guild_id", event.getGuild().getId())
58-
.append("channel_id", channel.getId())
59-
.append("message_id", mID)
60-
.append("button_label", buttonLabel)
61-
.append("emote", emote);
62-
63-
if (collection.find(criteria).first() == null) {
64-
65-
Document doc = new Document()
66-
.append("guild_id", event.getGuild().getId())
67-
.append("channel_id", channel.getId())
68-
.append("message_id", mID)
69-
.append("role_id", role.getId())
70-
.append("button_label", buttonLabel)
71-
.append("emote", emote);
72-
73-
collection.insertOne(doc);
74-
var e = new EmbedBuilder()
75-
.setTitle("Reaction Role created")
76-
.addField("Channel", "<#" + channel.getId() + ">", true)
77-
.addField("Role", role.getAsMention(), true)
78-
.addField("MessageID", "```" + mID + "```", false)
79-
.addField("Emote", "```" + emote + "```", true)
80-
.addField("Button Label", "```" + buttonLabel + "```", true)
81-
.setColor(Constants.GRAY)
82-
.setFooter(event.getUser().getAsTag(), event.getUser().getEffectiveAvatarUrl())
83-
.setTimestamp(new Date().toInstant())
84-
.build();
8520

86-
87-
Misc.sendToLog(event.getGuild(), e);
88-
89-
channel.retrieveMessageById(mID).queue(this::updateMessageComponents);
90-
return event.replyEmbeds(e).setEphemeral(true);
91-
} else return Responses.error(event,
92-
"A Reaction Role on message `" + mID + "` with emote `" + emote + "` and Button Label `" + buttonLabel + "` already exists.");
93-
}
94-
95-
private ReplyAction delete(SlashCommandEvent event, String mID, String buttonLabel, String emote) {
96-
97-
MongoDatabase database = mongoClient.getDatabase("other");
98-
MongoCollection<Document> collection = database.getCollection("reactionroles");
99-
100-
BasicDBObject criteria = new BasicDBObject()
101-
.append("guild_id", event.getGuild().getId())
102-
.append("message_id", mID)
103-
.append("emote", emote)
104-
.append("button_label", buttonLabel);
105-
106-
try {
107-
collection.find(criteria).first().toJson();
108-
} catch (NullPointerException e) {
109-
return Responses.error(event,
110-
"A Reaction Role on message `" + mID + "` with emote `" + emote + "` and Button Label `" + buttonLabel + "` does not exist.");
111-
}
112-
113-
collection.deleteOne(criteria);
114-
115-
var e = new EmbedBuilder()
116-
.setTitle("Reaction Role removed")
117-
.addField("MessageID", "```" + mID + "```", false)
118-
.addField("Emote", "```" + emote + "```", true)
119-
.addField("Button Label", "```" + buttonLabel + "```", true)
120-
.setColor(Constants.GRAY)
121-
.setFooter(event.getUser().getAsTag(), event.getUser().getEffectiveAvatarUrl())
122-
.setTimestamp(new Date().toInstant())
123-
.build();
124-
125-
126-
Misc.sendToLog(event.getGuild(), e);
127-
128-
event.getChannel().retrieveMessageById(mID).queue(this::updateMessageComponents);
129-
return event.replyEmbeds(e).setEphemeral(true);
130-
}
131-
132-
void updateMessageComponents (Message message) {
133-
134-
MongoDatabase database = mongoClient.getDatabase("other");
135-
MongoCollection<Document> collection = database.getCollection("reactionroles");
136-
137-
List<Button> buttons = new ArrayList<>();
138-
MongoCursor<Document> it = collection.find(eq("message_id", message.getId())).iterator();
139-
140-
while (it.hasNext()) {
141-
142-
JsonObject root = JsonParser.parseString(it.next().toJson()).getAsJsonObject();
143-
String label = root.get("button_label").getAsString();
144-
String emote = root.get("emote").getAsString();
145-
Emoji emoji = Emoji.fromMarkdown(emote);
146-
147-
buttons.add(Button.of(ButtonStyle.SECONDARY, "reactionroles:" + message.getId() + ":" + label + ":" + emoji.getId(), label, emoji));
148-
}
149-
150-
message.editMessageEmbeds(message.getEmbeds().get(0)).setActionRow(buttons.toArray(new Button[0])).queue();
21+
try { return super.handle(event);
22+
} catch (Exception e) { return Responses.error(event, "```" + e.getMessage() + "```"); }
15123
}
15224
}
25+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.javadiscord.javabot.commands.reaction_roles.subcommands;
2+
3+
import com.javadiscord.javabot.commands.SlashCommandHandler;
4+
import com.javadiscord.javabot.other.Constants;
5+
import com.javadiscord.javabot.other.Misc;
6+
import net.dv8tion.jda.api.EmbedBuilder;
7+
import net.dv8tion.jda.api.entities.Emoji;
8+
import net.dv8tion.jda.api.entities.Role;
9+
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
10+
import net.dv8tion.jda.api.interactions.components.ActionRow;
11+
import net.dv8tion.jda.api.interactions.components.Button;
12+
import net.dv8tion.jda.api.interactions.components.ButtonStyle;
13+
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction;
14+
15+
import java.time.Instant;
16+
import java.util.ArrayList;
17+
import java.util.Date;
18+
import java.util.List;
19+
20+
public class CreateReactionRole implements SlashCommandHandler {
21+
22+
/**
23+
* Represents the Button id for a Reaction Role Button.
24+
* The id consists of:
25+
<ol>
26+
* <li>"reaction-role:" - specifies the Button Type (see {@link com.javadiscord.javabot.events.InteractionListener})</li>
27+
* <li>"role.getID():" - The ID of the Role the Bot should give upon Interaction</li>
28+
* <li>"permanent:" - Specifies if the Role is permanent (see {@link com.javadiscord.javabot.events.InteractionListener})</li>
29+
* <li>"Instant.now();" - Value to avoid Buttons with the same ID.</li>
30+
* </ol>
31+
*
32+
* (This may be improved in the future.)
33+
*
34+
* @param role The Role the Bot should give upon Interaction
35+
* @param permanent Specifies if the Role is permanent
36+
*/
37+
private String buttonId(Role role, boolean permanent) {
38+
return "reaction-role:" + role.getId() + ":" + permanent + ":" + Instant.now();
39+
}
40+
41+
@Override
42+
public ReplyAction handle(SlashCommandEvent event) {
43+
var message = event.getChannel().retrieveMessageById(event.getOption("message-id").getAsString()).complete();
44+
var buttonLabel = event.getOption("label").getAsString();
45+
var role = event.getOption("role").getAsRole();
46+
47+
boolean permanent = event.getOption("permanent") != null && event.getOption("permanent").getAsBoolean();
48+
String emote = event.getOption("emote") == null ? null : event.getOption("emote").getAsString();
49+
50+
List<Button> buttons = new ArrayList<>(message.getButtons());
51+
if (emote != null) {
52+
buttons.add(Button.of(ButtonStyle.SECONDARY, buttonId(role, permanent), buttonLabel, Emoji.fromMarkdown(emote)));
53+
} else {
54+
buttons.add(Button.of(ButtonStyle.SECONDARY, buttonId(role, permanent), buttonLabel));
55+
}
56+
message.editMessageComponents(ActionRow.of(buttons)).queue();
57+
58+
var e = new EmbedBuilder()
59+
.setTitle("Reaction Role created")
60+
.setColor(Constants.GRAY)
61+
.addField("Channel", "<#" + event.getChannel().getId() + ">", true)
62+
.addField("Role", role.getAsMention(), true)
63+
.addField("MessageID", "```" + message.getId() + "```", false);
64+
if (emote != null) e.addField("Emote", "```" + emote + "```", true);
65+
e.addField("Button Label", "```" + buttonLabel + "```", true)
66+
.setFooter(event.getUser().getAsTag(), event.getUser().getEffectiveAvatarUrl())
67+
.setTimestamp(new Date().toInstant());
68+
Misc.sendToLog(event.getGuild(), e.build());
69+
return event.replyEmbeds(e.build()).setEphemeral(true);
70+
}
71+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.javadiscord.javabot.commands.reaction_roles.subcommands;
2+
3+
import com.javadiscord.javabot.commands.SlashCommandHandler;
4+
import com.javadiscord.javabot.other.Constants;
5+
import com.javadiscord.javabot.other.Misc;
6+
import net.dv8tion.jda.api.EmbedBuilder;
7+
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
8+
import net.dv8tion.jda.api.interactions.components.ActionRow;
9+
import net.dv8tion.jda.api.interactions.components.Button;
10+
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyAction;
11+
12+
import java.util.ArrayList;
13+
import java.util.Date;
14+
import java.util.List;
15+
16+
public class DeleteReactionRole implements SlashCommandHandler {
17+
18+
@Override
19+
public ReplyAction handle(SlashCommandEvent event) {
20+
var message = event.getChannel().retrieveMessageById(event.getOption("message-id").getAsString()).complete();
21+
String buttonLabel = event.getOption("label").getAsString();
22+
23+
List<Button> buttons = new ArrayList<>(message.getActionRows().get(0).getButtons());
24+
for (var ignored : message.getActionRows().get(0).getButtons()) buttons.removeIf(x -> x.getLabel().equals(buttonLabel));
25+
if (!buttons.isEmpty()) {
26+
message.editMessageComponents(ActionRow.of(buttons)).queue();
27+
} else {
28+
message.editMessageComponents().queue();
29+
}
30+
31+
var e = new EmbedBuilder()
32+
.setTitle("Reaction Role removed")
33+
.addField("MessageID", "```" + message.getId() + "```", false)
34+
.addField("Button Label", "```" + buttonLabel + "```", true)
35+
.setColor(Constants.GRAY)
36+
.setFooter(event.getUser().getAsTag(), event.getUser().getEffectiveAvatarUrl())
37+
.setTimestamp(new Date().toInstant())
38+
.build();
39+
Misc.sendToLog(event.getGuild(), e);
40+
return event.replyEmbeds(e).setEphemeral(true);
41+
}
42+
}

src/main/java/com/javadiscord/javabot/commands/reaction_roles/ReactionRoleList.java renamed to src/main/java/com/javadiscord/javabot/commands/reaction_roles/subcommands/ListReactionRoles.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.javadiscord.javabot.commands.reaction_roles;
1+
package com.javadiscord.javabot.commands.reaction_roles.subcommands;
22

33
import com.google.gson.JsonObject;
44
import com.google.gson.JsonParser;
@@ -17,7 +17,7 @@
1717
import static com.javadiscord.javabot.events.Startup.mongoClient;
1818
import static com.mongodb.client.model.Filters.eq;
1919

20-
public class ReactionRoleList implements SlashCommandHandler {
20+
public class ListReactionRoles implements SlashCommandHandler {
2121

2222
@Override
2323
public ReplyAction handle(SlashCommandEvent event) {

src/main/java/com/javadiscord/javabot/events/ButtonClickListener.java renamed to src/main/java/com/javadiscord/javabot/events/InteractionListener.java

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.google.gson.JsonObject;
44
import com.google.gson.JsonParser;
5-
import com.mongodb.BasicDBObject;
65
import com.mongodb.client.MongoCollection;
76
import com.mongodb.client.MongoDatabase;
87
import net.dv8tion.jda.api.entities.Guild;
@@ -16,11 +15,13 @@
1615
import static com.javadiscord.javabot.events.Startup.preferredGuild;
1716
import static com.mongodb.client.model.Filters.eq;
1817

19-
public class ButtonClickListener extends ListenerAdapter {
18+
public class InteractionListener extends ListenerAdapter {
19+
20+
// TODO: add Context-Menu Commands (once they're available in JDA)
21+
2022
@Override
2123
public void onButtonClick(ButtonClickEvent event) {
2224
if (event.getUser().isBot()) return;
23-
2425
event.deferEdit().queue();
2526

2627
Guild guild = preferredGuild;
@@ -29,7 +30,7 @@ public void onButtonClick(ButtonClickEvent event) {
2930
switch (id[0]) {
3031
case "dm-submission" -> this.handleDmSubmission(database, guild, event);
3132
case "submission" -> this.handleSubmission(database, guild, event);
32-
case "reactionroles" -> this.handleReactionRoles(database, guild, event);
33+
case "reaction-role" -> this.handleReactionRoles(event);
3334
}
3435
}
3536

@@ -60,29 +61,21 @@ private void handleSubmission(MongoDatabase database, Guild guild, ButtonClickEv
6061
submissionMessages.deleteOne(document);
6162
}
6263

63-
private void handleReactionRoles(MongoDatabase database, Guild guild, ButtonClickEvent event) {
64+
private void handleReactionRoles(ButtonClickEvent event) {
6465
String[] id = event.getComponentId().split(":");
65-
String messageID = id[1];
66-
String buttonLabel = id[2];
66+
String roleID = id[1];
67+
boolean permanent = Boolean.parseBoolean(id[2]);
6768

6869
Member member = event.getGuild().retrieveMemberById(event.getUser().getId()).complete();
69-
70-
BasicDBObject criteria = new BasicDBObject()
71-
.append("guild_id", event.getGuild().getId())
72-
.append("message_id", messageID)
73-
.append("button_label", buttonLabel);
74-
75-
MongoCollection<Document> reactionroles = database.getCollection("reactionroles");
76-
String JSON = reactionroles.find(criteria).first().toJson();
77-
78-
JsonObject Root = JsonParser.parseString(JSON).getAsJsonObject();
79-
String roleID = Root.get("role_id").getAsString();
80-
8170
Role role = event.getGuild().getRoleById(roleID);
8271

8372
if (member.getRoles().contains(role)) {
84-
event.getGuild().removeRoleFromMember(member, role).queue();
85-
event.getHook().sendMessage("Removed Role: " + role.getAsMention()).setEphemeral(true).queue();
73+
if (!permanent) {
74+
event.getGuild().removeRoleFromMember(member, role).queue();
75+
event.getHook().sendMessage("Removed Role: " + role.getAsMention()).setEphemeral(true).queue();
76+
} else {
77+
event.getHook().sendMessage("You already have Role: " + role.getAsMention()).setEphemeral(true).queue();
78+
}
8679
} else {
8780
event.getGuild().addRoleToMember(member, role).queue();
8881
event.getHook().sendMessage("Added Role: " + role.getAsMention()).setEphemeral(true).queue();

0 commit comments

Comments
 (0)