[AB-261] fixing invite filter only acting in the message received event

This commit is contained in:
Sheldan
2021-05-23 16:45:36 +02:00
parent 13a6e1fdca
commit 23af59ab9d
5 changed files with 256 additions and 200 deletions

View File

@@ -0,0 +1,61 @@
package dev.sheldan.abstracto.invitefilter.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageUpdatedListener;
import dev.sheldan.abstracto.core.models.listener.MessageUpdatedModel;
import dev.sheldan.abstracto.invitefilter.config.InviteFilterFeatureDefinition;
import dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterService;
import dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterServiceBean;
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 java.util.List;
@Component
@Slf4j
public class InviteLinkFilterEditedListener implements AsyncMessageUpdatedListener {
@Autowired
private InviteLinkFilterService inviteLinkFilterService;
@Autowired
private InviteLinkFilterServiceBean filterServiceBean;
@Override
public FeatureDefinition getFeature() {
return InviteFilterFeatureDefinition.INVITE_FILTER;
}
@Override
public DefaultListenerResult execute(MessageUpdatedModel model) {
Message message = model.getAfter();
if(!message.isFromGuild() || message.isWebhookMessage() || message.getType().isSystem()) {
return DefaultListenerResult.IGNORED;
}
List<String> foundInvites = inviteLinkFilterService.findInvitesInMessage(message);
if(foundInvites.isEmpty()){
return DefaultListenerResult.IGNORED;
}
if(!inviteLinkFilterService.isInviteFilterActiveInChannel(message.getChannel())) {
return DefaultListenerResult.IGNORED;
}
if(inviteLinkFilterService.isMemberImmuneAgainstInviteFilter(message.getMember())) {
log.info("Not checking for invites in message, because author {} in channel {} in guild {} is immune against invite filter.",
message.getMember().getIdLong(), message.getGuild().getIdLong(), message.getChannel().getIdLong());
return DefaultListenerResult.IGNORED;
}
// only to reduce code duplication, the interface is too concrete
filterServiceBean.resolveAndCheckInvites(message, foundInvites);
return DefaultListenerResult.PROCESSED;
}
}

View File

