package cc.fascinated.bat.service; import cc.fascinated.bat.common.TimerUtils; import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatUser; import com.mongodb.client.model.Filters; import lombok.Getter; import lombok.NonNull; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; import net.dv8tion.jda.api.events.user.update.UserUpdateGlobalNameEvent; import org.bson.Document; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; /** * @author Fascinated (fascinated7) */ @Service @Log4j2(topic = "User Service") @Getter @DependsOn({"discordService", "mongoService"}) public class UserService implements EventListener { private static final long SAVE_INTERVAL = TimeUnit.MINUTES.toMillis(5); /** * The cached users */ private final Map users = new HashMap<>(); @Autowired public UserService() { TimerUtils.scheduleRepeating(() -> { long before = System.currentTimeMillis(); for (BatUser user : users.values()) { user.save(); } log.info("Saved {} users in {}ms", users.size(), System.currentTimeMillis() - before); }, SAVE_INTERVAL, SAVE_INTERVAL); } /** * Gets a user by its ID * * @param id The ID of the user * @return The user */ public BatUser getUser(@NonNull String id) { long before = System.currentTimeMillis(); // User is cached if (users.containsKey(id)) { return users.get(id); } User user = DiscordService.JDA.getUserById(id); if (user == null) { log.warn("Attempted to get user with ID \"{}\" but they do not exist", id); return null; } if (user.isBot()) { log.warn("Attempted to get user with ID \"{}\" but they are a bot", id); return null; } // User is not cached Document document = MongoService.INSTANCE.getUsersCollection().find(Filters.eq("_id", id)).first(); if (document != null) { BatUser batUser = new BatUser(id, document); users.put(id, batUser); log.info("Loaded user \"{}\" in {}ms", batUser.getName(),System.currentTimeMillis() - before); return batUser; } // New user BatUser batUser = new BatUser(id, new Document()); users.put(id, batUser); log.info("Created user \"{}\" - \"{}\"", batUser.getName(), batUser.getId()); return batUser; } @Override public void onShutdown() { log.info("Saving all users before shutdown..."); for (BatUser user : users.values()) { user.save(); } log.info("Saved all users."); } @Override public void onGuildMemberJoin(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull GuildMemberJoinEvent event) { user.setGlobalName(event.getUser().getGlobalName()); // Ensure the user's name is up-to-date } @Override public void onUserUpdateGlobalName(@NonNull BatUser user, String oldName, String newName, @NonNull UserUpdateGlobalNameEvent event) { user.setGlobalName(newName); } }