diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/AutoRoleCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/AutoRoleCommand.java index c9c6678..53d4904 100644 --- a/src/main/java/cc/fascinated/bat/features/autorole/command/AutoRoleCommand.java +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/AutoRoleCommand.java @@ -12,14 +12,20 @@ import org.springframework.stereotype.Component; * @author Fascinated (fascinated7) */ @Component("autoroles.command") -@CommandInfo(name = "autorole", description = "Set up the automatic role system for members on join", requiredPermissions = Permission.MANAGE_SERVER, category = Category.SERVER) +@CommandInfo( + name = "autorole", + description = "Set up the automatic role system for members on join", + requiredPermissions = Permission.MANAGE_SERVER, + category = Category.SERVER +) public class AutoRoleCommand extends BatCommand { public AutoRoleCommand(@NonNull ApplicationContext context) { super.addSubCommands( context.getBean(ListSubCommand.class), context.getBean(AddSubCommand.class), context.getBean(RemoveSubCommand.class), - context.getBean(ClearSubCommand.class) + context.getBean(ClearSubCommand.class), + context.getBean(SyncSubCommand.class) ); } } diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/SyncSubCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/SyncSubCommand.java new file mode 100644 index 0000000..89952f4 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/SyncSubCommand.java @@ -0,0 +1,109 @@ +package cc.fascinated.bat.features.autorole.command; + +import cc.fascinated.bat.command.BatCommand; +import cc.fascinated.bat.command.CommandInfo; +import cc.fascinated.bat.common.EmbedDescriptionBuilder; +import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; +import cc.fascinated.bat.model.BatGuild; +import cc.fascinated.bat.model.BatUser; +import lombok.NonNull; +import lombok.extern.log4j.Log4j2; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import org.springframework.stereotype.Component; + +import java.util.*; + +/** + * @author Fascinated (fascinated7) + */ +@Log4j2(topic = "AutoRole Sync SubCommand") +@Component("autoroles:sync.sub") +@CommandInfo(name = "sync", description = "Gives everyone their missing auto roles") +public class SyncSubCommand extends BatCommand { + @Override + public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { + AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); + if (profile.getRoles().isEmpty()) { + event.replyEmbeds(EmbedUtils.errorEmbed() + .setDescription("There are no auto roles set") + .build()).queue(); + return; + } + + Guild discordGuild = guild.getDiscordGuild(); + event.replyEmbeds(EmbedUtils.genericEmbed() + .setDescription("Finding members that are missing auto roles...") + .build()) + .queue(message -> { + log.info("Finding members that are missing auto roles in guild \"{}\"", discordGuild.getName()); + List members = discordGuild.loadMembers().get(); + Map rolesGiven = new HashMap<>(); + + // Find members that are missing the auto roles + members.removeIf(foundMember -> { + if (foundMember.getUser().isBot()) return true; + if (foundMember.getId().equals(discordGuild.getSelfMember().getId())) return true; + return new HashSet<>(foundMember.getRoles()).containsAll(profile.getRoles()); + }); + log.info("Found {} members that are missing auto roles in guild \"{}\"", members.size(), discordGuild.getName()); + + // No members were missing roles + if (members.isEmpty()) { + message.editOriginalEmbeds(EmbedUtils.successEmbed() + .setDescription("There are no members missing auto roles") + .build()).queue(); + return; + } + + int finished = 0; + for (Member foundMember : members) { + // Check if the user doesn't have the role, so we can + // show the incremented count when we're done + for (Role role : profile.getRoles()) { + if (foundMember.getRoles().contains(role)) { + continue; + } + rolesGiven.put(role, rolesGiven.getOrDefault(role, 0) + 1); + } + // Give the user the roles + discordGuild.modifyMemberRoles(foundMember, profile.getRoles(), null).queue(); + finished++; + + // Update the message every 10 members + if (finished % 10 == 0 || finished == 1) { + message.editOriginalEmbeds(EmbedUtils.genericEmbed() + .setDescription(""" + Giving auto roles... + Completed: `%s`/`%s` + """.formatted(finished, members.size())) + .build()).queue(); + } + + // We're finished giving all the roles + if (finished == members.size()) { + EmbedDescriptionBuilder description = new EmbedDescriptionBuilder( + "Successfully gave auto roles to `%s` member%s that %s missing them!".formatted( + members.size(), + members.size() == 1 ? "" : "s", + members.size() == 1 ? "was" : "were" + )); + description.emptyLine(); + description.appendLine("**Auto Roles Given:**", false); + for (Map.Entry entry : rolesGiven.entrySet()) { + description.appendLine("%s: %s member%s".formatted( + entry.getKey().getAsMention(), + entry.getValue(), + entry.getValue() == 1 ? "" : "s" + ), true); + } + message.editOriginalEmbeds(EmbedUtils.successEmbed().setDescription(description.build()).build()).queue(); + } + } + }); + } +} diff --git a/src/main/java/cc/fascinated/bat/service/DiscordService.java b/src/main/java/cc/fascinated/bat/service/DiscordService.java index bbfa3ea..1420042 100644 --- a/src/main/java/cc/fascinated/bat/service/DiscordService.java +++ b/src/main/java/cc/fascinated/bat/service/DiscordService.java @@ -3,6 +3,7 @@ package cc.fascinated.bat.service; import cc.fascinated.bat.common.NumberFormatter; import cc.fascinated.bat.common.TimerUtils; import cc.fascinated.bat.config.Config; +import cc.fascinated.bat.event.EventListener; import lombok.Getter; import lombok.NonNull; import lombok.extern.log4j.Log4j2; @@ -25,7 +26,7 @@ import java.util.List; @Service @Getter @Log4j2(topic = "Discord Service") -public class DiscordService { +public class DiscordService implements EventListener { /** * The JDA instance */ @@ -75,4 +76,9 @@ public class DiscordService { .replace("{users}", NumberFormatter.format(JDA.getUsers().size())) )); } + + @Override + public void onShutdown() { + JDA.getPresence().setActivity(Activity.watching("Restarting...")); + } }