added scheduling support

added remind command
added support for parameters with spaces (they are contained by ")
fixed support for remainder parameters
added maxlength support for parameters
added ability to embed templates, to have a text as well
moved properties to a more appropriate position
added method do parse a duration
This commit is contained in:
Sheldan
2020-03-28 20:12:59 +01:00
parent e0474a4c98
commit 03e81a025b
64 changed files with 1318 additions and 125 deletions

View File

@@ -17,6 +17,12 @@
<artifactId>utility-int</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.scheduling</groupId>
<artifactId>scheduling-int</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,52 @@
package dev.sheldan.abstracto.utility.command.remind;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.utility.Utility;
import dev.sheldan.abstracto.utility.models.template.ReminderModel;
import dev.sheldan.abstracto.utility.service.ReminderService;
import net.dv8tion.jda.api.entities.MessageEmbed;
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 Remind implements Command {
@Autowired
private ReminderService remindService;
@Override
public Result execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Duration remindTime = (Duration) parameters.get(0);
String text = (String) parameters.get(1);
AUserInAServer aUserInAServer = commandContext.getUserInitiatedContext().getAUserInAServer();
ReminderModel remindModel = (ReminderModel) ContextConverter.fromCommandContext(commandContext, ReminderModel.class);
remindModel.setMessage(commandContext.getMessage());
remindModel.setRemindText(text);
remindService.createReminderInForUser(aUserInAServer, text, remindTime, remindModel);
return Result.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("remindTime").type(Duration.class).build());
parameters.add(Parameter.builder().name("remindText").type(String.class).maxLength(MessageEmbed.TEXT_MAX_LENGTH).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("remind")
.module(Utility.UTILITY)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
}

View File

@@ -0,0 +1,37 @@
package dev.sheldan.abstracto.utility.jobs;
import dev.sheldan.abstracto.utility.service.ReminderService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
@Slf4j
@DisallowConcurrentExecution
@Component
@PersistJobDataAfterExecution
public class ReminderJob extends QuartzJobBean {
private Long reminderId;
@Autowired
private ReminderService reminderService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
reminderService.executeReminder(reminderId);
log.info("executing reminder job for reminder {}", reminderId);
}
public Long getReminderId() {
return reminderId;
}
public void setReminderId(Long reminderId) {
this.reminderId = reminderId;
}
}

View File

@@ -0,0 +1,8 @@
package dev.sheldan.abstracto.utility.repository;
import dev.sheldan.abstracto.utility.models.Reminder;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ReminderRepository extends JpaRepository<Reminder, Long> {
}

View File

@@ -0,0 +1,101 @@
package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.embed.MessageToSend;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.scheduling.model.SchedulerService;
import dev.sheldan.abstracto.templating.TemplateService;
import dev.sheldan.abstracto.utility.models.Reminder;
import dev.sheldan.abstracto.utility.models.template.ExecutedReminderModel;
import dev.sheldan.abstracto.utility.models.template.ReminderModel;
import dev.sheldan.abstracto.utility.service.management.ReminderManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.TextChannel;
import org.quartz.JobDataMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class RemindServiceBean implements ReminderService {
public static final String REMINDER_EMBED_KEY = "remind_response";
@Autowired
private ReminderManagementService reminderManagementService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private SchedulerService schedulerService;
@Autowired
private Bot bot;
@Autowired
private ReminderService self;
@Override
public void createReminderInForUser(AUserInAServer user, String remindText, Duration remindIn, ReminderModel reminderModel) {
AChannel channel = channelManagementService.loadChannel(reminderModel.getChannel().getId());
AServerAChannelAUser aServerAChannelAUser = AServerAChannelAUser
.builder()
.user(user.getUserReference())
.aUserInAServer(user)
.guild(user.getServerReference())
.channel(channel)
.build();
Instant remindAt = Instant.now().plusNanos(remindIn.toNanos());
Reminder reminder = reminderManagementService.createReminder(aServerAChannelAUser, remindText, remindAt, reminderModel.getMessage().getIdLong());
reminderModel.setReminder(reminder);
MessageToSend message = templateService.renderEmbedTemplate(REMINDER_EMBED_KEY, reminderModel);
reminderModel.getTextChannel().sendMessage(message.getMessage()).embed(message.getEmbed()).queue();
if(remindIn.getSeconds() < 60) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.schedule(() -> {
self.executeReminder(reminder.getId());
}, remindIn.toNanos(), TimeUnit.NANOSECONDS);
} else {
JobDataMap parameters = new JobDataMap();
parameters.putAsString("reminderId", reminder.getId());
schedulerService.executeJobWithParametersOnce("reminderJob", "utility", parameters, Date.from(reminder.getTargetDate()));
}
}
@Override
@Transactional
public void executeReminder(Long reminderId) {
Reminder reminderToRemindFor = reminderManagementService.loadReminder(reminderId);
AServer server = reminderToRemindFor.getServer();
AChannel channel = reminderToRemindFor.getChannel();
AUser userReference = reminderToRemindFor.getToBeReminded().getUserReference();
Member memberInServer = bot.getMemberInServer(server.getId(), userReference.getId());
ExecutedReminderModel build = ExecutedReminderModel
.builder()
.reminder(reminderToRemindFor)
.member(memberInServer)
.build();
MessageToSend messageToSend = templateService.renderEmbedTemplate("remind_reminder", build);
// todo, if channel does not exist anymore
TextChannel channelToAnswerIn = bot.getTextChannelFromServer(server.getId(), channel.getId());
channelToAnswerIn.sendMessage(messageToSend.getMessage()).embed(messageToSend.getEmbed()).queue();
}
}

