I'm trying to make a mute command for a discord bot where it removes all the user's roles and gives them the Muted Role and then after a certain amount of time it gives them their old roles back. I am trying to use a Hashmap to store the player's roles and then give it back but it seems to not work. If anyone here could help I would be really thankful. Here is my code:
public static HashMap<List, Role> roleMap = new HashMap<>();
@Override
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
String command = event.getName();
if (command.equalsIgnoreCase("mute")) {
Member user = event.getOption("user").getAsMember();
roleMap.put(event.getOption("user").getAsMember().getRoles(), event.getGuild().getRoleById(id));
event.getGuild().modifyMemberRoles(event.getOption("user").getAsMember(), event.getGuild().getRoleById(id)).queue();
event.getChannel().sendMessage(event.getOption("user").getAsUser().getAsMention() " has been muted").queue();
if (!event.getMember().hasPermission(Permission.MANAGE_ROLES)) {
event.reply("You do not have the required permissions to use this command!").setEphemeral(true).queue();
}
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
event.getGuild().removeRoleFromMember(event.getOption("user").getAsUser(), event.getGuild().getRoleById("id")).queue();
event.getGuild().addRoleToMember(event.getOption("user").getAsUser(), roleMap.get(event.getOption("user").getAsMember().getRoles()));
}
},
event.getOption("duration").getAsLong() * 1000
);
}
}
CodePudding user response:
First, let’s make this more readable. You are calling event.getOption("user")
in seven different places, which makes the code hard to read. So let’s just call it once:
Guild guild = event.getGuild();
OptionMapping userOption = event.getOption("user");
User user = userOption.getAsUser();
Member member = userOption.getAsMember();
Now we can clean things up considerably:
@Override
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
String command = event.getName();
if (command.equalsIgnoreCase("mute")) {
Guild guild = event.getGuild();
OptionMapping userOption = event.getOption("user");
User user = userOption.getAsUser();
Member member = userOption.getAsMember();
if (!event.getMember().hasPermission(Permission.MANAGE_ROLES)) {
event.reply("You do not have the required permissions to use this command!").setEphemeral(true).queue();
return;
}
Iterable<Role> oldRoles = member.getRoles();
Role mutedRole = guild.getRoleById(id);
guild.modifyMemberRoles(member, mutedRole).queue();
event.getChannel().sendMessage(
user.getAsMention() " has been muted").queue();
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
guild.removeRoleFromMember(user, mutedRole).queue();
for (Role role : oldRoles) {
guild.addRoleToMember(user, role));
}
}
},
event.getOption("duration").getAsLong() * 1000
);
}
}
Notice that the permission check should be the first step performed. There is no reason to continue with any other logic if the user doesn’t have permission to execute the command.
Also notice the use of for (Role role : oldRoles)
to re-add the roles one by one.
You should not make multiple Timers. Just create one Timer, and keep it in a private field:
private final java.util.Timer timer = new java.util.Timer();
@Override
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
And then, of course, use it in your method:
timer.schedule(
new java.util.TimerTask() {
So the final version looks like this:
private final java.util.Timer timer = new java.util.Timer();
@Override
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
String command = event.getName();
if (command.equalsIgnoreCase("mute")) {
Guild guild = event.getGuild();
OptionMapping userOption = event.getOption("user");
User user = userOption.getAsUser();
Member member = userOption.getAsMember();
if (!event.getMember().hasPermission(Permission.MANAGE_ROLES)) {
event.reply("You do not have the required permissions to use this command!").setEphemeral(true).queue();
return;
}
Iterable<Role> oldRoles = member.getRoles();
Role mutedRole = guild.getRoleById(id);
guild.modifyMemberRoles(member, mutedRole).queue();
event.getChannel().sendMessage(
user.getAsMention() " has been muted").queue();
timer.schedule(
new java.util.TimerTask() {
@Override
public void run() {
guild.removeRoleFromMember(user, mutedRole).queue();
for (Role role : oldRoles) {
guild.addRoleToMember(user, role));
}
}
},
event.getOption("duration").getAsLong() * 1000
);
}
}
Your code is using guild.getRoleById(id)
to obtain the “muted” role. I assume you have set id
elsewhere in your class and it does in fact refer to a special role intended for muted users.
Disclaimer: I have never done Discord programming, and I have no way to test any of the above code. I mainly based this on the SlashCommandInteractionEvent documentation.