diff --git a/src/main/java/cc/fascinated/bat/common/EmbedUtils.java b/src/main/java/cc/fascinated/bat/common/EmbedUtils.java index ac164eb..d084707 100644 --- a/src/main/java/cc/fascinated/bat/common/EmbedUtils.java +++ b/src/main/java/cc/fascinated/bat/common/EmbedUtils.java @@ -14,12 +14,10 @@ public class EmbedUtils { /** * Builds a generic embed * - * @param description the description of the embed * @return the embed builder */ - public static EmbedBuilder buildGenericEmbed(String description) { + public static EmbedBuilder buildGenericEmbed() { return new EmbedBuilder() - .setDescription(description) .setTimestamp(LocalDateTime.now()) .setColor(Colors.DEFAULT); } @@ -27,12 +25,10 @@ public class EmbedUtils { /** * Builds an error embed * - * @param description the description of the embed * @return the embed builder */ - public static EmbedBuilder buildErrorEmbed(String description) { + public static EmbedBuilder buildErrorEmbed() { return new EmbedBuilder() - .setDescription(description) .setTimestamp(LocalDateTime.now()) .setColor(Colors.ERROR); } @@ -40,12 +36,10 @@ public class EmbedUtils { /** * Builds a success embed * - * @param description the description of the embed * @return the embed builder */ - public static EmbedBuilder buildSuccessEmbed(String description) { + public static EmbedBuilder buildSuccessEmbed() { return new EmbedBuilder() - .setDescription(description) .setTimestamp(LocalDateTime.now()) .setColor(Colors.SUCCESS); } diff --git a/src/main/java/cc/fascinated/bat/common/Profile.java b/src/main/java/cc/fascinated/bat/common/Profile.java index 83adbfc..56974c7 100644 --- a/src/main/java/cc/fascinated/bat/common/Profile.java +++ b/src/main/java/cc/fascinated/bat/common/Profile.java @@ -8,6 +8,7 @@ import org.springframework.data.annotation.Transient; /** * @author Fascinated (fascinated7) */ +@AllArgsConstructor @Getter @Setter public class Profile { /** @@ -15,9 +16,5 @@ public class Profile { */ private String profileKey; - public Profile(String profileKey) { - this.profileKey = profileKey; - } - public Profile() {} } diff --git a/src/main/java/cc/fascinated/bat/event/EventListener.java b/src/main/java/cc/fascinated/bat/event/EventListener.java index 92ecc1f..d00773c 100644 --- a/src/main/java/cc/fascinated/bat/event/EventListener.java +++ b/src/main/java/cc/fascinated/bat/event/EventListener.java @@ -1,8 +1,12 @@ package cc.fascinated.bat.event; +import cc.fascinated.bat.model.BatGuild; +import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberLeaderboardToken; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberPlayerScoreToken; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberScoreToken; +import lombok.NonNull; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; /** * @author Fascinated (fascinated7) @@ -15,6 +19,14 @@ public interface EventListener { * @param leaderboard the leaderboard that the score was set on * @param player the player that set the score */ - default void onScoresaberScoreReceived(ScoreSaberPlayerScoreToken score, ScoreSaberLeaderboardToken leaderboard, - ScoreSaberScoreToken.LeaderboardPlayerInfo player) {} + default void onScoresaberScoreReceived(@NonNull ScoreSaberPlayerScoreToken score, @NonNull ScoreSaberLeaderboardToken leaderboard, + @NonNull ScoreSaberScoreToken.LeaderboardPlayerInfo player) {} + + /** + * Called when a user joins a guild + * + * @param guild the guild the user joined + * @param user the user that joined the guild + */ + default void onGuildMemberJoin(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull GuildMemberJoinEvent event) {} } diff --git a/src/main/java/cc/fascinated/bat/features/autorole/AutoRoleListener.java b/src/main/java/cc/fascinated/bat/features/autorole/AutoRoleListener.java new file mode 100644 index 0000000..b80ec72 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/autorole/AutoRoleListener.java @@ -0,0 +1,41 @@ +package cc.fascinated.bat.features.autorole; + +import cc.fascinated.bat.event.EventListener; +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.Role; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Fascinated (fascinated7) + */ +@Component @Log4j2 +public class AutoRoleListener implements EventListener { + + @Override + public void onGuildMemberJoin(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull GuildMemberJoinEvent event) { + AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); + if (profile.getRoles().isEmpty()) { + return; + } + + List toRemove = new ArrayList<>(); + for (Role role : profile.getRoles()) { + if (event.getGuild().getRoleById(role.getId()) == null) { + toRemove.add(role.getId()); + continue; + } + event.getGuild().addRoleToMember(event.getMember(), role).queue(); + } + toRemove.forEach(profile::removeRole); + log.info("Gave user \"{}\" {} auto roles{}", user.getId(), profile.getRoles().size(), toRemove.isEmpty() ? "" + : " and removed %s invalid roles".formatted(toRemove.size())); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/AddSubCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/AddSubCommand.java new file mode 100644 index 0000000..62b2781 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/AddSubCommand.java @@ -0,0 +1,64 @@ +package cc.fascinated.bat.features.autorole.command; + +import cc.fascinated.bat.command.BatSubCommand; +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 cc.fascinated.bat.service.GuildService; +import lombok.NonNull; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component("autoroles:add.sub") +public class AddSubCommand extends BatSubCommand { + private final GuildService guildService; + + @Autowired + public AddSubCommand(GuildService guildService) { + this.guildService = guildService; + } + + @Override + public void execute(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull TextChannel channel, @NonNull Member member, @NonNull SlashCommandInteraction interaction) { + AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); + if (profile.getRoleSlotsInUse() >= profile.getMaxRoles()) { + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("You can only have a maximum of %d roles set for the auto role feature" + .formatted(profile.getMaxRoles())) + .build()).queue(); + return; + } + + OptionMapping option = interaction.getOption("role"); + if (option == null) { + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Please provide a role to add") + .build()).queue(); + return; + } + + Role role = option.getAsRole(); + if (profile.hasRole(role.getId())) { + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("The role %s is already in the auto roles list".formatted(role.getAsMention())) + .build()).queue(); + return; + } + + profile.addRole(role.getId()); + guildService.saveGuild(guild); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("Successfully added the role %s to the auto roles list".formatted(role.getAsMention())) + .build()).queue(); + } +} 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 new file mode 100644 index 0000000..61d71a8 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/AutoRoleCommand.java @@ -0,0 +1,42 @@ +package cc.fascinated.bat.features.autorole.command; + +import cc.fascinated.bat.command.BatCommand; +import lombok.NonNull; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; +import net.dv8tion.jda.internal.interactions.CommandDataImpl; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component("autoroles.command") +public class AutoRoleCommand extends BatCommand { + public AutoRoleCommand(@NonNull ApplicationContext context) { + super("autorole"); + super.setDescription("Set up the automatic role system for members on join"); + + super.addSubCommand("list", context.getBean(ListSubCommand.class)); + super.addSubCommand("add", context.getBean(AddSubCommand.class)); + super.addSubCommand("remove", context.getBean(RemoveSubCommand.class)); + super.addSubCommand("clear", context.getBean(ClearSubCommand.class)); + + super.setCommandData(new CommandDataImpl(this.getName(), this.getDescription()) + .setGuildOnly(true) + .addSubcommands(new SubcommandData("list", "Show the current automatic roles")) + .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) + .addSubcommands(new SubcommandData("add", "Add an automatic role") + .addOptions(new OptionData(OptionType.ROLE, "role", "The role to add", true)) + ).setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) + .addSubcommands(new SubcommandData("remove", "Remove an automatic role") + .addOptions(new OptionData(OptionType.ROLE, "role", "The role to remove", true)) + ).setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) + .addSubcommands(new SubcommandData("clear", "Clears all automatic roles")) + .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) + ); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/ClearSubCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/ClearSubCommand.java new file mode 100644 index 0000000..15aa220 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/ClearSubCommand.java @@ -0,0 +1,40 @@ +package cc.fascinated.bat.features.autorole.command; + +import cc.fascinated.bat.command.BatSubCommand; +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 cc.fascinated.bat.service.GuildService; +import lombok.NonNull; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component("autoroles:clear.sub") +public class ClearSubCommand extends BatSubCommand { + private final GuildService guildService; + + @Autowired + public ClearSubCommand(GuildService guildService) { + this.guildService = guildService; + } + + @Override + public void execute(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull TextChannel channel, @NonNull Member member, @NonNull SlashCommandInteraction interaction) { + AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); + + profile.clearRoles(); + guildService.saveGuild(guild); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("Successfully cleared all auto roles") + .build()).queue(); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/ListSubCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/ListSubCommand.java new file mode 100644 index 0000000..d7377c2 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/ListSubCommand.java @@ -0,0 +1,46 @@ +package cc.fascinated.bat.features.autorole.command; + +import cc.fascinated.bat.command.BatSubCommand; +import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; +import cc.fascinated.bat.features.scoresaber.profile.GuildUserScoreFeedProfile; +import cc.fascinated.bat.model.BatGuild; +import cc.fascinated.bat.model.BatUser; +import lombok.NonNull; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component("autoroles:list.sub") +public class ListSubCommand extends BatSubCommand { + + @Override + public void execute(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull TextChannel channel, @NonNull Member member, @NonNull SlashCommandInteraction interaction) { + AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); + if (profile.getRoles().isEmpty()) { + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("There are no auto roles set") + .build()).queue(); + return; + } + + StringBuilder roles = new StringBuilder(); + roles.append("There are %d/%d auto roles\n".formatted( + profile.getRoleSlotsInUse(), + profile.getMaxRoles() + )); + for (int i = 0; i < profile.getRoles().size(); i++) { + roles.append("%d. %s\n".formatted(i + 1, profile.getRoles().get(i).getAsMention())); + } + + EmbedBuilder embed = EmbedUtils.buildGenericEmbed(); + embed.setTitle("Auto Role List"); + embed.setDescription(roles.toString()); + interaction.replyEmbeds(embed.build()).queue(); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/RemoveSubCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/RemoveSubCommand.java new file mode 100644 index 0000000..899bedc --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/RemoveSubCommand.java @@ -0,0 +1,55 @@ +package cc.fascinated.bat.features.autorole.command; + +import cc.fascinated.bat.command.BatSubCommand; +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 cc.fascinated.bat.service.GuildService; +import lombok.NonNull; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component("autoroles:remove.sub") +public class RemoveSubCommand extends BatSubCommand { + private final GuildService guildService; + + @Autowired + public RemoveSubCommand(GuildService guildService) { + this.guildService = guildService; + } + + @Override + public void execute(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull TextChannel channel, @NonNull Member member, @NonNull SlashCommandInteraction interaction) { + AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); + OptionMapping option = interaction.getOption("role"); + if (option == null) { + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Please provide a role to remove") + .build()).queue(); + return; + } + + Role role = option.getAsRole(); + if (!profile.hasRole(role.getId())) { + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("The role %s is not in the auto roles list".formatted(role.getAsMention())) + .build()).queue(); + return; + } + + profile.removeRole(role.getId()); + guildService.saveGuild(guild); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Successfully removed the role %s from the auto roles list".formatted(role.getAsMention())) + .build()).queue(); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/autorole/profile/AutoRoleProfile.java b/src/main/java/cc/fascinated/bat/features/autorole/profile/AutoRoleProfile.java new file mode 100644 index 0000000..cc6b256 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/autorole/profile/AutoRoleProfile.java @@ -0,0 +1,111 @@ +package cc.fascinated.bat.features.autorole.profile; + +import cc.fascinated.bat.common.Profile; +import cc.fascinated.bat.service.DiscordService; +import lombok.Getter; +import lombok.Setter; +import net.dv8tion.jda.api.entities.Role; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Fascinated (fascinated7) + */ +@Setter @Getter +public class AutoRoleProfile extends Profile { + /** + * The roles to assign when a user joins + */ + private List roleIds; + + /** + * The maximum amount of roles that can be set + */ + private int maxRoles = 10; + + public AutoRoleProfile() { + super("auto-role"); + } + + /** + * Gets the amount of role slots left + * + * @return the amount + */ + public int getRoleSlotsLeft() { + return maxRoles - getRoles().size(); + } + + /** + * Gets the amount of role slots in use + * + * @return the amount + */ + public int getRoleSlotsInUse() { + return getRoles().size(); + } + + /** + * Adds a role to assign when a user joins + * + * @param roleId the role ID to add + */ + public void addRole(String roleId) { + if (this.roleIds == null) { + this.roleIds = new ArrayList<>(); + } + this.roleIds.add(roleId); + } + + /** + * Removes a role from being assigned when a user joins + * + * @param roleId the role ID to remove + */ + public void removeRole(String roleId) { + if (this.roleIds == null) { + this.roleIds = new ArrayList<>(); + } + this.roleIds.remove(roleId); + } + + public void clearRoles() { + if (this.roleIds == null) { + this.roleIds = new ArrayList<>(); + } + this.roleIds.clear(); + } + + /** + * Checks if a role is set to be assigned when a user joins + * + * @param roleId the role ID to check + * @return whether the role is set + */ + public boolean hasRole(String roleId) { + if (this.roleIds == null) { + this.roleIds = new ArrayList<>(); + } + return this.roleIds.contains(roleId); + } + + /** + * Gets the roles to assign when a user joins + * + * @return the roles + */ + public List getRoles() { + if (this.roleIds == null) { + this.roleIds = new ArrayList<>(); + } + List roles = new ArrayList<>(); + for (String id : this.roleIds) { + Role role = DiscordService.JDA.getRoleById(id); + if (role != null) { + roles.add(role); + } + } + return roles; + } +} diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/NumberOneScoreFeedListener.java b/src/main/java/cc/fascinated/bat/features/scoresaber/NumberOneScoreFeedListener.java index de3f686..4394a56 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/NumberOneScoreFeedListener.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/NumberOneScoreFeedListener.java @@ -5,7 +5,7 @@ import cc.fascinated.bat.common.DateUtils; import cc.fascinated.bat.common.NumberUtils; import cc.fascinated.bat.common.ScoreSaberUtils; import cc.fascinated.bat.event.EventListener; -import cc.fascinated.bat.features.scoresaber.profiles.GuildNumberOneScoreFeedProfile; +import cc.fascinated.bat.features.scoresaber.profile.GuildNumberOneScoreFeedProfile; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberLeaderboardToken; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberPlayerScoreToken; @@ -17,6 +17,7 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -33,8 +34,8 @@ public class NumberOneScoreFeedListener implements EventListener { } @Override - public void onScoresaberScoreReceived(ScoreSaberPlayerScoreToken score, ScoreSaberLeaderboardToken leaderboard, - ScoreSaberScoreToken.LeaderboardPlayerInfo player) { + public void onScoresaberScoreReceived(@NotNull ScoreSaberPlayerScoreToken score, @NotNull ScoreSaberLeaderboardToken leaderboard, + @NotNull ScoreSaberScoreToken.LeaderboardPlayerInfo player) { if (score.getScore().getRank() != 1) { // Only send if the score is a #1 score return; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/UserScoreFeedListener.java b/src/main/java/cc/fascinated/bat/features/scoresaber/UserScoreFeedListener.java index dd7f26a..4711e41 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/UserScoreFeedListener.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/UserScoreFeedListener.java @@ -5,7 +5,7 @@ import cc.fascinated.bat.common.DateUtils; import cc.fascinated.bat.common.NumberUtils; import cc.fascinated.bat.common.ScoreSaberUtils; import cc.fascinated.bat.event.EventListener; -import cc.fascinated.bat.features.scoresaber.profiles.GuildUserScoreFeedProfile; +import cc.fascinated.bat.features.scoresaber.profile.GuildUserScoreFeedProfile; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberLeaderboardToken; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberPlayerScoreToken; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberScoreToken; @@ -17,6 +17,7 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -33,8 +34,8 @@ public class UserScoreFeedListener implements EventListener { } @Override - public void onScoresaberScoreReceived(ScoreSaberPlayerScoreToken score, ScoreSaberLeaderboardToken leaderboard, - ScoreSaberScoreToken.LeaderboardPlayerInfo player) { + public void onScoresaberScoreReceived(@NotNull ScoreSaberPlayerScoreToken score, @NotNull ScoreSaberLeaderboardToken leaderboard, + @NotNull ScoreSaberScoreToken.LeaderboardPlayerInfo player) { for (Guild guild : DiscordService.JDA.getGuilds()) { BatGuild batGuild = guildService.getGuild(guild.getId()); if (batGuild == null) { diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ChannelSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ChannelSubCommand.java index adf3042..71a6648 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ChannelSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ChannelSubCommand.java @@ -3,8 +3,7 @@ package cc.fascinated.bat.features.scoresaber.command.numberone; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.TextChannelUtils; -import cc.fascinated.bat.features.scoresaber.profiles.GuildNumberOneScoreFeedProfile; -import cc.fascinated.bat.features.scoresaber.profiles.GuildUserScoreFeedProfile; +import cc.fascinated.bat.features.scoresaber.profile.GuildNumberOneScoreFeedProfile; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.service.GuildService; @@ -36,24 +35,30 @@ public class ChannelSubCommand extends BatSubCommand { OptionMapping option = interaction.getOption("channel"); if (option == null) { if (!TextChannelUtils.isValidChannel(profile.getChannelId())) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("Please provide a channel to set the ScoreSaber #1 feed channel to").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Please provide a channel to set the ScoreSaber #1 feed channel to") + .build()).queue(); return; } - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("The current ScoreSaber #1 feed channel is %s" - .formatted(TextChannelUtils.getChannelMention(profile.getChannelId()))).build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("The current ScoreSaber #1 feed channel is %s".formatted(TextChannelUtils.getChannelMention(profile.getChannelId()))) + .build()).queue(); return; } GuildChannelUnion targetChannel = option.getAsChannel(); if (targetChannel.getType() != ChannelType.TEXT) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("Invalid channel type, please provide a text channel").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Invalid channel type, please provide a text channel") + .build()).queue(); return; } profile.setChannelId(targetChannel.getId()); guildService.saveGuild(guild); - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("Successfully set the ScoreSaber #1 feed channel to %s" - .formatted(targetChannel.asTextChannel().getAsMention())).build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Successfully set the ScoreSaber #1 feed channel to %s".formatted(targetChannel.asTextChannel().getAsMention())) + .build()).queue(); } } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ClearChannelSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ClearChannelSubCommand.java index 6592798..2b38870 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ClearChannelSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ClearChannelSubCommand.java @@ -2,17 +2,13 @@ package cc.fascinated.bat.features.scoresaber.command.numberone; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.EmbedUtils; -import cc.fascinated.bat.common.TextChannelUtils; -import cc.fascinated.bat.features.scoresaber.profiles.GuildNumberOneScoreFeedProfile; +import cc.fascinated.bat.features.scoresaber.profile.GuildNumberOneScoreFeedProfile; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.service.GuildService; import lombok.NonNull; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; -import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -35,6 +31,8 @@ public class ClearChannelSubCommand extends BatSubCommand { profile.setChannelId(null); guildService.saveGuild(guild); - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("Successfully cleared the ScoreSaber #1 feed channel").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Successfully cleared the ScoreSaber #1 feed channel") + .build()).queue(); } } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/LinkSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/LinkSubCommand.java index 28080a6..4e9aab6 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/LinkSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/LinkSubCommand.java @@ -5,7 +5,7 @@ import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberAccountToken; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatUser; -import cc.fascinated.bat.features.scoresaber.profiles.UserScoreSaberProfile; +import cc.fascinated.bat.features.scoresaber.profile.UserScoreSaberProfile; import cc.fascinated.bat.service.ScoreSaberService; import cc.fascinated.bat.service.UserService; import lombok.NonNull; @@ -34,13 +34,17 @@ public class LinkSubCommand extends BatSubCommand { public void execute(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull TextChannel channel, @NonNull Member member, @NonNull SlashCommandInteraction interaction) { OptionMapping option = interaction.getOption("link"); if (option == null) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("Please provide a ScoreSaber profile link").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Please provide a ScoreSaber profile link") + .build()).queue(); return; } String link = option.getAsString(); if (!link.contains("scoresaber.com/u/")) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("Invalid ScoreSaber profile link").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Invalid ScoreSaber profile link") + .build()).queue(); return; } @@ -51,14 +55,16 @@ public class LinkSubCommand extends BatSubCommand { ScoreSaberAccountToken account = scoreSaberService.getAccount(id); if (account == null) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("Invalid ScoreSaber profile link").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Invalid ScoreSaber profile link") + .build()).queue(); return; } - ((UserScoreSaberProfile) user.getProfile(UserScoreSaberProfile.class)).setId(id); + ((UserScoreSaberProfile) user.getProfile(UserScoreSaberProfile.class)).setSteamId(id); userService.saveUser(user); - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("Successfully linked your [ScoreSaber](%s) profile".formatted( - "https://scoresaber.com/u/%s".formatted(id) - )).build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("Successfully linked your [ScoreSaber](%s) profile".formatted("https://scoresaber.com/u/%s".formatted(id))) + .build()).queue(); } } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ScoreSaberCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ScoreSaberCommand.java index 03ef9af..585f2bb 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ScoreSaberCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ScoreSaberCommand.java @@ -8,7 +8,7 @@ import cc.fascinated.bat.common.NumberUtils; import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberAccountToken; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatUser; -import cc.fascinated.bat.features.scoresaber.profiles.UserScoreSaberProfile; +import cc.fascinated.bat.features.scoresaber.profile.UserScoreSaberProfile; import cc.fascinated.bat.service.ScoreSaberService; import lombok.NonNull; import net.dv8tion.jda.api.EmbedBuilder; @@ -68,23 +68,29 @@ public class ScoreSaberCommand extends BatCommand { */ public static void sendProfileEmbed(boolean isSelf, BatUser user, ScoreSaberService scoreSaberService, SlashCommandInteraction interaction) { UserScoreSaberProfile profile = user.getProfile(UserScoreSaberProfile.class); - if (profile.getId() == null) { + if (profile.getSteamId() == null) { if (!isSelf) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("%s does not have a linked ScoreSaber account" - .formatted(user.getDiscordUser().getAsMention())).build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("%s does not have a linked ScoreSaber account".formatted(user.getDiscordUser().getAsMention())) + .build()).queue(); } - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("You do not have a linked ScoreSaber account").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("You do not have a linked ScoreSaber account") + .build()).queue(); return; } // todo: handle rate limits - ScoreSaberAccountToken account = scoreSaberService.getAccount(profile.getId()); + ScoreSaberAccountToken account = scoreSaberService.getAccount(profile.getSteamId()); if (account == null) { if (!isSelf) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("%s has an invalid ScoreSaber account linked, please ask them to re-link their account" - .formatted(user.getDiscordUser().getAsMention())).build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("%s has an invalid ScoreSaber account linked, please ask them to re-link their account" + .formatted(user.getDiscordUser().getAsMention())) + .build()).queue(); } - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("You have an invalid ScoreSaber account linked, please re-link your account") + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("You have an invalid ScoreSaber account linked, please re-link your account") .build()).queue(); return; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/UserSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/UserSubCommand.java index a6ba180..b977a3f 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/UserSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/UserSubCommand.java @@ -32,18 +32,24 @@ public class UserSubCommand extends BatSubCommand { public void execute(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull TextChannel channel, @NonNull Member member, @NonNull SlashCommandInteraction interaction) { OptionMapping option = interaction.getOption("user"); if (option == null) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("Please provide a user to view the ScoreSaber profile of").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Please provide a user to view the ScoreSaber profile of") + .build()).queue(); return; } if (option.getAsUser().isBot()) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("You cannot view the ScoreSaber profile for a Bot").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("You cannot view the ScoreSaber profile for a Bot") + .build()).queue(); return; } BatUser target = userService.getUser(option.getAsUser().getId()); if (target == null) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("Unknown user").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Unknown user") + .build()).queue(); return; } ScoreSaberCommand.sendProfileEmbed(false, target, scoreSaberService, interaction); diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ChannelSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ChannelSubCommand.java index 4ea6a36..472b221 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ChannelSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ChannelSubCommand.java @@ -4,7 +4,7 @@ import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.TextChannelUtils; import cc.fascinated.bat.model.BatGuild; -import cc.fascinated.bat.features.scoresaber.profiles.GuildUserScoreFeedProfile; +import cc.fascinated.bat.features.scoresaber.profile.GuildUserScoreFeedProfile; import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.service.GuildService; import lombok.NonNull; @@ -35,24 +35,30 @@ public class ChannelSubCommand extends BatSubCommand { OptionMapping option = interaction.getOption("channel"); if (option == null) { if (!TextChannelUtils.isValidChannel(profile.getChannelId())) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("Please provide a channel to set the ScoreSaber feed channel to").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("Please provide a channel to set the ScoreSaber feed channel to") + .build()).queue(); return; } - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("The current ScoreSaber feed channel is %s" - .formatted(TextChannelUtils.getChannelMention(profile.getChannelId()))).build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("The current ScoreSaber feed channel is %s".formatted(TextChannelUtils.getChannelMention(profile.getChannelId()))) + .build()).queue(); return; } GuildChannelUnion targetChannel = option.getAsChannel(); if (targetChannel.getType() != ChannelType.TEXT) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("Invalid channel type, please provide a text channel").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("Invalid channel type, please provide a text channel") + .build()).queue(); return; } profile.setChannelId(targetChannel.getId()); guildService.saveGuild(guild); - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("Successfully set the ScoreSaber feed channel to %s" - .formatted(targetChannel.asTextChannel().getAsMention())).build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("Successfully set the ScoreSaber feed channel to %s".formatted(targetChannel.asTextChannel().getAsMention())) + .build()).queue(); } } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ClearChannelSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ClearChannelSubCommand.java index 46f3729..465beff 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ClearChannelSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ClearChannelSubCommand.java @@ -2,8 +2,7 @@ package cc.fascinated.bat.features.scoresaber.command.userfeed; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.EmbedUtils; -import cc.fascinated.bat.features.scoresaber.profiles.GuildNumberOneScoreFeedProfile; -import cc.fascinated.bat.features.scoresaber.profiles.GuildUserScoreFeedProfile; +import cc.fascinated.bat.features.scoresaber.profile.GuildUserScoreFeedProfile; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.service.GuildService; @@ -32,6 +31,8 @@ public class ClearChannelSubCommand extends BatSubCommand { profile.setChannelId(null); guildService.saveGuild(guild); - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("Successfully cleared the ScoreSaber feed channel").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("Successfully cleared the ScoreSaber feed channel") + .build()).queue(); } } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ClearUsersSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ClearUsersSubCommand.java index 92e627b..7e1bfe8 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ClearUsersSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ClearUsersSubCommand.java @@ -3,10 +3,9 @@ package cc.fascinated.bat.features.scoresaber.command.userfeed; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.model.BatGuild; -import cc.fascinated.bat.features.scoresaber.profiles.GuildUserScoreFeedProfile; +import cc.fascinated.bat.features.scoresaber.profile.GuildUserScoreFeedProfile; import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.service.GuildService; -import cc.fascinated.bat.service.UserService; import lombok.NonNull; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; @@ -32,6 +31,8 @@ public class ClearUsersSubCommand extends BatSubCommand { profile.getTrackedUsers().clear(); guildService.saveGuild(guild); - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("Successfully cleared all users from the ScoreSaber feed").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("Successfully cleared all users from the ScoreSaber feed") + .build()).queue(); } } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserFeedCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserFeedCommand.java index 57d4563..d02d67f 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserFeedCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserFeedCommand.java @@ -14,7 +14,7 @@ import org.springframework.stereotype.Component; /** * @author Fascinated (fascinated7) */ -@Component("scoresaber-userfeed:feed.sub") +@Component("scoresaber-userfeed.command") public class UserFeedCommand extends BatCommand { public UserFeedCommand(@NonNull ApplicationContext context) { super("scoresaber-user-feed"); diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserSubCommand.java index 6fe1788..f331b8a 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserSubCommand.java @@ -3,9 +3,9 @@ package cc.fascinated.bat.features.scoresaber.command.userfeed; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.model.BatGuild; -import cc.fascinated.bat.features.scoresaber.profiles.GuildUserScoreFeedProfile; +import cc.fascinated.bat.features.scoresaber.profile.GuildUserScoreFeedProfile; import cc.fascinated.bat.model.BatUser; -import cc.fascinated.bat.features.scoresaber.profiles.UserScoreSaberProfile; +import cc.fascinated.bat.features.scoresaber.profile.UserScoreSaberProfile; import cc.fascinated.bat.service.GuildService; import cc.fascinated.bat.service.UserService; import lombok.NonNull; @@ -37,7 +37,9 @@ public class UserSubCommand extends BatSubCommand { OptionMapping option = interaction.getOption("user"); if (option == null){ if (profile.getTrackedUsers().isEmpty()) { - interaction.replyEmbeds(EmbedUtils.buildGenericEmbed("There are no users being tracked in the ScoreSaber feed").build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("There are no users being tracked in the ScoreSaber feed") + .build()).queue(); return; } StringBuilder stringBuilder = new StringBuilder(); @@ -47,24 +49,32 @@ public class UserSubCommand extends BatSubCommand { "https://scoresaber.com/u/%s".formatted(accountId) )); } - interaction.replyEmbeds(EmbedUtils.buildGenericEmbed("The current users being tracked in the ScoreSaber feed are:\n%s".formatted(stringBuilder.toString())).build()).queue(); + interaction.replyEmbeds(EmbedUtils.buildGenericEmbed() + .setDescription("The current users being tracked in the ScoreSaber feed are:\n%s".formatted(stringBuilder.toString())) + .build()).queue(); return; } User target = option.getAsUser(); BatUser targetUser = userService.getUser(target.getId()); UserScoreSaberProfile targetProfile = targetUser.getProfile(UserScoreSaberProfile.class); - if (targetProfile.getId() == null) { - interaction.replyEmbeds(EmbedUtils.buildErrorEmbed("The user you are trying to track does not have a linked ScoreSaber profile").build()).queue(); + if (targetProfile.getSteamId() == null) { + interaction.replyEmbeds(EmbedUtils.buildErrorEmbed() + .setDescription("The user you are trying to track does not have a linked ScoreSaber profile") + .build()).queue(); return; } - if (profile.getTrackedUsers().contains(targetProfile.getId())) { - profile.getTrackedUsers().remove(targetProfile.getId()); - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("Successfully removed %s from the ScoreSaber feed".formatted(target.getAsMention())).build()).queue(); + if (profile.getTrackedUsers().contains(targetProfile.getSteamId())) { + profile.getTrackedUsers().remove(targetProfile.getSteamId()); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("Successfully removed %s from the ScoreSaber feed".formatted(target.getAsMention())) + .build()).queue(); } else { - profile.getTrackedUsers().add(targetProfile.getId()); - interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed("Successfully added %s to the ScoreSaber feed".formatted(target.getAsMention())).build()).queue(); + profile.getTrackedUsers().add(targetProfile.getSteamId()); + interaction.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("Successfully added %s to the ScoreSaber feed".formatted(target.getAsMention())) + .build()).queue(); } guildService.saveGuild(guild); } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/profiles/GuildNumberOneScoreFeedProfile.java b/src/main/java/cc/fascinated/bat/features/scoresaber/profile/GuildNumberOneScoreFeedProfile.java similarity index 87% rename from src/main/java/cc/fascinated/bat/features/scoresaber/profiles/GuildNumberOneScoreFeedProfile.java rename to src/main/java/cc/fascinated/bat/features/scoresaber/profile/GuildNumberOneScoreFeedProfile.java index d49a646..cc932fe 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/profiles/GuildNumberOneScoreFeedProfile.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/profile/GuildNumberOneScoreFeedProfile.java @@ -1,4 +1,4 @@ -package cc.fascinated.bat.features.scoresaber.profiles; +package cc.fascinated.bat.features.scoresaber.profile; import cc.fascinated.bat.common.Profile; import cc.fascinated.bat.service.DiscordService; @@ -6,23 +6,20 @@ import lombok.Getter; import lombok.Setter; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import java.util.ArrayList; -import java.util.List; - /** * @author Fascinated (fascinated7) */ @Getter @Setter public class GuildNumberOneScoreFeedProfile extends Profile { - public GuildNumberOneScoreFeedProfile() { - super("scoresaber-number-one-score-feed"); - } - /** * The channel ID of the score feed */ private String channelId; + public GuildNumberOneScoreFeedProfile() { + super("scoresaber-number-one-score-feed"); + } + /** * Gets the channel as a TextChannel * diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/profiles/GuildUserScoreFeedProfile.java b/src/main/java/cc/fascinated/bat/features/scoresaber/profile/GuildUserScoreFeedProfile.java similarity index 96% rename from src/main/java/cc/fascinated/bat/features/scoresaber/profiles/GuildUserScoreFeedProfile.java rename to src/main/java/cc/fascinated/bat/features/scoresaber/profile/GuildUserScoreFeedProfile.java index aaeccc4..6571904 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/profiles/GuildUserScoreFeedProfile.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/profile/GuildUserScoreFeedProfile.java @@ -1,4 +1,4 @@ -package cc.fascinated.bat.features.scoresaber.profiles; +package cc.fascinated.bat.features.scoresaber.profile; import cc.fascinated.bat.common.Profile; import cc.fascinated.bat.service.DiscordService; @@ -14,10 +14,6 @@ import java.util.List; */ @Getter @Setter public class GuildUserScoreFeedProfile extends Profile { - public GuildUserScoreFeedProfile() { - super("scoresaber-user-score-feed"); - } - /** * The channel ID of the score feed */ @@ -28,6 +24,10 @@ public class GuildUserScoreFeedProfile extends Profile { */ private List trackedUsers; + public GuildUserScoreFeedProfile() { + super("scoresaber-user-score-feed"); + } + /** * Gets the tracked users * diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/profiles/UserScoreSaberProfile.java b/src/main/java/cc/fascinated/bat/features/scoresaber/profile/UserScoreSaberProfile.java similarity index 80% rename from src/main/java/cc/fascinated/bat/features/scoresaber/profiles/UserScoreSaberProfile.java rename to src/main/java/cc/fascinated/bat/features/scoresaber/profile/UserScoreSaberProfile.java index eca6493..e26edfb 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/profiles/UserScoreSaberProfile.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/profile/UserScoreSaberProfile.java @@ -1,4 +1,4 @@ -package cc.fascinated.bat.features.scoresaber.profiles; +package cc.fascinated.bat.features.scoresaber.profile; import cc.fascinated.bat.common.Profile; import lombok.Getter; @@ -12,7 +12,7 @@ public class UserScoreSaberProfile extends Profile { /** * The Account ID of the ScoreSaber profile */ - private String id; + private String steamId; public UserScoreSaberProfile() { super("scoresaber"); diff --git a/src/main/java/cc/fascinated/bat/service/CommandService.java b/src/main/java/cc/fascinated/bat/service/CommandService.java index 3d715e4..68fecd6 100644 --- a/src/main/java/cc/fascinated/bat/service/CommandService.java +++ b/src/main/java/cc/fascinated/bat/service/CommandService.java @@ -4,6 +4,7 @@ import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.impl.PingCommand; import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.features.autorole.command.AutoRoleCommand; import cc.fascinated.bat.features.scoresaber.command.numberone.NumberOneFeedCommand; import cc.fascinated.bat.features.scoresaber.command.scoresaber.ScoreSaberCommand; import cc.fascinated.bat.features.scoresaber.command.userfeed.UserFeedCommand; @@ -56,6 +57,7 @@ public class CommandService extends ListenerAdapter { // Guild commands registerCommand(context.getBean(UserFeedCommand.class)); registerCommand(context.getBean(NumberOneFeedCommand.class)); + registerCommand(context.getBean(AutoRoleCommand.class)); // Global commands registerCommand(context.getBean(ScoreSaberCommand.class)); @@ -127,8 +129,10 @@ public class CommandService extends ListenerAdapter { } } catch (Exception ex) { log.error("An error occurred while executing command \"{}\"", commandName, ex); - event.replyEmbeds(EmbedUtils.buildErrorEmbed("An error occurred while executing the command\n\n" + - ex.getLocalizedMessage()).build()).queue(); + + event.replyEmbeds(EmbedUtils.buildSuccessEmbed() + .setDescription("An error occurred while executing the command\n\n" + ex.getLocalizedMessage()) + .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 a19137a..4e89a3a 100644 --- a/src/main/java/cc/fascinated/bat/service/DiscordService.java +++ b/src/main/java/cc/fascinated/bat/service/DiscordService.java @@ -36,7 +36,8 @@ public class DiscordService { ) throws Exception { JDA = JDABuilder.createLight(token, EnumSet.of( GatewayIntent.GUILD_MESSAGES, - GatewayIntent.MESSAGE_CONTENT + GatewayIntent.MESSAGE_CONTENT, + GatewayIntent.GUILD_MEMBERS )).build() .awaitReady(); TimerUtils.scheduleRepeating(this::updateActivity, 0, 1000 * 60 * 2); diff --git a/src/main/java/cc/fascinated/bat/service/EventService.java b/src/main/java/cc/fascinated/bat/service/EventService.java index 8e3eb3a..d9965a2 100644 --- a/src/main/java/cc/fascinated/bat/service/EventService.java +++ b/src/main/java/cc/fascinated/bat/service/EventService.java @@ -1,12 +1,20 @@ package cc.fascinated.bat.service; import cc.fascinated.bat.event.EventListener; +import cc.fascinated.bat.features.autorole.AutoRoleListener; import cc.fascinated.bat.features.scoresaber.NumberOneScoreFeedListener; import cc.fascinated.bat.features.scoresaber.UserScoreFeedListener; +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.events.guild.member.GuildMemberJoinEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Service; import java.util.HashSet; @@ -16,17 +24,26 @@ import java.util.Set; * @author Fascinated (fascinated7) */ @Service @Log4j2 -public class EventService { +@DependsOn("discordService") +public class EventService extends ListenerAdapter { + private final GuildService guildService; + private final UserService userService; + /** * The list of listeners registered */ public static final Set LISTENERS = new HashSet<>(); @Autowired - public EventService(@NonNull ApplicationContext context) { + public EventService(@NonNull GuildService guildService, @NonNull UserService userService, @NonNull ApplicationContext context) { + this.guildService = guildService; + this.userService = userService; + DiscordService.JDA.addEventListener(this); + registerListeners( context.getBean(UserScoreFeedListener.class), - context.getBean(NumberOneScoreFeedListener.class) + context.getBean(NumberOneScoreFeedListener.class), + context.getBean(AutoRoleListener.class) ); log.info("Registered {} listeners.", LISTENERS.size()); } @@ -39,4 +56,14 @@ public class EventService { public void registerListeners(EventListener... listener) { LISTENERS.addAll(Set.of(listener)); } + + @Override + public void onGuildMemberJoin(@NotNull GuildMemberJoinEvent event) { + BatGuild guild = guildService.getGuild(event.getGuild().getId()); + BatUser user = userService.getUser(event.getUser().getId()); + + for (EventListener listener : LISTENERS) { + listener.onGuildMemberJoin(guild, user, event); + } + } } diff --git a/src/main/java/cc/fascinated/bat/service/ScoreSaberService.java b/src/main/java/cc/fascinated/bat/service/ScoreSaberService.java index 5783708..a976d4d 100644 --- a/src/main/java/cc/fascinated/bat/service/ScoreSaberService.java +++ b/src/main/java/cc/fascinated/bat/service/ScoreSaberService.java @@ -6,8 +6,7 @@ import cc.fascinated.bat.common.WebRequest; import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.exception.BadRequestException; import cc.fascinated.bat.exception.ResourceNotFoundException; -import cc.fascinated.bat.model.beatsaber.scoresaber.*; -import cc.fascinated.bat.features.scoresaber.profiles.UserScoreSaberProfile; +import cc.fascinated.bat.features.scoresaber.profile.UserScoreSaberProfile; import cc.fascinated.bat.model.token.beatsaber.scoresaber.*; import com.google.gson.JsonObject; import lombok.NonNull; @@ -67,8 +66,8 @@ public class ScoreSaberService extends TextWebSocketHandler { * @return The scores. */ public ScoreSaberScoresPageToken getPageScores(UserScoreSaberProfile profile, int page) { - log.info("Fetching scores for account '{}' from page {}.", profile.getId(), page); - ScoreSaberScoresPageToken pageToken = WebRequest.getAsEntity(String.format(GET_PLAYER_SCORES_ENDPOINT, profile.getId(), "recent", page), ScoreSaberScoresPageToken.class); + log.info("Fetching scores for account '{}' from page {}.", profile.getSteamId(), page); + ScoreSaberScoresPageToken pageToken = WebRequest.getAsEntity(String.format(GET_PLAYER_SCORES_ENDPOINT, profile.getSteamId(), "recent", page), ScoreSaberScoresPageToken.class); if (pageToken == null) { // Check if the page doesn't exist. return null; } @@ -89,7 +88,7 @@ public class ScoreSaberService extends TextWebSocketHandler { List scores = new ArrayList<>(List.of(getPageScores(profile, 1))); ScoreSaberPageMetadataToken metadata = scores.get(0).getMetadata(); int totalPages = (int) Math.ceil((double) metadata.getTotal() / metadata.getItemsPerPage()); - log.info("Fetching {} pages of scores for account '{}'.", totalPages, profile.getId()); + log.info("Fetching {} pages of scores for account '{}'.", totalPages, profile.getSteamId()); for (int i = 2; i <= totalPages; i++) { scores.add(getPageScores(profile, i)); }