[AB-240] changing invite filter to actively filter the server instead of only being based on the code

moving invite filter to separate module
updating to newer liquibase version
changing concept of immune roles which are directly associated to commands to immune roles which are immune against certain effects. these effects can be configured directly by the command (and a condition checks this effect), but they can be used in services as well, unrelated to commands
adding checks to not execute message received listeners for the wrong message types
adding metric support for 502 status
fixing duplicating help entries when two module definitions with the same key are present
This commit is contained in:
Sheldan
2021-05-10 20:45:34 +02:00
parent 9ae35a7e9d
commit e31d257e6f
389 changed files with 21069 additions and 18187 deletions

View File

@@ -1,52 +0,0 @@
package dev.sheldan.abstracto.moderation.command;
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.moderation.config.ModerationModuleDefinition;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterServiceBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class AllowInvite extends AbstractConditionableCommand {
@Autowired
private InviteLinkFilterServiceBean inviteLinkFilterServiceBean;
@Override
public CommandResult execute(CommandContext commandContext) {
String inviteLink = (String) commandContext.getParameters().getParameters().get(0);
inviteLinkFilterServiceBean.allowInvite(inviteLink, commandContext.getGuild().getIdLong());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("invite").type(String.class).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("allowInvite")
.module(ModerationModuleDefinition.MODERATION)
.templated(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return ModerationFeatureDefinition.INVITE_FILTER;
}
}

View File

@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.EffectConfig;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
@@ -20,9 +21,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.moderation.service.BanService.BAN_EFFECT_KEY;
@Component
@Slf4j
public class Ban extends AbstractConditionableCommand {
@@ -55,11 +59,13 @@ public class Ban extends AbstractConditionableCommand {
parameters.add(Parameter.builder().name("user").templated(true).type(Member.class).build());
parameters.add(Parameter.builder().name("reason").templated(true).type(String.class).optional(true).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
List<EffectConfig> effectConfig = Arrays.asList(EffectConfig.builder().position(0).effectKey(BAN_EFFECT_KEY).build());
return CommandConfiguration.builder()
.name("ban")
.module(ModerationModuleDefinition.MODERATION)
.templated(true)
.async(true)
.effects(effectConfig)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)

View File

@@ -1,52 +0,0 @@
package dev.sheldan.abstracto.moderation.command;
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.moderation.config.ModerationModuleDefinition;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterServiceBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class DisAllowInvite extends AbstractConditionableCommand {
@Autowired
private InviteLinkFilterServiceBean inviteLinkFilterServiceBean;
@Override
public CommandResult execute(CommandContext commandContext) {
String inviteLink = (String) commandContext.getParameters().getParameters().get(0);
inviteLinkFilterServiceBean.disAllowInvite(inviteLink, commandContext.getGuild().getIdLong());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("invite").type(String.class).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("disAllowInvite")
.module(ModerationModuleDefinition.MODERATION)
.templated(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return ModerationFeatureDefinition.INVITE_FILTER;
}
}

View File

@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.EffectConfig;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
@@ -19,9 +20,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.moderation.service.KickService.KICK_EFFECT_KEY;
@Component
public class Kick extends AbstractConditionableCommand {
@@ -51,6 +55,7 @@ public class Kick extends AbstractConditionableCommand {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("user").templated(true).type(Member.class).build());
parameters.add(Parameter.builder().name("reason").templated(true).type(String.class).optional(true).remainder(true).build());
List<EffectConfig> effectConfig = Arrays.asList(EffectConfig.builder().position(0).effectKey(KICK_EFFECT_KEY).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
return CommandConfiguration.builder()
.name("kick")
@@ -58,6 +63,7 @@ public class Kick extends AbstractConditionableCommand {
.templated(true)
.supportsEmbedException(true)
.async(true)
.effects(effectConfig)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)

View File

@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.EffectConfig;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
@@ -20,9 +21,12 @@ import org.springframework.stereotype.Component;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.moderation.service.MuteService.MUTE_EFFECT_KEY;
@Component
public class Mute extends AbstractConditionableCommand {
@@ -63,11 +67,13 @@ public class Mute extends AbstractConditionableCommand {
parameters.add(Parameter.builder().name("duration").templated(true).type(Duration.class).build());
parameters.add(Parameter.builder().name("reason").templated(true).type(String.class).optional(true).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
List<EffectConfig> effectConfig = Arrays.asList(EffectConfig.builder().position(0).effectKey(MUTE_EFFECT_KEY).build());
return CommandConfiguration.builder()
.name("mute")
.module(ModerationModuleDefinition.MODERATION)
.templated(true)
.async(true)
.effects(effectConfig)
.causesReaction(true)
.supportsEmbedException(true)
.parameters(parameters)

View File

@@ -1,65 +0,0 @@
package dev.sheldan.abstracto.moderation.command;
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.config.FeatureMode;
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.feature.mode.InviteFilterMode;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Component
public class RemoveTrackedInviteLinks extends AbstractConditionableCommand {
@Autowired
private InviteLinkFilterService inviteLinkFilterService;
@Override
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
if(!parameters.isEmpty()) {
String invite = (String) parameters.get(0);
inviteLinkFilterService.clearAllUses(invite, commandContext.getGuild().getIdLong());
} else {
inviteLinkFilterService.clearAllTrackedInviteCodes(commandContext.getGuild().getIdLong());
}
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("invite").type(String.class).optional(true).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("removeTrackedInviteLinks")
.module(ModerationModuleDefinition.MODERATION)
.templated(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return ModerationFeatureDefinition.INVITE_FILTER;
}
@Override
public List<FeatureMode> getFeatureModeLimitations() {
return Arrays.asList(InviteFilterMode.TRACK_USES);
}
}

View File

@@ -1,86 +0,0 @@
package dev.sheldan.abstracto.moderation.command;
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.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.feature.mode.InviteFilterMode;
import dev.sheldan.abstracto.moderation.model.database.FilteredInviteLink;
import dev.sheldan.abstracto.moderation.model.template.command.TrackedInviteLinksModel;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class ShowTrackedInviteLinks extends AbstractConditionableCommand {
@Autowired
private InviteLinkFilterService inviteLinkFilterService;
@Autowired
private ChannelService channelService;
@Autowired
private TemplateService templateService;
public static final String TRACKED_INVITE_LINKS_EMBED_TEMPLATE_KEY = "showTrackedInviteLinks_response";
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
TrackedInviteLinksModel model = (TrackedInviteLinksModel) ContextConverter.slimFromCommandContext(commandContext, TrackedInviteLinksModel.class);
List<Object> parameters = commandContext.getParameters().getParameters();
List<FilteredInviteLink> inviteLinks;
if(!parameters.isEmpty()) {
Integer count = (Integer) parameters.get(0);
inviteLinks = inviteLinkFilterService.getTopFilteredInviteLinks(commandContext.getGuild().getIdLong(), count);
} else {
inviteLinks = inviteLinkFilterService.getTopFilteredInviteLinks(commandContext.getGuild().getIdLong());
}
model.setInviteLinks(inviteLinks);
MessageToSend messageToSend = templateService.renderEmbedTemplate(TRACKED_INVITE_LINKS_EMBED_TEMPLATE_KEY, model, commandContext.getGuild().getIdLong());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("amount").type(Integer.class).optional(true).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("showTrackedInviteLinks")
.module(ModerationModuleDefinition.MODERATION)
.templated(true)
.async(true)
.supportsEmbedException(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return ModerationFeatureDefinition.INVITE_FILTER;
}
@Override
public List<FeatureMode> getFeatureModeLimitations() {
return Arrays.asList(InviteFilterMode.TRACK_USES);
}
}

View File

@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.EffectConfig;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
@@ -20,9 +21,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.moderation.service.WarnService.WARN_EFFECT_KEY;
@Component
@Slf4j
public class Warn extends AbstractConditionableCommand {
@@ -53,6 +57,7 @@ public class Warn extends AbstractConditionableCommand {
parameters.add(Parameter.builder().name("user").type(Member.class).templated(true).build());
parameters.add(Parameter.builder().name("reason").type(String.class).templated(true).optional(true).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
List<EffectConfig> effectConfig = Arrays.asList(EffectConfig.builder().position(0).effectKey(WARN_EFFECT_KEY).build());
return CommandConfiguration.builder()
.name("warn")
.module(ModerationModuleDefinition.MODERATION)
@@ -60,6 +65,7 @@ public class Warn extends AbstractConditionableCommand {
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.effects(effectConfig)
.parameters(parameters)
.help(helpInfo)
.build();

View File

@@ -1,156 +0,0 @@
package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.ListenerPriority;
import dev.sheldan.abstracto.core.listener.ConsumableListenerResult;
import dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListener;
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
import dev.sheldan.abstracto.core.metric.service.MetricService;
import dev.sheldan.abstracto.core.metric.service.MetricTag;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.feature.mode.InviteFilterMode;
import dev.sheldan.abstracto.moderation.config.posttarget.InviteFilterPostTarget;
import dev.sheldan.abstracto.moderation.model.template.listener.DeletedInvite;
import dev.sheldan.abstracto.moderation.model.template.listener.DeletedInvitesNotificationModel;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
@Component
@Slf4j
public class InviteLinkFilterListener implements MessageReceivedListener {
@Autowired
private InviteLinkFilterService inviteLinkFilterService;
@Autowired
private FeatureModeService featureModeService;
@Autowired
private PostTargetService postTargetService;
@Autowired
private TemplateService templateService;
@Autowired
private MetricService metricService;
@Autowired
private MessageService messageService;
public static final String MODERATION_PURGE_METRIC = "invite.filter";
public static final String CONSEQUENCE = "consequence";
private static final CounterMetric MESSAGE_INVITE_FILTERED =
CounterMetric
.builder()
.tagList(Arrays.asList(MetricTag.getTag(CONSEQUENCE, "filtered")))
.name(MODERATION_PURGE_METRIC)
.build();
public static final String INVITE_LINK_DELETED_NOTIFICATION_EMBED_TEMPLATE_KEY = "invite_link_deleted_notification";
@Override
public ConsumableListenerResult execute(MessageReceivedModel model) {
Message message = model.getMessage();
Long serverId = message.getGuild().getIdLong();
Matcher matcher = Message.INVITE_PATTERN.matcher(message.getContentRaw());
ServerUser author = ServerUser.builder().userId(message.getAuthor().getIdLong()).serverId(message.getGuild().getIdLong()).build();
boolean toDelete = false;
List<String> codesToTrack = new ArrayList<>();
while(matcher.find()) {
String code = matcher.group("code");
boolean codeFiltered = inviteLinkFilterService.isCodeFiltered(code, author);
if(codeFiltered) {
codesToTrack.add(code);
toDelete = true;
}
}
if(toDelete) {
metricService.incrementCounter(MESSAGE_INVITE_FILTERED);
messageService.deleteMessage(message);
boolean trackUsages = featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, serverId, InviteFilterMode.TRACK_USES);
if(trackUsages) {
codesToTrack.forEach(s -> inviteLinkFilterService.storeFilteredInviteLinkUsage(s, author));
}
boolean sendNotification = featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, serverId, InviteFilterMode.FILTER_NOTIFICATIONS);
if(sendNotification) {
sendDeletionNotification(codesToTrack, message);
}
return ConsumableListenerResult.DELETED;
} else {
return ConsumableListenerResult.PROCESSED;
}
}
private void sendDeletionNotification(List<String> codes, Message message) {
Long serverId = message.getGuild().getIdLong();
if(!postTargetService.postTargetDefinedInServer(InviteFilterPostTarget.INVITE_DELETE_LOG, serverId)) {
log.info("Post target {} not defined for server {} - not sending invite link deletion notification.", InviteFilterPostTarget.INVITE_DELETE_LOG.getKey(), serverId);
return;
}
DeletedInvitesNotificationModel model = DeletedInvitesNotificationModel
.builder()
.author(message.getMember())
.guild(message.getGuild())
.message(message)
.channel(message.getTextChannel())
.invites(groupInvites(codes))
.build();
log.info("Sending notification about {} deleted invite links in guild {} from user {} in channel {} in message {}.",
codes.size(), serverId, message.getAuthor().getIdLong(), message.getTextChannel().getIdLong(), message.getIdLong());
MessageToSend messageToSend = templateService.renderEmbedTemplate(INVITE_LINK_DELETED_NOTIFICATION_EMBED_TEMPLATE_KEY, model, message.getGuild().getIdLong());
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, InviteFilterPostTarget.INVITE_DELETE_LOG, serverId);
FutureUtils.toSingleFutureGeneric(messageFutures).thenAccept(unused ->
log.debug("Successfully send notification about deleted invite link in message {}.", message.getIdLong())
).exceptionally(throwable -> {
log.error("Failed to send notification about deleted invite link in message {}.", message.getIdLong());
return null;
});
}
private List<DeletedInvite> groupInvites(List<String> codes) {
return codes
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.map(functionLongEntry -> new DeletedInvite(functionLongEntry.getKey(), functionLongEntry.getValue()))
.collect(Collectors.toList());
}
@Override
public FeatureDefinition getFeature() {
return ModerationFeatureDefinition.INVITE_FILTER;
}
@Override
public Integer getPriority() {
return ListenerPriority.HIGH;
}
@PostConstruct
public void postConstruct() {
metricService.registerCounter(MESSAGE_INVITE_FILTERED, "Amount of messages containing an invite filtered");
}
}

View File

@@ -1,16 +0,0 @@
package dev.sheldan.abstracto.moderation.repository;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.moderation.model.database.AllowedInviteLink;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface AllowedInviteLinkRepository extends JpaRepository<AllowedInviteLink, Long> {
Optional<AllowedInviteLink> findByCodeAndServer(String code, AServer server);
Optional<AllowedInviteLink> findByCodeAndServer_Id(String code, Long serverId);
}

View File

@@ -1,23 +0,0 @@
package dev.sheldan.abstracto.moderation.repository;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.moderation.model.database.FilteredInviteLink;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface FilteredInviteLinkRepository extends JpaRepository<FilteredInviteLink, Long> {
Optional<FilteredInviteLink> findByCodeAndServer(String code, AServer server);
Optional<FilteredInviteLink> findByCodeAndServer_Id(String code, Long serverId);
void deleteByServer_Id(Long serverId);
void deleteByCodeAndServer_Id(String code, Long serverId);
List<FilteredInviteLink> findAllByServer_IdOrderByUsesDesc(Long serverId, Pageable pageable);
}

View File

@@ -1,112 +0,0 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.moderation.exception.InvalidInviteException;
import dev.sheldan.abstracto.moderation.model.database.FilteredInviteLink;
import dev.sheldan.abstracto.moderation.service.management.AllowedInviteLinkManagement;
import dev.sheldan.abstracto.moderation.service.management.FilteredInviteLinkManagement;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Component
public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
@Autowired
private AllowedInviteLinkManagement allowedInviteLinkManagement;
@Autowired
private FilteredInviteLinkManagement filteredInviteLinkManagement;
@Autowired
private ServerManagementService serverManagementService;
private static final Pattern INVITE_CODE_PATTERN = Pattern.compile("(?<code>[a-z0-9-]+)", Pattern.CASE_INSENSITIVE);
@Override
public boolean isCodeFiltered(String code, ServerUser serverUser) {
return !isCodeAllowed(code, serverUser);
}
@Override
public boolean isCodeAllowed(String code, ServerUser serverUser) {
return allowedInviteLinkManagement.allowedInviteLinkExists(serverUser, code);
}
@Override
public boolean isCodeAllowed(String code, Long serverId) {
return allowedInviteLinkManagement.allowedInviteLinkExists(serverId, code);
}
@Override
public void storeFilteredInviteLinkUsage(String code, ServerUser serverUser) {
Optional<FilteredInviteLink> inviteLinkOptional = filteredInviteLinkManagement.findInviteLinkViaCode(serverUser.getServerId(), code);
if(inviteLinkOptional.isPresent()) {
inviteLinkOptional.ifPresent(filteredInviteLink -> filteredInviteLink.setUses(filteredInviteLink.getUses() + 1));
} else {
AServer server = serverManagementService.loadServer(serverUser.getServerId());
filteredInviteLinkManagement.createFilteredInviteLink(server, code);
}
}
@Override
public void allowInvite(String invite, Long serverId) {
String inviteCode = extractCode(invite);
if(isCodeAllowed(inviteCode, serverId)) {
return;
}
AServer server = serverManagementService.loadServer(serverId);
allowedInviteLinkManagement.createAllowedInviteLink(server, inviteCode);
}
private String extractCode(String invite) {
Matcher matcher = Message.INVITE_PATTERN.matcher(invite);
String inviteCode;
if(matcher.find()) {
inviteCode = matcher.group("code");
} else {
Matcher codeOnlyMatcher = INVITE_CODE_PATTERN.matcher(invite);
if(codeOnlyMatcher.find()) {
inviteCode = codeOnlyMatcher.group("code");
} else {
throw new InvalidInviteException("Invalid invite was provided.");
}
}
return inviteCode;
}
@Override
public void disAllowInvite(String invite, Long serverId) {
String inviteCode = extractCode(invite);
AServer server = serverManagementService.loadServer(serverId);
allowedInviteLinkManagement.removeAllowedInviteLink(server, inviteCode);
}
@Override
public void clearAllTrackedInviteCodes(Long serverId) {
filteredInviteLinkManagement.clearFilteredInviteLinks(serverId);
}
@Override
public void clearAllUses(String code, Long serverId) {
String inviteCode = extractCode(code);
filteredInviteLinkManagement.clearFilteredInviteLink(inviteCode, serverId);
}
@Override
public List<FilteredInviteLink> getTopFilteredInviteLinks(Long serverId, Integer count) {
return filteredInviteLinkManagement.getTopFilteredInviteLink(serverId, count);
}
@Override
public List<FilteredInviteLink> getTopFilteredInviteLinks(Long serverId) {
return getTopFilteredInviteLinks(serverId, 5);
}
}

View File

@@ -1,48 +0,0 @@
package dev.sheldan.abstracto.moderation.service.management;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.moderation.exception.AllowedInviteLinkNotFound;
import dev.sheldan.abstracto.moderation.model.database.AllowedInviteLink;
import dev.sheldan.abstracto.moderation.repository.AllowedInviteLinkRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AllowedInviteLinkManagementBean implements AllowedInviteLinkManagement {
@Autowired
private AllowedInviteLinkRepository repository;
@Override
public AllowedInviteLink createAllowedInviteLink(AServer server, String code) {
AllowedInviteLink inviteLink = AllowedInviteLink.builder().code(code).server(server).build();
return repository.save(inviteLink);
}
@Override
public void removeAllowedInviteLink(AServer server, String code) {
AllowedInviteLink existingCode = findAllowedInviteLinkByCode(server, code);
repository.delete(existingCode);
}
@Override
public AllowedInviteLink findAllowedInviteLinkByCode(AServer server, String code) {
return repository.findByCodeAndServer(code, server).orElseThrow(() -> new AllowedInviteLinkNotFound("Allowed invite code not found."));
}
@Override
public boolean allowedInviteLinkExists(AServer server, String code) {
return repository.findByCodeAndServer(code, server).isPresent();
}
@Override
public boolean allowedInviteLinkExists(Long serverId, String code) {
return repository.findByCodeAndServer_Id(code, serverId).isPresent();
}
@Override
public boolean allowedInviteLinkExists(ServerUser serverUser, String code) {
return repository.findByCodeAndServer_Id(code, serverUser.getServerId()).isPresent();
}
}

View File

@@ -1,64 +0,0 @@
package dev.sheldan.abstracto.moderation.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.moderation.model.database.FilteredInviteLink;
import dev.sheldan.abstracto.moderation.repository.FilteredInviteLinkRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
public class FilteredInviteLinkManagementBean implements FilteredInviteLinkManagement {
@Autowired
private FilteredInviteLinkRepository repository;
@Override
public FilteredInviteLink createFilteredInviteLink(AServer server, String code) {
FilteredInviteLink inviteLink = FilteredInviteLink
.builder()
.code(code)
.server(server)
.uses(1L)
.build();
return repository.save(inviteLink);
}
@Override
public Optional<FilteredInviteLink> findInviteLinkViaCode(AServer server, String code) {
return repository.findByCodeAndServer(code, server);
}
@Override
public Optional<FilteredInviteLink> findInviteLinkViaCode(Long serverId, String code) {
return repository.findByCodeAndServer_Id(code, serverId);
}
@Override
public void clearFilteredInviteLinks(Long serverId) {
repository.deleteByServer_Id(serverId);
}
@Override
public void clearFilteredInviteLinks(AServer server) {
clearFilteredInviteLinks(server.getId());
}
@Override
public void clearFilteredInviteLink(String code, Long serverId) {
repository.deleteByCodeAndServer_Id(code, serverId);
}
@Override
public void clearFilteredInviteLink(String code, AServer server) {
clearFilteredInviteLink(code, server.getId());
}
@Override
public List<FilteredInviteLink> getTopFilteredInviteLink(Long serverId, Integer count) {
return repository.findAllByServer_IdOrderByUsesDesc(serverId, PageRequest.of(0, count));
}
}

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="moderation-tables/tables.xml" relativeToChangelogFile="true"/>
<include file="moderation-seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<property name="moderationModule" value="(SELECT id FROM module WHERE name = 'moderation')"/>
<property name="moderationFeature" value="(SELECT id FROM feature WHERE key = 'moderation')"/>
<property name="warningsFeature" value="(SELECT id FROM feature WHERE key = 'warnings')"/>
@@ -13,7 +13,6 @@
<property name="mutingFeature" value="(SELECT id FROM feature WHERE key = 'muting')"/>
<property name="warnDecayFeature" value="(SELECT id FROM feature WHERE key = 'warnDecay')"/>
<property name="userNotesFeature" value="(SELECT id FROM feature WHERE key = 'userNotes')"/>
<property name="inviteLinkFilteringFeature" value="(SELECT id FROM feature WHERE key = 'inviteFilter')"/>
<changeSet author="Sheldan" id="moderation_moderation-commands">
<insert tableName="command">
@@ -115,27 +114,4 @@
</insert>
</changeSet>
<changeSet author="Sheldan" id="moderation_inviteFilter-commands">
<insert tableName="command">
<column name="name" value="allowInvite"/>
<column name="module_id" valueComputed="${moderationModule}"/>
<column name="feature_id" valueComputed="${inviteLinkFilteringFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="disAllowInvite"/>
<column name="module_id" valueComputed="${moderationModule}"/>
<column name="feature_id" valueComputed="${inviteLinkFilteringFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="removeTrackedInviteLinks"/>
<column name="module_id" valueComputed="${moderationModule}"/>
<column name="feature_id" valueComputed="${inviteLinkFilteringFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="showTrackedInviteLinks"/>
<column name="module_id" valueComputed="${moderationModule}"/>
<column name="feature_id" valueComputed="${inviteLinkFilteringFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="un_mute_job.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="warn_decay_job.xml" relativeToChangelogFile="true"/>

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="moderation_feature-insertion">
<insert tableName="feature">
<column name="key" value="moderation"/>
@@ -22,8 +22,5 @@
<insert tableName="feature">
<column name="key" value="userNotes"/>
</insert>
<insert tableName="feature">
<column name="key" value="inviteFilter"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -3,12 +3,17 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="moderation-module-insertion">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">
SELECT COUNT(*) FROM module WHERE name='moderation';
</sqlCheck>
</preConditions>
<insert tableName="module">
<column name="name" value="moderation"/>
<column name="name" value="moderation"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="un-mute-job-insert">
<insert tableName="scheduler_job">
<column name="name" value="unMuteJob"/>

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="warn-decay-job-insert">
<insert tableName="scheduler_job">
<column name="name" value="warnDecayJob"/>

View File

@@ -1,41 +0,0 @@
<?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" >
<changeSet author="Sheldan" id="allowed_invite_link-table">
<createTable tableName="allowed_invite_link">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="allowed_invite_link_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="code" type="VARCHAR(32)">
<constraints nullable="false"/>
</column>
<column name="server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
<createIndex indexName="idx_allowed_invite_code_server" tableName="allowed_invite_link">
<column name="code"/>
<column name="server_id"/>
</createIndex>
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="allowed_invite_link" constraintName="fk_allowed_invite_link_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS allowed_invite_link_update_trigger ON allowed_invite_link;
CREATE TRIGGER allowed_invite_link_update_trigger BEFORE UPDATE ON allowed_invite_link FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS allowed_invite_link_insert_trigger ON allowed_invite_link;
CREATE TRIGGER allowed_invite_link_insert_trigger BEFORE INSERT ON allowed_invite_link FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -1,47 +0,0 @@
<?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" >
<changeSet author="Sheldan" id="filtered_invite_link-table">
<createTable tableName="filtered_invite_link">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="filtered_invite_link_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="uses" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="code" type="VARCHAR(32)">
<constraints nullable="false"/>
</column>
<column name="server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
<createIndex indexName="idx_filtered_invite_link_server" tableName="filtered_invite_link">
<column name="server_id"/>
</createIndex>
<createIndex indexName="idx_filtered_invite_link_code_server" tableName="filtered_invite_link">
<column name="code"/>
<column name="server_id"/>
</createIndex>
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="filtered_invite_link" constraintName="fk_filtered_invite_link_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS filtered_invite_link_update_trigger ON filtered_invite_link;
CREATE TRIGGER filtered_invite_link_update_trigger BEFORE UPDATE ON filtered_invite_link FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS filtered_invite_link_insert_trigger ON filtered_invite_link;
CREATE TRIGGER filtered_invite_link_insert_trigger BEFORE INSERT ON filtered_invite_link FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="mute-table">
<createTable tableName="mute">
<column name="id" type="BIGINT" />

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="mute_role-table">
<createTable tableName="mute_role">

View File

@@ -3,13 +3,11 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="mute.xml" relativeToChangelogFile="true"/>
<include file="mute_role.xml" relativeToChangelogFile="true"/>
<include file="user_note.xml" relativeToChangelogFile="true"/>
<include file="warning.xml" relativeToChangelogFile="true"/>
<include file="allowed_invite_link.xml" relativeToChangelogFile="true"/>
<include file="filtered_invite_link.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="user_note-table">
<createTable tableName="user_note">
<column autoIncrement="true" name="id" type="BIGINT" >

View File

@@ -3,9 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="warning-table">
<createTable tableName="warning">
<column name="id" type="BIGINT">

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.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="moderation-seedData/data.xml" relativeToChangelogFile="true"/>
</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.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="effect_types.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,23 @@
<?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.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="moderation_effect_types-insertion">
<insert tableName="effect_type">
<column name="effect_type_key" value="ban"/>
</insert>
<insert tableName="effect_type">
<column name="effect_type_key" value="mute"/>
</insert>
<insert tableName="effect_type">
<column name="effect_type_key" value="kick"/>
</insert>
<insert tableName="effect_type">
<column name="effect_type_key" value="warn"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -257,6 +257,7 @@
<xsd:attributeGroup name="changeLogAttributes">
<xsd:attribute name="logicalFilePath" type="xsd:string"/>
<xsd:attribute name="context" type="xsd:string"/>
<xsd:attribute name="changeLogId" type="xsd:string"/>
<xsd:attribute name="objectQuotingStrategy" type="objectQuotingStrategy" default="LEGACY"/>
</xsd:attributeGroup>
@@ -277,11 +278,12 @@
<xsd:attribute name="created" type="xsd:string"/>
<xsd:attribute name="runOrder" type="xsd:string"/>
<xsd:attribute name="ignore" type="booleanExp"/>
<xsd:attribute name="runWith" type="xsd:string" />
</xsd:attributeGroup>
<!-- Attributes for changes -->
<xsd:attributeGroup name="changeAttributes">
<xsd:anyAttribute namespace="##any" processContents="lax"/>
<xsd:anyAttribute namespace="##other" processContents="lax"/>
</xsd:attributeGroup>
<!-- Attributes for constraints -->
@@ -306,7 +308,7 @@
<xsd:attribute name="validateNullable" type="booleanExp"/>
<xsd:attribute name="validateUnique" type="booleanExp"/>
<xsd:attribute name="validatePrimaryKey" type="booleanExp"/>
<xsd:attribute name="validateForeignKey " type="booleanExp"/>
<xsd:attribute name="validateForeignKey" type="booleanExp"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="column">
@@ -420,9 +422,10 @@
<xsd:attribute name="incrementBy" type="xsd:string"/>
<xsd:attribute name="maxValue" type="xsd:string"/>
<xsd:attribute name="minValue" type="xsd:string"/>
<xsd:attribute name="ordered" type="booleanExp"/>
<xsd:attribute name="ordered" type="xsd:string"/>
<xsd:attribute name="cacheSize" type="xsd:string"/>
<xsd:attribute name="cycle" type="booleanExp">
<xsd:attribute name="dataType" type="xsd:string" />
<xsd:attribute name="cycle" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
true for a cycling sequence, false for a non-cycling sequence.
@@ -481,11 +484,15 @@
<xsd:attributeGroup ref="changeAttributes"/>
<xsd:attributeGroup ref="tableNameAttribute"/>
<xsd:attribute name="constraintName" type="xsd:string"/>
<xsd:attribute name="dropIndex" type="booleanExp"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="addUniqueConstraint">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
</xsd:choice>
<xsd:attributeGroup ref="changeAttributes"/>
<xsd:attributeGroup ref="tableNameAttribute"/>
<xsd:attribute name="columnNames" type="xsd:string"
@@ -616,6 +623,7 @@
<xsd:attribute name="header" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="allowUpdate" type="booleanExp"/>
<xsd:attribute name="defaultValue" type="xsd:string"/>
<xsd:attribute name="defaultValueNumeric" type="xsd:string"/>
<xsd:attribute name="defaultValueDate" type="xsd:string"/>
@@ -919,6 +927,7 @@
<xsd:attribute name="schemaName" type="xsd:string"/>
<xsd:attribute name="tableName" type="xsd:string" use="required"/>
<xsd:attribute name="columnName" type="xsd:string" use="required"/>
<xsd:attribute name="columnDataType" type="xsd:string"/>
<xsd:attribute name="remarks" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
@@ -957,6 +966,7 @@
<xsd:attributeGroup ref="tableNameAttribute"/>
<xsd:attribute name="tablespace" type="xsd:string"/>
<xsd:attribute name="remarks" type="xsd:string"/>
<xsd:anyAttribute namespace="##other" processContents="lax"/>
</xsd:complexType>
</xsd:element>
@@ -1124,7 +1134,7 @@
<xsd:complexType>
<xsd:attributeGroup ref="changeAttributes"/>
<xsd:attribute name="tag" type="xsd:string" use="required"/>
<xsd:anyAttribute namespace="##other" processContents="lax"/>
</xsd:complexType>
</xsd:element>
@@ -1226,7 +1236,6 @@
<xsd:complexType>
<xsd:attributeGroup ref="changeAttributes"/>
<xsd:attributeGroup ref="sequenceAttributes"/>
<xsd:attribute name="dataType" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
@@ -1283,7 +1292,7 @@
</xsd:sequence>
<xsd:attributeGroup ref="changeAttributes"/>
<xsd:attribute name="class" type="xsd:string" use="required"/>
<xsd:anyAttribute processContents="lax" />
</xsd:complexType>
</xsd:element>
@@ -1374,4 +1383,4 @@
</xsd:sequence>
</xsd:group>
</xsd:schema>
</xsd:schema>

View File

@@ -3,8 +3,9 @@
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" >
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="1.0-moderation/collection.xml" relativeToChangelogFile="true"/>
<include file="1.2.11-moderation/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -16,15 +16,11 @@ abstracto.featureFlags.muting.enabled=false
abstracto.featureFlags.userNotes.featureName=userNotes
abstracto.featureFlags.userNotes.enabled=false
abstracto.featureFlags.inviteFilter.featureName=inviteFilter
abstracto.featureFlags.inviteFilter.enabled=false
abstracto.postTargets.warnLog.name=warnLog
abstracto.postTargets.kickLog.name=kickLog
abstracto.postTargets.banLog.name=banLog
abstracto.postTargets.muteLog.name=muteLog
abstracto.postTargets.decayLog.name=decayLog
abstracto.postTargets.inviteDeleteLog.name=inviteDeleteLog
abstracto.featureModes.banLogging.featureName=moderation
@@ -58,12 +54,3 @@ abstracto.featureModes.unMuteLogging.enabled=true
abstracto.featureModes.manualUnMuteLogging.featureName=muting
abstracto.featureModes.manualUnMuteLogging.mode=manualUnMuteLogging
abstracto.featureModes.manualUnMuteLogging.enabled=true
abstracto.featureModes.trackUses.featureName=inviteFilter
abstracto.featureModes.trackUses.mode=trackUses
abstracto.featureModes.trackUses.enabled=true
abstracto.featureModes.filterNotifications.featureName=inviteFilter
abstracto.featureModes.filterNotifications.mode=filterNotifications
abstracto.featureModes.filterNotifications.enabled=true

View File

@@ -1,44 +0,0 @@
package dev.sheldan.abstracto.moderation.command.invite;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.moderation.command.AllowInvite;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterServiceBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class AllowInviteTest {
@InjectMocks
private AllowInvite testUnit;
@Mock
private InviteLinkFilterServiceBean inviteLinkFilterServiceBean;
private static final String INVITE_STRING = "invite";
@Test
public void testExecuteCommand() {
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(INVITE_STRING));
CommandResult result = testUnit.execute(parameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(inviteLinkFilterServiceBean, times(1)).allowInvite(INVITE_STRING, parameters.getGuild().getIdLong());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -1,44 +0,0 @@
package dev.sheldan.abstracto.moderation.command.invite;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.moderation.command.DisAllowInvite;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterServiceBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class DisAllowInviteTest {
@InjectMocks
private DisAllowInvite testUnit;
@Mock
private InviteLinkFilterServiceBean inviteLinkFilterServiceBean;
private static final String INVITE_STRING = "invite";
@Test
public void testExecuteCommand() {
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(INVITE_STRING));
CommandResult result = testUnit.execute(parameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(inviteLinkFilterServiceBean, times(1)).disAllowInvite(INVITE_STRING, parameters.getGuild().getIdLong());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -1,52 +0,0 @@
package dev.sheldan.abstracto.moderation.command.invite;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.moderation.command.RemoveTrackedInviteLinks;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class RemoveTrackedInviteLinksTest {
@InjectMocks
private RemoveTrackedInviteLinks testUnit;
@Mock
private InviteLinkFilterService inviteLinkFilterService;
private static final String INVITE_STRING = "invite";
@Test
public void testExecuteCommandNoParameter() {
CommandContext parameters = CommandTestUtilities.getNoParameters();
CommandResult result = testUnit.execute(parameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(inviteLinkFilterService, times(1)).clearAllTrackedInviteCodes(parameters.getGuild().getIdLong());
}
@Test
public void testExecuteCommandForSpecificInvite() {
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(INVITE_STRING));
CommandResult result = testUnit.execute(parameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(inviteLinkFilterService, times(1)).clearAllUses(INVITE_STRING, parameters.getGuild().getIdLong());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -1,76 +0,0 @@
package dev.sheldan.abstracto.moderation.command.invite;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.moderation.command.ShowTrackedInviteLinks;
import dev.sheldan.abstracto.moderation.model.database.FilteredInviteLink;
import dev.sheldan.abstracto.moderation.model.template.command.TrackedInviteLinksModel;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.moderation.command.ShowTrackedInviteLinks.TRACKED_INVITE_LINKS_EMBED_TEMPLATE_KEY;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class ShowTrackedInviteLinksTest {
@InjectMocks
private ShowTrackedInviteLinks testUnit;
@Mock
private InviteLinkFilterService inviteLinkFilterService;
@Mock
private ChannelService channelService;
@Mock
private TemplateService templateService;
private static final Long SERVER_ID = 1L;
@Test
public void testExecuteCommandNoParameter() {
CommandContext parameters = CommandTestUtilities.getNoParameters();
when(parameters.getGuild().getIdLong()).thenReturn(SERVER_ID);
FilteredInviteLink filteredInviteLink = Mockito.mock(FilteredInviteLink.class);
when(inviteLinkFilterService.getTopFilteredInviteLinks(parameters.getGuild().getIdLong())).thenReturn(Arrays.asList(filteredInviteLink));
MessageToSend messageToSend = Mockito.mock(MessageToSend.class);
when(templateService.renderEmbedTemplate(eq(TRACKED_INVITE_LINKS_EMBED_TEMPLATE_KEY), any(TrackedInviteLinksModel.class), eq(SERVER_ID))).thenReturn(messageToSend);
when(channelService.sendMessageToSendToChannel(messageToSend, parameters.getChannel())).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> resultFuture = testUnit.executeAsync(parameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(resultFuture);
}
@Test
public void testExecuteCommandAmountParameter() {
Integer amount = 4;
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(amount));
when(parameters.getGuild().getIdLong()).thenReturn(SERVER_ID);
FilteredInviteLink filteredInviteLink = Mockito.mock(FilteredInviteLink.class);
when(inviteLinkFilterService.getTopFilteredInviteLinks(parameters.getGuild().getIdLong(), amount)).thenReturn(Arrays.asList(filteredInviteLink));
MessageToSend messageToSend = Mockito.mock(MessageToSend.class);
when(templateService.renderEmbedTemplate(eq(TRACKED_INVITE_LINKS_EMBED_TEMPLATE_KEY), any(TrackedInviteLinksModel.class), eq(SERVER_ID))).thenReturn(messageToSend);
when(channelService.sendMessageToSendToChannel(messageToSend, parameters.getChannel())).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> resultFuture = testUnit.executeAsync(parameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(resultFuture);
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -1,199 +0,0 @@
package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.listener.ConsumableListenerResult;
import dev.sheldan.abstracto.core.metric.service.MetricService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.feature.mode.InviteFilterMode;
import dev.sheldan.abstracto.moderation.config.posttarget.InviteFilterPostTarget;
import dev.sheldan.abstracto.moderation.model.template.listener.DeletedInvitesNotificationModel;
import dev.sheldan.abstracto.moderation.service.InviteLinkFilterService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.concurrent.CompletableFuture;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class InviteLinkFilterListenerTest {
@InjectMocks
private InviteLinkFilterListener testUnit;
@Mock
private InviteLinkFilterService inviteLinkFilterService;
@Mock
private FeatureModeService featureModeService;
@Mock
private PostTargetService postTargetService;
@Mock
private TemplateService templateService;
@Mock
private MessageService messageService;
@Mock
private Message message;
@Mock
private User author;
@Mock
private TextChannel textChannel;
@Mock
private Guild guild;
@Mock
private MetricService metricService;
@Mock
private MessageReceivedModel model;
private static final Long SERVER_ID = 1L;
private static final Long CHANNEL_ID = 2L;
private static final Long USER_ID = 3L;
private static final Long MESSAGE_ID = 4L;
private static final String INVITE_CODE = "asdf";
private static final String INVITE_LINK = "discord.gg/" + INVITE_CODE;
@Test
public void testExecutionWithNoInvite() {
when(message.getContentRaw()).thenReturn("text");
setupBasicMessage();
when(model.getMessage()).thenReturn(message);
ConsumableListenerResult result = testUnit.execute(model);
Assert.assertEquals(ConsumableListenerResult.PROCESSED, result);
}
@Test
public void testExecutionWithOneAllowedInvite() {
when(message.getContentRaw()).thenReturn(INVITE_LINK);
when(inviteLinkFilterService.isCodeFiltered(eq(INVITE_CODE), any(ServerUser.class))).thenReturn(false);
setupBasicMessage();
when(model.getMessage()).thenReturn(message);
ConsumableListenerResult result = testUnit.execute(model);
Assert.assertEquals(ConsumableListenerResult.PROCESSED, result);
}
@Test
public void testExecutionWithOneNotAllowedInviteNoTrackNoNotification() {
when(message.getContentRaw()).thenReturn(INVITE_LINK);
when(messageService.deleteMessage(message)).thenReturn(CompletableFuture.completedFuture(null));
when(inviteLinkFilterService.isCodeFiltered(eq(INVITE_CODE), any(ServerUser.class))).thenReturn(true);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.TRACK_USES)).thenReturn(false);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(false);
setupBasicMessage();
when(model.getMessage()).thenReturn(message);
ConsumableListenerResult result = testUnit.execute(model);
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
verify(metricService, times(1)).incrementCounter(any());
}
@Test
public void testExecutionWithOneNotAllowedInviteTrackNoNotification() {
when(message.getContentRaw()).thenReturn(INVITE_LINK);
when(messageService.deleteMessage(message)).thenReturn(CompletableFuture.completedFuture(null));
when(inviteLinkFilterService.isCodeFiltered(eq(INVITE_CODE), any(ServerUser.class))).thenReturn(true);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.TRACK_USES)).thenReturn(true);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(false);
setupBasicMessage();
when(model.getMessage()).thenReturn(message);
ConsumableListenerResult result = testUnit.execute(model);
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
verifyTracking();
verify(metricService, times(1)).incrementCounter(any());
}
@Test
public void testExecutionWithOneNotAllowedInviteTrackNotification() {
when(message.getContentRaw()).thenReturn(INVITE_LINK);
when(messageService.deleteMessage(message)).thenReturn(CompletableFuture.completedFuture(null));
when(inviteLinkFilterService.isCodeFiltered(eq(INVITE_CODE), any(ServerUser.class))).thenReturn(true);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.TRACK_USES)).thenReturn(true);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(true);
setupForNotification();
setupBasicMessage();
when(model.getMessage()).thenReturn(message);
ConsumableListenerResult result = testUnit.execute(model);
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
verifyTracking();
verify(metricService, times(1)).incrementCounter(any());
}
@Test
public void testExecutionWithOneNotAllowedInviteNoTrackNotification() {
when(message.getContentRaw()).thenReturn(INVITE_LINK);
when(messageService.deleteMessage(message)).thenReturn(CompletableFuture.completedFuture(null));
when(inviteLinkFilterService.isCodeFiltered(eq(INVITE_CODE), any(ServerUser.class))).thenReturn(true);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.TRACK_USES)).thenReturn(false);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(true);
setupForNotification();
setupBasicMessage();
when(model.getMessage()).thenReturn(message);
ConsumableListenerResult result = testUnit.execute(model);
verify(metricService, times(1)).incrementCounter(any());
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
verify(inviteLinkFilterService, times(0)).storeFilteredInviteLinkUsage(eq(INVITE_CODE), any(ServerUser.class));
}
@Test
public void testExecutionWithOneNotAllowedInviteNoTrackNotificationNoPostTarget() {
when(message.getContentRaw()).thenReturn(INVITE_LINK);
when(messageService.deleteMessage(message)).thenReturn(CompletableFuture.completedFuture(null));
when(inviteLinkFilterService.isCodeFiltered(eq(INVITE_CODE), any(ServerUser.class))).thenReturn(true);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.TRACK_USES)).thenReturn(false);
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(true);
when(postTargetService.postTargetDefinedInServer(InviteFilterPostTarget.INVITE_DELETE_LOG, SERVER_ID)).thenReturn(false);
setupBasicMessage();
when(model.getMessage()).thenReturn(message);
ConsumableListenerResult result = testUnit.execute(model);
verify(metricService, times(1)).incrementCounter(any());
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
verify(inviteLinkFilterService, times(0)).storeFilteredInviteLinkUsage(eq(INVITE_CODE), any(ServerUser.class));
verify(templateService, times(0)).renderEmbedTemplate(eq(InviteLinkFilterListener.INVITE_LINK_DELETED_NOTIFICATION_EMBED_TEMPLATE_KEY), any(DeletedInvitesNotificationModel.class), eq(SERVER_ID));
}
private void verifyTracking() {
verify(inviteLinkFilterService, times(1)).storeFilteredInviteLinkUsage(eq(INVITE_CODE), any(ServerUser.class));
}
private void setupForNotification() {
when(postTargetService.postTargetDefinedInServer(InviteFilterPostTarget.INVITE_DELETE_LOG, SERVER_ID)).thenReturn(true);
MessageToSend messageToSend = Mockito.mock(MessageToSend.class);
when(templateService.renderEmbedTemplate(eq(InviteLinkFilterListener.INVITE_LINK_DELETED_NOTIFICATION_EMBED_TEMPLATE_KEY), any(DeletedInvitesNotificationModel.class), eq(SERVER_ID))).thenReturn(messageToSend);
when(postTargetService.sendEmbedInPostTarget(messageToSend, InviteFilterPostTarget.INVITE_DELETE_LOG, SERVER_ID)).thenReturn(CommandTestUtilities.messageFutureList());
when(textChannel.getIdLong()).thenReturn(CHANNEL_ID);
when(message.getIdLong()).thenReturn(MESSAGE_ID);
when(message.getTextChannel()).thenReturn(textChannel);
}
private void setupBasicMessage() {
when(message.getAuthor()).thenReturn(author);
when(author.getIdLong()).thenReturn(USER_ID);
when(message.getGuild()).thenReturn(guild);
when(guild.getIdLong()).thenReturn(SERVER_ID);
}
}

View File

@@ -1,155 +0,0 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.moderation.exception.InvalidInviteException;
import dev.sheldan.abstracto.moderation.model.database.FilteredInviteLink;
import dev.sheldan.abstracto.moderation.service.management.AllowedInviteLinkManagement;
import dev.sheldan.abstracto.moderation.service.management.FilteredInviteLinkManagement;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class InviteLinkFilterServiceBeanTest {
@InjectMocks
private InviteLinkFilterServiceBean testUnit;
@Mock
private AllowedInviteLinkManagement allowedInviteLinkManagement;
@Mock
private FilteredInviteLinkManagement filteredInviteLinkManagement;
@Mock
private ServerManagementService serverManagementService;
@Mock
private AServer server;
@Mock
private ServerUser serverUser;
private static final String INVITE_CODE = "asdf";
private static final String FULL_INVITE = "discord.gg/" + INVITE_CODE;
private static final Long SERVER_ID = 1L;
@Test
public void testIsCodeAllowedViaId() {
when(allowedInviteLinkManagement.allowedInviteLinkExists(SERVER_ID, FULL_INVITE)).thenReturn(true);
boolean codeAllowed = testUnit.isCodeAllowed(FULL_INVITE, SERVER_ID);
Assert.assertTrue(codeAllowed);
}
@Test
public void testIsCodeAllowed() {
when(allowedInviteLinkManagement.allowedInviteLinkExists(serverUser, FULL_INVITE)).thenReturn(true);
boolean codeAllowed = testUnit.isCodeAllowed(FULL_INVITE, serverUser);
Assert.assertTrue(codeAllowed);
}
@Test
public void testIsCodeFiltered() {
when(allowedInviteLinkManagement.allowedInviteLinkExists(serverUser, FULL_INVITE)).thenReturn(true);
boolean codeAllowed = testUnit.isCodeFiltered(FULL_INVITE, serverUser);
Assert.assertFalse(codeAllowed);
}
@Test
public void testStoreFilteredInviteLinkUsage() {
when(serverUser.getServerId()).thenReturn(SERVER_ID);
FilteredInviteLink mockedFilteredInviteLink = Mockito.mock(FilteredInviteLink.class);
when(mockedFilteredInviteLink.getUses()).thenReturn(1L);
when(filteredInviteLinkManagement.findInviteLinkViaCode(SERVER_ID, FULL_INVITE)).thenReturn(Optional.of(mockedFilteredInviteLink));
testUnit.storeFilteredInviteLinkUsage(FULL_INVITE, serverUser);
verify(mockedFilteredInviteLink, times(1)).setUses(2L);
}
@Test
public void testStoreFilteredInviteLinkUsageNotPresent() {
when(serverUser.getServerId()).thenReturn(SERVER_ID);
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
when(filteredInviteLinkManagement.findInviteLinkViaCode(SERVER_ID, FULL_INVITE)).thenReturn(Optional.empty());
testUnit.storeFilteredInviteLinkUsage(FULL_INVITE, serverUser);
verify(filteredInviteLinkManagement, times(1)).createFilteredInviteLink(server, FULL_INVITE);
}
@Test
public void testAllowInvite() {
when(allowedInviteLinkManagement.allowedInviteLinkExists(SERVER_ID, INVITE_CODE)).thenReturn(false);
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
testUnit.allowInvite(FULL_INVITE, SERVER_ID);
verify(allowedInviteLinkManagement, times(1)).createAllowedInviteLink(server, INVITE_CODE);
}
@Test(expected = InvalidInviteException.class)
public void testAllowInviteIllegalInvite() {
testUnit.allowInvite("#", SERVER_ID);
}
@Test
public void testAllowInviteInviteCode() {
when(allowedInviteLinkManagement.allowedInviteLinkExists(SERVER_ID, INVITE_CODE)).thenReturn(false);
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
testUnit.allowInvite(INVITE_CODE, SERVER_ID);
verify(allowedInviteLinkManagement, times(1)).createAllowedInviteLink(server, INVITE_CODE);
}
@Test
public void testAllowInviteAlreadyPresent() {
when(allowedInviteLinkManagement.allowedInviteLinkExists(SERVER_ID, INVITE_CODE)).thenReturn(true);
testUnit.allowInvite(FULL_INVITE, SERVER_ID);
verify(allowedInviteLinkManagement, times(0)).createAllowedInviteLink(any(AServer.class), anyString());
}
@Test
public void testDisallowInvite() {
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
testUnit.disAllowInvite(FULL_INVITE, SERVER_ID);
verify(allowedInviteLinkManagement, times(1)).removeAllowedInviteLink(server, INVITE_CODE);
}
@Test
public void testClearAllTrackedInviteCodes() {
testUnit.clearAllTrackedInviteCodes(SERVER_ID);
verify(filteredInviteLinkManagement, times(1)).clearFilteredInviteLinks(SERVER_ID);
}
@Test
public void testClearAllUses() {
testUnit.clearAllUses(FULL_INVITE, SERVER_ID);
verify(filteredInviteLinkManagement, times(1)).clearFilteredInviteLink(INVITE_CODE, SERVER_ID);
}
@Test
public void testGetTopFilteredInviteLinksWithCount() {
int count = 4;
FilteredInviteLink mockedFilteredInviteLink = Mockito.mock(FilteredInviteLink.class);
when(filteredInviteLinkManagement.getTopFilteredInviteLink(SERVER_ID, count)).thenReturn(Arrays.asList(mockedFilteredInviteLink));
List<FilteredInviteLink> filteredInviteLinks = testUnit.getTopFilteredInviteLinks(SERVER_ID, count);
Assert.assertEquals(1, filteredInviteLinks.size());
Assert.assertEquals(mockedFilteredInviteLink, filteredInviteLinks.get(0));
}
@Test
public void testGetTopFilteredInviteLinksDefaultCount() {
FilteredInviteLink mockedFilteredInviteLink = Mockito.mock(FilteredInviteLink.class);
when(filteredInviteLinkManagement.getTopFilteredInviteLink(SERVER_ID, 5)).thenReturn(Arrays.asList(mockedFilteredInviteLink));
List<FilteredInviteLink> filteredInviteLinks = testUnit.getTopFilteredInviteLinks(SERVER_ID);
Assert.assertEquals(1, filteredInviteLinks.size());
Assert.assertEquals(mockedFilteredInviteLink, filteredInviteLinks.get(0));
}
}

View File

@@ -1,98 +0,0 @@
package dev.sheldan.abstracto.moderation.service.management;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.moderation.exception.AllowedInviteLinkNotFound;
import dev.sheldan.abstracto.moderation.model.database.AllowedInviteLink;
import dev.sheldan.abstracto.moderation.repository.AllowedInviteLinkRepository;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Optional;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class AllowedInviteLinkManagementBeanTest {
@InjectMocks
private AllowedInviteLinkManagementBean testUnit;
@Mock
private AllowedInviteLinkRepository repository;
@Mock
private AServer server;
@Mock
private AllowedInviteLink mockedInviteLink;
private static final Long SERVER_ID = 1L;
private static final String INVITE = "invite";
@Captor
private ArgumentCaptor<AllowedInviteLink> linkCaptor;
@Test
public void testCreateAllowedInviteLink() {
when(repository.save(linkCaptor.capture())).thenReturn(mockedInviteLink);
AllowedInviteLink allowedInviteLink = testUnit.createAllowedInviteLink(server, INVITE);
verify(repository, times(1)).save(linkCaptor.capture());
Assert.assertEquals(allowedInviteLink, mockedInviteLink);
AllowedInviteLink repositoryAllowedInviteLink = linkCaptor.getValue();
Assert.assertEquals(server, repositoryAllowedInviteLink.getServer());
Assert.assertEquals(INVITE, repositoryAllowedInviteLink.getCode());
}
@Test
public void testRemoveAllowedInviteLink() {
when(repository.findByCodeAndServer(INVITE, server)).thenReturn(Optional.of(mockedInviteLink));
testUnit.removeAllowedInviteLink(server, INVITE);
verify(repository, times(1)).delete(mockedInviteLink);
}
@Test(expected = AllowedInviteLinkNotFound.class)
public void testRemoveNotPresentAllowedInviteLink() {
when(repository.findByCodeAndServer(INVITE, server)).thenReturn(Optional.empty());
testUnit.removeAllowedInviteLink(server, INVITE);
}
@Test
public void testFindAllowedInviteLinkByCode() {
when(repository.findByCodeAndServer(INVITE, server)).thenReturn(Optional.of(mockedInviteLink));
AllowedInviteLink allowedInviteLinkByCode = testUnit.findAllowedInviteLinkByCode(server, INVITE);
Assert.assertEquals(mockedInviteLink, allowedInviteLinkByCode);
}
@Test(expected = AllowedInviteLinkNotFound.class)
public void testFindNotPresentAllowedInviteLinkByCode() {
when(repository.findByCodeAndServer(INVITE, server)).thenReturn(Optional.empty());
testUnit.findAllowedInviteLinkByCode(server, INVITE);
}
@Test
public void testAllowedInviteLinkExists() {
when(repository.findByCodeAndServer(INVITE, server)).thenReturn(Optional.of(mockedInviteLink));
boolean exists = testUnit.allowedInviteLinkExists(server, INVITE);
Assert.assertTrue(exists);
}
@Test
public void testAllowedInviteLinkExistsViaId() {
when(repository.findByCodeAndServer_Id(INVITE, SERVER_ID)).thenReturn(Optional.of(mockedInviteLink));
boolean exists = testUnit.allowedInviteLinkExists(SERVER_ID, INVITE);
Assert.assertTrue(exists);
}
@Test
public void testAllowedInviteLinkExistsViaServerUser() {
ServerUser serverUser = Mockito.mock(ServerUser.class);
when(serverUser.getServerId()).thenReturn(SERVER_ID);
when(repository.findByCodeAndServer_Id(INVITE, SERVER_ID)).thenReturn(Optional.of(mockedInviteLink));
boolean exists = testUnit.allowedInviteLinkExists(serverUser, INVITE);
Assert.assertTrue(exists);
}
}

View File

@@ -1,105 +0,0 @@
package dev.sheldan.abstracto.moderation.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.moderation.model.database.FilteredInviteLink;
import dev.sheldan.abstracto.moderation.repository.FilteredInviteLinkRepository;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Pageable;
import java.util.Optional;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class FilteredInviteLinkManagementBeanTest {
@InjectMocks
private FilteredInviteLinkManagementBean testUnit;
@Mock
private FilteredInviteLinkRepository repository;
@Mock
private AServer server;
@Mock
private FilteredInviteLink mockedFilteredLink;
private static final String INVITE = "invite";
private static final Long SERVER_ID = 1L;
@Captor
private ArgumentCaptor<FilteredInviteLink> linkCaptor;
@Test
public void testCreateFilteredInviteLink() {
when(repository.save(linkCaptor.capture())).thenReturn(mockedFilteredLink);
FilteredInviteLink filteredInviteLink = testUnit.createFilteredInviteLink(server, INVITE);
verify(repository, times(1)).save(linkCaptor.capture());
Assert.assertEquals(filteredInviteLink, mockedFilteredLink);
FilteredInviteLink repositoryFilteredInviteLink = linkCaptor.getValue();
Assert.assertEquals(server, repositoryFilteredInviteLink.getServer());
Assert.assertEquals(INVITE, repositoryFilteredInviteLink.getCode());
Assert.assertEquals(1, repositoryFilteredInviteLink.getUses().intValue());
}
@Test
public void testFindInviteLinkViaCode() {
when(repository.findByCodeAndServer(INVITE, server)).thenReturn(Optional.of(mockedFilteredLink));
Optional<FilteredInviteLink> filteredInviteLinkOptional = testUnit.findInviteLinkViaCode(server, INVITE);
Assert.assertTrue(filteredInviteLinkOptional.isPresent());
filteredInviteLinkOptional.ifPresent(filteredInviteLink -> Assert.assertEquals(mockedFilteredLink, filteredInviteLink));
}
@Test
public void testFindInviteLinkViaCodeById() {
when(repository.findByCodeAndServer_Id(INVITE, SERVER_ID)).thenReturn(Optional.of(mockedFilteredLink));
Optional<FilteredInviteLink> filteredInviteLinkOptional = testUnit.findInviteLinkViaCode(SERVER_ID, INVITE);
Assert.assertTrue(filteredInviteLinkOptional.isPresent());
filteredInviteLinkOptional.ifPresent(filteredInviteLink -> Assert.assertEquals(mockedFilteredLink, filteredInviteLink));
}
@Test
public void testClearFilteredInviteLinksViaId() {
testUnit.clearFilteredInviteLinks(SERVER_ID);
verify(repository, times(1)).deleteByServer_Id(SERVER_ID);
}
@Test
public void testClearFilteredInviteLinks() {
when(server.getId()).thenReturn(SERVER_ID);
testUnit.clearFilteredInviteLinks(server);
verify(repository, times(1)).deleteByServer_Id(SERVER_ID);
}
@Test
public void testClearFilteredInviteLinkViaId() {
testUnit.clearFilteredInviteLink(INVITE, SERVER_ID);
verify(repository, times(1)).deleteByCodeAndServer_Id(INVITE, SERVER_ID);
}
@Test
public void testClearFilteredInviteLink() {
when(server.getId()).thenReturn(SERVER_ID);
testUnit.clearFilteredInviteLink(INVITE, server);
verify(repository, times(1)).deleteByCodeAndServer_Id(INVITE, SERVER_ID);
}
@Test
public void testGetTopFilteredInviteLink() {
Integer count = 4;
testUnit.getTopFilteredInviteLink(SERVER_ID, count);
ArgumentCaptor<Pageable> pageableArgumentCaptor = ArgumentCaptor.forClass(Pageable.class);
verify(repository, times(1)).findAllByServer_IdOrderByUsesDesc(eq(SERVER_ID), pageableArgumentCaptor.capture());
Pageable paginator = pageableArgumentCaptor.getValue();
Assert.assertEquals(count.intValue(), paginator.getPageSize());
Assert.assertEquals(0, paginator.getPageNumber());
}
}