From 50391e53449ac3d371b5272b2c769c8456bad0ba Mon Sep 17 00:00:00 2001 From: Liam Date: Sun, 30 Jun 2024 03:36:00 +0100 Subject: [PATCH] add name history tracking --- .../cc/fascinated/bat/common/Profile.java | 5 +- .../fascinated/bat/event/EventListener.java | 23 +++++ .../birthday/command/MessageSubCommand.java | 4 - .../birthday/command/ViewSubCommand.java | 1 - .../namehistory/NameHistoryFeature.java | 17 ++++ .../namehistory/NameHistoryListener.java | 43 ++++++++++ .../bat/features/namehistory/TrackedName.java | 22 +++++ .../namehistory/command/GuildSubCommand.java | 62 +++++++++++++ .../command/NameHistoryCommand.java | 21 +++++ .../namehistory/command/UserSubCommand.java | 59 +++++++++++++ .../profile/guild/NameHistoryProfile.java | 78 +++++++++++++++++ .../profile/user/NameHistoryProfile.java | 75 ++++++++++++++++ .../BirthdayProfileChangelog.java | 2 +- ...oresaberProfileRenamePackageChangelog.java | 86 +++++++++++++++++++ .../cc/fascinated/bat/model/BatGuild.java | 10 +++ .../java/cc/fascinated/bat/model/BatUser.java | 12 ++- .../fascinated/bat/service/EventService.java | 27 ++++++ 17 files changed, 537 insertions(+), 10 deletions(-) create mode 100644 src/main/java/cc/fascinated/bat/features/namehistory/NameHistoryFeature.java create mode 100644 src/main/java/cc/fascinated/bat/features/namehistory/NameHistoryListener.java create mode 100644 src/main/java/cc/fascinated/bat/features/namehistory/TrackedName.java create mode 100644 src/main/java/cc/fascinated/bat/features/namehistory/command/GuildSubCommand.java create mode 100644 src/main/java/cc/fascinated/bat/features/namehistory/command/NameHistoryCommand.java create mode 100644 src/main/java/cc/fascinated/bat/features/namehistory/command/UserSubCommand.java create mode 100644 src/main/java/cc/fascinated/bat/features/namehistory/profile/guild/NameHistoryProfile.java create mode 100644 src/main/java/cc/fascinated/bat/features/namehistory/profile/user/NameHistoryProfile.java rename src/main/java/cc/fascinated/bat/migrations/{ => changelogs}/BirthdayProfileChangelog.java (96%) create mode 100644 src/main/java/cc/fascinated/bat/migrations/changelogs/ScoresaberProfileRenamePackageChangelog.java diff --git a/src/main/java/cc/fascinated/bat/common/Profile.java b/src/main/java/cc/fascinated/bat/common/Profile.java index 79e0624..fb23c1d 100644 --- a/src/main/java/cc/fascinated/bat/common/Profile.java +++ b/src/main/java/cc/fascinated/bat/common/Profile.java @@ -2,12 +2,14 @@ package cc.fascinated.bat.common; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; /** * @author Fascinated (fascinated7) */ @AllArgsConstructor +@NoArgsConstructor @Getter @Setter public abstract class Profile { @@ -16,9 +18,6 @@ public abstract class Profile { */ private String profileKey; - public Profile() { - } - /** * Resets the profile */ diff --git a/src/main/java/cc/fascinated/bat/event/EventListener.java b/src/main/java/cc/fascinated/bat/event/EventListener.java index e6caa6f..699d0e4 100644 --- a/src/main/java/cc/fascinated/bat/event/EventListener.java +++ b/src/main/java/cc/fascinated/bat/event/EventListener.java @@ -8,10 +8,12 @@ import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberScoreToken; import lombok.NonNull; import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; +import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent; import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.user.update.UserUpdateGlobalNameEvent; /** * @author Fascinated (fascinated7) @@ -81,4 +83,25 @@ public interface EventListener { */ default void onModalInteraction(BatGuild guild, @NonNull BatUser user, @NonNull ModalInteractionEvent event) { } + + /** + * Called when a user updates their global name + * + * @param user the user that updated their global name + * @param oldName the old global name + * @param newName the new global name + */ + default void onUserUpdateGlobalName(@NonNull BatUser user, String oldName, String newName, @NonNull UserUpdateGlobalNameEvent event) { + } + + /** + * Called when a user updates their nickname in a guild + * + * @param guild the guild that the user updated their nickname in + * @param user the user that updated their nickname + * @param oldName the old nickname + * @param newName the new nickname + */ + default void onGuildMemberUpdateNickname(@NonNull BatGuild guild, @NonNull BatUser user, String oldName, String newName, @NonNull GuildMemberUpdateNicknameEvent event) { + } } diff --git a/src/main/java/cc/fascinated/bat/features/birthday/command/MessageSubCommand.java b/src/main/java/cc/fascinated/bat/features/birthday/command/MessageSubCommand.java index 2b9edde..4963396 100644 --- a/src/main/java/cc/fascinated/bat/features/birthday/command/MessageSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/birthday/command/MessageSubCommand.java @@ -17,10 +17,6 @@ import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - /** * @author Fascinated (fascinated7) diff --git a/src/main/java/cc/fascinated/bat/features/birthday/command/ViewSubCommand.java b/src/main/java/cc/fascinated/bat/features/birthday/command/ViewSubCommand.java index 0f55487..3e0a945 100644 --- a/src/main/java/cc/fascinated/bat/features/birthday/command/ViewSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/birthday/command/ViewSubCommand.java @@ -7,7 +7,6 @@ import cc.fascinated.bat.features.birthday.UserBirthday; import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.model.BatGuild; 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; diff --git a/src/main/java/cc/fascinated/bat/features/namehistory/NameHistoryFeature.java b/src/main/java/cc/fascinated/bat/features/namehistory/NameHistoryFeature.java new file mode 100644 index 0000000..555efa6 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/namehistory/NameHistoryFeature.java @@ -0,0 +1,17 @@ +package cc.fascinated.bat.features.namehistory; + +import cc.fascinated.bat.command.Category; +import cc.fascinated.bat.features.Feature; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component +public class NameHistoryFeature extends Feature { + public static final int NAME_HISTORY_SIZE = 25; + + public NameHistoryFeature() { + super("Name History", Category.UTILITY); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/namehistory/NameHistoryListener.java b/src/main/java/cc/fascinated/bat/features/namehistory/NameHistoryListener.java new file mode 100644 index 0000000..2bbe3b1 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/namehistory/NameHistoryListener.java @@ -0,0 +1,43 @@ +package cc.fascinated.bat.features.namehistory; + +import cc.fascinated.bat.event.EventListener; +import cc.fascinated.bat.features.namehistory.profile.user.NameHistoryProfile; +import cc.fascinated.bat.model.BatGuild; +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.events.guild.member.update.GuildMemberUpdateNicknameEvent; +import net.dv8tion.jda.api.events.user.update.UserUpdateGlobalNameEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component +public class NameHistoryListener implements EventListener { + private final UserService userService; + private final GuildService guildService; + + @Autowired + public NameHistoryListener(@NonNull UserService userService, @NonNull GuildService guildService) { + this.userService = userService; + this.guildService = guildService; + } + + @Override + public void onUserUpdateGlobalName(@NonNull BatUser user, String oldName, String newName, @NonNull UserUpdateGlobalNameEvent event) { + NameHistoryProfile profile = user.getNameHistoryProfile(); + profile.addName(newName); + userService.saveUser(user); + } + + @Override + public void onGuildMemberUpdateNickname(@NonNull BatGuild guild, @NonNull BatUser user, String oldName, String newName, + @NonNull GuildMemberUpdateNicknameEvent event) { + cc.fascinated.bat.features.namehistory.profile.guild.NameHistoryProfile profile = guild.getNameHistoryProfile(); + profile.addName(user, newName); + guildService.saveGuild(guild); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/namehistory/TrackedName.java b/src/main/java/cc/fascinated/bat/features/namehistory/TrackedName.java new file mode 100644 index 0000000..b30728c --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/namehistory/TrackedName.java @@ -0,0 +1,22 @@ +package cc.fascinated.bat.features.namehistory; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Date; + +/** + * @author Fascinated (fascinated7) + */ +@AllArgsConstructor @Getter +public class TrackedName { + /** + * The new name of the user + */ + private final String name; + + /** + * The date the name was changed + */ + private final Date changedDate; +} diff --git a/src/main/java/cc/fascinated/bat/features/namehistory/command/GuildSubCommand.java b/src/main/java/cc/fascinated/bat/features/namehistory/command/GuildSubCommand.java new file mode 100644 index 0000000..9802f3b --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/namehistory/command/GuildSubCommand.java @@ -0,0 +1,62 @@ +package cc.fascinated.bat.features.namehistory.command; + +import cc.fascinated.bat.command.BatSubCommand; +import cc.fascinated.bat.command.CommandInfo; +import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.features.namehistory.TrackedName; +import cc.fascinated.bat.features.namehistory.profile.guild.NameHistoryProfile; +import cc.fascinated.bat.model.BatGuild; +import cc.fascinated.bat.model.BatUser; +import cc.fascinated.bat.service.UserService; +import lombok.NonNull; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component("namehistory:guild.sub") +@CommandInfo(name = "guild", description = "View the guild nickname history of a user") +public class GuildSubCommand extends BatSubCommand { + private final UserService userService; + + @Autowired + public GuildSubCommand(@NonNull UserService userService) { + this.userService = userService; + super.addOption(OptionType.USER, "user", "The user to view the name history of", false); + } + + @Override + public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) { + OptionMapping userOption = interaction.getOption("user"); + BatUser target = userOption == null ? user : userService.getUser(userOption.getAsUser().getId()); + if (target == null) { + channel.sendMessage("User not found").queue(); + return; + } + + NameHistoryProfile profile = guild.getNameHistoryProfile(); + StringBuilder builder = new StringBuilder(); + if (profile.getNameHistory(target).isEmpty()) { + builder.append("%s has no name history".formatted(target.getDiscordUser().getAsMention())); + } else { + for (TrackedName trackedName : profile.getNameHistorySorted(target)) { + builder.append("%s - \n".formatted( + trackedName.getName() == null ? "Removed Nickname" : "`%s`".formatted(trackedName.getName()), + trackedName.getChangedDate().toInstant().toEpochMilli()/1000 + )); + } + } + + interaction.replyEmbeds(EmbedUtils.genericEmbed() + .setAuthor("%s's Nickname History in %s".formatted(target.getName(), guild.getName())) + .setDescription(builder.toString()) + .build() + ).queue(); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/namehistory/command/NameHistoryCommand.java b/src/main/java/cc/fascinated/bat/features/namehistory/command/NameHistoryCommand.java new file mode 100644 index 0000000..65b24d2 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/namehistory/command/NameHistoryCommand.java @@ -0,0 +1,21 @@ +package cc.fascinated.bat.features.namehistory.command; + +import cc.fascinated.bat.command.BatCommand; +import cc.fascinated.bat.command.CommandInfo; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component +@CommandInfo(name = "namehistory", description = "View the name history of a user") +public class NameHistoryCommand extends BatCommand { + @Autowired + public NameHistoryCommand(@NonNull ApplicationContext context) { + super.addSubCommand(context.getBean(UserSubCommand.class)); + super.addSubCommand(context.getBean(GuildSubCommand.class)); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/namehistory/command/UserSubCommand.java b/src/main/java/cc/fascinated/bat/features/namehistory/command/UserSubCommand.java new file mode 100644 index 0000000..70bd8c9 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/namehistory/command/UserSubCommand.java @@ -0,0 +1,59 @@ +package cc.fascinated.bat.features.namehistory.command; + +import cc.fascinated.bat.command.BatSubCommand; +import cc.fascinated.bat.command.CommandInfo; +import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.features.namehistory.TrackedName; +import cc.fascinated.bat.features.namehistory.profile.user.NameHistoryProfile; +import cc.fascinated.bat.model.BatGuild; +import cc.fascinated.bat.model.BatUser; +import cc.fascinated.bat.service.UserService; +import lombok.NonNull; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component("namehistory:user.sub") +@CommandInfo(name = "user", description = "View the global name history of a user", guildOnly = false) +public class UserSubCommand extends BatSubCommand { + private final UserService userService; + + @Autowired + public UserSubCommand(@NonNull UserService userService) { + this.userService = userService; + super.addOption(OptionType.USER, "user", "The user to view the name history of", false); + } + + @Override + public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) { + OptionMapping userOption = interaction.getOption("user"); + BatUser target = userOption == null ? user : userService.getUser(userOption.getAsUser().getId()); + if (target == null) { + channel.sendMessage("User not found").queue(); + return; + } + + NameHistoryProfile profile = target.getNameHistoryProfile(); + StringBuilder builder = new StringBuilder(); + if (profile.getNameHistory().isEmpty()) { + builder.append("%s has no name history".formatted(target.getDiscordUser().getAsMention())); + } else { + for (TrackedName trackedName : profile.getNameHistorySorted()) { + builder.append("`%s` - \n".formatted(trackedName.getName(), trackedName.getChangedDate().toInstant().toEpochMilli()/1000)); + } + } + + interaction.replyEmbeds(EmbedUtils.genericEmbed() + .setAuthor("%s's Global Name History".formatted(target.getName())) + .setDescription(builder.toString()) + .build() + ).queue(); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/namehistory/profile/guild/NameHistoryProfile.java b/src/main/java/cc/fascinated/bat/features/namehistory/profile/guild/NameHistoryProfile.java new file mode 100644 index 0000000..01e0df9 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/namehistory/profile/guild/NameHistoryProfile.java @@ -0,0 +1,78 @@ +package cc.fascinated.bat.features.namehistory.profile.guild; + +import cc.fascinated.bat.common.Profile; +import cc.fascinated.bat.features.namehistory.NameHistoryFeature; +import cc.fascinated.bat.features.namehistory.TrackedName; +import cc.fascinated.bat.model.BatUser; + +import java.util.*; + +/** + * @author Fascinated (fascinated7) + */ +public class NameHistoryProfile extends Profile { + private Map> nameHistory; + + public NameHistoryProfile() { + super("name-history"); + } + + /** + * Gets the name history of the user + * + * @param user the user to get the name history of + * @return the name history of the user + */ + public List getNameHistory(BatUser user) { + if (this.nameHistory == null) { + this.nameHistory = new HashMap<>(); + } + if (!this.nameHistory.containsKey(user.getId())) { + this.nameHistory.put(user.getId(), new LinkedList<>()); + } + return this.nameHistory.get(user.getId()); + } + + /** + * Gets the name history of the user sorted + * + * @param user the user to get the name history of + * @return the name history of the user sorted + */ + public List getNameHistorySorted(BatUser user) { + return getNameHistory(user).stream().sorted((o1, o2) -> o2.getChangedDate().compareTo(o1.getChangedDate())).toList(); + } + + /** + * Adds a name to the name history + * + * @param user the user to add the name to + * @param name the name to add + */ + public void addName(BatUser user, String name) { + getNameHistory(user).add(new TrackedName(name, new Date())); + cleanup(); + } + + /** + * Cleans up the name history + *

+ * This will remove any names that are not within + * the size limit of the name history + *

+ */ + private void cleanup() { + for (String userId : this.nameHistory.keySet()) { + List trackedNames = this.nameHistory.get(userId); + if (trackedNames.size() > NameHistoryFeature.NAME_HISTORY_SIZE) { + trackedNames.sort((o1, o2) -> o2.getChangedDate().compareTo(o1.getChangedDate())); + trackedNames.subList(NameHistoryFeature.NAME_HISTORY_SIZE, trackedNames.size()).clear(); + } + } + } + + @Override + public void reset() { + this.nameHistory = null; + } +} diff --git a/src/main/java/cc/fascinated/bat/features/namehistory/profile/user/NameHistoryProfile.java b/src/main/java/cc/fascinated/bat/features/namehistory/profile/user/NameHistoryProfile.java new file mode 100644 index 0000000..2048a10 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/namehistory/profile/user/NameHistoryProfile.java @@ -0,0 +1,75 @@ +package cc.fascinated.bat.features.namehistory.profile.user; + +import cc.fascinated.bat.common.Profile; +import cc.fascinated.bat.features.namehistory.NameHistoryFeature; +import cc.fascinated.bat.features.namehistory.TrackedName; + +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +/** + * @author Fascinated (fascinated7) + */ +public class NameHistoryProfile extends Profile { + private List nameHistory; + + public NameHistoryProfile() { + super("name-history"); + } + + /** + * Gets the name history of the user + * + * @return the name history of the user + */ + public List getNameHistory() { + if (this.nameHistory == null) { + this.nameHistory = new LinkedList<>(); + } + return nameHistory; + } + + /** + * Gets the name history of the user sorted + * + * @return the name history of the user sorted + */ + public List getNameHistorySorted() { + return getNameHistory().stream().sorted((o1, o2) -> o2.getChangedDate().compareTo(o1.getChangedDate())).toList(); + } + + /** + * Adds a name to the name history + * + * @param name the name to add + */ + public void addName(String name) { + if (this.nameHistory == null) { + this.nameHistory = new LinkedList<>(); + } + this.nameHistory.add(new TrackedName(name, new Date())); + cleanup(); + } + + /** + * Cleans up the name history + *

+ * This will remove any names that are not within + * the size limit of the name history + *

+ */ + private void cleanup() { + if (this.nameHistory.size() > NameHistoryFeature.NAME_HISTORY_SIZE) { + List trackedNames = new ArrayList<>(this.nameHistory); + trackedNames.sort((o1, o2) -> o2.getChangedDate().compareTo(o1.getChangedDate())); + this.nameHistory = trackedNames.subList(0, NameHistoryFeature.NAME_HISTORY_SIZE); + } + } + + @Override + public void reset() { + this.nameHistory = null; + } +} diff --git a/src/main/java/cc/fascinated/bat/migrations/BirthdayProfileChangelog.java b/src/main/java/cc/fascinated/bat/migrations/changelogs/BirthdayProfileChangelog.java similarity index 96% rename from src/main/java/cc/fascinated/bat/migrations/BirthdayProfileChangelog.java rename to src/main/java/cc/fascinated/bat/migrations/changelogs/BirthdayProfileChangelog.java index 2413a8a..77f2d99 100644 --- a/src/main/java/cc/fascinated/bat/migrations/BirthdayProfileChangelog.java +++ b/src/main/java/cc/fascinated/bat/migrations/changelogs/BirthdayProfileChangelog.java @@ -1,4 +1,4 @@ -package cc.fascinated.bat.migrations; +package cc.fascinated.bat.migrations.changelogs; import com.mongodb.client.FindIterable; import io.mongock.api.annotations.ChangeUnit; diff --git a/src/main/java/cc/fascinated/bat/migrations/changelogs/ScoresaberProfileRenamePackageChangelog.java b/src/main/java/cc/fascinated/bat/migrations/changelogs/ScoresaberProfileRenamePackageChangelog.java new file mode 100644 index 0000000..eeec163 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/migrations/changelogs/ScoresaberProfileRenamePackageChangelog.java @@ -0,0 +1,86 @@ +package cc.fascinated.bat.migrations.changelogs; + +import com.mongodb.client.FindIterable; +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; +import org.bson.Document; +import org.springframework.data.mongodb.core.MongoTemplate; + +/** + * @author Fascinated (fascinated7) + */ +@ChangeUnit(id = "scoresaber-profile-rename-package-changelog", order = "001", author = "fascinated7") +public class ScoresaberProfileRenamePackageChangelog { + private final MongoTemplate mongoTemplate; + + public ScoresaberProfileRenamePackageChangelog(MongoTemplate mongoTemplate) { + this.mongoTemplate = mongoTemplate; + } + + @Execution + public void changeSet() { + FindIterable guilds = mongoTemplate.getCollection("guilds").find(); + guilds.forEach(guild -> { + Document profiles = guild.get("profiles", Document.class); + if (profiles == null) { + return; + } + + // NumberOneScoreFeedProfile + Document numberOneScoreFeedProfile = profiles.get("scoresaber-number-one-score-feed", Document.class); + if (numberOneScoreFeedProfile == null) { + return; + } + numberOneScoreFeedProfile.put("_class", "cc.fascinated.bat.features.scoresaber.profile.guild.NumberOneScoreFeedProfile"); + profiles.put("scoresaber-number-one-score-feed", numberOneScoreFeedProfile); + + guild.put("profiles", profiles); + mongoTemplate.getCollection("guilds").replaceOne(new Document("_id", guild.get("_id")), guild); + }); + + guilds.forEach(guild -> { + Document profiles = guild.get("profiles", Document.class); + if (profiles == null) { + return; + } + + // UserScoreFeedProfile + Document userScoreFeedProfile = profiles.get("scoresaber-number-one-score-feed", Document.class); + if (userScoreFeedProfile == null) { + return; + } + + userScoreFeedProfile.put("_class", "cc.fascinated.bat.features.scoresaber.profile.guild.UserScoreFeedProfile"); + profiles.put("scoresaber-user-score-feed", userScoreFeedProfile); + + guild.put("profiles", profiles); + mongoTemplate.getCollection("guilds").replaceOne(new Document("_id", guild.get("_id")), guild); + }); + + FindIterable users = mongoTemplate.getCollection("users").find(); + users.forEach(guild -> { + Document profiles = guild.get("profiles", Document.class); + if (profiles == null) { + return; + } + + // ScoreSaberProfile + Document userScoreFeedProfile = profiles.get("scoresaber", Document.class); + if (userScoreFeedProfile == null) { + return; + } + + userScoreFeedProfile.put("_class", "cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile"); + profiles.put("scoresaber", userScoreFeedProfile); + + guild.put("profiles", profiles); + mongoTemplate.getCollection("users").replaceOne(new Document("_id", guild.get("_id")), guild); + }); + } + + @RollbackExecution + public void rollback() { + // DO NOTHING + } +} \ No newline at end of file diff --git a/src/main/java/cc/fascinated/bat/model/BatGuild.java b/src/main/java/cc/fascinated/bat/model/BatGuild.java index c80a008..ebf1558 100644 --- a/src/main/java/cc/fascinated/bat/model/BatGuild.java +++ b/src/main/java/cc/fascinated/bat/model/BatGuild.java @@ -1,6 +1,7 @@ package cc.fascinated.bat.model; import cc.fascinated.bat.common.ProfileHolder; +import cc.fascinated.bat.features.namehistory.profile.guild.NameHistoryProfile; import cc.fascinated.bat.service.DiscordService; import lombok.*; import net.dv8tion.jda.api.entities.Guild; @@ -65,6 +66,15 @@ public class BatGuild extends ProfileHolder { return DiscordService.JDA.getGuildById(id); } + /** + * Gets the user's name history profile + * + * @return the user's name history profile + */ + public NameHistoryProfile getNameHistoryProfile() { + return getProfile(NameHistoryProfile.class); + } + @AllArgsConstructor @Getter @Setter diff --git a/src/main/java/cc/fascinated/bat/model/BatUser.java b/src/main/java/cc/fascinated/bat/model/BatUser.java index c14b7d6..830b6ee 100644 --- a/src/main/java/cc/fascinated/bat/model/BatUser.java +++ b/src/main/java/cc/fascinated/bat/model/BatUser.java @@ -1,6 +1,7 @@ package cc.fascinated.bat.model; import cc.fascinated.bat.common.ProfileHolder; +import cc.fascinated.bat.features.namehistory.profile.user.NameHistoryProfile; import cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile; import cc.fascinated.bat.service.DiscordService; import lombok.Getter; @@ -37,7 +38,7 @@ public class BatUser extends ProfileHolder { * The name of the user */ public String getName() { - return getDiscordUser().getName(); + return getDiscordUser().getEffectiveName(); } /** @@ -57,4 +58,13 @@ public class BatUser extends ProfileHolder { public ScoreSaberProfile getScoreSaberProfile() { return getProfile(ScoreSaberProfile.class); } + + /** + * Gets the user's name history profile + * + * @return the user's name history profile + */ + public NameHistoryProfile getNameHistoryProfile() { + return getProfile(NameHistoryProfile.class); + } } diff --git a/src/main/java/cc/fascinated/bat/service/EventService.java b/src/main/java/cc/fascinated/bat/service/EventService.java index 77a104c..9a456fa 100644 --- a/src/main/java/cc/fascinated/bat/service/EventService.java +++ b/src/main/java/cc/fascinated/bat/service/EventService.java @@ -7,10 +7,12 @@ import lombok.NonNull; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; +import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent; import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.user.update.UserUpdateGlobalNameEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; @@ -131,4 +133,29 @@ public class EventService extends ListenerAdapter { listener.onModalInteraction(guild, user, event); } } + + @Override + public void onUserUpdateGlobalName(@NotNull UserUpdateGlobalNameEvent event) { + if (event.getUser().isBot()) { + return; + } + BatUser user = userService.getUser(event.getUser().getId()); + + for (EventListener listener : LISTENERS) { + listener.onUserUpdateGlobalName(user, event.getOldGlobalName(), event.getNewGlobalName(), event); + } + } + + @Override + public void onGuildMemberUpdateNickname(@NotNull GuildMemberUpdateNicknameEvent event) { + if (event.getUser().isBot()) { + return; + } + BatGuild guild = guildService.getGuild(event.getGuild().getId()); + BatUser user = userService.getUser(event.getUser().getId()); + + for (EventListener listener : LISTENERS) { + listener.onGuildMemberUpdateNickname(guild, user, event.getOldNickname(), event.getNewNickname(), event); + } + } }