View File

@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.management.EmoteManagementService;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.embed.MessageToSend;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.PostTargetService;
@@ -55,12 +56,12 @@ public class SuggestionServiceBean implements SuggestionService {
Suggestion suggestion = suggestionManagementService.createSuggestion(member, text);
suggestionLog.setSuggestion(suggestion);
suggestionLog.setText(text);
MessageEmbed embed = templateService.renderEmbedTemplate(SUGGESTION_LOG_TEMPLATE, suggestionLog);
MessageToSend messageToSend = templateService.renderEmbedTemplate(SUGGESTION_LOG_TEMPLATE, suggestionLog);
long guildId = member.getGuild().getIdLong();
JDA instance = botService.getInstance();
Guild guildById = instance.getGuildById(guildId);
if(guildById != null) {
postTargetService.sendEmbedInPostTarget(embed, SUGGESTIONS_TARGET, guildId).thenAccept(message -> {
postTargetService.sendEmbedInPostTarget(messageToSend, SUGGESTIONS_TARGET, guildId).thenAccept(message -> {
messageService.addReactionToMessage(SUGGESTION_YES_EMOTE, guildId, message);
messageService.addReactionToMessage(SUGGESTION_NO_EMOTE, guildId, message);
suggestionManagementService.setPostedMessage(suggestion, message);
@@ -110,8 +111,8 @@ public class SuggestionServiceBean implements SuggestionService {
MessageEmbed suggestionEmbed = embedOptional.get();
suggestionLog.setReason(text);
suggestionLog.setText(suggestionEmbed.getDescription());
MessageEmbed embed = templateService.renderEmbedTemplate(SUGGESTION_LOG_TEMPLATE, suggestionLog);
postTargetService.sendEmbedInPostTarget(embed, SUGGESTIONS_TARGET, suggestionLog.getServer().getId());
MessageToSend messageToSend = templateService.renderEmbedTemplate(SUGGESTION_LOG_TEMPLATE, suggestionLog);
postTargetService.sendEmbedInPostTarget(messageToSend, SUGGESTIONS_TARGET, suggestionLog.getServer().getId());
}
}

View File

@@ -0,0 +1,39 @@
package dev.sheldan.abstracto.utility.service.management;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.utility.models.Reminder;
import dev.sheldan.abstracto.utility.repository.ReminderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Instant;
@Component
public class ReminderManagementServiceBean implements ReminderManagementService {
@Autowired
private ReminderRepository reminderRepository;
@Override
public Reminder createReminder(AServerAChannelAUser userToBeReminded, String text, Instant timeToBeRemindedAt, Long messageId) {
Reminder reminder = Reminder.builder()
.channel(userToBeReminded.getChannel())
.server(userToBeReminded.getGuild())
.toBeReminded(userToBeReminded.getAUserInAServer())
.reminded(false)
.text(text)
.reminderDate(Instant.now())
.targetDate(timeToBeRemindedAt)
.messageId(messageId)
.build();
reminderRepository.save(reminder);
return reminder;
}
@Override
public Reminder loadReminder(Long reminderId) {
return reminderRepository.getOne(reminderId);
}
}

View File

@@ -0,0 +1 @@
Reminds you in the given period of the given text.

View File

@@ -0,0 +1,13 @@
{
"author": {
"name": "${member.effectiveName}",
"avatar": "${member.user.effectiveAvatarUrl}"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"description": "You wanted to be reminded of: '${reminder.text}'. Original message was [here](${messageUrl}).",
"additionalMessage": "${member.asMention}"
}

View File

@@ -0,0 +1,13 @@
{
"author": {
"name": "${member.effectiveName}",
"avatar": "${member.user.effectiveAvatarUrl}"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"description": "Scheduled reminder ${reminder.id} to remind you of [this](${message.jumpUrl})",
"additionalMessage": "${member.asMention}"
}

View File

@@ -1,2 +1,8 @@
abstracto.postTargets.utility=suggestions
abstracto.emoteNames.suggestion=SUGGESTION_YES,SUGGESTION_NO
abstracto.emoteNames.suggestion=SUGGESTION_YES,SUGGESTION_NO
abstracto.scheduling.jobs.reminderJob.name=reminderJob
abstracto.scheduling.jobs.reminderJob.group=utility
abstracto.scheduling.jobs.reminderJob.clazz=dev.sheldan.abstracto.utility.jobs.ReminderJob
abstracto.scheduling.jobs.reminderJob.standAlone=false
abstracto.scheduling.jobs.reminderJob.active=true