impl birthday feature
All checks were successful
Deploy to Dokku / docker (ubuntu-latest) (push) Successful in 36s
All checks were successful
Deploy to Dokku / docker (ubuntu-latest) (push) Successful in 36s
This commit is contained in:
parent
e7159ad514
commit
6d593246e8
@ -8,14 +8,15 @@ import lombok.extern.log4j.Log4j2;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.cache.annotation.EnableCaching;
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@EnableCaching
|
@EnableCaching @EnableScheduling
|
||||||
@SpringBootApplication()
|
@SpringBootApplication
|
||||||
@Log4j2(topic = "Ember")
|
@Log4j2(topic = "Ember")
|
||||||
public class BatApplication {
|
public class BatApplication {
|
||||||
public static Gson GSON = new GsonBuilder().create();
|
public static Gson GSON = new GsonBuilder().create();
|
||||||
|
@ -44,19 +44,11 @@ public abstract class BatCommand implements BatCommandExecutor {
|
|||||||
*/
|
*/
|
||||||
private final Map<String, BatSubCommand> subCommands = new HashMap<>();
|
private final Map<String, BatSubCommand> subCommands = new HashMap<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* The category of the command
|
|
||||||
*/
|
|
||||||
private Category category;
|
|
||||||
|
|
||||||
public BatCommand(@NonNull String name, @NonNull String description, boolean guildOnly, Permission... permissions) {
|
public BatCommand(@NonNull String name, @NonNull String description, boolean guildOnly, Permission... permissions) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.requiredPermissions = List.of(permissions);
|
this.requiredPermissions = List.of(permissions);
|
||||||
|
|
||||||
// Default values
|
|
||||||
this.category = Category.GENERAL;
|
|
||||||
|
|
||||||
this.commandData = new CommandDataImpl(this.name, description)
|
this.commandData = new CommandDataImpl(this.name, description)
|
||||||
.setGuildOnly(guildOnly);
|
.setGuildOnly(guildOnly);
|
||||||
}
|
}
|
||||||
@ -101,20 +93,4 @@ public abstract class BatCommand implements BatCommandExecutor {
|
|||||||
public List<String> getOptions(SlashCommandInteraction interaction) {
|
public List<String> getOptions(SlashCommandInteraction interaction) {
|
||||||
return interaction.getOptions().stream().map(OptionMapping::getName).toList();
|
return interaction.getOptions().stream().map(OptionMapping::getName).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The category of the command
|
|
||||||
*/
|
|
||||||
@AllArgsConstructor @Getter
|
|
||||||
protected enum Category {
|
|
||||||
GENERAL("General"),
|
|
||||||
MODERATION("Moderation"),
|
|
||||||
SERVER("Server"),
|
|
||||||
BEAT_SABER("Beat Saber");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the category
|
|
||||||
*/
|
|
||||||
private final String name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,16 @@ import lombok.Setter;
|
|||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Getter @Setter
|
@Getter @Setter
|
||||||
public class Profile {
|
public abstract class Profile {
|
||||||
/**
|
/**
|
||||||
* The key of the profile.
|
* The key of the profile.
|
||||||
*/
|
*/
|
||||||
private String profileKey;
|
private String profileKey;
|
||||||
|
|
||||||
public Profile() {}
|
public Profile() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the profile
|
||||||
|
*/
|
||||||
|
public abstract void reset();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cc.fascinated.bat.features;
|
package cc.fascinated.bat.features;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -15,4 +16,25 @@ public abstract class Feature {
|
|||||||
* The name of the feature
|
* The name of the feature
|
||||||
*/
|
*/
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The category of the feature
|
||||||
|
*/
|
||||||
|
private final Category category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The category of the feature
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor @Getter
|
||||||
|
public enum Category {
|
||||||
|
GENERAL("General"),
|
||||||
|
MODERATION("Moderation"),
|
||||||
|
SERVER("Server"),
|
||||||
|
BEAT_SABER("Beat Saber");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the category
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import org.springframework.stereotype.Component;
|
|||||||
public class AutoRoleFeature extends Feature {
|
public class AutoRoleFeature extends Feature {
|
||||||
@Autowired
|
@Autowired
|
||||||
public AutoRoleFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) {
|
public AutoRoleFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) {
|
||||||
super("AutoRole");
|
super("AutoRole", Category.SERVER);
|
||||||
|
|
||||||
commandService.registerCommand(context.getBean(AutoRoleCommand.class));
|
commandService.registerCommand(context.getBean(AutoRoleCommand.class));
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ public class ClearSubCommand extends BatSubCommand {
|
|||||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||||
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);
|
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);
|
||||||
|
|
||||||
profile.clearRoles();
|
profile.reset();
|
||||||
guildService.saveGuild(guild);
|
guildService.saveGuild(guild);
|
||||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||||
.setDescription("Successfully cleared all auto roles")
|
.setDescription("Successfully cleared all auto roles")
|
||||||
|
@ -14,6 +14,8 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Setter @Getter
|
@Setter @Getter
|
||||||
public class AutoRoleProfile extends Profile {
|
public class AutoRoleProfile extends Profile {
|
||||||
|
private static final int DEFAULT_MAX_ROLES = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The roles to assign when a user joins
|
* The roles to assign when a user joins
|
||||||
*/
|
*/
|
||||||
@ -70,13 +72,6 @@ public class AutoRoleProfile extends Profile {
|
|||||||
this.roleIds.remove(roleId);
|
this.roleIds.remove(roleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearRoles() {
|
|
||||||
if (this.roleIds == null) {
|
|
||||||
this.roleIds = new ArrayList<>();
|
|
||||||
}
|
|
||||||
this.roleIds.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a role is set to be assigned when a user joins
|
* Checks if a role is set to be assigned when a user joins
|
||||||
*
|
*
|
||||||
@ -108,4 +103,10 @@ public class AutoRoleProfile extends Profile {
|
|||||||
}
|
}
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
roleIds.clear();
|
||||||
|
maxRoles = DEFAULT_MAX_ROLES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package cc.fascinated.bat.features.birthday;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.common.TimerUtils;
|
||||||
|
import cc.fascinated.bat.features.Feature;
|
||||||
|
import cc.fascinated.bat.features.birthday.command.BirthdayCommand;
|
||||||
|
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile;
|
||||||
|
import cc.fascinated.bat.model.BatGuild;
|
||||||
|
import cc.fascinated.bat.service.CommandService;
|
||||||
|
import cc.fascinated.bat.service.GuildService;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BirthdayFeature extends Feature {
|
||||||
|
private final GuildService guildService;
|
||||||
|
|
||||||
|
public BirthdayFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService, @NonNull GuildService guildService) {
|
||||||
|
super("Birthday", Category.GENERAL);
|
||||||
|
this.guildService = guildService;
|
||||||
|
|
||||||
|
commandService.registerCommand(context.getBean(BirthdayCommand.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check birthdays every day at midnight
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0 0 0 * * *")
|
||||||
|
private void checkBirthdays() {
|
||||||
|
for (BatGuild guild : guildService.getAllGuilds()) {
|
||||||
|
BirthdayProfile profile = guild.getProfile(BirthdayProfile.class);
|
||||||
|
profile.checkBirthdays(guild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package cc.fascinated.bat.features.birthday.command;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.command.BatCommand;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BirthdayCommand extends BatCommand {
|
||||||
|
@Autowired
|
||||||
|
public BirthdayCommand(@NonNull ApplicationContext context) {
|
||||||
|
super("birthday", "Modify your birthday settings.", true);
|
||||||
|
|
||||||
|
super.addSubCommand("set", context.getBean(SetSubCommand.class));
|
||||||
|
super.addSubCommand("remove", context.getBean(RemoveSubCommand.class));
|
||||||
|
super.addSubCommand("channel", context.getBean(ChannelSubCommand.class));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package cc.fascinated.bat.features.birthday.command;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.command.BatSubCommand;
|
||||||
|
import cc.fascinated.bat.common.EmbedUtils;
|
||||||
|
import cc.fascinated.bat.common.TextChannelUtils;
|
||||||
|
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile;
|
||||||
|
import cc.fascinated.bat.features.scoresaber.profile.GuildUserScoreFeedProfile;
|
||||||
|
import cc.fascinated.bat.model.BatGuild;
|
||||||
|
import cc.fascinated.bat.model.BatUser;
|
||||||
|
import cc.fascinated.bat.service.GuildService;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component("birthday:channel.sub")
|
||||||
|
public class ChannelSubCommand extends BatSubCommand {
|
||||||
|
private final GuildService guildService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public ChannelSubCommand(GuildService guildService) {
|
||||||
|
super("channel", "Sets the birthday notification channel");
|
||||||
|
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);
|
||||||
|
OptionMapping option = interaction.getOption("channel");
|
||||||
|
if (option == null) {
|
||||||
|
if (!TextChannelUtils.isValidChannel(profile.getChannelId())) {
|
||||||
|
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("Please provide a channel to set the birthday channel to")
|
||||||
|
.build()).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
interaction.replyEmbeds(EmbedUtils.genericEmbed()
|
||||||
|
.setDescription("The current birthday channel is %s".formatted(TextChannelUtils.getChannelMention(profile.getChannelId())))
|
||||||
|
.build()).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuildChannelUnion targetChannel = option.getAsChannel();
|
||||||
|
if (targetChannel.getType() != ChannelType.TEXT) {
|
||||||
|
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("Invalid channel type, please provide a text channel")
|
||||||
|
.build()).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package cc.fascinated.bat.features.birthday.command;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.command.BatSubCommand;
|
||||||
|
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.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;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component("birthday:remove.sub")
|
||||||
|
public class RemoveSubCommand extends BatSubCommand {
|
||||||
|
private final GuildService guildService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public RemoveSubCommand(GuildService guildService) {
|
||||||
|
super("remove", "Remove your birthday from this guild");
|
||||||
|
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);
|
||||||
|
|
||||||
|
profile.removeBirthday(user.getId());
|
||||||
|
guildService.saveGuild(guild);
|
||||||
|
|
||||||
|
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||||
|
.setDescription("Your birthday has been removed from this guild")
|
||||||
|
.build()).queue();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package cc.fascinated.bat.features.birthday.command;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.command.BatSubCommand;
|
||||||
|
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.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;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component("birthday:add.sub")
|
||||||
|
public class SetSubCommand extends BatSubCommand {
|
||||||
|
private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd/MM/yyyy");
|
||||||
|
private final GuildService guildService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public SetSubCommand(GuildService guildService) {
|
||||||
|
super("set", "Add your birthday to this guild");
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!profile.hasChannelSetup()) {
|
||||||
|
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("Birthdays have not been enabled in this guild. Please ask an administrator to enable them.")
|
||||||
|
.build()).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionMapping birthdayOption = interaction.getOption("birthday");
|
||||||
|
if (birthdayOption == null) {
|
||||||
|
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("You must provide a birthday")
|
||||||
|
.build()).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String birthdayString = birthdayOption.getAsString();
|
||||||
|
Date birthday = parseBirthday(birthdayString);
|
||||||
|
if (birthday == null) {
|
||||||
|
interaction.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("Invalid birthday format. Please use the format: DAY/MONTH/YEAR - 01/05/2004")
|
||||||
|
.build()).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.addBirthday(member.getId(), birthday);
|
||||||
|
guildService.saveGuild(guild);
|
||||||
|
|
||||||
|
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||||
|
.setDescription("You have updated your birthday!")
|
||||||
|
.build()).queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a birthday from the string
|
||||||
|
*
|
||||||
|
* @param birthday the date to parse
|
||||||
|
* @return the birthday
|
||||||
|
*/
|
||||||
|
private Date parseBirthday(String birthday) {
|
||||||
|
try {
|
||||||
|
return FORMATTER.parse(birthday);
|
||||||
|
} catch (ParseException ignored) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,210 @@
|
|||||||
|
package cc.fascinated.bat.features.birthday.profile;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.common.Profile;
|
||||||
|
import cc.fascinated.bat.model.BatGuild;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Getter @Setter
|
||||||
|
public class BirthdayProfile extends Profile {
|
||||||
|
/**
|
||||||
|
* The list of birthdays that are being tracked
|
||||||
|
*/
|
||||||
|
private Map<String, Date> birthdays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The channel ID of the birthday feed
|
||||||
|
*/
|
||||||
|
private String channelId;
|
||||||
|
|
||||||
|
public BirthdayProfile() {
|
||||||
|
super("birthday");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a birthday to be tracked
|
||||||
|
*
|
||||||
|
* @param userId the id of the user to track
|
||||||
|
* @param birthday the birthday of the user
|
||||||
|
*/
|
||||||
|
public void addBirthday(String userId, Date birthday) {
|
||||||
|
if (birthdays == null) {
|
||||||
|
birthdays = new HashMap<>();
|
||||||
|
}
|
||||||
|
birthdays.put(userId, birthday);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a birthday from being tracked
|
||||||
|
*
|
||||||
|
* @param userId the id of the user to remove
|
||||||
|
*/
|
||||||
|
public void removeBirthday(String userId) {
|
||||||
|
if (birthdays == null) {
|
||||||
|
birthdays = new HashMap<>();
|
||||||
|
}
|
||||||
|
birthdays.remove(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the birthday of a user
|
||||||
|
*
|
||||||
|
* @param userId the id of the user
|
||||||
|
* @return the birthday of the user
|
||||||
|
*/
|
||||||
|
public Date getBirthday(String userId) {
|
||||||
|
if (birthdays == null) {
|
||||||
|
birthdays = new HashMap<>();
|
||||||
|
}
|
||||||
|
return birthdays.get(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the profile has a channel setup
|
||||||
|
*
|
||||||
|
* @return if the profile has a channel setup
|
||||||
|
*/
|
||||||
|
public boolean hasChannelSetup() {
|
||||||
|
return channelId != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the age of a user
|
||||||
|
*
|
||||||
|
* @param userId the id of the user
|
||||||
|
* @return the age of the user
|
||||||
|
*/
|
||||||
|
public int calculateAge(String userId) {
|
||||||
|
Date birthday = getBirthday(userId);
|
||||||
|
if (birthday == null) {
|
||||||
|
return 0; // or throw an exception
|
||||||
|
}
|
||||||
|
|
||||||
|
Calendar birthdayCalendar = Calendar.getInstance();
|
||||||
|
birthdayCalendar.setTime(birthday);
|
||||||
|
|
||||||
|
Calendar today = Calendar.getInstance();
|
||||||
|
|
||||||
|
int age = today.get(Calendar.YEAR) - birthdayCalendar.get(Calendar.YEAR);
|
||||||
|
|
||||||
|
// Check if the birthday hasn't occurred yet this year
|
||||||
|
if (today.get(Calendar.DAY_OF_YEAR) < birthdayCalendar.get(Calendar.DAY_OF_YEAR)) {
|
||||||
|
age--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validate(BatGuild guild) {
|
||||||
|
if (birthdays == null) {
|
||||||
|
birthdays = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> toRemove = new ArrayList<>();
|
||||||
|
Guild discordGuild = guild.getDiscordGuild();
|
||||||
|
for (Map.Entry<String, Date> entry : birthdays.entrySet()) {
|
||||||
|
String userId = entry.getKey();
|
||||||
|
Date birthday = entry.getValue();
|
||||||
|
|
||||||
|
if (userId == null || birthday == null) { // this should never happen
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the user is still in the guild, if not remove them
|
||||||
|
Member member = discordGuild.getMemberById(userId);
|
||||||
|
if (member == null) {
|
||||||
|
toRemove.add(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String userId : toRemove) {
|
||||||
|
birthdays.remove(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelId == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discordGuild.getTextChannelById(channelId) == null) {
|
||||||
|
channelId = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if it is any user's birthday
|
||||||
|
*
|
||||||
|
* @param guild the guild to check for
|
||||||
|
*/
|
||||||
|
public void checkBirthdays(BatGuild guild) {
|
||||||
|
if (!validate(guild)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get today's day and month
|
||||||
|
Calendar today = Calendar.getInstance();
|
||||||
|
int todayDay = today.get(Calendar.DAY_OF_MONTH);
|
||||||
|
int todayMonth = today.get(Calendar.MONTH); // Note: January is 0
|
||||||
|
|
||||||
|
Iterator<Map.Entry<String, Date>> iterator = birthdays.entrySet().iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<String, Date> entry = iterator.next();
|
||||||
|
Date birthday = entry.getValue();
|
||||||
|
|
||||||
|
if (birthday == null) {
|
||||||
|
iterator.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Calendar birthdayCalendar = Calendar.getInstance();
|
||||||
|
birthdayCalendar.setTime(birthday);
|
||||||
|
|
||||||
|
int birthdayDay = birthdayCalendar.get(Calendar.DAY_OF_MONTH);
|
||||||
|
int birthdayMonth = birthdayCalendar.get(Calendar.MONTH);
|
||||||
|
|
||||||
|
// Check if the birthday matches today's day and month
|
||||||
|
if (birthdayDay == todayDay && birthdayMonth == todayMonth) {
|
||||||
|
notifyBirthday(guild, entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies a user that it is their birthday
|
||||||
|
*
|
||||||
|
* @param guild the guild
|
||||||
|
* @param userId the id of the user
|
||||||
|
*/
|
||||||
|
private void notifyBirthday(BatGuild guild, String userId) {
|
||||||
|
Guild discordGuild = guild.getDiscordGuild();
|
||||||
|
Member member = discordGuild.getMemberById(userId);
|
||||||
|
if (member == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextChannel channel = discordGuild.getTextChannelById(channelId);
|
||||||
|
if (channel == null) { // this should never happen
|
||||||
|
channelId = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
channel.sendMessage("Happy Birthday %s :tada: :birthday: You are now %s years old!".formatted(
|
||||||
|
member.getAsMention(),
|
||||||
|
calculateAge(userId)
|
||||||
|
)).queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
birthdays.clear();
|
||||||
|
channelId = null;
|
||||||
|
}
|
||||||
|
}
|
@ -25,7 +25,7 @@ import org.springframework.stereotype.Component;
|
|||||||
public class ScoreSaberFeature extends Feature {
|
public class ScoreSaberFeature extends Feature {
|
||||||
@Autowired
|
@Autowired
|
||||||
public ScoreSaberFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) {
|
public ScoreSaberFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) {
|
||||||
super("ScoreSaber");
|
super("ScoreSaber", Category.BEAT_SABER);
|
||||||
|
|
||||||
commandService.registerCommand(context.getBean(ScoreSaberCommand.class));
|
commandService.registerCommand(context.getBean(ScoreSaberCommand.class));
|
||||||
commandService.registerCommand(context.getBean(UserFeedCommand.class));
|
commandService.registerCommand(context.getBean(UserFeedCommand.class));
|
||||||
|
@ -13,7 +13,6 @@ import org.springframework.stereotype.Component;
|
|||||||
public class NumberOneFeedCommand extends BatCommand {
|
public class NumberOneFeedCommand extends BatCommand {
|
||||||
public NumberOneFeedCommand(@NonNull ApplicationContext context) {
|
public NumberOneFeedCommand(@NonNull ApplicationContext context) {
|
||||||
super("scoresaber-number-one-feed", "Modifies the settings for the feed.", true, Permission.MANAGE_SERVER);
|
super("scoresaber-number-one-feed", "Modifies the settings for the feed.", true, Permission.MANAGE_SERVER);
|
||||||
super.setCategory(Category.BEAT_SABER);
|
|
||||||
|
|
||||||
super.addSubCommand("channel", context.getBean(ChannelSubCommand.class));
|
super.addSubCommand("channel", context.getBean(ChannelSubCommand.class));
|
||||||
super.addSubCommand("reset", context.getBean(ResetSubCommand.class));
|
super.addSubCommand("reset", context.getBean(ResetSubCommand.class));
|
||||||
|
@ -29,7 +29,7 @@ public class ResetSubCommand extends BatSubCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||||
GuildNumberOneScoreFeedProfile profile = guild.getProfile(GuildNumberOneScoreFeedProfile.class);
|
GuildNumberOneScoreFeedProfile profile = guild.getProfile(GuildNumberOneScoreFeedProfile.class);
|
||||||
profile.setChannelId(null);
|
profile.reset();
|
||||||
guildService.saveGuild(guild);
|
guildService.saveGuild(guild);
|
||||||
|
|
||||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||||
|
41
src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ResetSubCommand.java
Normal file
41
src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ResetSubCommand.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package cc.fascinated.bat.features.scoresaber.command.scoresaber;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.command.BatSubCommand;
|
||||||
|
import cc.fascinated.bat.common.EmbedUtils;
|
||||||
|
import cc.fascinated.bat.features.scoresaber.profile.GuildUserScoreFeedProfile;
|
||||||
|
import cc.fascinated.bat.features.scoresaber.profile.UserScoreSaberProfile;
|
||||||
|
import cc.fascinated.bat.model.BatGuild;
|
||||||
|
import cc.fascinated.bat.model.BatUser;
|
||||||
|
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;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component("scoresaber:reset.sub")
|
||||||
|
public class ResetSubCommand extends BatSubCommand {
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public ResetSubCommand(@NonNull UserService userService) {
|
||||||
|
super("reset", "Resets the settings");
|
||||||
|
this.userService = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||||
|
UserScoreSaberProfile profile = guild.getProfile(UserScoreSaberProfile.class);
|
||||||
|
profile.reset();
|
||||||
|
userService.saveUser(user);
|
||||||
|
|
||||||
|
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||||
|
.setDescription("Successfully reset your settings.")
|
||||||
|
.build()).queue();
|
||||||
|
}
|
||||||
|
}
|
@ -31,12 +31,12 @@ public class ScoreSaberCommand extends BatCommand {
|
|||||||
@Autowired
|
@Autowired
|
||||||
public ScoreSaberCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull ApplicationContext context) {
|
public ScoreSaberCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull ApplicationContext context) {
|
||||||
super("scoresaber", "General ScoreSaber commands");
|
super("scoresaber", "General ScoreSaber commands");
|
||||||
super.setCategory(Category.BEAT_SABER);
|
|
||||||
this.scoreSaberService = scoreSaberService;
|
this.scoreSaberService = scoreSaberService;
|
||||||
|
|
||||||
super.addSubCommand("link", context.getBean(LinkSubCommand.class));
|
super.addSubCommand("link", context.getBean(LinkSubCommand.class));
|
||||||
super.addSubCommand("user", context.getBean(UserSubCommand.class));
|
super.addSubCommand("user", context.getBean(UserSubCommand.class));
|
||||||
super.addSubCommand("me", context.getBean(MeSubCommand.class));
|
super.addSubCommand("me", context.getBean(MeSubCommand.class));
|
||||||
|
super.addSubCommand("reset", context.getBean(ResetSubCommand.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,8 +29,7 @@ public class ResetSubCommand extends BatSubCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) {
|
||||||
GuildUserScoreFeedProfile profile = guild.getProfile(GuildUserScoreFeedProfile.class);
|
GuildUserScoreFeedProfile profile = guild.getProfile(GuildUserScoreFeedProfile.class);
|
||||||
profile.setChannelId(null);
|
profile.reset();
|
||||||
profile.getTrackedUsers().clear();
|
|
||||||
guildService.saveGuild(guild);
|
guildService.saveGuild(guild);
|
||||||
|
|
||||||
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
interaction.replyEmbeds(EmbedUtils.successEmbed()
|
||||||
|
@ -13,7 +13,6 @@ import org.springframework.stereotype.Component;
|
|||||||
public class UserFeedCommand extends BatCommand {
|
public class UserFeedCommand extends BatCommand {
|
||||||
public UserFeedCommand(@NonNull ApplicationContext context) {
|
public UserFeedCommand(@NonNull ApplicationContext context) {
|
||||||
super("scoresaber-user-feed", "Modifies the settings for the feed.", true, Permission.MANAGE_SERVER);
|
super("scoresaber-user-feed", "Modifies the settings for the feed.", true, Permission.MANAGE_SERVER);
|
||||||
super.setCategory(Category.BEAT_SABER);
|
|
||||||
|
|
||||||
super.addSubCommand("user", context.getBean(UserSubCommand.class));
|
super.addSubCommand("user", context.getBean(UserSubCommand.class));
|
||||||
super.addSubCommand("channel", context.getBean(ChannelSubCommand.class));
|
super.addSubCommand("channel", context.getBean(ChannelSubCommand.class));
|
||||||
|
@ -28,4 +28,9 @@ public class GuildNumberOneScoreFeedProfile extends Profile {
|
|||||||
public TextChannel getAsTextChannel() {
|
public TextChannel getAsTextChannel() {
|
||||||
return DiscordService.JDA.getTextChannelById(channelId);
|
return DiscordService.JDA.getTextChannelById(channelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
this.channelId = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,4 +72,10 @@ public class GuildUserScoreFeedProfile extends Profile {
|
|||||||
public TextChannel getAsTextChannel() {
|
public TextChannel getAsTextChannel() {
|
||||||
return DiscordService.JDA.getTextChannelById(channelId);
|
return DiscordService.JDA.getTextChannelById(channelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
this.channelId = null;
|
||||||
|
this.trackedUsers = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,4 +17,9 @@ public class UserScoreSaberProfile extends Profile {
|
|||||||
public UserScoreSaberProfile() {
|
public UserScoreSaberProfile() {
|
||||||
super("scoresaber");
|
super("scoresaber");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
this.steamId = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import org.springframework.cache.annotation.Cacheable;
|
|||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +38,7 @@ public class GuildService extends ListenerAdapter {
|
|||||||
* @param id The ID of the guild
|
* @param id The ID of the guild
|
||||||
* @return The guild
|
* @return The guild
|
||||||
*/
|
*/
|
||||||
@Cacheable(cacheNames = {"guilds"}, key = "#id")
|
// @Cacheable(cacheNames = {"guilds"}, key = "#id")
|
||||||
public BatGuild getGuild(@NonNull String id) {
|
public BatGuild getGuild(@NonNull String id) {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
Optional<BatGuild> optionalGuild = guildRepository.findById(id);
|
Optional<BatGuild> optionalGuild = guildRepository.findById(id);
|
||||||
@ -54,11 +55,20 @@ public class GuildService extends ListenerAdapter {
|
|||||||
*
|
*
|
||||||
* @param guild The guild to save
|
* @param guild The guild to save
|
||||||
*/
|
*/
|
||||||
@CachePut(cacheNames = {"guilds"}, key = "#id")
|
// @CachePut(cacheNames = {"guilds"}, key = "#id")
|
||||||
public void saveGuild(@NonNull BatGuild guild) {
|
public void saveGuild(@NonNull BatGuild guild) {
|
||||||
guildRepository.save(guild);
|
guildRepository.save(guild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all guilds
|
||||||
|
*
|
||||||
|
* @return all guilds
|
||||||
|
*/
|
||||||
|
public List<BatGuild> getAllGuilds() {
|
||||||
|
return guildRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onGuildJoin(GuildJoinEvent event) {
|
public final void onGuildJoin(GuildJoinEvent event) {
|
||||||
log.info("Joined guild \"{}\"", event.getGuild().getId());
|
log.info("Joined guild \"{}\"", event.getGuild().getId());
|
||||||
|
@ -34,7 +34,7 @@ public class UserService {
|
|||||||
* @param id The ID of the user
|
* @param id The ID of the user
|
||||||
* @return The user
|
* @return The user
|
||||||
*/
|
*/
|
||||||
@Cacheable(cacheNames = {"users"}, key = "#id")
|
// @Cacheable(cacheNames = {"users"}, key = "#id")
|
||||||
public BatUser getUser(@NonNull String id) {
|
public BatUser getUser(@NonNull String id) {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
Optional<BatUser> optionalUser = userRepository.findById(id);
|
Optional<BatUser> optionalUser = userRepository.findById(id);
|
||||||
@ -51,7 +51,7 @@ public class UserService {
|
|||||||
*
|
*
|
||||||
* @param user The user to save
|
* @param user The user to save
|
||||||
*/
|
*/
|
||||||
@CachePut(cacheNames = {"users"}, key = "#id")
|
// @CachePut(cacheNames = {"users"}, key = "#id")
|
||||||
public void saveUser(@NonNull BatUser user) {
|
public void saveUser(@NonNull BatUser user) {
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user