renamed feature display to feature config

added concept of feature dependencies, if one feature depends on another feature, and it gets enabled, the other feature is enabled as well
changed some feature related apis
added ability to automatically decay warnings (separate feature)
added command to trigger the warn decay manually
added command to decay all active warnings
added method to scheduler service to directly start a cron job
This commit is contained in:
Sheldan
2020-04-29 21:25:26 +02:00
parent 85c47db5ed
commit d5482fabd4
60 changed files with 571 additions and 97 deletions

View File

@@ -0,0 +1,53 @@
package dev.sheldan.abstracto.moderation.commands;
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.FeatureEnum;
import dev.sheldan.abstracto.moderation.config.ModerationModule;
import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures;
import dev.sheldan.abstracto.moderation.service.WarnService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class DecayAllWarnings extends AbstractConditionableCommand {
@Autowired
private WarnService warnService;
@Override
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Boolean logWarnings = !parameters.isEmpty() ? (Boolean) parameters.get(0) : Boolean.FALSE;
warnService.decayAllWarningsForServer(commandContext.getUserInitiatedContext().getServer(), logWarnings);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
Parameter logWarnings = Parameter.builder().optional(true).type(Boolean.class).build();
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
parameters.add(logWarnings);
return CommandConfiguration.builder()
.name("decayAllWarnings")
.module(ModerationModule.MODERATION)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return ModerationFeatures.WARNING;
}
}

View File

@@ -0,0 +1,49 @@
package dev.sheldan.abstracto.moderation.commands;
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.FeatureEnum;
import dev.sheldan.abstracto.moderation.config.ModerationModule;
import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures;
import dev.sheldan.abstracto.moderation.service.WarnService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class DecayWarnings extends AbstractConditionableCommand {
@Autowired
private WarnService warnService;
@Override
public CommandResult execute(CommandContext commandContext) {
warnService.decayWarningsForServer(commandContext.getUserInitiatedContext().getServer());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("decayWarnings")
.module(ModerationModule.MODERATION)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return ModerationFeatures.AUTOMATIC_WARN_DECAY;
}
}

View File

@@ -0,0 +1,53 @@
package dev.sheldan.abstracto.moderation.job;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.moderation.config.features.WarningDecayFeature;
import dev.sheldan.abstracto.moderation.service.WarnService;
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;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Slf4j
@DisallowConcurrentExecution
@Component
@PersistJobDataAfterExecution
public class WarnDecayJob extends QuartzJobBean {
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private FeatureFlagManagementService featureFlagManagementService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private WarningDecayFeature warningDecayFeature;
@Autowired
private WarnService warnService;
@Override
@Transactional
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
List<AServer> allServers = serverManagementService.getAllServers();
allServers.forEach(server -> {
boolean featureEnabled = featureFlagService.isFeatureEnabled(warningDecayFeature, server);
if(featureEnabled) {
warnService.decayWarningsForServer(server);
}
});
}
}

View File

@@ -0,0 +1,23 @@
package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.listener.ServerConfigListener;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class WarnDecayConfigListener implements ServerConfigListener {
@Autowired
private ConfigManagementService configManagementService;
@Value("${abstracto.warnings.warnDecay.days}")
private Long decayDays;
@Override
public void updateServerConfig(AServer server) {
configManagementService.createIfNotExists(server.getId(), "decayDays", decayDays.doubleValue());
}
}

View File

@@ -1,7 +1,14 @@
package dev.sheldan.abstracto.moderation.repository;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.moderation.models.database.Warning;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.time.Instant;
import java.util.List;
@Repository
public interface WarnRepository extends JpaRepository<Warning, Long> {
List<Warning> findAllByWarnedUser_ServerReferenceAndDecayedFalseAndWarnDateLessThan(AServer server, Instant cutOffDate);
}

View File

