Skip to content

Commit

Permalink
feat(core): Added DelayedTaskService and Remindme command (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
Seb committed Jun 7, 2022
1 parent ca3c646 commit 1bce1a4
Show file tree
Hide file tree
Showing 9 changed files with 492 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/main/java/de/voidtech/gerald/Gerald.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
@SpringBootApplication
public class Gerald {

@Bean
@Bean("JDA")
@DependsOn(value = {"sessionFactory"})
@Order(3)
@Autowired
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/de/voidtech/gerald/annotations/Task.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main.java.de.voidtech.gerald.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.stereotype.Component;

@Component
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Task {

}
154 changes: 154 additions & 0 deletions src/main/java/de/voidtech/gerald/commands/utils/RemindMeCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package main.java.de.voidtech.gerald.commands.utils;

import java.awt.Color;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;

import main.java.de.voidtech.gerald.annotations.Command;
import main.java.de.voidtech.gerald.commands.AbstractCommand;
import main.java.de.voidtech.gerald.commands.CommandCategory;
import main.java.de.voidtech.gerald.commands.CommandContext;
import main.java.de.voidtech.gerald.service.RemindMeService;
import main.java.de.voidtech.gerald.util.ParsingUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;

@Command
public class RemindMeCommand extends AbstractCommand {

@Autowired
private RemindMeService remindMeService;

private static HashMap<String, Integer> TimeMultipliers = new HashMap<String, Integer>();

@EventListener(ApplicationReadyEvent.class)
private void populateTimeMultipliers() {
TimeMultipliers.put("w", Integer.valueOf(604800));
TimeMultipliers.put("d", Integer.valueOf(86400));
TimeMultipliers.put("h", Integer.valueOf(3600));
TimeMultipliers.put("m", Integer.valueOf(60));
TimeMultipliers.put("s", Integer.valueOf(1));
}

@Override
public void executeInternal(CommandContext context, List<String> args) {
if (args.isEmpty()) showUserReminders(context);
else {
if (args.get(0).equals("delete")) deleteReminder(context, args);
else createReminder(context, args);
}
}

private void createReminder(CommandContext context, List<String> args) {
if (args.size() == 1) {
context.reply("**You need to specify a reminder message!**");
return;
}

String timeString = args.get(0);
String message = String.join(" ", args.subList(1, args.size()));
String timeMultiplier = timeString.substring(timeString.length() - 1, timeString.length());

if (!TimeMultipliers.containsKey(timeMultiplier)) {
context.reply("**You need to enter a valid time multiplier!**");
return;
}

String timeOnly = timeString.replaceAll(timeMultiplier, "");
if (!ParsingUtils.isInteger(timeOnly)) {
context.reply("**You need to enter a valid time quantity! (Must be a number)**");
return;
}

long timeValue = Integer.parseInt(timeOnly);
if (timeValue < 1) {
context.reply("**You need to specify a higher time value! (Must be at least 1)**");
return;
}

long multiplicationFactor = TimeMultipliers.get(timeMultiplier).longValue();
long time = (timeValue * multiplicationFactor) + Instant.now().getEpochSecond();

remindMeService.addReminder(context, message, time);
context.reply("**Reminder added!**");
}

private void deleteReminder(CommandContext context, List<String> args) {
if (args.size() == 1) {
context.reply("**You need to specify a reminder ID to delete! Use the** `reminders` **command to see your reminders!**");
return;
}
String ID = args.get(1);
if (!ParsingUtils.isInteger(ID)) {
context.reply("**Reminder ID must be a number!**");
return;
}
boolean taskDeleted = remindMeService.deleteReminder(context.getAuthor().getId(), Long.parseLong(ID));
context.reply(taskDeleted ? "**Reminder deleted!**" : "**No task with ID** `" + ID + "` **was found!**");
}

private void showUserReminders(CommandContext context) {
MessageEmbed remindersEmbed = new EmbedBuilder()
.setColor(Color.ORANGE)
.setTitle(context.getAuthor().getName() + "'s Reminders")
.setDescription(remindMeService.getRemindersList(context))
.build();
context.reply(remindersEmbed);
}

@Override
public String getDescription() {
return "Need a reminder to do something in a little while? Or maybe you want to remind yourself of an event in a few weeks?"
+ " This command is for you! Simply enter the time delay and a reminder message and you're set!\n\n"
+ "Use w, d, h and m (months, weeks, days, hours, minutes) to set your time delay. Examples: 12d, 13m, 4w\n"
+ "Please note that there should be no spaces between the quantity and time multiplier.";
}

@Override
public String getUsage() {
return "remindme (to see your reminders)\n"
+ "remindme [time delay] [reminder message]\n"
+ "remindme delete [reminder ID]";
}

@Override
public String getName() {
return "remindme";
}

@Override
public CommandCategory getCommandCategory() {
return CommandCategory.UTILS;
}

@Override
public boolean isDMCapable() {
return false;
}

@Override
public boolean requiresArguments() {
return false;
}

@Override
public String[] getCommandAliases() {
return new String[] {"reminder", "reminders"};
}

@Override
public boolean canBeDisabled() {
return true;
}

@Override
public boolean isSlashCompatible() {
return true;
}

}
74 changes: 74 additions & 0 deletions src/main/java/de/voidtech/gerald/entities/DelayedTask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package main.java.de.voidtech.gerald.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.json.JSONObject;

import main.java.de.voidtech.gerald.tasks.TaskType;

@Entity
@Table(name = "delayedtask")

public class DelayedTask {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@Column
private String args;

@Column
private String type;

@Column
private long time;

@Column
private String guildID;

@Column
private String userID;

@Deprecated
//ONLY FOR HIBERNATE, DO NOT USE
DelayedTask() {
}

public DelayedTask(TaskType type, JSONObject args, String guildID, String userID, long time) {
this.args = args.toString();
this.type = type.getType();
this.time = time;
this.guildID = guildID;
this.userID = userID;
}

public String getTaskType() {
return this.type;
}

public long getExecutionTime() {
return this.time;
}

public JSONObject getArgs() {
return new JSONObject(this.args);
}

public long getTaskID() {
return this.id;
}

public String getGuildID() {
return this.guildID;
}

public String getUserID() {
return this.userID;
}
}
122 changes: 122 additions & 0 deletions src/main/java/de/voidtech/gerald/service/DelayedTaskService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package main.java.de.voidtech.gerald.service;

import java.time.Instant;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import main.java.de.voidtech.gerald.entities.DelayedTask;
import main.java.de.voidtech.gerald.entities.GeraldLogger;
import main.java.de.voidtech.gerald.tasks.AbstractTask;
import main.java.de.voidtech.gerald.tasks.TaskType;
import net.dv8tion.jda.api.JDA;

@Lazy
@Service
public class DelayedTaskService {

@Autowired
private SessionFactory sessionFactory;

@Autowired
private List<AbstractTask> abstractTasks;

@Lazy
@Autowired
private JDA jda;

//Time in milliseconds
private static final int DELAYED_TASK_TIMER_INTERVAL = 10000;
//Time in seconds
private static final int UPCOMING_TASKS_TIME = 5;

private static final GeraldLogger LOGGER = LogService.GetLogger(DelayedTaskService.class.getSimpleName());

@EventListener(ApplicationReadyEvent.class)
private void startTimer() {
TimerTask requestAllowanceIncrement = new TimerTask() {
public void run() {
Thread.currentThread().setName("Task Timer");
checkForTasks();
}
};

Timer timer = new Timer();
timer.schedule(requestAllowanceIncrement, DELAYED_TASK_TIMER_INTERVAL, DELAYED_TASK_TIMER_INTERVAL);
}

private void checkForTasks() {
long taskTimeThreshold = Instant.now().getEpochSecond() + UPCOMING_TASKS_TIME;
List<DelayedTask> tasks = getUpcomingTasks(taskTimeThreshold);
if (tasks.isEmpty()) return;
for (DelayedTask task : tasks) {
AbstractTask taskExecutor = abstractTasks.stream()
.filter(t -> t.getTaskType().getType().equals(task.getTaskType()))
.findFirst()
.orElse(null);
if (taskExecutor == null) LOGGER.log(Level.SEVERE, "Task with unknown type '" + task.getTaskType() + "' found");
else taskExecutor.execute(task.getArgs(), jda, task.getUserID(), task.getGuildID());

deleteTask(task);
}
}

public void saveDelayedTask(DelayedTask task) {
try(Session session = sessionFactory.openSession())
{
session.getTransaction().begin();
session.saveOrUpdate(task);
session.getTransaction().commit();
}
}

public void deleteTask(DelayedTask task) {
try(Session session = sessionFactory.openSession()) {
session.getTransaction().begin();
session.createQuery("DELETE FROM DelayedTask WHERE id = :id")
.setParameter("id", task.getTaskID())
.executeUpdate();
session.getTransaction().commit();
}
}

@SuppressWarnings("unchecked")
private List<DelayedTask> getUpcomingTasks(long taskTimeThreshold) {
try(Session session = sessionFactory.openSession())
{
return session.createQuery("FROM DelayedTask WHERE time < :timeThreshold")
.setParameter("timeThreshold", taskTimeThreshold)
.list();
}
}

@SuppressWarnings("unchecked")
public List<DelayedTask> getUserTasksOfType(String userID, TaskType type) {
try(Session session = sessionFactory.openSession())
{
return session.createQuery("FROM DelayedTask WHERE userID = :userID AND type = :type")
.setParameter("userID", userID)
.setParameter("type", type.getType())
.list();
}
}

public DelayedTask getTaskByID(long id) {
try(Session session = sessionFactory.openSession())
{
return (DelayedTask) session.createQuery("FROM DelayedTask WHERE id = :id")
.setParameter("id", id)
.uniqueResult();
}
}

}
Loading

0 comments on commit 1bce1a4

Please sign in to comment.