[AB-291] refactoring pagination to custom button pagination

adding mutes command
fixing edit message not considering components
reversing the origin comparison in a few button click listeners
fixing ordering of warnings and mutes from converter
This commit is contained in:
Sheldan
2021-12-01 01:14:29 +01:00
parent f2aa7035aa
commit 0e7ea25aef
40 changed files with 860 additions and 201 deletions

View File

@@ -0,0 +1,116 @@
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.exception.EntityGuildMismatchException;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.PaginatorService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
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.converter.MuteEntryConverter;
import dev.sheldan.abstracto.moderation.model.template.command.MuteEntry;
import dev.sheldan.abstracto.moderation.model.template.command.MutesModel;
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class Mutes extends AbstractConditionableCommand {
private static final String NO_MUTES_TEMPLATE_KEY = "mutes_no_mutes_found";
private static final String MUTES_DISPLAY_TEMPLATE_KEY = "mutes_display_response";
@Autowired
private MuteManagementService muteManagementService;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Autowired
private MuteEntryConverter muteEntryConverter;
@Autowired
private Mutes self;
@Autowired
private PaginatorService paginatorService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<dev.sheldan.abstracto.moderation.model.database.Mute> mutesToDisplay;
if(commandContext.getParameters().getParameters().isEmpty()) {
AServer server = serverManagementService.loadServer(commandContext.getGuild().getIdLong());
mutesToDisplay = muteManagementService.getAllMutes(server);
} else {
Member member = (Member) commandContext.getParameters().getParameters().get(0);
if(!member.getGuild().equals(commandContext.getGuild())) {
throw new EntityGuildMismatchException();
}
mutesToDisplay = muteManagementService.getAllMutesOf(userInServerManagementService.loadOrCreateUser(member));
}
if(mutesToDisplay.isEmpty()) {
MessageToSend messageToSend = templateService.renderEmbedTemplate(NO_MUTES_TEMPLATE_KEY, new Object(), commandContext.getGuild().getIdLong());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromSuccess());
} else {
return muteEntryConverter.fromMutes(mutesToDisplay)
.thenCompose(muteEntries -> self.renderMutes(commandContext, muteEntries)
.thenApply(unused -> CommandResult.fromIgnored()));
}
}
@Transactional
public CompletableFuture<Void> renderMutes(CommandContext commandContext, List<MuteEntry> mutes) {
MutesModel model = (MutesModel) ContextConverter.slimFromCommandContext(commandContext, MutesModel.class);
model.setMutes(mutes);
return paginatorService.createPaginatorFromTemplate(MUTES_DISPLAY_TEMPLATE_KEY, model, commandContext.getChannel(), commandContext.getAuthor().getIdLong());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("member").templated(true).type(Member.class).optional(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("mutes")
.module(ModerationModuleDefinition.MODERATION)
.templated(true)
.supportsEmbedException(true)
.async(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return ModerationFeatureDefinition.MUTING;
}
}

View File

@@ -1,7 +1,5 @@
package dev.sheldan.abstracto.moderation.command;
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
import com.jagrosh.jdautilities.menu.Paginator;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
@@ -38,7 +36,7 @@ import java.util.concurrent.CompletableFuture;
@Component
public class Warnings extends AbstractConditionableCommand {
public static final String WARNINGS_RESPONSE_TEMPLATE = "warnings_response";
public static final String WARNINGS_RESPONSE_TEMPLATE = "warnings_display_response";
public static final String NO_WARNINGS_TEMPLATE_KEY = "warnings_no_warnings_found";
@Autowired
private WarnManagementService warnManagementService;
@@ -52,9 +50,6 @@ public class Warnings extends AbstractConditionableCommand {
@Autowired
private PaginatorService paginatorService;
@Autowired
private EventWaiter eventWaiter;
@Autowired
private ServerManagementService serverManagementService;
@@ -86,22 +81,20 @@ public class Warnings extends AbstractConditionableCommand {
.thenApply(unused -> CommandResult.fromSuccess());
} else {
return warnEntryConverter.fromWarnings(warnsToDisplay).thenApply(warnEntries -> {
self.renderWarnings(commandContext, warnEntries);
return CommandResult.fromSuccess();
});
return warnEntryConverter.fromWarnings(warnsToDisplay)
.thenCompose(warnEntries -> self.renderWarnings(commandContext, warnEntries))
.thenApply(unused -> CommandResult.fromIgnored());
}
}
@Transactional
public void renderWarnings(CommandContext commandContext, List<WarnEntry> warnEntries) {
public CompletableFuture<Void> renderWarnings(CommandContext commandContext, List<WarnEntry> warnEntries) {
WarningsModel model = (WarningsModel) ContextConverter.slimFromCommandContext(commandContext, WarningsModel.class);
model.setWarnings(warnEntries);
Paginator paginator = paginatorService.createPaginatorFromTemplate(WARNINGS_RESPONSE_TEMPLATE, model, eventWaiter, commandContext.getGuild().getIdLong());
paginator.display(commandContext.getChannel());
return paginatorService.createPaginatorFromTemplate(WARNINGS_RESPONSE_TEMPLATE, model, commandContext.getChannel(), commandContext.getAuthor().getIdLong());
}
@Override

View File

@@ -0,0 +1,93 @@
package dev.sheldan.abstracto.moderation.converter;
import dev.sheldan.abstracto.core.models.FutureMemberPair;
import dev.sheldan.abstracto.core.models.MemberDisplayModel;
import dev.sheldan.abstracto.core.models.ServerSpecificId;
import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.moderation.model.database.Mute;
import dev.sheldan.abstracto.moderation.model.template.command.MuteEntry;
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@Component
public class MuteEntryConverter {
@Autowired
private MemberService memberService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private MuteManagementService muteManagementService;
@Autowired
private MuteEntryConverter self;
public CompletableFuture<List<MuteEntry>> fromMutes(List<Mute> mutes) {
Map<ServerSpecificId, FutureMemberPair> loadedMutes = new HashMap<>();
List<CompletableFuture<Member>> allFutures = new ArrayList<>();
mutes.forEach(mute -> {
CompletableFuture<Member> mutingMemberFuture = memberService.getMemberInServerAsync(mute.getMutingUser());
CompletableFuture<Member> mutedMemberFuture = memberService.getMemberInServerAsync(mute.getMutedUser());
FutureMemberPair futurePair = FutureMemberPair
.builder()
.firstMember(mutingMemberFuture)
.secondMember(mutedMemberFuture)
.build();
loadedMutes.put(mute.getMuteId(), futurePair);
allFutures.add(mutingMemberFuture);
allFutures.add(mutedMemberFuture);
});
CompletableFuture<List<MuteEntry>> future = new CompletableFuture<>();
FutureUtils.toSingleFutureGeneric(allFutures)
.whenComplete((unused, throwable) -> future.complete(self.loadFullMuteEntries(loadedMutes)))
.exceptionally(throwable -> {
future.completeExceptionally(throwable);
return null;
});
return future;
}
@Transactional
public List<MuteEntry> loadFullMuteEntries(Map<ServerSpecificId, FutureMemberPair> loadedMuteInfo) {
List<MuteEntry> entries = new ArrayList<>();
List<ServerSpecificId> muteIds = new ArrayList<>(loadedMuteInfo.keySet());
muteIds.sort(Comparator.comparing(ServerSpecificId::getId));
muteIds.forEach(muteInfo -> {
FutureMemberPair memberPair = loadedMuteInfo.get(muteInfo);
Mute mute = muteManagementService.findMute(muteInfo.getId(), muteInfo.getServerId());
Member mutedMember = !memberPair.getSecondMember().isCompletedExceptionally() ? memberPair.getSecondMember().join() : null;
MemberDisplayModel mutedUser = MemberDisplayModel
.builder()
.member(mutedMember)
.userId(mute.getMutedUser().getUserReference().getId())
.build();
Member mutingMember = !memberPair.getFirstMember().isCompletedExceptionally() ? memberPair.getFirstMember().join() : null;
MemberDisplayModel mutingUser = MemberDisplayModel
.builder()
.member(mutingMember)
.userId(mute.getMutingUser().getUserReference().getId())
.build();
MuteEntry entry = MuteEntry
.builder()
.mutedUser(mutedUser)
.mutingUser(mutingUser)
.mute(mute)
.muteDuration(Duration.between(mute.getMuteDate(), mute.getMuteTargetDate()))
.build();
entries.add(entry);
});
return entries;
}
}

View File

@@ -14,10 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@Component
@@ -38,7 +35,6 @@ public class WarnEntryConverter {
public CompletableFuture<List<WarnEntry>> fromWarnings(List<Warning> warnings) {
Map<ServerSpecificId, FutureMemberPair> loadedWarnings = new HashMap<>();
List<CompletableFuture<Member>> allFutures = new ArrayList<>();
// TODO maybe optimize to not need to look into the cache twice
warnings.forEach(warning -> {
CompletableFuture<Member> warningMemberFuture = memberService.getMemberInServerAsync(warning.getWarningUser());
CompletableFuture<Member> warnedMemberFuture = memberService.getMemberInServerAsync(warning.getWarnedUser());
@@ -59,8 +55,10 @@ public class WarnEntryConverter {
@Transactional
public List<WarnEntry> loadFullWarnEntries(Map<ServerSpecificId, FutureMemberPair> loadedWarnInfo) {
List<ServerSpecificId> warnIds = new ArrayList<>(loadedWarnInfo.keySet());
warnIds.sort(Comparator.comparing(ServerSpecificId::getId));
List<WarnEntry> entries = new ArrayList<>();
loadedWarnInfo.keySet().forEach(warning -> {
warnIds.forEach(warning -> {
Warning warn = warnManagementService.findById(warning.getId(), warning.getServerId());
FutureMemberPair memberPair = loadedWarnInfo.get(warning);
Member warnedMember = !memberPair.getSecondMember().isCompletedExceptionally() ? memberPair.getSecondMember().join() : null;

View File

@@ -1,6 +1,7 @@
package dev.sheldan.abstracto.moderation.repository;
import dev.sheldan.abstracto.core.models.ServerSpecificId;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.moderation.model.database.Mute;
import org.jetbrains.annotations.NotNull;
@@ -18,6 +19,10 @@ public interface MuteRepository extends JpaRepository<Mute, ServerSpecificId> {
List<Mute> findAllByMutedUserAndMuteEndedFalseOrderByMuteId_IdDesc(AUserInAServer aUserInAServer);
List<Mute> findAllByMutedUserOrderByMuteId_IdAsc(AUserInAServer aUserInAServer);
List<Mute> findAllByServerOrderByMuteId_IdAsc(AServer server);
@NotNull
Optional<Mute> findByMuteId_IdAndMuteId_ServerId(Long muteId, Long serverId);
}

View File

@@ -365,7 +365,7 @@ public class MuteServiceBean implements MuteService {
@Override
public void completelyUnMuteUser(AUserInAServer aUserInAServer) {
log.info("Completely unmuting user {} in server {}.", aUserInAServer.getUserReference().getId(), aUserInAServer.getServerReference().getId());
List<Mute> allMutesOfUser = muteManagementService.getAllMutesOf(aUserInAServer);
List<Mute> allMutesOfUser = muteManagementService.getAllActiveMutesOf(aUserInAServer);
allMutesOfUser.forEach(mute -> {
mute.setMuteEnded(true);
cancelUnMuteJob(mute);

View File

@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.moderation.service.management;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
import dev.sheldan.abstracto.core.models.ServerSpecificId;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.moderation.model.database.Mute;
@@ -84,9 +85,19 @@ public class MuteManagementServiceBean implements MuteManagementService {
}
@Override
public List<Mute> getAllMutesOf(AUserInAServer aUserInAServer) {
public List<Mute> getAllActiveMutesOf(AUserInAServer aUserInAServer) {
return muteRepository.findAllByMutedUserAndMuteEndedFalseOrderByMuteId_IdDesc(aUserInAServer);
}
@Override
public List<Mute> getAllMutesOf(AUserInAServer aUserInAServer) {
return muteRepository.findAllByMutedUserOrderByMuteId_IdAsc(aUserInAServer);
}
@Override
public List<Mute> getAllMutes(AServer server) {
return muteRepository.findAllByServerOrderByMuteId_IdAsc(server);
}
}

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="seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,20 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.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')"/>
<changeSet author="Sheldan" id="mutes-command">
<insert tableName="command">
<column name="name" value="mutes"/>
<column name="module_id" valueComputed="${moderationModule}"/>
<column name="feature_id" valueComputed="${moderationFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

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

View File

@@ -12,4 +12,5 @@
<include file="1.2.16/collection.xml" relativeToChangelogFile="true"/>
<include file="1.3.4/collection.xml" relativeToChangelogFile="true"/>
<include file="1.3.9/collection.xml" relativeToChangelogFile="true"/>
<include file="1.3.10/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,125 +0,0 @@
package dev.sheldan.abstracto.moderation.command;
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
import com.jagrosh.jdautilities.menu.Paginator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.PaginatorService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.moderation.converter.WarnEntryConverter;
import dev.sheldan.abstracto.moderation.model.database.Warning;
import dev.sheldan.abstracto.moderation.model.template.command.WarnEntry;
import dev.sheldan.abstracto.moderation.model.template.command.WarningsModel;
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
import net.dv8tion.jda.api.entities.Member;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class WarningsTest {
@InjectMocks
private Warnings testUnit;
@Mock
private WarnManagementService warnManagementService;
@Mock
private UserInServerManagementService userInServerManagementService;
@Mock
private WarnEntryConverter warnEntryConverter;
@Mock
private PaginatorService paginatorService;
@Mock
private ServerManagementService serverManagementService;
@Mock
private EventWaiter eventWaiter;
@Captor
private ArgumentCaptor<WarningsModel> captor;
@Mock
private Warnings self;
private static final Long SERVER_ID = 1L;
@Test
public void testNoParametersForWarningsCommand(){
CommandContext noParams = CommandTestUtilities.getNoParameters();
Warning firstWarning = Mockito.mock(Warning.class);
WarnEntry firstModelWarning = Mockito.mock(WarnEntry.class);
Warning secondWarning = Mockito.mock(Warning.class);
WarnEntry secondModelWarning = Mockito.mock(WarnEntry.class);
List<Warning> warningsToDisplay = Arrays.asList(firstWarning, secondWarning);
List<WarnEntry> modelWarnings = Arrays.asList(firstModelWarning, secondModelWarning);
AServer server = Mockito.mock(AServer.class);
when(serverManagementService.loadServer(noParams.getGuild())).thenReturn(server);
when(warnManagementService.getAllWarningsOfServer(server)).thenReturn(warningsToDisplay);
when(warnEntryConverter.fromWarnings(warningsToDisplay)).thenReturn(CompletableFuture.completedFuture(modelWarnings));
CompletableFuture<CommandResult> result = testUnit.executeAsync(noParams);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
verify(self, times(1)).renderWarnings(noParams, modelWarnings);
}
@Test
public void testWarningsRendering() {
CommandContext noParams = CommandTestUtilities.getNoParameters();
WarnEntry firstModelWarning = Mockito.mock(WarnEntry.class);
WarnEntry secondModelWarning = Mockito.mock(WarnEntry.class);
Paginator paginator = Mockito.mock(Paginator.class);
when(noParams.getGuild().getIdLong()).thenReturn(SERVER_ID);
when(paginatorService.createPaginatorFromTemplate(eq(Warnings.WARNINGS_RESPONSE_TEMPLATE), captor.capture(), eq(eventWaiter), eq(SERVER_ID))).thenReturn(paginator);
List<WarnEntry> modelWarnings = Arrays.asList(firstModelWarning, secondModelWarning);
testUnit.renderWarnings(noParams, modelWarnings);
WarningsModel warningsModel = captor.getValue();
Assert.assertEquals(firstModelWarning, warningsModel.getWarnings().get(0));
Assert.assertEquals(secondModelWarning, warningsModel.getWarnings().get(1));
}
@Test
public void testExecuteWarningsForMember(){
Member member = Mockito.mock(Member.class);
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(member));
when(member.getGuild()).thenReturn(parameters.getGuild());
AUserInAServer warnedUser = Mockito.mock(AUserInAServer.class);
Warning firstWarning = Mockito.mock(Warning.class);
WarnEntry firstModelWarning = Mockito.mock(WarnEntry.class);
Warning secondWarning = Mockito.mock(Warning.class);
WarnEntry secondModelWarning = Mockito.mock(WarnEntry.class);
List<Warning> warningsToDisplay = Arrays.asList(firstWarning, secondWarning);
List<WarnEntry> modelWarnings = Arrays.asList(firstModelWarning, secondModelWarning);
when(userInServerManagementService.loadOrCreateUser(member)).thenReturn(warnedUser);
when(warnManagementService.getAllWarnsForUser(warnedUser)).thenReturn(warningsToDisplay);
when(warnEntryConverter.fromWarnings(warningsToDisplay)).thenReturn(CompletableFuture.completedFuture(modelWarnings));
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
verify(self, times(1)).renderWarnings(parameters, modelWarnings);
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -361,7 +361,7 @@ public class MuteServiceBeanTest {
public void testCompletelyUnMuteNotMutedUser() {
when(userBeingMuted.getUserReference()).thenReturn(user);
when(userBeingMuted.getServerReference()).thenReturn(server);
when(muteManagementService.getAllMutesOf(userBeingMuted)).thenReturn(Arrays.asList());
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList());
testUnit.completelyUnMuteUser(userBeingMuted);
verify(muteManagementService, times(0)).saveMute(any(Mute.class));
}
@@ -370,7 +370,7 @@ public class MuteServiceBeanTest {
public void testCompletelyUnMuteNotScheduledMuteUser() {
when(userBeingMuted.getUserReference()).thenReturn(user);
when(userBeingMuted.getServerReference()).thenReturn(server);
when(muteManagementService.getAllMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
testUnit.completelyUnMuteUser(userBeingMuted);
verify(muteManagementService, times(1)).saveMute(any(Mute.class));
verify(schedulerService, times(0)).stopTrigger(anyString());
@@ -381,7 +381,7 @@ public class MuteServiceBeanTest {
when(mute.getTriggerKey()).thenReturn(TRIGGER);
when(userBeingMuted.getUserReference()).thenReturn(user);
when(userBeingMuted.getServerReference()).thenReturn(server);
when(muteManagementService.getAllMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
testUnit.completelyUnMuteUser(userBeingMuted);
verify(muteManagementService, times(1)).saveMute(any(Mute.class));
verify(schedulerService, times(1)).stopTrigger(TRIGGER);
@@ -392,7 +392,7 @@ public class MuteServiceBeanTest {
when(userBeingMuted.getUserReference()).thenReturn(user);
when(userBeingMuted.getServerReference()).thenReturn(server);
when(mute.getTriggerKey()).thenReturn(TRIGGER);
when(muteManagementService.getAllMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
when(userInServerManagementService.loadOrCreateUser(memberBeingMuted)).thenReturn(userBeingMuted);
testUnit.completelyUnMuteMember(memberBeingMuted);
verify(muteManagementService, times(1)).saveMute(any(Mute.class));

View File

@@ -126,7 +126,7 @@ public class MuteManagementServiceBeanTest {
Mute mute = Mockito.mock(Mute.class);
Mute mute2 = Mockito.mock(Mute.class);
when(muteRepository.findAllByMutedUserAndMuteEndedFalseOrderByMuteId_IdDesc(userInAServer)).thenReturn(Arrays.asList(mute, mute2));
List<Mute> allMutesOf = testUnit.getAllMutesOf(userInAServer);
List<Mute> allMutesOf = testUnit.getAllActiveMutesOf(userInAServer);
Assert.assertEquals(2, allMutesOf.size());
Assert.assertEquals(mute, allMutesOf.get(0));
Assert.assertEquals(mute2, allMutesOf.get(1));

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.moderation.model.template.command;
import dev.sheldan.abstracto.core.models.MemberDisplayModel;
import dev.sheldan.abstracto.moderation.model.database.Mute;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.time.Duration;
@Getter
@Setter
@Builder
public class MuteEntry {
/**
* The {@link Mute} of this entry
*/
private Mute mute;
/**
* The {@link MemberDisplayModel} containing information about the user being muted. The member property is null if the user left the server
*/
private MemberDisplayModel mutedUser;
/**
* The {@link MemberDisplayModel} containing information about the user muting. The member property is null if the user left the server
*/
private MemberDisplayModel mutingUser;
private Duration muteDuration;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.moderation.model.template.command;
import dev.sheldan.abstracto.core.models.context.SlimUserInitiatedServerContext;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import java.util.List;
@Getter
@Setter
@SuperBuilder
public class MutesModel extends SlimUserInitiatedServerContext {
private List<MuteEntry> mutes;
}

View File

@@ -1,6 +1,7 @@
package dev.sheldan.abstracto.moderation.service.management;
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.moderation.model.database.Mute;
import net.dv8tion.jda.api.entities.Member;
@@ -75,5 +76,18 @@ public interface MuteManagementService {
* @param aUserInAServer The {@link AUserInAServer} to search the active mutes for
* @return A collection of {@link Mute} objects of the user which are active
*/
List<Mute> getAllActiveMutesOf(AUserInAServer aUserInAServer);
/**
* Retrieves all mutes of the given {@link AUserInAServer} in a collection
* @param aUserInAServer The {@link AUserInAServer} to search the mutes for
* @return A collection of {@link Mute} objects of the user
*/
List<Mute> getAllMutesOf(AUserInAServer aUserInAServer);
/**
* Retrieves all {@link Mute} from the given {@link AServer}
* @return All found mutes of this server
*/
List<Mute> getAllMutes(AServer server);
}