@@ -3,39 +3,16 @@ package dev.sheldan.abstracto.invitefilter.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageReceivedListener;
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.*;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.invitefilter.config.InviteFilterFeatureDefinition;
import dev.sheldan.abstracto.invitefilter.config.InviteFilterMode;
import dev.sheldan.abstracto.invitefilter.config.InviteFilterPostTarget;
import dev.sheldan.abstracto.invitefilter.model.template.listener.DeletedInvite;
import dev.sheldan.abstracto.invitefilter.model.template.listener.DeletedInvitesNotificationModel;
import dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterService;
import dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterServiceBean;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Invite;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import static dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterService.INVITE_FILTER_CHANNEL_GROUP_TYPE;
import static dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterService.INVITE_FILTER_EFFECT_KEY;
import java.util.List;
@Component
@Slf4j
@@ -45,88 +22,13 @@ public class InviteLinkFilterListener implements AsyncMessageReceivedListener {
private InviteLinkFilterService inviteLinkFilterService;
@Autowired
private FeatureModeService featureModeService;
@Autowired
private PostTargetService postTargetService;
@Autowired
private TemplateService templateService;
@Autowired
private MetricService metricService;
@Autowired
private MessageService messageService;
@Autowired
private ChannelGroupService channelGroupService;
@Autowired
private RoleImmunityService roleImmunityService;
public static final String INVITE_FILTER_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(INVITE_FILTER_METRIC)
.build();
public static final String INVITE_LINK_DELETED_NOTIFICATION_EMBED_TEMPLATE_KEY = "invite_link_deleted_notification";
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.getChannel())
.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.getChannel().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());
}
private InviteLinkFilterServiceBean filterServiceBean;
@Override
public FeatureDefinition getFeature() {
return InviteFilterFeatureDefinition.INVITE_FILTER;
}
@PostConstruct
public void postConstruct() {
metricService.registerCounter(MESSAGE_INVITE_FILTERED, "Amount of messages containing an invite filtered");
}
private boolean isInviteFilterActiveInChannel(MessageChannel channel) {
return channelGroupService.isChannelInEnabledChannelGroupOfType(INVITE_FILTER_CHANNEL_GROUP_TYPE, channel.getIdLong());
}
@Override
public DefaultListenerResult execute(MessageReceivedModel model) {
Message message = model.getMessage();
@@ -135,72 +37,24 @@ public class InviteLinkFilterListener implements AsyncMessageReceivedListener {
return DefaultListenerResult.IGNORED;
}
List<String> foundInvites = new ArrayList<>();
Matcher matcher = Message.INVITE_PATTERN.matcher(message.getContentRaw());
while(matcher.find()) {
foundInvites.add(matcher.group("code"));
}
List<String> foundInvites = inviteLinkFilterService.findInvitesInMessage(message);
if(foundInvites.isEmpty()){
return DefaultListenerResult.IGNORED;
}
if(!isInviteFilterActiveInChannel(model.getMessage().getChannel())) {
if(!inviteLinkFilterService.isInviteFilterActiveInChannel(message.getChannel())) {
return DefaultListenerResult.IGNORED;
}
if(roleImmunityService.isImmune(message.getMember(), INVITE_FILTER_EFFECT_KEY)) {
if(inviteLinkFilterService.isMemberImmuneAgainstInviteFilter(message.getMember())) {
log.info("Not checking for invites in message, because author {} in channel {} in guild {} is immune against invite filter.",
message.getMember().getIdLong(), message.getGuild().getIdLong(), message.getChannel().getIdLong());
return DefaultListenerResult.IGNORED;
}
List<CompletableFuture<Invite>> inviteList = new ArrayList<>();
JDA jda = model.getMessage().getJDA();
foundInvites.forEach(s -> inviteList.add(inviteLinkFilterService.resolveInvite(jda, s)));
CompletableFutureList<Invite> list = new CompletableFutureList<>(inviteList);
list.getMainFuture().whenComplete((unused, throwable) -> {
List<Invite> invites = list.getObjects();
Long serverId = message.getGuild().getIdLong();
ServerUser author = ServerUser.builder().userId(message.getAuthor().getIdLong()).serverId(message.getGuild().getIdLong()).build();
boolean toDelete = false;
Map<Long, String> targetServers = new HashMap<>();
List<String> deletedInvites = new ArrayList<>();
for (Invite invite : invites) {
if (invite.getType().equals(Invite.InviteType.GUILD)
&& inviteLinkFilterService.isCodeFiltered(invite.getGuild().getIdLong(), author)) {
toDelete = true;
deletedInvites.add(invite.getCode());
targetServers.put(invite.getGuild().getIdLong(), invite.getGuild().getName());
}
}
List<String> unResolvedInvites = new ArrayList<>();
foundInvites.forEach(possibleUnresolvedInvite -> {
if(invites.stream().noneMatch(invite -> invite.getCode().equals(possibleUnresolvedInvite))) {
unResolvedInvites.add(possibleUnresolvedInvite);
}
});
for(String unresolvedInvite : unResolvedInvites) {
if(inviteLinkFilterService.isCodeFiltered(unresolvedInvite, author)) {
toDelete = true;
deletedInvites.add(unresolvedInvite);
}
}
if(toDelete) {
metricService.incrementCounter(MESSAGE_INVITE_FILTERED);
messageService.deleteMessage(message);
boolean trackUsages = featureModeService.featureModeActive(InviteFilterFeatureDefinition.INVITE_FILTER, serverId, InviteFilterMode.TRACK_USES);
if(trackUsages) {
targetServers.forEach((targetServerId, serverName) -> inviteLinkFilterService.storeFilteredInviteLinkUsage(targetServerId, serverName, author));
}
boolean sendNotification = featureModeService.featureModeActive(InviteFilterFeatureDefinition.INVITE_FILTER, serverId, InviteFilterMode.FILTER_NOTIFICATIONS);
if(sendNotification) {
sendDeletionNotification(deletedInvites, message);
}
}
});
// only to reduce code duplication, the interface is too concrete
filterServiceBean.resolveAndCheckInvites(message, foundInvites);
return DefaultListenerResult.PROCESSED;
}

View File

@@ -1,26 +1,43 @@
package dev.sheldan.abstracto.invitefilter.service;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
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.database.AServer;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.invitefilter.config.InviteFilterFeatureDefinition;
import dev.sheldan.abstracto.invitefilter.config.InviteFilterMode;
import dev.sheldan.abstracto.invitefilter.config.InviteFilterPostTarget;
import dev.sheldan.abstracto.invitefilter.exception.InvalidInviteException;
import dev.sheldan.abstracto.invitefilter.model.database.FilteredInviteLink;
import dev.sheldan.abstracto.invitefilter.model.template.listener.DeletedInvite;
import dev.sheldan.abstracto.invitefilter.model.template.listener.DeletedInvitesNotificationModel;
import dev.sheldan.abstracto.invitefilter.service.management.AllowedInviteLinkManagement;
import dev.sheldan.abstracto.invitefilter.service.management.FilteredInviteLinkManagement;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Invite;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Component
@Slf4j
@@ -38,8 +55,42 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
@Autowired
private InviteLinkFilterServiceBean self;
@Autowired
private FeatureModeService featureModeService;
@Autowired
private PostTargetService postTargetService;
@Autowired
private TemplateService templateService;
@Autowired
private MetricService metricService;
@Autowired
private MessageService messageService;
@Autowired
private ChannelGroupService channelGroupService;
@Autowired
private RoleImmunityService roleImmunityService;
private static final Pattern INVITE_CODE_PATTERN = Pattern.compile("(?<code>[a-z0-9-]+)", Pattern.CASE_INSENSITIVE);
public static final String INVITE_FILTER_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(INVITE_FILTER_METRIC)
.build();
public static final String INVITE_LINK_DELETED_NOTIFICATION_EMBED_TEMPLATE_KEY = "invite_link_deleted_notification";
@Override
public boolean isCodeFiltered(Long targetServerId, ServerUser serverUser) {
return !isCodeAllowed(targetServerId, serverUser);
@@ -170,4 +221,116 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
public CompletableFuture<Invite> resolveInvite(JDA jda, String code) {
return Invite.resolve(jda, extractCode(code)).submit();
}
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.getChannel())
.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.getChannel().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 boolean isInviteFilterActiveInChannel(MessageChannel channel) {
return channelGroupService.isChannelInEnabledChannelGroupOfType(INVITE_FILTER_CHANNEL_GROUP_TYPE, channel.getIdLong());
}
@Override
public boolean isMemberImmuneAgainstInviteFilter(Member member) {
return roleImmunityService.isImmune(member, INVITE_FILTER_EFFECT_KEY);
}
@Override
public List<String> findInvitesInMessage(Message message) {
List<String> foundInvites;
foundInvites = new ArrayList<>();
Matcher matcher = Message.INVITE_PATTERN.matcher(message.getContentRaw());
while(matcher.find()) {
foundInvites.add(matcher.group("code"));
}
return foundInvites;
}
public void resolveAndCheckInvites(Message message, List<String> foundInvites) {
List<CompletableFuture<Invite>> inviteList = new ArrayList<>();
JDA jda = message.getJDA();
foundInvites.forEach(s -> inviteList.add(resolveInvite(jda, s)));
CompletableFutureList<Invite> list = new CompletableFutureList<>(inviteList);
list.getMainFuture().whenComplete((unused, throwable) -> {
List<Invite> invites = list.getObjects();
Long serverId = message.getGuild().getIdLong();
ServerUser author = ServerUser.builder().userId(message.getAuthor().getIdLong()).serverId(message.getGuild().getIdLong()).build();
boolean toDelete = false;
Map<Long, String> targetServers = new HashMap<>();
List<String> deletedInvites = new ArrayList<>();
for (Invite invite : invites) {
if (invite.getType().equals(Invite.InviteType.GUILD)
&& isCodeFiltered(invite.getGuild().getIdLong(), author)) {
toDelete = true;
deletedInvites.add(invite.getCode());
targetServers.put(invite.getGuild().getIdLong(), invite.getGuild().getName());
}
}
List<String> unResolvedInvites = new ArrayList<>();
foundInvites.forEach(possibleUnresolvedInvite -> {
if(invites.stream().noneMatch(invite -> invite.getCode().equals(possibleUnresolvedInvite))) {
unResolvedInvites.add(possibleUnresolvedInvite);
}
});
for(String unresolvedInvite : unResolvedInvites) {
if(isCodeFiltered(unresolvedInvite, author)) {
toDelete = true;
deletedInvites.add(unresolvedInvite);
}
}
if(toDelete) {
metricService.incrementCounter(MESSAGE_INVITE_FILTERED);
messageService.deleteMessage(message);
boolean trackUsages = featureModeService.featureModeActive(InviteFilterFeatureDefinition.INVITE_FILTER, serverId, InviteFilterMode.TRACK_USES);
if(trackUsages) {
targetServers.forEach((targetServerId, serverName) -> storeFilteredInviteLinkUsage(targetServerId, serverName, author));
}
boolean sendNotification = featureModeService.featureModeActive(InviteFilterFeatureDefinition.INVITE_FILTER, serverId, InviteFilterMode.FILTER_NOTIFICATIONS);
if(sendNotification) {
sendDeletionNotification(deletedInvites, message);
}
}
});
}
@PostConstruct
public void postConstruct() {
metricService.registerCounter(MESSAGE_INVITE_FILTERED, "Amount of messages containing an invite filtered");
}
}

View File

@@ -2,23 +2,24 @@ package dev.sheldan.abstracto.invitefilter.listener;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.ChannelGroupService;
import dev.sheldan.abstracto.core.service.RoleImmunityService;
import dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterService;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.*;
import dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterServiceBean;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.MessageType;
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 java.util.ArrayList;
import java.util.Arrays;
import static dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterService.INVITE_FILTER_CHANNEL_GROUP_TYPE;
import static dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterService.INVITE_FILTER_EFFECT_KEY;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class InviteLinkFilterListenerTest {
@@ -32,9 +33,6 @@ public class InviteLinkFilterListenerTest {
@Mock
private Message message;
@Mock
private User author;
@Mock
private Member member;
@@ -42,66 +40,40 @@ public class InviteLinkFilterListenerTest {
private MessageChannel messageChannel;
@Mock
private Guild guild;
private InviteLinkFilterServiceBean filterServiceBean;
@Mock
private MessageReceivedModel model;
@Mock
private ChannelGroupService channelGroupService;
@Mock
private RoleImmunityService roleImmunityService;
@Mock
private JDA jda;
@Mock
private Invite invite;
private static final Long SERVER_ID = 1L;
private static final Long CHANNEL_ID = 2L;
private static final Long USER_ID = 3L;
private static final String INVITE_CODE = "code";
private static final String INVITE_LINK = "discord.gg/" + INVITE_CODE;
@Test
public void testExecutionWithNoInvite() {
when(message.getContentRaw()).thenReturn("text");
when(inviteLinkFilterService.findInvitesInMessage(message)).thenReturn(new ArrayList<>());
setupBasicMessage();
setupFiltering();
when(model.getMessage()).thenReturn(message);
DefaultListenerResult result = testUnit.execute(model);
Assert.assertEquals(DefaultListenerResult.IGNORED, result);
verify(filterServiceBean, times(0)).resolveAndCheckInvites(eq(message), any());
}
@Test
public void testExecutionWithOneInvite() {
setupFiltering();
when(message.getContentRaw()).thenReturn(INVITE_LINK);
when(inviteLinkFilterService.findInvitesInMessage(message)).thenReturn(Arrays.asList(INVITE_CODE));
setupBasicMessage();
when(inviteLinkFilterService.resolveInvite(jda, INVITE_CODE)).thenReturn(CompletableFuture.completedFuture(invite));
when(model.getMessage()).thenReturn(message);
DefaultListenerResult result = testUnit.execute(model);
Assert.assertEquals(DefaultListenerResult.PROCESSED, result);
}
private void setupFiltering() {
when(channelGroupService.isChannelInEnabledChannelGroupOfType(INVITE_FILTER_CHANNEL_GROUP_TYPE, CHANNEL_ID)).thenReturn(true);
when(roleImmunityService.isImmune(member, INVITE_FILTER_EFFECT_KEY)).thenReturn(false);
verify(filterServiceBean, times(1)).resolveAndCheckInvites(eq(message), any());
}
private void setupBasicMessage() {
when(messageChannel.getIdLong()).thenReturn(CHANNEL_ID);
when(message.getChannel()).thenReturn(messageChannel);
when(message.getAuthor()).thenReturn(author);
when(message.getMember()).thenReturn(member);
when(author.getIdLong()).thenReturn(USER_ID);
when(message.getGuild()).thenReturn(guild);
when(guild.getIdLong()).thenReturn(SERVER_ID);
when(message.isFromGuild()).thenReturn(true);
when(message.isWebhookMessage()).thenReturn(false);
when(message.getJDA()).thenReturn(jda);
when(inviteLinkFilterService.isInviteFilterActiveInChannel(messageChannel)).thenReturn(true);
when(inviteLinkFilterService.isMemberImmuneAgainstInviteFilter(member)).thenReturn(false);
MessageType type = MessageType.DEFAULT;
when(message.getType()).thenReturn(type);
}

View File

@@ -4,6 +4,9 @@ import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.invitefilter.model.database.FilteredInviteLink;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Invite;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -25,4 +28,7 @@ public interface InviteLinkFilterService {
List<FilteredInviteLink> getTopFilteredInviteLinks(Long serverId, Integer count);
List<FilteredInviteLink> getTopFilteredInviteLinks(Long serverId);
CompletableFuture<Invite> resolveInvite(JDA jda, String code);
boolean isInviteFilterActiveInChannel(MessageChannel channel);
boolean isMemberImmuneAgainstInviteFilter(Member member);
List<String> findInvitesInMessage(Message message);
}