big ass refactor to handle loading guilds and users without spring to make it more futureproof
All checks were successful
Deploy to Dokku / docker (ubuntu-latest) (push) Successful in 44s
All checks were successful
Deploy to Dokku / docker (ubuntu-latest) (push) Successful in 44s
This commit is contained in:
parent
f566c3bcb5
commit
d372c41c98
@ -1,25 +0,0 @@
|
||||
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 {
|
||||
/**
|
||||
* The key of the profile.
|
||||
*/
|
||||
private String profileKey;
|
||||
|
||||
/**
|
||||
* Resets the profile
|
||||
*/
|
||||
public abstract void reset();
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
package cc.fascinated.bat.common;
|
||||
|
||||
import cc.fascinated.bat.BatApplication;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -9,11 +12,11 @@ import java.util.Map;
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Getter
|
||||
public class ProfileHolder {
|
||||
public abstract class ProfileHolder {
|
||||
/**
|
||||
* The profiles for the holder
|
||||
*/
|
||||
private Map<String, Profile> profiles;
|
||||
private final Map<String, Serializable> profiles = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Gets a profile for the holder
|
||||
@ -22,19 +25,25 @@ public class ProfileHolder {
|
||||
* @param <T> The type of the profile
|
||||
* @return The profile
|
||||
*/
|
||||
public <T extends Profile> T getProfile(Class<T> clazz) {
|
||||
if (profiles == null) {
|
||||
profiles = new HashMap<>();
|
||||
}
|
||||
public abstract <T extends Serializable> T getProfile(Class<T> clazz);
|
||||
|
||||
Profile profile = profiles.values().stream().filter(clazz::isInstance).findFirst().orElse(null);
|
||||
/**
|
||||
* Gets the profiles for the holder
|
||||
* using the provided document
|
||||
*
|
||||
* @return the profiles
|
||||
*/
|
||||
@SneakyThrows
|
||||
protected <T extends Serializable> T getProfileFromDocument(Class<T> clazz, Document document) {
|
||||
Serializable profile = getProfiles().get(clazz.getSimpleName());
|
||||
if (profile == null) {
|
||||
try {
|
||||
profile = clazz.newInstance();
|
||||
profiles.put(profile.getProfileKey(), profile);
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
T newProfile = clazz.cast(clazz.getDeclaredConstructors()[0].newInstance());
|
||||
org.bson.Document profiles = document.get("profiles", new org.bson.Document());
|
||||
org.bson.Document profileDocument = (org.bson.Document) profiles.getOrDefault(clazz.getSimpleName(), new org.bson.Document());
|
||||
|
||||
newProfile.load(profileDocument, BatApplication.GSON);
|
||||
getProfiles().put(clazz.getSimpleName(), newProfile);
|
||||
return newProfile;
|
||||
}
|
||||
return clazz.cast(profile);
|
||||
}
|
||||
|
36
src/main/java/cc/fascinated/bat/common/Serializable.java
Normal file
36
src/main/java/cc/fascinated/bat/common/Serializable.java
Normal file
@ -0,0 +1,36 @@
|
||||
package cc.fascinated.bat.common;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public abstract class Serializable {
|
||||
/**
|
||||
* Load data from the provided document into this profile
|
||||
*
|
||||
* @param document the document to load data from
|
||||
* @param gson the GSON instance to use
|
||||
*/
|
||||
public abstract void load(Document document, Gson gson);
|
||||
|
||||
/**
|
||||
* Serialize this profile into a Bson document
|
||||
*
|
||||
* @param gson the GSON instance to use
|
||||
* @return the serialized document
|
||||
*/
|
||||
public abstract Document serialize(Gson gson);
|
||||
|
||||
/**
|
||||
* Resets the profile to its default state
|
||||
*/
|
||||
public abstract void reset();
|
||||
}
|
@ -4,10 +4,8 @@ import cc.fascinated.bat.event.EventListener;
|
||||
import cc.fascinated.bat.features.afk.profile.AfkProfile;
|
||||
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.events.message.MessageReceivedEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@ -15,13 +13,6 @@ import org.springframework.stereotype.Component;
|
||||
*/
|
||||
@Component
|
||||
public class AfkReturnListener implements EventListener {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public AfkReturnListener(@NonNull GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuildMessageReceive(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull MessageReceivedEvent event) {
|
||||
AfkProfile profile = guild.getProfile(AfkProfile.class);
|
||||
@ -29,7 +20,6 @@ public class AfkReturnListener implements EventListener {
|
||||
return;
|
||||
}
|
||||
profile.removeAfkUser(guild, user.getId());
|
||||
guildService.saveGuild(guild);
|
||||
event.getMessage().reply("Welcome back, %s! You are no longer AFK.".formatted(user.getDiscordUser().getAsMention())).queue();
|
||||
}
|
||||
}
|
||||
|
@ -6,14 +6,12 @@ import cc.fascinated.bat.common.MemberUtils;
|
||||
import cc.fascinated.bat.features.afk.profile.AfkProfile;
|
||||
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.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;
|
||||
|
||||
/**
|
||||
@ -22,11 +20,7 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
@CommandInfo(name = "afk", description = "Sets your AFK status")
|
||||
public class AfkCommand extends BatCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public AfkCommand(@NonNull GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
public AfkCommand() {
|
||||
super.addOption(OptionType.STRING, "reason", "The reason for being AFK", false);
|
||||
}
|
||||
|
||||
@ -40,7 +34,6 @@ public class AfkCommand extends BatCommand {
|
||||
}
|
||||
|
||||
profile.addAfkUser(guild, member.getId(), reason);
|
||||
guildService.saveGuild(guild);
|
||||
interaction.reply("You are now AFK: %s%s".formatted(
|
||||
profile.getAfkReason(member.getId()),
|
||||
MemberUtils.hasPermissionToEdit(guild, user) ? "" :
|
||||
|
@ -1,9 +1,12 @@
|
||||
package cc.fascinated.bat.features.afk.profile;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.NoArgsConstructor;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.bson.Document;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -13,7 +16,8 @@ import java.util.Map;
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Component
|
||||
public class AfkProfile extends Profile {
|
||||
@NoArgsConstructor
|
||||
public class AfkProfile extends Serializable {
|
||||
private static final String DEFAULT_REASON = "Away";
|
||||
|
||||
/**
|
||||
@ -21,10 +25,6 @@ public class AfkProfile extends Profile {
|
||||
*/
|
||||
private Map<String, String> afkUsers;
|
||||
|
||||
public AfkProfile() {
|
||||
super("afk");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a user to the AFK list
|
||||
*
|
||||
@ -102,4 +102,21 @@ public class AfkProfile extends Profile {
|
||||
public void reset() {
|
||||
afkUsers = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
afkUsers = new HashMap<>();
|
||||
for (String key : document.keySet()) {
|
||||
afkUsers.put(key, document.getString(key));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
for (String key : afkUsers.keySet()) {
|
||||
document.put(key, afkUsers.get(key));
|
||||
}
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import cc.fascinated.bat.common.RoleUtils;
|
||||
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;
|
||||
@ -24,12 +23,9 @@ import org.springframework.stereotype.Component;
|
||||
@Component("autoroles:add.sub")
|
||||
@CommandInfo(name = "add", description = "Adds a role to the auto roles list")
|
||||
public class AddSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public AddSubCommand(@NonNull GuildService guildService) {
|
||||
public AddSubCommand() {
|
||||
super.addOption(OptionType.ROLE, "role", "The role to add", true);
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,7 +76,6 @@ public class AddSubCommand extends BatSubCommand {
|
||||
|
||||
// Add the role to the auto roles list
|
||||
profile.addRole(role.getId());
|
||||
guildService.saveGuild(guild);
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("You have added %s to the auto roles list".formatted(role.getAsMention()))
|
||||
.build()).queue();
|
||||
|
@ -6,12 +6,10 @@ 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.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@ -20,19 +18,11 @@ import org.springframework.stereotype.Component;
|
||||
@Component("autoroles:clear.sub")
|
||||
@CommandInfo(name = "clear", description = "Clears all auto roles")
|
||||
public class ClearSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public ClearSubCommand(GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);
|
||||
|
||||
profile.reset();
|
||||
guildService.saveGuild(guild);
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully cleared all auto roles")
|
||||
.build()).queue();
|
||||
|
@ -6,7 +6,6 @@ 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;
|
||||
@ -23,12 +22,9 @@ import org.springframework.stereotype.Component;
|
||||
@Component("autoroles:remove.sub")
|
||||
@CommandInfo(name = "remove", description = "Removes a role from the auto roles list")
|
||||
public class RemoveSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public RemoveSubCommand(GuildService guildService) {
|
||||
public RemoveSubCommand() {
|
||||
super.addOption(OptionType.ROLE, "role", "The role to remove", true);
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -51,7 +47,6 @@ public class RemoveSubCommand extends BatSubCommand {
|
||||
}
|
||||
|
||||
profile.removeRole(role.getId());
|
||||
guildService.saveGuild(guild);
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully removed the role %s from the auto roles list".formatted(role.getAsMention()))
|
||||
.build()).queue();
|
||||
|
@ -1,11 +1,14 @@
|
||||
package cc.fascinated.bat.features.autorole.profile;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.service.DiscordService;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -15,7 +18,8 @@ import java.util.List;
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class AutoRoleProfile extends Profile {
|
||||
@NoArgsConstructor
|
||||
public class AutoRoleProfile extends Serializable {
|
||||
private static final int DEFAULT_MAX_ROLES = 10;
|
||||
private static final int PREMIUM_MAX_ROLES = 25;
|
||||
|
||||
@ -24,10 +28,6 @@ public class AutoRoleProfile extends Profile {
|
||||
*/
|
||||
private List<String> roleIds;
|
||||
|
||||
public AutoRoleProfile() {
|
||||
super("auto-role");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum amount of roles that can be set in the guild
|
||||
*
|
||||
@ -35,7 +35,7 @@ public class AutoRoleProfile extends Profile {
|
||||
* @return the amount of role slots
|
||||
*/
|
||||
public static int getMaxRoleSlots(BatGuild guild) {
|
||||
if (guild.getPremium().hasPremium()) {
|
||||
if (guild.getPremiumProfile().hasPremium()) {
|
||||
return PREMIUM_MAX_ROLES;
|
||||
}
|
||||
return DEFAULT_MAX_ROLES;
|
||||
@ -110,4 +110,16 @@ public class AutoRoleProfile extends Profile {
|
||||
public void reset() {
|
||||
roleIds.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
roleIds = document.getList("roleIds", String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
document.put("roleIds", roleIds);
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cc.fascinated.bat.command.BatSubCommand;
|
||||
import cc.fascinated.bat.command.CommandInfo;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import cc.fascinated.bat.premium.PremiumProfile;
|
||||
import cc.fascinated.bat.service.GuildService;
|
||||
import lombok.NonNull;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
@ -41,14 +42,13 @@ public class RemoveSubCommand extends BatSubCommand {
|
||||
interaction.reply("The guild with the id %s does not exist".formatted(guildId)).queue();
|
||||
return;
|
||||
}
|
||||
BatGuild.Premium premium = batGuild.getPremium();
|
||||
PremiumProfile premium = batGuild.getPremiumProfile();
|
||||
if (!premium.hasPremium()) {
|
||||
interaction.reply("The guild does not have premium").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
premium.removePremium();
|
||||
guildService.saveGuild(batGuild);
|
||||
interaction.reply("The guild **%s** has had its premium removed".formatted(guild.getName())).queue();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cc.fascinated.bat.command.BatSubCommand;
|
||||
import cc.fascinated.bat.command.CommandInfo;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import cc.fascinated.bat.premium.PremiumProfile;
|
||||
import cc.fascinated.bat.service.GuildService;
|
||||
import lombok.NonNull;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
@ -23,7 +24,7 @@ public class SetSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public SetSubCommand(GuildService guildService) {
|
||||
public SetSubCommand(@NonNull GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
super.addOption(OptionType.STRING, "guild", "The guild id to set as premium", true);
|
||||
super.addOption(OptionType.BOOLEAN, "infinite", "Whether the premium length should be infinite", true);
|
||||
@ -49,13 +50,12 @@ public class SetSubCommand extends BatSubCommand {
|
||||
interaction.reply("The guild with the id %s does not exist".formatted(guildId)).queue();
|
||||
return;
|
||||
}
|
||||
BatGuild.Premium premium = batGuild.getPremium();
|
||||
PremiumProfile premium = batGuild.getPremiumProfile();
|
||||
if (!infinite) {
|
||||
premium.addTime();
|
||||
} else {
|
||||
premium.addInfiniteTime();
|
||||
}
|
||||
guildService.saveGuild(batGuild);
|
||||
if (!infinite) {
|
||||
interaction.reply("The guild **%s** has been set as premium until <t:%s>".formatted(guild.getName(), premium.getExpiresAt().toInstant().toEpochMilli() / 1000)).queue();
|
||||
} else {
|
||||
|
@ -5,6 +5,7 @@ import cc.fascinated.bat.command.CommandInfo;
|
||||
import cc.fascinated.bat.common.EmbedUtils;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import cc.fascinated.bat.premium.PremiumProfile;
|
||||
import lombok.NonNull;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
@ -21,7 +22,7 @@ import org.springframework.stereotype.Component;
|
||||
public class PremiumCommand extends BatCommand {
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
BatGuild.Premium premium = guild.getPremium();
|
||||
PremiumProfile premium = guild.getPremiumProfile();
|
||||
EmbedBuilder embed = EmbedUtils.genericEmbed().setAuthor("Premium Information");
|
||||
if (premium.hasPremium()) {
|
||||
embed.addField("Premium", premium.hasPremium() ? "Yes" : "No", true);
|
||||
|
@ -8,7 +8,6 @@ import cc.fascinated.bat.features.base.profile.FeatureProfile;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import cc.fascinated.bat.service.FeatureService;
|
||||
import cc.fascinated.bat.service.GuildService;
|
||||
import lombok.NonNull;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
@ -24,11 +23,8 @@ import org.springframework.stereotype.Component;
|
||||
@Component("feature:disable.sub")
|
||||
@CommandInfo(name = "disable", description = "Disables a feature")
|
||||
public class DisableSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public DisableSubCommand(@NonNull GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
public DisableSubCommand() {
|
||||
super.addOption(OptionType.STRING, "feature", "The feature to disable", true);
|
||||
}
|
||||
|
||||
@ -52,15 +48,14 @@ public class DisableSubCommand extends BatSubCommand {
|
||||
Feature feature = FeatureService.INSTANCE.getFeature(featureName);
|
||||
if (featureProfile.isFeatureDisabled(feature)) {
|
||||
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||
.setDescription("The feature `%s` is already enabled".formatted(feature.getName()))
|
||||
.setDescription("The feature `%s` is already disabled".formatted(feature.getName()))
|
||||
.build()).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
featureProfile.disableFeature(feature);
|
||||
guildService.saveGuild(guild);
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully enabled the `%s` feature".formatted(feature.getName()))
|
||||
.setDescription("Successfully disabled the `%s` feature".formatted(feature.getName()))
|
||||
.build()).queue();
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import cc.fascinated.bat.features.base.profile.FeatureProfile;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import cc.fascinated.bat.service.FeatureService;
|
||||
import cc.fascinated.bat.service.GuildService;
|
||||
import lombok.NonNull;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
@ -24,11 +23,8 @@ import org.springframework.stereotype.Component;
|
||||
@Component("feature:enable.sub")
|
||||
@CommandInfo(name = "enable", description = "Enables a feature")
|
||||
public class EnableSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public EnableSubCommand(@NonNull GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
public EnableSubCommand() {
|
||||
super.addOption(OptionType.STRING, "feature", "The feature to enable", true);
|
||||
}
|
||||
|
||||
@ -58,7 +54,6 @@ public class EnableSubCommand extends BatSubCommand {
|
||||
}
|
||||
|
||||
featureProfile.enableFeature(feature);
|
||||
guildService.saveGuild(guild);
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully enabled the `%s` feature".formatted(feature.getName()))
|
||||
.build()).queue();
|
||||
|
@ -1,9 +1,12 @@
|
||||
package cc.fascinated.bat.features.base.profile;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import cc.fascinated.bat.features.Feature;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -11,7 +14,8 @@ import java.util.Map;
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
public class FeatureProfile extends Profile {
|
||||
@NoArgsConstructor
|
||||
public class FeatureProfile extends Serializable {
|
||||
private static final FeatureState DEFAULT_STATE = FeatureState.ENABLED;
|
||||
|
||||
/**
|
||||
@ -19,19 +23,12 @@ public class FeatureProfile extends Profile {
|
||||
*/
|
||||
private Map<String, FeatureState> featureStates;
|
||||
|
||||
public FeatureProfile() {
|
||||
super("feature");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the feature states
|
||||
*
|
||||
* @return the feature states
|
||||
*/
|
||||
public FeatureState getFeatureState(Feature feature) {
|
||||
if (this.featureStates == null) {
|
||||
this.featureStates = new HashMap<>();
|
||||
}
|
||||
if (feature == null) {
|
||||
return DEFAULT_STATE;
|
||||
}
|
||||
@ -85,9 +82,6 @@ public class FeatureProfile extends Profile {
|
||||
* @param state the state to set
|
||||
*/
|
||||
public void setFeatureState(Feature feature, FeatureState state) {
|
||||
if (this.featureStates == null) {
|
||||
this.featureStates = new HashMap<>();
|
||||
}
|
||||
this.featureStates.put(feature.getName().toUpperCase(), state);
|
||||
}
|
||||
|
||||
@ -96,6 +90,23 @@ public class FeatureProfile extends Profile {
|
||||
this.featureStates = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.featureStates = new HashMap<>();
|
||||
for (String key : document.keySet()) {
|
||||
this.featureStates.put(key, FeatureState.valueOf(document.getString(key)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
for (String key : this.featureStates.keySet()) {
|
||||
document.put(key, this.featureStates.get(key).name());
|
||||
}
|
||||
return document;
|
||||
}
|
||||
|
||||
@AllArgsConstructor @Getter
|
||||
public enum FeatureState {
|
||||
ENABLED(":white_check_mark:"),
|
||||
@ -104,6 +115,6 @@ public class FeatureProfile extends Profile {
|
||||
/**
|
||||
* The emoji for the feature state
|
||||
*/
|
||||
private String emoji;
|
||||
private final String emoji;
|
||||
}
|
||||
}
|
||||
|
@ -31,9 +31,8 @@ public class BirthdayFeature extends Feature implements EventListener {
|
||||
|
||||
@Override
|
||||
public void onGuildMemberLeave(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull GuildMemberRemoveEvent event) {
|
||||
BirthdayProfile profile = guild.getProfile(BirthdayProfile.class);
|
||||
BirthdayProfile profile = guild.getBirthdayProfile();
|
||||
profile.removeBirthday(user.getId());
|
||||
guildService.saveGuild(guild);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,8 +40,8 @@ public class BirthdayFeature extends Feature implements EventListener {
|
||||
*/
|
||||
@Scheduled(cron = "0 1 0 * * *")
|
||||
private void checkBirthdays() {
|
||||
for (BatGuild guild : guildService.getAllGuilds()) {
|
||||
BirthdayProfile profile = guild.getProfile(BirthdayProfile.class);
|
||||
for (BatGuild guild : guildService.getGuilds().values()) {
|
||||
BirthdayProfile profile = guild.getBirthdayProfile();
|
||||
profile.checkBirthdays(guild);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package cc.fascinated.bat.features.birthday;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
@ -11,11 +12,9 @@ import java.util.Date;
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserBirthday {
|
||||
public class UserBirthday extends Serializable {
|
||||
/**
|
||||
* The user's birthday
|
||||
*/
|
||||
@ -43,4 +42,23 @@ public class UserBirthday {
|
||||
}
|
||||
return age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.birthday = document.getDate("birthday");
|
||||
this.hidden = document.getBoolean("hidden", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
document.put("birthday", this.birthday);
|
||||
document.put("hidden", this.hidden);
|
||||
return document;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import cc.fascinated.bat.common.TextChannelUtils;
|
||||
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 lombok.NonNull;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
@ -26,17 +25,14 @@ import org.springframework.stereotype.Component;
|
||||
@Component("birthday:channel.sub")
|
||||
@CommandInfo(name = "channel", description = "Sets the birthday notification channel", requiredPermissions = Permission.MANAGE_SERVER)
|
||||
public class ChannelSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public ChannelSubCommand(GuildService guildService) {
|
||||
public ChannelSubCommand() {
|
||||
super.addOption(OptionType.CHANNEL, "channel", "The channel birthdays will be sent in", false);
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
BirthdayProfile profile = guild.getProfile(BirthdayProfile.class);
|
||||
BirthdayProfile profile = guild.getBirthdayProfile();
|
||||
OptionMapping option = interaction.getOption("channel");
|
||||
if (option == null) {
|
||||
if (!TextChannelUtils.isValidChannel(profile.getChannelId())) {
|
||||
@ -60,8 +56,6 @@ public class ChannelSubCommand extends BatSubCommand {
|
||||
}
|
||||
|
||||
profile.setChannelId(targetChannel.getId());
|
||||
guildService.saveGuild(guild);
|
||||
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully set the birthday channel to %s".formatted(targetChannel.asTextChannel().getAsMention()))
|
||||
.build()).queue();
|
||||
|
@ -6,7 +6,6 @@ import cc.fascinated.bat.common.EmbedUtils;
|
||||
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 lombok.NonNull;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
@ -24,17 +23,14 @@ import org.springframework.stereotype.Component;
|
||||
@Component("birthday:message.sub")
|
||||
@CommandInfo(name = "message", description = "Changes the message that is sent when it is a user's birthday", requiredPermissions = Permission.MANAGE_SERVER)
|
||||
public class MessageSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public MessageSubCommand(GuildService guildService) {
|
||||
public MessageSubCommand() {
|
||||
super.addOption(OptionType.STRING, "message", "The message that is sent. (Placeholders: {user}, {age})", true);
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
BirthdayProfile profile = guild.getProfile(BirthdayProfile.class);
|
||||
BirthdayProfile profile = guild.getBirthdayProfile();
|
||||
OptionMapping messageOption = interaction.getOption("message");
|
||||
if (messageOption == null) {
|
||||
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||
@ -58,7 +54,6 @@ public class MessageSubCommand extends BatSubCommand {
|
||||
}
|
||||
|
||||
profile.setMessage(message);
|
||||
guildService.saveGuild(guild);
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("You have updated the birthday message!\n\n**Message:** %s".formatted(profile.getBirthdayMessage(user.getDiscordUser())))
|
||||
.build()).queue();
|
||||
|
@ -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 lombok.NonNull;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
@ -24,17 +23,14 @@ import org.springframework.stereotype.Component;
|
||||
@Component("birthday:private.sub")
|
||||
@CommandInfo(name = "private", description = "Changes whether your birthday is private or not")
|
||||
public class PrivateSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public PrivateSubCommand(@NonNull GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
public PrivateSubCommand() {
|
||||
super.addOption(OptionType.BOOLEAN, "enabled", "Whether your birthday is private or not", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
BirthdayProfile profile = guild.getProfile(BirthdayProfile.class);
|
||||
BirthdayProfile profile = guild.getBirthdayProfile();
|
||||
OptionMapping enabledOption = interaction.getOption("enabled");
|
||||
if (enabledOption == null) {
|
||||
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||
@ -53,8 +49,6 @@ public class PrivateSubCommand extends BatSubCommand {
|
||||
}
|
||||
|
||||
birthday.setHidden(enabled);
|
||||
guildService.saveGuild(guild);
|
||||
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Your birthday privacy settings have been updated\n\n**Private:** " + (enabled ? "Yes" : "No"))
|
||||
.build()).queue();
|
||||
|
@ -6,12 +6,10 @@ import cc.fascinated.bat.common.EmbedUtils;
|
||||
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 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.SlashCommandInteraction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@ -21,20 +19,11 @@ import org.springframework.stereotype.Component;
|
||||
@Component("birthday:remove.sub")
|
||||
@CommandInfo(name = "remove", description = "Remove your birthday from this guild")
|
||||
public class RemoveSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public RemoveSubCommand(GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
BirthdayProfile profile = guild.getProfile(BirthdayProfile.class);
|
||||
BirthdayProfile profile = guild.getBirthdayProfile();
|
||||
|
||||
profile.removeBirthday(user.getId());
|
||||
guildService.saveGuild(guild);
|
||||
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Your birthday has been removed from this guild")
|
||||
.build()).queue();
|
||||
|
@ -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 lombok.NonNull;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
@ -29,17 +28,15 @@ import java.util.Date;
|
||||
@CommandInfo(name = "set", description = "Add your birthday to this guild")
|
||||
public class SetSubCommand extends BatSubCommand {
|
||||
private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd/MM/yyyy");
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public SetSubCommand(GuildService guildService) {
|
||||
public SetSubCommand() {
|
||||
super.addOption(OptionType.STRING, "birthday", "Your birthday (format: DAY/MONTH/YEAR - 01/05/2004)", true);
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
BirthdayProfile profile = guild.getProfile(BirthdayProfile.class);
|
||||
BirthdayProfile profile = guild.getBirthdayProfile();
|
||||
if (!profile.hasChannelSetup()) {
|
||||
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||
.setDescription("Birthdays have not been enabled in this guild. Please ask an administrator to enable them.")
|
||||
@ -66,9 +63,10 @@ public class SetSubCommand extends BatSubCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
profile.addBirthday(member.getId(), new UserBirthday(birthday, false));
|
||||
guildService.saveGuild(guild);
|
||||
|
||||
UserBirthday userBirthday = new UserBirthday();
|
||||
userBirthday.setBirthday(birthday);
|
||||
userBirthday.setHidden(false);
|
||||
profile.addBirthday(member.getId(), userBirthday);
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("You have updated your birthday!")
|
||||
.build()).queue();
|
||||
|
@ -34,7 +34,7 @@ public class ViewSubCommand extends BatSubCommand {
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
BirthdayProfile profile = guild.getProfile(BirthdayProfile.class);
|
||||
BirthdayProfile profile = guild.getBirthdayProfile();
|
||||
if (!profile.hasChannelSetup()) {
|
||||
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||
.setDescription("Birthdays have not been enabled in this guild. Please ask an administrator to enable them.")
|
||||
|
@ -1,14 +1,17 @@
|
||||
package cc.fascinated.bat.features.birthday.profile;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import cc.fascinated.bat.features.birthday.UserBirthday;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -17,7 +20,8 @@ import java.util.*;
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class BirthdayProfile extends Profile {
|
||||
@NoArgsConstructor
|
||||
public class BirthdayProfile extends Serializable {
|
||||
private static final String DEFAULT_MESSAGE = "Happy Birthday {user} :tada: :birthday: You are now {age} years old!";
|
||||
|
||||
/**
|
||||
@ -35,10 +39,6 @@ public class BirthdayProfile extends Profile {
|
||||
*/
|
||||
private String message = DEFAULT_MESSAGE;
|
||||
|
||||
public BirthdayProfile() {
|
||||
super("birthday");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a birthday to be tracked
|
||||
*
|
||||
@ -202,4 +202,27 @@ public class BirthdayProfile extends Profile {
|
||||
birthdays.clear();
|
||||
channelId = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
birthdays = new HashMap<>();
|
||||
for (String key : document.keySet()) {
|
||||
UserBirthday userBirthday = new UserBirthday();
|
||||
userBirthday.load((Document) document.get(key), gson);
|
||||
birthdays.put(key, userBirthday);
|
||||
}
|
||||
channelId = document.getString("channelId");
|
||||
message = (String) document.getOrDefault("message", DEFAULT_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
for (String key : birthdays.keySet()) {
|
||||
document.put(key, birthdays.get(key).serialize(gson));
|
||||
}
|
||||
document.put("channelId", channelId);
|
||||
document.put("message", message);
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import cc.fascinated.bat.service.FeatureService;
|
||||
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;
|
||||
@ -18,13 +17,11 @@ import org.springframework.stereotype.Component;
|
||||
*/
|
||||
@Component
|
||||
public class NameHistoryListener implements EventListener {
|
||||
private final UserService userService;
|
||||
private final GuildService guildService;
|
||||
private final FeatureService featureService;
|
||||
|
||||
@Autowired
|
||||
public NameHistoryListener(@NonNull UserService userService, @NonNull GuildService guildService, @NonNull FeatureService featureService) {
|
||||
this.userService = userService;
|
||||
public NameHistoryListener(@NonNull GuildService guildService, @NonNull FeatureService featureService) {
|
||||
this.guildService = guildService;
|
||||
this.featureService = featureService;
|
||||
}
|
||||
@ -33,7 +30,6 @@ public class NameHistoryListener implements EventListener {
|
||||
public void onUserUpdateGlobalName(@NonNull BatUser user, String oldName, String newName, @NonNull UserUpdateGlobalNameEvent event) {
|
||||
NameHistoryProfile profile = user.getNameHistoryProfile();
|
||||
profile.addName(newName);
|
||||
userService.saveUser(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -46,6 +42,5 @@ public class NameHistoryListener implements EventListener {
|
||||
|
||||
cc.fascinated.bat.features.namehistory.profile.guild.NameHistoryProfile profile = guild.getNameHistoryProfile();
|
||||
profile.addName(user, newName);
|
||||
guildService.saveGuild(guild);
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,42 @@
|
||||
package cc.fascinated.bat.features.namehistory;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@AllArgsConstructor @Getter
|
||||
public class TrackedName {
|
||||
@Getter @Setter
|
||||
public class TrackedName extends Serializable {
|
||||
/**
|
||||
* The new name of the user
|
||||
*/
|
||||
private final String name;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The date the name was changed
|
||||
*/
|
||||
private final Date changedDate;
|
||||
private Date changedDate;
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.name = document.getString("name");
|
||||
this.changedDate = document.getDate("changedDate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
document.put("name", this.name);
|
||||
document.put("changedDate", this.changedDate);
|
||||
return document;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {}
|
||||
}
|
||||
|
@ -1,22 +1,25 @@
|
||||
package cc.fascinated.bat.features.namehistory.profile.guild;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import cc.fascinated.bat.features.namehistory.NameHistoryFeature;
|
||||
import cc.fascinated.bat.features.namehistory.TrackedName;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
public class NameHistoryProfile extends Profile {
|
||||
@NoArgsConstructor
|
||||
public class NameHistoryProfile extends Serializable {
|
||||
/**
|
||||
* The name history of the user
|
||||
*/
|
||||
private Map<String, List<TrackedName>> nameHistory;
|
||||
|
||||
public NameHistoryProfile() {
|
||||
super("name-history");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name history of the user
|
||||
*
|
||||
@ -50,7 +53,10 @@ public class NameHistoryProfile extends Profile {
|
||||
* @param name the name to add
|
||||
*/
|
||||
public void addName(BatUser user, String name) {
|
||||
getNameHistory(user).add(new TrackedName(name, new Date()));
|
||||
TrackedName trackedName = new TrackedName();
|
||||
trackedName.setName(name);
|
||||
trackedName.setChangedDate(new Date());
|
||||
getNameHistory(user).add(trackedName);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@ -75,4 +81,31 @@ public class NameHistoryProfile extends Profile {
|
||||
public void reset() {
|
||||
this.nameHistory = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.nameHistory = new HashMap<>();
|
||||
for (String key : document.keySet()) {
|
||||
List<TrackedName> trackedNames = new LinkedList<>();
|
||||
for (Document trackedNameDocument : (List<Document>) document.get(key)) {
|
||||
TrackedName trackedName = new TrackedName();
|
||||
trackedName.load(trackedNameDocument, gson);
|
||||
trackedNames.add(trackedName);
|
||||
}
|
||||
this.nameHistory.put(key, trackedNames);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
for (String key : this.nameHistory.keySet()) {
|
||||
List<Document> trackedNames = new LinkedList<>();
|
||||
for (TrackedName trackedName : this.nameHistory.get(key)) {
|
||||
trackedNames.add(trackedName.serialize(gson));
|
||||
}
|
||||
document.put(key, trackedNames);
|
||||
}
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
package cc.fascinated.bat.features.namehistory.profile.user;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import cc.fascinated.bat.features.namehistory.NameHistoryFeature;
|
||||
import cc.fascinated.bat.features.namehistory.TrackedName;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
@ -12,13 +15,13 @@ import java.util.List;
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
public class NameHistoryProfile extends Profile {
|
||||
@NoArgsConstructor
|
||||
public class NameHistoryProfile extends Serializable {
|
||||
/**
|
||||
* The name history of the user
|
||||
*/
|
||||
private List<TrackedName> nameHistory;
|
||||
|
||||
public NameHistoryProfile() {
|
||||
super("name-history");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name history of the user
|
||||
*
|
||||
@ -49,7 +52,10 @@ public class NameHistoryProfile extends Profile {
|
||||
if (this.nameHistory == null) {
|
||||
this.nameHistory = new LinkedList<>();
|
||||
}
|
||||
this.nameHistory.add(new TrackedName(name, new Date()));
|
||||
TrackedName trackedName = new TrackedName();
|
||||
trackedName.setName(name);
|
||||
trackedName.setChangedDate(new Date());
|
||||
this.nameHistory.add(trackedName);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@ -72,4 +78,29 @@ public class NameHistoryProfile extends Profile {
|
||||
public void reset() {
|
||||
this.nameHistory = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.nameHistory = new LinkedList<>();
|
||||
for (Document trackedNameDocument : document.getList("nameHistory", Document.class)) {
|
||||
TrackedName trackedName = new TrackedName();
|
||||
trackedName.load(trackedNameDocument, gson);
|
||||
|
||||
this.nameHistory.add(trackedName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
List<Document> trackedNames = new ArrayList<>();
|
||||
for (TrackedName trackedName : this.nameHistory) {
|
||||
Document trackedNameDocument = new Document();
|
||||
trackedNameDocument.put("name", trackedName.getName());
|
||||
trackedNameDocument.put("changedDate", trackedName.getChangedDate());
|
||||
trackedNames.add(trackedNameDocument);
|
||||
}
|
||||
document.put("nameHistory", trackedNames);
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,6 @@ public class NumberOneScoreFeedListener implements EventListener {
|
||||
if (channel == null) {
|
||||
log.error("Scoresaber user feed channel is null for guild {}, removing the stored channel.", guild.getId());
|
||||
profile.setChannelId(null);
|
||||
guildService.saveGuild(batGuild);
|
||||
continue;
|
||||
}
|
||||
channel.sendMessageEmbeds(ScoreSaberFeature.buildScoreEmbed(score)).queue();
|
||||
|
@ -53,7 +53,6 @@ public class UserScoreFeedListener implements EventListener {
|
||||
if (channel == null) {
|
||||
log.error("Scoresaber user feed channel is null for guild {}, removing the stored channel.", guild.getId());
|
||||
profile.setChannelId(null);
|
||||
guildService.saveGuild(batGuild);
|
||||
continue;
|
||||
}
|
||||
channel.sendMessageEmbeds(ScoreSaberFeature.buildScoreEmbed(score)).queue();
|
||||
|
@ -7,7 +7,6 @@ import cc.fascinated.bat.common.TextChannelUtils;
|
||||
import cc.fascinated.bat.features.scoresaber.profile.guild.NumberOneScoreFeedProfile;
|
||||
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;
|
||||
@ -25,12 +24,9 @@ import org.springframework.stereotype.Component;
|
||||
@Component("scoresaber-number-one-feed:channel.sub")
|
||||
@CommandInfo(name = "channel", description = "Sets the feed channel")
|
||||
public class ChannelSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public ChannelSubCommand(GuildService guildService) {
|
||||
public ChannelSubCommand() {
|
||||
super.addOption(OptionType.CHANNEL, "channel", "The channel scores are sent in", false);
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -59,8 +55,6 @@ public class ChannelSubCommand extends BatSubCommand {
|
||||
}
|
||||
|
||||
profile.setChannelId(targetChannel.getId());
|
||||
guildService.saveGuild(guild);
|
||||
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully set the feed channel to %s".formatted(targetChannel.asTextChannel().getAsMention()))
|
||||
.build()).queue();
|
||||
|
@ -6,12 +6,10 @@ import cc.fascinated.bat.common.EmbedUtils;
|
||||
import cc.fascinated.bat.features.scoresaber.profile.guild.NumberOneScoreFeedProfile;
|
||||
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.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@ -20,18 +18,10 @@ import org.springframework.stereotype.Component;
|
||||
@Component("scoresaber-number-one-feed:reset.sub")
|
||||
@CommandInfo(name = "reset", description = "Resets the settings")
|
||||
public class ResetSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public ResetSubCommand(GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
NumberOneScoreFeedProfile profile = guild.getProfile(NumberOneScoreFeedProfile.class);
|
||||
profile.reset();
|
||||
guildService.saveGuild(guild);
|
||||
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully reset the settings.")
|
||||
|
@ -7,7 +7,6 @@ import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import cc.fascinated.bat.model.token.beatsaber.scoresaber.ScoreSaberAccountToken;
|
||||
import cc.fascinated.bat.service.ScoreSaberService;
|
||||
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;
|
||||
@ -24,13 +23,11 @@ import org.springframework.stereotype.Component;
|
||||
@CommandInfo(name = "link", description = "Links your ScoreSaber profile")
|
||||
public class LinkSubCommand extends BatSubCommand {
|
||||
private final ScoreSaberService scoreSaberService;
|
||||
private final UserService userService;
|
||||
|
||||
@Autowired
|
||||
public LinkSubCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull UserService userService) {
|
||||
public LinkSubCommand(@NonNull ScoreSaberService scoreSaberService) {
|
||||
super.addOption(OptionType.STRING, "link", "Link your ScoreSaber profile", true);
|
||||
this.scoreSaberService = scoreSaberService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,7 +62,6 @@ public class LinkSubCommand extends BatSubCommand {
|
||||
}
|
||||
|
||||
user.getScoreSaberProfile().setAccountId(id);
|
||||
userService.saveUser(user);
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully linked your [ScoreSaber](%s) profile".formatted("https://scoresaber.com/u/%s".formatted(id)))
|
||||
.build()).queue();
|
||||
|
@ -6,12 +6,10 @@ import cc.fascinated.bat.common.EmbedUtils;
|
||||
import cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile;
|
||||
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.SlashCommandInteraction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@ -20,18 +18,10 @@ import org.springframework.stereotype.Component;
|
||||
@Component("scoresaber:reset.sub")
|
||||
@CommandInfo(name = "reset", description = "Reset your settings")
|
||||
public class ResetSubCommand extends BatSubCommand {
|
||||
private final UserService userService;
|
||||
|
||||
@Autowired
|
||||
public ResetSubCommand(@NonNull UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
ScoreSaberProfile profile = user.getScoreSaberProfile();
|
||||
profile.reset();
|
||||
userService.saveUser(user);
|
||||
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully reset your settings.")
|
||||
|
@ -7,7 +7,6 @@ import cc.fascinated.bat.common.TextChannelUtils;
|
||||
import cc.fascinated.bat.features.scoresaber.profile.guild.UserScoreFeedProfile;
|
||||
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;
|
||||
@ -25,12 +24,9 @@ import org.springframework.stereotype.Component;
|
||||
@Component("scoresaber-user-feed:channel.sub")
|
||||
@CommandInfo(name = "channel", description = "Sets the feed channel")
|
||||
public class ChannelSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public ChannelSubCommand(GuildService guildService) {
|
||||
public ChannelSubCommand() {
|
||||
super.addOption(OptionType.CHANNEL, "channel", "The channel scores are sent in", false);
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -59,8 +55,6 @@ public class ChannelSubCommand extends BatSubCommand {
|
||||
}
|
||||
|
||||
profile.setChannelId(targetChannel.getId());
|
||||
guildService.saveGuild(guild);
|
||||
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully set the feed channel to %s".formatted(targetChannel.asTextChannel().getAsMention()))
|
||||
.build()).queue();
|
||||
|
@ -6,12 +6,10 @@ import cc.fascinated.bat.common.EmbedUtils;
|
||||
import cc.fascinated.bat.features.scoresaber.profile.guild.UserScoreFeedProfile;
|
||||
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.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@ -20,19 +18,10 @@ import org.springframework.stereotype.Component;
|
||||
@Component("scoresaber-user-feed:reset.sub")
|
||||
@CommandInfo(name = "reset", description = "Resets the settings")
|
||||
public class ResetSubCommand extends BatSubCommand {
|
||||
private final GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
public ResetSubCommand(GuildService guildService) {
|
||||
this.guildService = guildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
UserScoreFeedProfile profile = guild.getProfile(UserScoreFeedProfile.class);
|
||||
profile.reset();
|
||||
guildService.saveGuild(guild);
|
||||
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("Successfully reset the settings.")
|
||||
.build()).queue();
|
||||
|
@ -83,6 +83,5 @@ public class UserSubCommand extends BatSubCommand {
|
||||
target.getAsMention()
|
||||
))
|
||||
.build()).queue();
|
||||
guildService.saveGuild(guild);
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,26 @@
|
||||
package cc.fascinated.bat.features.scoresaber.profile.guild;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import cc.fascinated.bat.service.DiscordService;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class NumberOneScoreFeedProfile extends Profile {
|
||||
@NoArgsConstructor
|
||||
public class NumberOneScoreFeedProfile extends Serializable {
|
||||
/**
|
||||
* The channel ID of the score feed
|
||||
*/
|
||||
private String channelId;
|
||||
|
||||
public NumberOneScoreFeedProfile() {
|
||||
super("scoresaber-number-one-score-feed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the channel as a TextChannel
|
||||
*
|
||||
@ -34,4 +34,16 @@ public class NumberOneScoreFeedProfile extends Profile {
|
||||
public void reset() {
|
||||
this.channelId = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.channelId = document.getString("channelId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
document.put("channelId", this.channelId);
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package cc.fascinated.bat.features.scoresaber.profile.guild;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import cc.fascinated.bat.service.DiscordService;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -14,7 +17,8 @@ import java.util.List;
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserScoreFeedProfile extends Profile {
|
||||
@NoArgsConstructor
|
||||
public class UserScoreFeedProfile extends Serializable {
|
||||
/**
|
||||
* The channel ID of the score feed
|
||||
*/
|
||||
@ -25,10 +29,6 @@ public class UserScoreFeedProfile extends Profile {
|
||||
*/
|
||||
private List<String> trackedUsers;
|
||||
|
||||
public UserScoreFeedProfile() {
|
||||
super("scoresaber-user-score-feed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tracked users
|
||||
*
|
||||
@ -92,4 +92,18 @@ public class UserScoreFeedProfile extends Profile {
|
||||
this.channelId = null;
|
||||
this.trackedUsers = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.channelId = document.getString("channelId");
|
||||
this.trackedUsers = document.getList("trackedUsers", String.class, new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
document.put("channelId", this.channelId);
|
||||
document.put("trackedUsers", this.trackedUsers);
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,38 @@
|
||||
package cc.fascinated.bat.features.scoresaber.profile.user;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class ScoreSaberProfile extends Profile {
|
||||
@NoArgsConstructor
|
||||
public class ScoreSaberProfile extends Serializable {
|
||||
/**
|
||||
* The Account ID of the ScoreSaber profile
|
||||
*/
|
||||
private String accountId;
|
||||
|
||||
public ScoreSaberProfile() {
|
||||
super("scoresaber");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.accountId = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.accountId = document.getString("accountId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
document.put("accountId", this.accountId);
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,11 @@ import cc.fascinated.bat.exception.BatException;
|
||||
import cc.fascinated.bat.features.spotify.profile.SpotifyProfile;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import cc.fascinated.bat.service.UserService;
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@ -24,13 +22,6 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
@CommandInfo(name = "unlink", description = "Unlink your Spotify account")
|
||||
public class UnlinkSubCommand extends BatSubCommand implements EventListener {
|
||||
private final UserService userService;
|
||||
|
||||
@Autowired
|
||||
public UnlinkSubCommand(@NonNull UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@Override @SneakyThrows
|
||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||
SpotifyProfile profile = user.getProfile(SpotifyProfile.class);
|
||||
@ -39,7 +30,6 @@ public class UnlinkSubCommand extends BatSubCommand implements EventListener {
|
||||
}
|
||||
|
||||
profile.reset();
|
||||
userService.saveUser(user);
|
||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||
.setDescription("%s Successfully unlinked your Spotify account.".formatted(Emojis.CHECK_MARK_EMOJI))
|
||||
.build())
|
||||
|
@ -1,14 +1,16 @@
|
||||
package cc.fascinated.bat.features.spotify.profile;
|
||||
|
||||
import cc.fascinated.bat.common.Profile;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Getter @Setter
|
||||
public class SpotifyProfile extends Profile {
|
||||
public class SpotifyProfile extends Serializable {
|
||||
/**
|
||||
* The access token
|
||||
*/
|
||||
@ -24,10 +26,6 @@ public class SpotifyProfile extends Profile {
|
||||
*/
|
||||
private Long expiresAt;
|
||||
|
||||
public SpotifyProfile() {
|
||||
super("spotify");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the account has a linked account
|
||||
*
|
||||
@ -42,4 +40,20 @@ public class SpotifyProfile extends Profile {
|
||||
this.accessToken = null;
|
||||
this.refreshToken = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.accessToken = document.getString("accessToken");
|
||||
this.refreshToken = document.getString("refreshToken");
|
||||
this.expiresAt = document.getLong("expiresAt");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
document.put("accessToken", this.accessToken);
|
||||
document.put("refreshToken", this.refreshToken);
|
||||
document.put("expiresAt", this.expiresAt);
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
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="birthday-changelog", order = "001", author = "fascinated7")
|
||||
public class BirthdayProfileChangelog {
|
||||
private final MongoTemplate mongoTemplate;
|
||||
|
||||
public BirthdayProfileChangelog(MongoTemplate mongoTemplate) {
|
||||
this.mongoTemplate = mongoTemplate;
|
||||
}
|
||||
|
||||
@Execution
|
||||
public void changeSet() {
|
||||
FindIterable<Document> guilds = mongoTemplate.getCollection("guilds").find();
|
||||
guilds.forEach(guild -> {
|
||||
Document profiles = guild.get("profiles", Document.class);
|
||||
if (profiles == null) {
|
||||
return;
|
||||
}
|
||||
Document birthdayProfile = profiles.get("birthday", Document.class);
|
||||
if (birthdayProfile == null) {
|
||||
return;
|
||||
}
|
||||
birthdayProfile.remove("birthdays");
|
||||
profiles.put("birthday", birthdayProfile);
|
||||
guild.put("profiles", profiles);
|
||||
mongoTemplate.getCollection("guilds").replaceOne(new Document("_id", guild.get("_id")), guild);
|
||||
});
|
||||
}
|
||||
|
||||
@RollbackExecution
|
||||
public void rollback() {
|
||||
// DO NOTHING
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
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<Document> 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<Document> 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
|
||||
}
|
||||
}
|
@ -1,25 +1,41 @@
|
||||
package cc.fascinated.bat.model;
|
||||
|
||||
import cc.fascinated.bat.BatApplication;
|
||||
import cc.fascinated.bat.common.ProfileHolder;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import cc.fascinated.bat.features.base.profile.FeatureProfile;
|
||||
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile;
|
||||
import cc.fascinated.bat.features.namehistory.profile.guild.NameHistoryProfile;
|
||||
import cc.fascinated.bat.premium.PremiumProfile;
|
||||
import cc.fascinated.bat.service.DiscordService;
|
||||
import lombok.*;
|
||||
import cc.fascinated.bat.service.MongoService;
|
||||
import com.mongodb.client.model.ReplaceOptions;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@Document(collection = "guilds")
|
||||
public class BatGuild extends ProfileHolder {
|
||||
private static final Logger log = LoggerFactory.getLogger(BatGuild.class);
|
||||
/**
|
||||
* The document that belongs to this guild
|
||||
*/
|
||||
private final org.bson.Document document;
|
||||
|
||||
/**
|
||||
* The ID of the guild
|
||||
*/
|
||||
@ -30,23 +46,13 @@ public class BatGuild extends ProfileHolder {
|
||||
/**
|
||||
* The time this guild was joined
|
||||
*/
|
||||
private Date createdAt = new Date();
|
||||
private Date createdAt;
|
||||
|
||||
/**
|
||||
* The premium information for the guild
|
||||
*/
|
||||
private Premium premium;
|
||||
|
||||
/**
|
||||
* The premium information for the guild
|
||||
*
|
||||
* @return the premium information
|
||||
*/
|
||||
public Premium getPremium() {
|
||||
if (this.premium == null) {
|
||||
this.premium = new Premium(null, null, null);
|
||||
}
|
||||
return this.premium;
|
||||
public BatGuild(@NonNull String id, @NonNull org.bson.Document document) {
|
||||
this.id = id;
|
||||
this.document = document;
|
||||
boolean newAccount = this.document.isEmpty();
|
||||
this.createdAt = newAccount ? new Date() : document.getDate("createdAt");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,91 +91,46 @@ public class BatGuild extends ProfileHolder {
|
||||
return getProfile(FeatureProfile.class);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Premium {
|
||||
/**
|
||||
* The time the premium was activated
|
||||
*/
|
||||
private Date activatedAt;
|
||||
/**
|
||||
* Gets the premium profile
|
||||
*
|
||||
* @return the premium profile
|
||||
*/
|
||||
public PremiumProfile getPremiumProfile() {
|
||||
return getProfile(PremiumProfile.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the premium expires
|
||||
*/
|
||||
private Date expiresAt;
|
||||
/**
|
||||
* Gets the birthday profile
|
||||
*
|
||||
* @return the birthday profile
|
||||
*/
|
||||
public BirthdayProfile getBirthdayProfile() {
|
||||
return getProfile(BirthdayProfile.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of premium
|
||||
*/
|
||||
private Type type;
|
||||
/**
|
||||
* Saves the user
|
||||
*/
|
||||
public void save() {
|
||||
document.put("_id", id);
|
||||
document.put("createdAt", createdAt);
|
||||
|
||||
/**
|
||||
* Checks if the guild has premium
|
||||
*
|
||||
* @return whether the guild has premium
|
||||
*/
|
||||
public boolean hasPremium() {
|
||||
return this.type == Type.INFINITE || (this.expiresAt != null && this.expiresAt.after(new Date()));
|
||||
Map<String, org.bson.Document> profileDocuments = new HashMap<>();
|
||||
for (Serializable profile : getProfiles().values()) {
|
||||
profileDocuments.put(profile.getClass().getSimpleName(), profile.serialize(BatApplication.GSON));
|
||||
}
|
||||
document.put("profiles", profileDocuments);
|
||||
|
||||
/**
|
||||
* Adds a month to the premium time
|
||||
*/
|
||||
public void addTime(int months) {
|
||||
if (this.type == null) { // If the type is null, set it to monthly
|
||||
this.type = Type.MONTHLY;
|
||||
}
|
||||
if (this.expiresAt == null) {
|
||||
this.expiresAt = new Date();
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(new Date());
|
||||
calendar.add(Calendar.MONTH, months);
|
||||
this.expiresAt = calendar.getTime();
|
||||
this.type = Type.MONTHLY;
|
||||
}
|
||||
MongoService.INSTANCE.getGuildsCollection().replaceOne(
|
||||
new org.bson.Document("_id", id),
|
||||
this.getDocument(),
|
||||
new ReplaceOptions().upsert(true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a month to the premium time
|
||||
*/
|
||||
public void addTime() {
|
||||
addTime(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds infinite time to the premium
|
||||
*/
|
||||
public void addInfiniteTime() {
|
||||
this.type = Type.INFINITE;
|
||||
this.expiresAt = null;
|
||||
this.activatedAt = new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the premium from the guild
|
||||
*/
|
||||
public void removePremium() {
|
||||
this.activatedAt = null;
|
||||
this.expiresAt = null;
|
||||
this.type = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the premium is infinite
|
||||
*
|
||||
* @return whether the premium is infinite
|
||||
*/
|
||||
public boolean isInfinite() {
|
||||
return this.type == Type.INFINITE;
|
||||
}
|
||||
|
||||
/**
|
||||
* The premium type for the guild
|
||||
*/
|
||||
public enum Type {
|
||||
INFINITE,
|
||||
MONTHLY
|
||||
}
|
||||
@Override
|
||||
public <T extends Serializable> T getProfile(Class<T> clazz) {
|
||||
return getProfileFromDocument(clazz, document);
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,26 @@
|
||||
package cc.fascinated.bat.model;
|
||||
|
||||
import cc.fascinated.bat.BatApplication;
|
||||
import cc.fascinated.bat.common.ProfileHolder;
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
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 cc.fascinated.bat.service.MongoService;
|
||||
import com.mongodb.client.model.ReplaceOptions;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
@ -22,6 +30,12 @@ import java.util.Date;
|
||||
@Setter
|
||||
@Document(collection = "users")
|
||||
public class BatUser extends ProfileHolder {
|
||||
private static final Logger log = LoggerFactory.getLogger(BatUser.class);
|
||||
/**
|
||||
* The document that belongs to this user
|
||||
*/
|
||||
private final org.bson.Document document;
|
||||
|
||||
/**
|
||||
* The ID of the user
|
||||
*/
|
||||
@ -32,7 +46,14 @@ public class BatUser extends ProfileHolder {
|
||||
/**
|
||||
* The time this user was created
|
||||
*/
|
||||
private Date createdAt = new Date();
|
||||
private Date createdAt;
|
||||
|
||||
public BatUser(@NonNull String id, @NonNull org.bson.Document document) {
|
||||
this.id = id;
|
||||
this.document = document;
|
||||
boolean newAccount = this.document.isEmpty();
|
||||
this.createdAt = newAccount ? new Date() : document.getDate("createdAt");
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the user
|
||||
@ -67,4 +88,29 @@ public class BatUser extends ProfileHolder {
|
||||
public NameHistoryProfile getNameHistoryProfile() {
|
||||
return getProfile(NameHistoryProfile.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the user
|
||||
*/
|
||||
public void save() {
|
||||
document.put("_id", id);
|
||||
document.put("createdAt", createdAt);
|
||||
|
||||
Map<String, org.bson.Document> profileDocuments = new HashMap<>();
|
||||
for (Serializable profile : getProfiles().values()) {
|
||||
profileDocuments.put(profile.getClass().getSimpleName(), profile.serialize(BatApplication.GSON));
|
||||
}
|
||||
document.put("profiles", profileDocuments);
|
||||
|
||||
MongoService.INSTANCE.getUsersCollection().replaceOne(
|
||||
new org.bson.Document("_id", id),
|
||||
this.getDocument(),
|
||||
new ReplaceOptions().upsert(true)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Serializable> T getProfile(Class<T> clazz) {
|
||||
return getProfileFromDocument(clazz, document);
|
||||
}
|
||||
}
|
||||
|
134
src/main/java/cc/fascinated/bat/premium/PremiumProfile.java
Normal file
134
src/main/java/cc/fascinated/bat/premium/PremiumProfile.java
Normal file
@ -0,0 +1,134 @@
|
||||
package cc.fascinated.bat.premium;
|
||||
|
||||
import cc.fascinated.bat.common.Serializable;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class PremiumProfile extends Serializable {
|
||||
/**
|
||||
* The time the premium was activated
|
||||
*/
|
||||
private Date activatedAt;
|
||||
|
||||
/**
|
||||
* The time the premium expires
|
||||
*/
|
||||
private Date expiresAt;
|
||||
|
||||
/**
|
||||
* The type of premium
|
||||
*/
|
||||
private Type type;
|
||||
|
||||
/**
|
||||
* Checks if the guild has premium
|
||||
*
|
||||
* @return whether the guild has premium
|
||||
*/
|
||||
public boolean hasPremium() {
|
||||
return this.type == Type.INFINITE || (this.expiresAt != null && this.expiresAt.after(new Date()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a month to the premium time
|
||||
*/
|
||||
public void addTime(int months) {
|
||||
if (this.type == null) { // If the type is null, set it to monthly
|
||||
this.type = Type.MONTHLY;
|
||||
}
|
||||
if (this.expiresAt == null) {
|
||||
this.expiresAt = new Date();
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(new Date());
|
||||
calendar.add(Calendar.MONTH, months);
|
||||
this.expiresAt = calendar.getTime();
|
||||
this.type = Type.MONTHLY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a month to the premium time
|
||||
*/
|
||||
public void addTime() {
|
||||
addTime(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds infinite time to the premium
|
||||
*/
|
||||
public void addInfiniteTime() {
|
||||
this.type = Type.INFINITE;
|
||||
this.expiresAt = null;
|
||||
this.activatedAt = new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the premium from the guild
|
||||
*/
|
||||
public void removePremium() {
|
||||
this.activatedAt = null;
|
||||
this.expiresAt = null;
|
||||
this.type = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the premium is infinite
|
||||
*
|
||||
* @return whether the premium is infinite
|
||||
*/
|
||||
public boolean isInfinite() {
|
||||
return this.type == Type.INFINITE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the premium has expired
|
||||
*
|
||||
* @return whether the premium has expired
|
||||
*/
|
||||
public boolean hasExpired() {
|
||||
return this.expiresAt != null && this.expiresAt.before(new Date());
|
||||
}
|
||||
|
||||
/**
|
||||
* The premium type for the guild
|
||||
*/
|
||||
public enum Type {
|
||||
INFINITE,
|
||||
MONTHLY
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document, Gson gson) {
|
||||
this.activatedAt = (Date) document.getOrDefault("activatedAt", new Date());
|
||||
this.expiresAt = (Date) document.getOrDefault("expiresAt", null);
|
||||
this.type = document.containsKey("type") ? Type.valueOf(document.getString("type")) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document serialize(Gson gson) {
|
||||
Document document = new Document();
|
||||
document.put("activatedAt", this.activatedAt);
|
||||
document.put("expiresAt", this.expiresAt);
|
||||
document.put("type", this.type.name());
|
||||
return document;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.activatedAt = null;
|
||||
this.expiresAt = null;
|
||||
this.type = null;
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package cc.fascinated.bat.repository;
|
||||
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
public interface GuildRepository extends MongoRepository<BatGuild, String> {
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package cc.fascinated.bat.repository;
|
||||
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
public interface UserRepository extends MongoRepository<BatUser, String> {
|
||||
}
|
@ -27,7 +27,7 @@ import java.util.*;
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Service
|
||||
@Log4j2
|
||||
@Log4j2(topic = "Command Service")
|
||||
@Getter
|
||||
@DependsOn("discordService")
|
||||
public class CommandService extends ListenerAdapter {
|
||||
|
@ -3,6 +3,7 @@ package cc.fascinated.bat.service;
|
||||
import cc.fascinated.bat.common.NumberFormatter;
|
||||
import cc.fascinated.bat.common.TimerUtils;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.entities.Activity;
|
||||
@ -20,6 +21,7 @@ import java.util.List;
|
||||
*/
|
||||
@Service
|
||||
@Getter
|
||||
@Log4j2(topic = "Discord Service")
|
||||
public class DiscordService {
|
||||
/**
|
||||
* The JDA instance
|
||||
@ -37,6 +39,7 @@ public class DiscordService {
|
||||
public DiscordService(
|
||||
@Value("${discord.token}") String token
|
||||
) throws Exception {
|
||||
log.info("Starting Discord bot...");
|
||||
JDA = JDABuilder.create(token, EnumSet.of(
|
||||
GatewayIntent.GUILD_MESSAGES,
|
||||
GatewayIntent.MESSAGE_CONTENT,
|
||||
@ -51,6 +54,7 @@ public class DiscordService {
|
||||
CacheFlag.SCHEDULED_EVENTS
|
||||
).build()
|
||||
.awaitReady();
|
||||
log.info("Connected to Discord as {}", JDA.getSelfUser().getEffectiveName());
|
||||
TimerUtils.scheduleRepeating(this::updateActivity, 0, 1000 * 60 * 2);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ import java.util.Set;
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Service
|
||||
@Log4j2
|
||||
@Log4j2(topic = "Event Service")
|
||||
@DependsOn("discordService")
|
||||
public class EventService extends ListenerAdapter {
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ import java.util.Map;
|
||||
*/
|
||||
@Service
|
||||
@Getter
|
||||
@Log4j2
|
||||
@Log4j2(topic = "Feature Service")
|
||||
@DependsOn("commandService")
|
||||
public class FeatureService {
|
||||
public static FeatureService INSTANCE;
|
||||
|
@ -1,57 +1,63 @@
|
||||
package cc.fascinated.bat.service;
|
||||
|
||||
import cc.fascinated.bat.common.TimerUtils;
|
||||
import cc.fascinated.bat.model.BatGuild;
|
||||
import cc.fascinated.bat.repository.GuildRepository;
|
||||
import cc.fascinated.bat.premium.PremiumProfile;
|
||||
import com.mongodb.client.model.Filters;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.events.guild.GuildJoinEvent;
|
||||
import net.dv8tion.jda.api.events.guild.GuildLeaveEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.jodah.expiringmap.ExpiringMap;
|
||||
import org.bson.Document;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Service
|
||||
@Log4j2
|
||||
@Log4j2(topic = "Guild Service")
|
||||
@Getter
|
||||
@DependsOn("discordService")
|
||||
@DependsOn({"discordService", "mongoService"})
|
||||
public class GuildService extends ListenerAdapter {
|
||||
private static final long SAVE_INTERVAL = TimeUnit.MINUTES.toMillis(5);
|
||||
|
||||
/**
|
||||
* The cached guilds
|
||||
*/
|
||||
private final Map<String, BatGuild> guilds = ExpiringMap.builder()
|
||||
.expiration(6, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* The guild repository to use
|
||||
*/
|
||||
private final GuildRepository guildRepository;
|
||||
private final Map<String, BatGuild> guilds = new HashMap<>();
|
||||
|
||||
@Autowired
|
||||
public GuildService(@NonNull GuildRepository guildRepository) {
|
||||
this.guildRepository = guildRepository;
|
||||
public GuildService() {
|
||||
TimerUtils.scheduleRepeating(() -> {
|
||||
long before = System.currentTimeMillis();
|
||||
for (BatGuild guild : guilds.values()) {
|
||||
guild.save();
|
||||
}
|
||||
log.info("Saved {} guilds in {}ms", guilds.size(), System.currentTimeMillis() - before);
|
||||
}, SAVE_INTERVAL, SAVE_INTERVAL);
|
||||
|
||||
DiscordService.JDA.addEventListener(this);
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 0 0 * * *")
|
||||
private void validatePremiumStatus() {
|
||||
for (BatGuild guild : guilds.values()) {
|
||||
BatGuild.Premium premium = guild.getPremium();
|
||||
if (premium.getExpiresAt() != null && premium.getExpiresAt().before(new Date())) {
|
||||
premium.removePremium();
|
||||
guildRepository.save(guild);
|
||||
log.info("Removed premium status from guild \"{}\"", guild.getName());
|
||||
PremiumProfile premium = guild.getPremiumProfile();
|
||||
if (!premium.hasExpired()) {
|
||||
return;
|
||||
}
|
||||
premium.removePremium();
|
||||
log.info("Removed premium status from guild \"{}\"", guild.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,51 +68,37 @@ public class GuildService extends ListenerAdapter {
|
||||
* @return The guild
|
||||
*/
|
||||
public BatGuild getGuild(@NonNull String id) {
|
||||
long before = System.currentTimeMillis();
|
||||
// Guild is cached
|
||||
if (guilds.containsKey(id)) {
|
||||
return guilds.get(id);
|
||||
}
|
||||
if (DiscordService.JDA.getGuildById(id) == null) {
|
||||
return null;
|
||||
}
|
||||
long start = System.currentTimeMillis();
|
||||
Optional<BatGuild> optionalGuild = guildRepository.findById(id);
|
||||
|
||||
if (optionalGuild.isPresent()) {
|
||||
BatGuild guild = optionalGuild.get();
|
||||
// Guild is not cached
|
||||
Document document = MongoService.INSTANCE.getGuildsCollection().find(Filters.eq("_id", id)).first();
|
||||
if (document != null) {
|
||||
BatGuild guild = new BatGuild(id, document);
|
||||
guilds.put(id, guild);
|
||||
log.info("Loaded guild \"{}\" in {}ms", guild.getName(),System.currentTimeMillis() - before);
|
||||
return guild;
|
||||
}
|
||||
BatGuild guild = guildRepository.save(new BatGuild(id));
|
||||
log.info("Created guild \"{}\" in {}ms", guild.getName(), System.currentTimeMillis() - start);
|
||||
// New guild
|
||||
BatGuild guild = new BatGuild(id, new Document());
|
||||
guilds.put(id, guild);
|
||||
log.info("Created guild \"{}\" - \"{}\"", guild.getName(), guild.getId());
|
||||
return guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a guild
|
||||
*
|
||||
* @param guild The guild to save
|
||||
*/
|
||||
public void saveGuild(@NonNull BatGuild guild) {
|
||||
guildRepository.save(guild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all guilds
|
||||
*
|
||||
* @return all guilds
|
||||
*/
|
||||
public List<BatGuild> getAllGuilds() {
|
||||
List<BatGuild> guilds = new ArrayList<>();
|
||||
for (Guild guild : DiscordService.JDA.getGuilds()) {
|
||||
guilds.add(getGuild(guild.getId()));
|
||||
}
|
||||
return guilds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onGuildJoin(GuildJoinEvent event) {
|
||||
Guild guild = event.getGuild();
|
||||
BatGuild guild = getGuild(event.getGuild().getId());
|
||||
log.info("Joined guild \"{}\"", guild.getName());
|
||||
getGuild(guild.getId()); // Ensure the guild is in the database
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuildLeave(@NotNull GuildLeaveEvent event) {
|
||||
BatGuild guild = getGuild(event.getGuild().getId());
|
||||
log.info("Left guild \"{}\"", guild.getName());
|
||||
guild.save();
|
||||
guilds.remove(guild.getId());
|
||||
}
|
||||
}
|
||||
|
40
src/main/java/cc/fascinated/bat/service/MongoService.java
Normal file
40
src/main/java/cc/fascinated/bat/service/MongoService.java
Normal file
@ -0,0 +1,40 @@
|
||||
package cc.fascinated.bat.service;
|
||||
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import org.bson.Document;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Service
|
||||
public class MongoService {
|
||||
public static MongoService INSTANCE;
|
||||
private final MongoTemplate mongo;
|
||||
|
||||
@Autowired
|
||||
public MongoService(MongoTemplate mongo) {
|
||||
INSTANCE = this;
|
||||
this.mongo = mongo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guilds collection
|
||||
*
|
||||
* @return The guilds collection
|
||||
*/
|
||||
public MongoCollection<Document> getGuildsCollection() {
|
||||
return mongo.getCollection("guilds");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the users collection
|
||||
*
|
||||
* @return The users collection
|
||||
*/
|
||||
public MongoCollection<Document> getUsersCollection() {
|
||||
return mongo.getCollection("users");
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
@Service
|
||||
@Getter
|
||||
@Log4j2
|
||||
@Log4j2(topic = "Spotify Service")
|
||||
public class SpotifyService {
|
||||
/**
|
||||
* The access token map.
|
||||
@ -189,7 +189,6 @@ public class SpotifyService {
|
||||
AuthorizationCodeCredentials credentials = api.authorizationCodeRefresh().build().execute();
|
||||
profile.setAccessToken(credentials.getAccessToken());
|
||||
profile.setExpiresAt(System.currentTimeMillis() + (credentials.getExpiresIn() * 1000));
|
||||
userService.saveUser(user);
|
||||
log.info("Refreshed Spotify token for user {}", user.getName());
|
||||
} catch (SpotifyWebApiException ex) {
|
||||
log.error("Failed to refresh Spotify token", ex);
|
||||
@ -213,7 +212,6 @@ public class SpotifyService {
|
||||
profile.setAccessToken(credentials.getAccessToken());
|
||||
profile.setRefreshToken(credentials.getRefreshToken());
|
||||
profile.setExpiresAt(System.currentTimeMillis() + (credentials.getExpiresIn() * 1000));
|
||||
userService.saveUser(user);
|
||||
log.info("Linked Spotify account for user {}", user.getName());
|
||||
}
|
||||
|
||||
|
@ -1,73 +1,70 @@
|
||||
package cc.fascinated.bat.service;
|
||||
|
||||
import cc.fascinated.bat.common.TimerUtils;
|
||||
import cc.fascinated.bat.model.BatUser;
|
||||
import cc.fascinated.bat.repository.UserRepository;
|
||||
import com.mongodb.client.model.Filters;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.jodah.expiringmap.ExpiringMap;
|
||||
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.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@Service
|
||||
@Log4j2
|
||||
@Log4j2(topic = "User Service")
|
||||
@Getter
|
||||
@DependsOn("discordService")
|
||||
@DependsOn({"discordService", "mongoService"})
|
||||
public class UserService {
|
||||
private static final long SAVE_INTERVAL = TimeUnit.MINUTES.toMillis(5);
|
||||
|
||||
/**
|
||||
* The cached users
|
||||
*/
|
||||
private final Map<String, BatUser> users = ExpiringMap.builder()
|
||||
.expiration(6, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* The user repository to use
|
||||
*/
|
||||
private final UserRepository userRepository;
|
||||
private final Map<String, BatUser> users = new HashMap<>();
|
||||
|
||||
@Autowired
|
||||
public UserService(@NonNull UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
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 their ID
|
||||
* 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);
|
||||
}
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
Optional<BatUser> optionalUser = userRepository.findById(id);
|
||||
if (optionalUser.isPresent()) {
|
||||
BatUser user = optionalUser.get();
|
||||
// User is not cached
|
||||
Document document = MongoService.INSTANCE.getUsersCollection().find(Filters.eq("_id", id)).first();
|
||||
if (document != null) {
|
||||
BatUser user = new BatUser(id, document);
|
||||
users.put(id, user);
|
||||
log.info("Loaded user \"{}\" in {}ms", user.getName(),System.currentTimeMillis() - before);
|
||||
return user;
|
||||
}
|
||||
BatUser user = userRepository.save(new BatUser(id));
|
||||
log.info("Created user for \"{}\" in {}ms", user.getDiscordUser().getName(), System.currentTimeMillis() - start);
|
||||
// New user
|
||||
BatUser user = new BatUser(id, new Document());
|
||||
users.put(id, user);
|
||||
log.info("Created user \"{}\" - \"{}\"", user.getName(), user.getId());
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a user
|
||||
*
|
||||
* @param user The user to save
|
||||
*/
|
||||
public void saveUser(@NonNull BatUser user) {
|
||||
userRepository.save(user);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user