[AB-174] adding command to re-schedule reminders

This commit is contained in:
Sheldan
2021-04-25 14:46:59 +02:00
parent 2c2e5c02b1
commit 68e2dad2ae
12 changed files with 156 additions and 4 deletions

View File

@@ -0,0 +1,62 @@
package dev.sheldan.abstracto.remind.command;
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.remind.config.RemindFeatureDefinition;
import dev.sheldan.abstracto.remind.service.ReminderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
@Component
public class Snooze extends AbstractConditionableCommand {
@Autowired
private ReminderService reminderService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Override
public CommandResult execute(CommandContext commandContext) {
List<Object> newParameters = commandContext.getParameters().getParameters();
Long reminderId = (Long) newParameters.get(0);
Duration newDuration = (Duration) newParameters.get(1);
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
reminderService.snoozeReminder(reminderId, aUserInAServer, newDuration);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("reminderId").type(Long.class).templated(true).build());
parameters.add(Parameter.builder().name("duration").type(Duration.class).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("snooze")
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return RemindFeatureDefinition.REMIND;
}
}

View File

@@ -13,5 +13,6 @@ public interface ReminderRepository extends JpaRepository<Reminder, Long> {
List<Reminder> getByRemindedUserAndRemindedFalse(AUserInAServer aUserInAServer);
Reminder getByIdAndRemindedUserAndRemindedFalse(Long reminderId, AUserInAServer aUserInAServer);
Reminder getByIdAndRemindedUser(Long reminderId, AUserInAServer aUserInAServer);
}

View File

@@ -11,6 +11,7 @@ import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.remind.exception.NotPossibleToSnoozeException;
import dev.sheldan.abstracto.remind.exception.ReminderNotFoundException;
import dev.sheldan.abstracto.remind.model.database.Reminder;
import dev.sheldan.abstracto.remind.model.template.commands.ExecutedReminderModel;
@@ -90,7 +91,13 @@ public class RemindServiceBean implements ReminderService {
log.info("Creating reminder for user {} in guild {} due at {}.",
user.getUserReference().getId(), user.getServerReference().getId(), remindAt);
scheduleReminder(remindIn, reminder);
return reminder;
}
private void scheduleReminder(Duration remindIn, Reminder reminder) {
if(remindIn.getSeconds() < 60) {
reminder.setJobTriggerKey(null);
log.info("Directly scheduling unremind for reminder {}, because it was below the threshold.", reminder.getId());
instantReminderScheduler.schedule(() -> {
try {
@@ -108,7 +115,6 @@ public class RemindServiceBean implements ReminderService {
reminder.setJobTriggerKey(triggerKey);
reminderManagementService.saveReminder(reminder);
}
return reminder;
}
@Override
@@ -164,4 +170,16 @@ public class RemindServiceBean implements ReminderService {
schedulerService.stopTrigger(reminder.getJobTriggerKey());
}
}
@Override
public void snoozeReminder(Long reminderId, AUserInAServer user, Duration newDuration) {
Reminder reminder = reminderManagementService.getReminderByAndByUser(user, reminderId).orElseThrow(() -> new ReminderNotFoundException(reminderId));
if(reminder.getTargetDate().isAfter(Instant.now())) {
throw new NotPossibleToSnoozeException();
}
log.info("Snoozing reminder {} to be executed in {}.", reminderId, newDuration);
reminder.setTargetDate(Instant.now().plus(newDuration));
reminder.setReminded(false);
scheduleReminder(newDuration, reminder);
}
}

View File

@@ -70,5 +70,10 @@ public class ReminderManagementServiceBean implements ReminderManagementService
return Optional.ofNullable(reminderRepository.getByIdAndRemindedUserAndRemindedFalse(reminderId, aUserInAServer));
}
@Override
public Optional<Reminder> getReminderByAndByUser(AUserInAServer aUserInAServer, Long reminderId) {
return Optional.ofNullable(reminderRepository.getByIdAndRemindedUser(reminderId, aUserInAServer));
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../dbchangelog-3.8.xsd" >
<include file="remind-seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,20 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
<property name="remindFeature" value="(SELECT id FROM feature WHERE key = 'remind')"/>
<changeSet author="Sheldan" id="snooze-command">
<insert tableName="command">
<column name="name" value="snooze"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${remindFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="command.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -7,4 +7,5 @@
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog-3.8.xsd" >
<include file="1.0-remind/collection.xml" relativeToChangelogFile="true"/>
<include file="1.2.10-remind/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,21 @@
package dev.sheldan.abstracto.remind.exception;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
public class NotPossibleToSnoozeException extends AbstractoRunTimeException implements Templatable {
public NotPossibleToSnoozeException() {
super("Reminder has not yet finished. Not possible to snooze");
}
@Override
public String getTemplateName() {
return "reminder_snooze_not_possible_exception";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -11,4 +11,5 @@ public interface ReminderService {
Reminder createReminderInForUser(AUserInAServer user, String remindText, Duration remindIn, Long channelId, Long messageId);
void executeReminder(Long reminderId);
void unRemind(Long reminderId, AUserInAServer userInAServer);
void snoozeReminder(Long reminderId, AUserInAServer user, Duration newDuration);
}

View File

@@ -16,4 +16,5 @@ public interface ReminderManagementService {
Reminder saveReminder(Reminder reminder);
List<Reminder> getActiveRemindersForUser(AUserInAServer aUserInAServer);
Optional<Reminder> getReminderByAndByUserNotReminded(AUserInAServer aUserInAServer, Long reminderId);
Optional<Reminder> getReminderByAndByUser(AUserInAServer aUserInAServer, Long reminderId);
}

View File

@@ -7,15 +7,17 @@ Feature key: `remind`
==== Commands
Create a reminder::
* Usage: `remind <duration> <text>`
* Description: Creates a reminder with `text` which will be triggered after `duration`. This command uses duration parsing. The reminder will ping when the duration has passed and provide
the context of the reminder.
* Description: Creates a reminder with `text` which will be triggered after `duration`. This command uses duration parsing. The reminder will ping when the duration has passed and provide the context of the reminder.
* Example: `remind 1h2m3s text` in order to be reminded in 1 hour 2 minutes and 3 seconds with the reason `text`
Cancelling a reminder::
* Usage `unRemind <reminderId>`
* Description: Cancels this reminder reminder and will cause this reminder to not be executed.
* Description: Cancels this reminder and will cause this reminder to not be executed. Only possible for reminders started by you.
Listing all active reminders::
* Usage: `reminders`
* Description: Lists all the currently not yet executed reminders and information about each of them.
Re-schedule a past reminder::
* Usage: `snooze <reminderId> <duration>`
* Description: Schedules the reminder identified by `reminderId` to be triggered after `duration` again. It is only possible to do this for reminders which have already been executed. Only possible for reminders started by you.
=== Starboard