diff --git a/pom.xml b/pom.xml
index bbdbb1a1b..836341252 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,6 +94,11 @@
json
20220320
+
+ commons-validator
+ commons-validator
+ 1.7
+
club.minnced
discord-webhooks
diff --git a/src/main/java/de/presti/ree6/commands/impl/community/Birthday.java b/src/main/java/de/presti/ree6/commands/impl/community/Birthday.java
new file mode 100644
index 000000000..e10dd5c95
--- /dev/null
+++ b/src/main/java/de/presti/ree6/commands/impl/community/Birthday.java
@@ -0,0 +1,95 @@
+package de.presti.ree6.commands.impl.community;
+
+import de.presti.ree6.commands.Category;
+import de.presti.ree6.commands.CommandEvent;
+import de.presti.ree6.commands.interfaces.Command;
+import de.presti.ree6.commands.interfaces.ICommand;
+import de.presti.ree6.main.Main;
+import net.dv8tion.jda.api.Permission;
+import net.dv8tion.jda.api.interactions.commands.build.CommandData;
+import org.apache.commons.validator.GenericValidator;
+
+/**
+ * This command is used to let the bot remember your Birthday.
+ */
+@Command(name = "birthday", description = "Let the bot remember your Birthday.", category = Category.COMMUNITY)
+public class Birthday implements ICommand {
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public void onPerform(CommandEvent commandEvent) {
+ if (commandEvent.isSlashCommand()) {
+ Main.getInstance().getCommandManager().sendMessage("This Command doesn't support slash commands yet.", commandEvent.getChannel(), commandEvent.getInteractionHook());
+ return;
+ }
+
+ if (commandEvent.getArguments().length == 1) {
+ if (commandEvent.getArguments()[0].equalsIgnoreCase("remove")) {
+ Main.getInstance().getSqlConnector().getSqlWorker().removeBirthday(commandEvent.getGuild().getId(), commandEvent.getMember().getId());
+ Main.getInstance().getCommandManager().sendMessage("Your Birthday has been removed!", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ } else {
+ Main.getInstance().getCommandManager().sendMessage("Please use " + Main.getInstance().getSqlConnector().getSqlWorker().getSetting(commandEvent.getGuild().getId(), "chatprefix").getStringValue() + "birthday add/remove [Birthday(day.month.year)] [@User]", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ }
+ }
+ if (commandEvent.getArguments().length == 2) {
+ if (commandEvent.getArguments()[0].equalsIgnoreCase("remove")) {
+ if (commandEvent.getMember().hasPermission(Permission.ADMINISTRATOR)) {
+ if (commandEvent.getMessage() != null &&
+ commandEvent.getMessage().getMentions().getMembers().isEmpty()) {
+ Main.getInstance().getCommandManager().sendMessage("Please mention a user!", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ } else {
+ Main.getInstance().getSqlConnector().getSqlWorker().removeBirthday(commandEvent.getGuild().getId(), commandEvent.getMessage().getMentions().getMembers().get(0).getId());
+ Main.getInstance().getCommandManager().sendMessage("The Birthday of <@" + commandEvent.getMessage().getMentions().getMembers().get(0).getId() + "> has been removed!", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ }
+ } else {
+ Main.getInstance().getCommandManager().sendMessage("You don't have the permission to remove a Birthday!", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ }
+ } else if (commandEvent.getArguments()[0].equalsIgnoreCase("add")) {
+ if (GenericValidator.isDate(commandEvent.getArguments()[1], "dd.MM.yyyy", true)) {
+ Main.getInstance().getSqlConnector().getSqlWorker().addBirthday(commandEvent.getGuild().getId(), commandEvent.getChannel().getId(), commandEvent.getMember().getId(), commandEvent.getArguments()[1]);
+ Main.getInstance().getCommandManager().sendMessage("Your Birthday has been added!", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ } else {
+ Main.getInstance().getCommandManager().sendMessage("Please use a valid Date!\nNote that we use the the format dd.MM.yyyy (day.month.year)!", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ }
+ } else {
+ Main.getInstance().getCommandManager().sendMessage("Please use " + Main.getInstance().getSqlConnector().getSqlWorker().getSetting(commandEvent.getGuild().getId(), "chatprefix").getStringValue() + "birthday add/remove [Birthday(day.month.year)] [@User]", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ }
+ } else if (commandEvent.getArguments().length == 3) {
+ if (commandEvent.getArguments()[0].equalsIgnoreCase("add")) {
+ if (GenericValidator.isDate(commandEvent.getArguments()[1], "dd.MM.yyyy", true)) {
+ if (commandEvent.getMessage() != null &&
+ commandEvent.getMessage().getMentions().getMembers().isEmpty()) {
+ Main.getInstance().getCommandManager().sendMessage("Please mention a user!", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ } else {
+ Main.getInstance().getSqlConnector().getSqlWorker().addBirthday(commandEvent.getGuild().getId(), commandEvent.getChannel().getId(), commandEvent.getMessage().getMentions().getMembers().get(0).getId(), commandEvent.getArguments()[1]);
+ Main.getInstance().getCommandManager().sendMessage("The Birthday of <@" + commandEvent.getMessage().getMentions().getMembers().get(0).getId() + "> has been added!", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ }
+ } else {
+ Main.getInstance().getCommandManager().sendMessage("Please use a valid Date!\nNote that we use the the format dd.MM.yyyy (day.month.year)!", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ }
+ } else {
+ Main.getInstance().getCommandManager().sendMessage("Please use " + Main.getInstance().getSqlConnector().getSqlWorker().getSetting(commandEvent.getGuild().getId(), "chatprefix").getStringValue() + "birthday add/remove [Birthday(day.month.year)] [@User]", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ }
+ } else {
+ Main.getInstance().getCommandManager().sendMessage("Please use " + Main.getInstance().getSqlConnector().getSqlWorker().getSetting(commandEvent.getGuild().getId(), "chatprefix").getStringValue() + "birthday add/remove [Birthday(day.month.year)] [@User]", 5, commandEvent.getChannel(), commandEvent.getInteractionHook());
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public CommandData getCommandData() {
+ return null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public String[] getAlias() {
+ return new String[]{"bday"};
+ }
+}
diff --git a/src/main/java/de/presti/ree6/main/Main.java b/src/main/java/de/presti/ree6/main/Main.java
index 206b075b2..7e012b80e 100644
--- a/src/main/java/de/presti/ree6/main/Main.java
+++ b/src/main/java/de/presti/ree6/main/Main.java
@@ -17,14 +17,18 @@
import de.presti.ree6.utils.apis.Notifier;
import de.presti.ree6.utils.data.ArrayUtil;
import de.presti.ree6.utils.data.Config;
+import de.presti.ree6.utils.others.ThreadUtil;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.VoiceChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
+import java.time.Duration;
+import java.util.Calendar;
import java.util.Date;
/**
@@ -82,11 +86,6 @@ public class Main {
*/
Config config;
- /**
- * A Thread used to check if a day has passed, and if so to clean the cache.
- */
- Thread checker;
-
/**
* String used to identify the last day.
*/
@@ -250,13 +249,6 @@ private void shutdown() {
getNotifier().getTwitchClient().close();
instance.logger.info("[Main] Twitch API Instance closed!");
- if (checker != null && !checker.isInterrupted()) {
- // Shutdown Checker Thread.
- instance.logger.info("[Main] Interrupting the Checker thread!");
- checker.interrupt();
- instance.logger.info("[Main] Interrupted the Checker thread!");
- }
-
// Shutdown the Bot instance.
instance.logger.info("[Main] JDA Instance shutdown init. !");
BotWorker.shutdown();
@@ -271,7 +263,7 @@ private void shutdown() {
* Method creates a Thread used to create a Checker Thread.
*/
public void createCheckerThread() {
- checker = new Thread(() -> {
+ ThreadUtil.createNewThread(x -> {
while (BotWorker.getState() != BotState.STOPPED) {
if (!lastDay.equalsIgnoreCase(new SimpleDateFormat("dd").format(new Date()))) {
@@ -293,6 +285,22 @@ public void createCheckerThread() {
instance.logger.info("[Stats] Guilds: {}", BotWorker.getShardManager().getGuilds().size());
instance.logger.info("[Stats] Overall Users: {}", BotWorker.getShardManager().getGuilds().stream().mapToInt(Guild::getMemberCount).sum());
instance.logger.info("[Stats] ");
+
+ Calendar currentCalendar = Calendar.getInstance();
+
+ getSqlConnector().getSqlWorker()
+ .getBirthdays().stream().filter(birthday -> {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(birthday.getBirthdate());
+ return calendar.get(Calendar.MONTH) == currentCalendar.get(Calendar.MONTH) &&
+ calendar.get(Calendar.DAY_OF_MONTH) == currentCalendar.get(Calendar.DAY_OF_MONTH);
+ }).forEach(birthday -> {
+ TextChannel textChannel = BotWorker.getShardManager().getTextChannelById(birthday.getChannelId());
+
+ if (textChannel != null && textChannel.canTalk())
+ textChannel.sendMessage("Happy birthday to <@" + birthday.getUserId() + ">!").queue();
+ });
+
lastDay = new SimpleDateFormat("dd").format(new Date());
}
@@ -314,15 +322,8 @@ public void createCheckerThread() {
getLogger().error("Error accessing the AudioPlayer.", ex);
}
}
-
- try {
- Thread.sleep((10 * (60000L)));
- } catch (InterruptedException exception) {
- getInstance().getLogger().error("Checker Thread interrupted", exception);
- }
}
- });
- checker.start();
+ }, null, Duration.ofMinutes(1), true, false);
}
/**
@@ -416,15 +417,6 @@ public Logger getAnalyticsLogger() {
return analyticsLogger;
}
- /**
- * Retrieve the Instance of the Checker-Thread.
- *
- * @return {@link Thread} Instance of the Checker-Thread.
- */
- public Thread getChecker() {
- return checker;
- }
-
/**
* Retrieve the Instance of the Config.
*
diff --git a/src/main/java/de/presti/ree6/sql/SQLConnector.java b/src/main/java/de/presti/ree6/sql/SQLConnector.java
index 5e5785bdc..dd65c507c 100644
--- a/src/main/java/de/presti/ree6/sql/SQLConnector.java
+++ b/src/main/java/de/presti/ree6/sql/SQLConnector.java
@@ -12,6 +12,7 @@
import java.sql.*;
import java.util.Base64;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -192,6 +193,8 @@ public StoredResultSet querySQL(String sqlQuery, Object... objcObjects) {
preparedStatement.setObject(index++, SQLUtil.convertJSONToBlob(jsonElement), Types.BLOB);
} else if (obj instanceof byte[] byteArray) {
preparedStatement.setObject(index++, Base64.getEncoder().encodeToString(byteArray), Types.VARCHAR);
+ } else if (obj instanceof Date date) {
+ preparedStatement.setObject(index++, date.getTime(), Types.BIGINT);
}
}
diff --git a/src/main/java/de/presti/ree6/sql/SQLWorker.java b/src/main/java/de/presti/ree6/sql/SQLWorker.java
index cde846ceb..67fa8cecb 100644
--- a/src/main/java/de/presti/ree6/sql/SQLWorker.java
+++ b/src/main/java/de/presti/ree6/sql/SQLWorker.java
@@ -11,6 +11,7 @@
import de.presti.ree6.sql.base.data.SQLParameter;
import de.presti.ree6.sql.base.data.SQLResponse;
import de.presti.ree6.sql.base.data.SQLUtil;
+import de.presti.ree6.sql.entities.BirthdayWish;
import de.presti.ree6.sql.entities.Blacklist;
import de.presti.ree6.sql.entities.Invite;
import de.presti.ree6.sql.entities.Setting;
@@ -27,6 +28,8 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.*;
/**
@@ -1784,6 +1787,76 @@ public void optIn(String guildId, String userId) {
//endregion
+ //region Birthday
+
+ /**
+ * Store the birthday of the user in the database
+ * @param guildId the ID of the Guild.
+ * @param channelId the ID of the Channel.
+ * @param userId the ID of the User.
+ * @param birthday the birthday of the user.
+ */
+ public void addBirthday(String guildId, String channelId, String userId, String birthday) {
+ try {
+ if (isBirthdaySaved(guildId, userId)) {
+ BirthdayWish newBirthday = new BirthdayWish(guildId, channelId, userId, new SimpleDateFormat("dd.MM.yyyy").parse(birthday));
+ updateEntity(getBirthday(guildId, userId), newBirthday, true);
+ } else {
+ saveEntity(new BirthdayWish(guildId, channelId, userId, new SimpleDateFormat("dd.MM.yyyy").parse(birthday)));
+ }
+ } catch (ParseException ignore) {}
+ }
+
+ /**
+ * Check if there is any saved birthday for the given User.
+ * @param guildId the ID of the Guild.
+ * @param userId the ID of the User.
+ */
+ public void removeBirthday(String guildId, String userId) {
+ if (isBirthdaySaved(guildId, userId)) {
+ sqlConnector.querySQL("DELETE FROM BirthdayWish WHERE GID=? AND UID=?", guildId, userId);
+ }
+ }
+
+ /**
+ * Check if a birthday is saved for the given User.
+ * @param guildId the ID of the Guild.
+ * @param userId the ID of the User.
+ * @return {@link Boolean} as result. If true, there is data saved in the Database | If false, there is no data saved.
+ */
+ public boolean isBirthdaySaved(String guildId, String userId) {
+ return sqlConnector.querySQL("SELECT * FROM BirthdayWish WHERE GID=? AND UID=?", guildId, userId).hasResults();
+ }
+
+ /**
+ * Get the birthday of the given User.
+ * @param guildId the ID of the Guild.
+ * @param userId the ID of the User.
+ * @return {@link BirthdayWish} as result. If true, there is data saved in the Database | If false, there is no data saved.
+ */
+ public BirthdayWish getBirthday(String guildId, String userId) {
+ return (BirthdayWish) getEntity(BirthdayWish.class, "SELECT * FROM BirthdayWish WHERE GID=? AND UID=?", guildId, userId).getEntity();
+ }
+
+ /**
+ * Get all saved birthdays.
+ * @param guildId the ID of the Guild.
+ * @return {@link List} of {@link BirthdayWish} as result. If true, there is data saved in the Database | If false, there is no data saved.
+ */
+ public List getBirthdays(String guildId) {
+ return getEntity(BirthdayWish.class, "SELECT * FROM BirthdayWish WHERE GID=?", guildId).getEntities().stream().map(BirthdayWish.class::cast).toList();
+ }
+
+ /**
+ * Get all saved birthdays.
+ * @return {@link List} of {@link BirthdayWish} as result. If true, there is data saved in the Database | If false, there is no data saved.
+ */
+ public List getBirthdays() {
+ return getEntity(BirthdayWish.class, "SELECT * FROM BirthdayWish").getEntities().stream().map(BirthdayWish.class::cast).toList();
+ }
+
+ //endregion
+
//region Data delete
/**
diff --git a/src/main/java/de/presti/ree6/sql/base/data/SQLUtil.java b/src/main/java/de/presti/ree6/sql/base/data/SQLUtil.java
index 6a7580862..baea63fd2 100644
--- a/src/main/java/de/presti/ree6/sql/base/data/SQLUtil.java
+++ b/src/main/java/de/presti/ree6/sql/base/data/SQLUtil.java
@@ -10,10 +10,7 @@
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.sql.Blob;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.List;
+import java.util.*;
/**
* SQLUtil class to help with SQL-Queries.
@@ -70,7 +67,7 @@ public static String mapJavaToSQL(Class> javaObjectClass) {
javaObjectClass.isAssignableFrom(char.class)) {
return "CHAR(1)";
} else if (javaObjectClass.isAssignableFrom(java.util.Date.class)) {
- return "DATETIME";
+ return "BIGINT";
} else if (javaObjectClass.isAssignableFrom(java.sql.Date.class)) {
return "DATE";
} else if (javaObjectClass.isAssignableFrom(java.sql.Time.class)) {
@@ -225,7 +222,7 @@ public static List getAllSQLParameter(Object entity, boolean onlyU
* @param entityClass the Entity.
* @param entityInstance the Entity instance.
* @param onlyUpdateField if fields with the updateQuery value set to false should still be included.
- * @param ignoreNull if null values should be ignored.
+ * @param ignoreNull if null values should be ignored.
* @return {@link List} of {@link Object} as the {@link SQLParameter} value.
*/
public static List