@@ -2,7 +2,11 @@ package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.FullUser;
import dev.sheldan.abstracto.core.models.context.ServerContext;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.moderation.models.template.job.WarnDecayLogModel;
import dev.sheldan.abstracto.moderation.models.template.job.WarnDecayWarning;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.moderation.models.template.commands.WarnLog;
import dev.sheldan.abstracto.moderation.models.template.commands.WarnNotification;
@@ -17,6 +21,12 @@ import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Component
@@ -42,6 +52,9 @@ public class WarnServiceBean implements WarnService {
@Autowired
private MessageService messageService;
@Autowired
private ConfigService configService;
private static final String WARN_LOG_TEMPLATE = "warn_log";
private static final String WARN_NOTIFICATION_TEMPLATE = "warn_notification";
@@ -95,6 +108,54 @@ public class WarnServiceBean implements WarnService {
this.sendWarnLog(warnLog);
}
@Override
@Transactional
public void decayWarningsForServer(AServer server) {
Double days = configService.getDoubleValue("decayDays", server.getId());
Instant cutOffDay = Instant.now().minus(days.longValue(), ChronoUnit.DAYS);
List<Warning> warningsToDecay = warnManagementService.getActiveWarningsInServerOlderThan(server, cutOffDay);
decayWarnings(warningsToDecay);
logDecayedWarnings(server, warningsToDecay);
}
private void decayWarnings(List<Warning> warningsToDecay) {
Instant now = Instant.now();
warningsToDecay.forEach(warning -> {
warning.setDecayDate(now);
warning.setDecayed(true);
});
}
private void logDecayedWarnings(AServer server, List<Warning> warningsToDecay) {
List<WarnDecayWarning> warnDecayWarnings = new ArrayList<>();
warningsToDecay.forEach(warning -> {
WarnDecayWarning warnDecayWarning = WarnDecayWarning
.builder()
.warnedMember(botService.getMemberInServer(warning.getWarnedUser()))
.warningMember(botService.getMemberInServer(warning.getWarningUser()))
.warning(warning)
.build();
warnDecayWarnings.add(warnDecayWarning);
});
WarnDecayLogModel warnDecayLogModel = WarnDecayLogModel
.builder()
.guild(botService.getGuildByIdNullable(server.getId()))
.server(server)
.warnings(warnDecayWarnings)
.build();
MessageToSend messageToSend = templateService.renderEmbedTemplate("warn_decay_log", warnDecayLogModel);
postTargetService.sendEmbedInPostTarget(messageToSend, "decayLog", server.getId());
}
@Override
public void decayAllWarningsForServer(AServer server, Boolean logWarnings) {
List<Warning> warningsToDecay = warnManagementService.getActiveWarningsInServerOlderThan(server, Instant.now());
decayWarnings(warningsToDecay);
if(logWarnings) {
logDecayedWarnings(server, warningsToDecay);
}
}
private void sendWarnLog(ServerContext warnLogModel) {
MessageToSend message = templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, warnLogModel);
postTargetService.sendEmbedInPostTarget(message, WARN_LOG_TARGET, warnLogModel.getServer().getId());

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.moderation.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.moderation.models.database.Warning;
import dev.sheldan.abstracto.moderation.repository.WarnRepository;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
@@ -7,6 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.List;
@Component
public class WarnManagementServiceBean implements WarnManagementService {
@@ -21,8 +23,14 @@ public class WarnManagementServiceBean implements WarnManagementService {
.warnedUser(warnedAUser)
.warningUser(warningAUser)
.warnDate(Instant.now())
.decayed(false)
.build();
warnRepository.save(warning);
return warning;
}
@Override
public List<Warning> getActiveWarningsInServerOlderThan(AServer server, Instant date) {
return warnRepository.findAllByWarnedUser_ServerReferenceAndDecayedFalseAndWarnDateLessThan(server, date);
}
}

View File

@@ -1,12 +1,21 @@
abstracto.postTargets.moderation=joinLog,leaveLog,warnLog,kickLog,banLog,editLog,deleteLog,muteLog
abstracto.postTargets.moderation=joinLog,leaveLog,warnLog,kickLog,banLog,editLog,deleteLog,muteLog,decayLog
abstracto.features.moderation=false
abstracto.features.warning=false
abstracto.features.logging=true
abstracto.features.mutes=true
abstracto.warnings.warnDecay.days=90
abstracto.scheduling.jobs.unMuteJob.name=unMuteJob
abstracto.scheduling.jobs.unMuteJob.group=moderation
abstracto.scheduling.jobs.unMuteJob.clazz=dev.sheldan.abstracto.moderation.job.UnMuteJob
abstracto.scheduling.jobs.unMuteJob.standAlone=false
abstracto.scheduling.jobs.unMuteJob.active=true
abstracto.scheduling.jobs.unMuteJob.recovery=false
abstracto.scheduling.jobs.unMuteJob.recovery=false
abstracto.scheduling.jobs.warnDecayJob.name=warnDecayJob
abstracto.scheduling.jobs.warnDecayJob.group=moderation
abstracto.scheduling.jobs.warnDecayJob.clazz=dev.sheldan.abstracto.moderation.job.WarnDecayJob
abstracto.scheduling.jobs.warnDecayJob.standAlone=true
abstracto.scheduling.jobs.warnDecayJob.active=true
abstracto.scheduling.jobs.warnDecayJob.cronExpression=0 0 * * * ?
abstracto.scheduling.jobs.warnDecayJob.recovery=false

View File

@@ -0,0 +1 @@
Decays all warnings which are currently active on this server, and logs them to the `decayLog` post target, if the parameter was true.

View File

@@ -0,0 +1 @@
Causes the warnings older than the configured threshold in days to be decayed. They are still stored but there is an indication, that they are now longer active.

View File

@@ -0,0 +1,17 @@
{
"title": {
"title": "Warnings have been decayed"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"description": "<#list warnings as warning>
<#if warning.warnedMember??>${warning.warnedMember.asMention} (${warning.warnedMember.id})<#else>${warning.warning.warnedUser.userReference.id?c}</#if> was warned on ${formatInstant(warning.warning.warnDate, "yyyy-MM-dd HH:mm:ss")}
with reason `${warning.warning.reason}` by <#if warning.warningMember??>${warning.warningMember.asMention} (${warning.warningMember.id})<#else>${warning.warning.warningUser.userReference.id?c}</#if>
<#else>
No warnings to decay.
</#list>"
}