mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-21 15:25:50 +00:00
[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:
@@ -219,7 +219,7 @@ public class AssignableRoleButtonClickedListener implements ButtonClickedListene
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return model.getOrigin().equals(AssignableRolePlaceServiceBean.ASSIGNABLE_ROLE_COMPONENT_ORIGIN);
|
||||
return AssignableRolePlaceServiceBean.ASSIGNABLE_ROLE_COMPONENT_ORIGIN.equals(model.getOrigin());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -77,7 +77,7 @@ public class MessageEmbedDeleteButtonClickedListener implements ButtonClickedLis
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return model.getOrigin().equals(MessageEmbedServiceBean.MESSAGE_EMBED_DELETE_ORIGIN);
|
||||
return MessageEmbedServiceBean.MESSAGE_EMBED_DELETE_ORIGIN.equals(model.getOrigin());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class SuggestionButtonVoteClickedListener implements ButtonClickedListene
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return model.getOrigin().equals(SuggestionServiceBean.SUGGESTION_VOTE_ORIGIN);
|
||||
return SuggestionServiceBean.SUGGESTION_VOTE_ORIGIN.equals(model.getOrigin());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -103,7 +103,7 @@ public class ConfirmationButtonClickedListener implements ButtonClickedListener
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return model.getOrigin().equals(CommandReceivedHandler.COMMAND_CONFIRMATION_ORIGIN);
|
||||
return CommandReceivedHandler.COMMAND_CONFIRMATION_ORIGIN.equals(model.getOrigin());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.sheldan.abstracto.core.job;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.PaginatorServiceBean;
|
||||
import dev.sheldan.abstracto.core.service.management.ComponentPayloadManagementService;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.quartz.PersistJobDataAfterExecution;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@DisallowConcurrentExecution
|
||||
@Component
|
||||
@PersistJobDataAfterExecution
|
||||
@Setter
|
||||
public class PaginatorCleanupJob extends QuartzJobBean {
|
||||
|
||||
private String paginatorId;
|
||||
private String accessorId;
|
||||
|
||||
@Autowired
|
||||
private PaginatorServiceBean paginatorServiceBean;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private ComponentPayloadManagementService componentPayloadManagementService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
PaginatorServiceBean.PaginatorInfo info = paginatorServiceBean.getPaginatorInfo(paginatorId);
|
||||
log.info("Executing paginator cleanup for paginator {}", paginatorId);
|
||||
if(info != null && info.getLastAccessor().equals(accessorId)) {
|
||||
log.info("Last accessor was {} - which was the start of this job - deleting", info.getLastAccessor());
|
||||
paginatorServiceBean.cleanupPaginator(info);
|
||||
} else {
|
||||
log.info("The last accessor did either not start this job, or there was no configuration found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package dev.sheldan.abstracto.core.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.ButtonClickedListener;
|
||||
import dev.sheldan.abstracto.core.model.PaginatorButtonPayload;
|
||||
import dev.sheldan.abstracto.core.models.listener.ButtonClickedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.PaginatorServiceBean;
|
||||
import dev.sheldan.abstracto.core.templating.model.EmbedConfiguration;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateServiceBean;
|
||||
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.UUID;
|
||||
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class PaginatorButtonListener implements ButtonClickedListener {
|
||||
|
||||
@Autowired
|
||||
private PaginatorServiceBean paginatorServiceBean;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private TemplateServiceBean templateServiceBean;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Override
|
||||
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
|
||||
PaginatorButtonPayload payload = (PaginatorButtonPayload) model.getDeserializedPayload();
|
||||
|
||||
Message originalMessage = model.getEvent().getMessage();
|
||||
if(originalMessage == null) {
|
||||
return ButtonClickedListenerResult.IGNORED;
|
||||
}
|
||||
if(payload.getAllowedUser() != null && model.getEvent().getUser().getIdLong() != payload.getAllowedUser()) {
|
||||
return ButtonClickedListenerResult.IGNORED;
|
||||
}
|
||||
String buttonId = model.getEvent().getComponentId();
|
||||
if(buttonId.equals(payload.getExitButtonId())) {
|
||||
log.info("Deleting paginator {} because of exit button {}.", payload.getPaginatorId(), buttonId);
|
||||
originalMessage.delete().queue();
|
||||
paginatorServiceBean.cleanupPaginatorPayloads(payload);
|
||||
return ButtonClickedListenerResult.ACKNOWLEDGED;
|
||||
}
|
||||
if(payload.getSinglePage()) {
|
||||
return ButtonClickedListenerResult.IGNORED;
|
||||
}
|
||||
int targetPage;
|
||||
if(buttonId.equals(payload.getStartButtonId())) {
|
||||
targetPage = 0;
|
||||
} else if(buttonId.equals(payload.getPreviousButtonId())) {
|
||||
targetPage = Math.max(paginatorServiceBean.getCurrentPage(payload.getPaginatorId()) - 1, 0);
|
||||
} else if(buttonId.equals(payload.getNextButtonId())) {
|
||||
targetPage = Math.min(paginatorServiceBean.getCurrentPage(payload.getPaginatorId()) + 1, payload.getEmbedConfigs().size() - 1);
|
||||
} else if(buttonId.equals(payload.getLastButtonId())) {
|
||||
targetPage = payload.getEmbedConfigs().size() - 1;
|
||||
} else {
|
||||
return ButtonClickedListenerResult.IGNORED;
|
||||
}
|
||||
log.debug("Moving to page {} in paginator {}.", targetPage, payload.getPaginatorId());
|
||||
EmbedConfiguration embedConfiguration = payload.getEmbedConfigs().get(targetPage);
|
||||
MessageToSend messageToSend = templateServiceBean.convertEmbedConfigurationToMessageToSend(embedConfiguration);
|
||||
messageService.editMessageInChannel(model.getEvent().getMessageChannel(), messageToSend, originalMessage.getIdLong())
|
||||
.thenAccept(unused -> log.info("Updated paginator {} to switch to page {}.", payload.getPaginatorId(), targetPage));
|
||||
String accessorId = UUID.randomUUID().toString();
|
||||
paginatorServiceBean.updateCurrentPage(payload.getPaginatorId(), targetPage, accessorId);
|
||||
paginatorServiceBean.schedulePaginationDeletion(payload.getPaginatorId(), accessorId);
|
||||
return ButtonClickedListenerResult.ACKNOWLEDGED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.HIGH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return PaginatorServiceBean.PAGINATOR_BUTTON.equals(model.getOrigin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return CoreFeatureDefinition.CORE_FEATURE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package dev.sheldan.abstracto.core.model;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.button.ButtonPayload;
|
||||
import dev.sheldan.abstracto.core.templating.model.EmbedConfiguration;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class PaginatorButtonPayload implements ButtonPayload {
|
||||
private List<EmbedConfiguration> embedConfigs;
|
||||
private String paginatorId;
|
||||
private String exitButtonId;
|
||||
private String startButtonId;
|
||||
private String previousButtonId;
|
||||
private String nextButtonId;
|
||||
private String lastButtonId;
|
||||
private Boolean singlePage;
|
||||
private Long allowedUser;
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.model;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.button.ButtonConfigModel;
|
||||
import dev.sheldan.abstracto.core.templating.model.EmbedConfiguration;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -10,9 +12,14 @@ import java.util.List;
|
||||
@Setter
|
||||
@Builder
|
||||
public class PaginatorConfiguration {
|
||||
private String headerText;
|
||||
private List<String> items;
|
||||
private List<EmbedConfiguration> embedConfigs;
|
||||
private String paginatorId;
|
||||
private Long timeoutSeconds;
|
||||
private Boolean showPageNumbers;
|
||||
private Boolean useNumberedItems;
|
||||
private Boolean restrictUser;
|
||||
private ButtonConfigModel exitButton;
|
||||
private ButtonConfigModel startButton;
|
||||
private ButtonConfigModel previousButton;
|
||||
private ButtonConfigModel nextButton;
|
||||
private ButtonConfigModel lastButton;
|
||||
private Boolean singlePage;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.abstracto.core.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class PaginatorFooterModel {
|
||||
private Integer page;
|
||||
private Integer pageCount;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.sheldan.abstracto.core.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class PaginatorModel {
|
||||
private Object innerModel;
|
||||
private String exitButtonId;
|
||||
private String startButtonId;
|
||||
private String previousButtonId;
|
||||
private String nextButtonId;
|
||||
private String lastButtonId;
|
||||
}
|
||||
@@ -307,6 +307,7 @@ public class ChannelServiceBean implements ChannelService {
|
||||
if(messageToSend.getReferencedMessageId() != null) {
|
||||
messageAction = messageAction.referenceById(messageToSend.getReferencedMessageId());
|
||||
}
|
||||
messageAction = messageAction.setActionRows(messageToSend.getActionRows());
|
||||
metricService.incrementCounter(MESSAGE_EDIT_METRIC);
|
||||
return messageAction.submit();
|
||||
}
|
||||
|
||||
@@ -191,6 +191,11 @@ public class MessageServiceBean implements MessageService {
|
||||
return openPrivateChannelForUser(user).thenCompose(privateChannel -> channelService.editMessageInAChannelFuture(messageToSend, privateChannel, messageId).thenApply(message -> null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> editMessageInChannel(MessageChannel channel, MessageToSend messageToSend, Long messageId) {
|
||||
return channelService.editMessageInAChannelFuture(messageToSend, channel, messageId).thenApply(message -> null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> loadMessageFromCachedMessage(CachedMessage cachedMessage) {
|
||||
return loadMessage(cachedMessage.getServerId(), cachedMessage.getChannelId(), cachedMessage.getMessageId());
|
||||
|
||||
@@ -1,19 +1,39 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
|
||||
import com.jagrosh.jdautilities.menu.Paginator;
|
||||
import dev.sheldan.abstracto.core.model.PaginatorButtonPayload;
|
||||
import dev.sheldan.abstracto.core.model.PaginatorConfiguration;
|
||||
import dev.sheldan.abstracto.core.model.PaginatorFooterModel;
|
||||
import dev.sheldan.abstracto.core.model.PaginatorModel;
|
||||
import dev.sheldan.abstracto.core.models.template.button.ButtonConfigModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ComponentPayloadManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.EmbedConfiguration;
|
||||
import dev.sheldan.abstracto.core.templating.model.EmbedFooter;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateServiceBean;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.scheduling.model.JobParameters;
|
||||
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
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.concurrent.TimeUnit;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class PaginatorServiceBean implements PaginatorService {
|
||||
|
||||
@Autowired
|
||||
@@ -28,42 +48,224 @@ public class PaginatorServiceBean implements PaginatorService {
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Override
|
||||
public Paginator createPaginatorFromTemplate(String templateKey, Object model, EventWaiter waiter, Long server) {
|
||||
String embedConfig = templateService.renderTemplate(templateKey + "_paginator", model);
|
||||
PaginatorConfiguration configuration = gson.fromJson(embedConfig, PaginatorConfiguration.class);
|
||||
List<String> items = configuration.getItems();
|
||||
int itemsPerPage = findAppropriateCountPerPage(items);
|
||||
@Autowired
|
||||
private ComponentService componentService;
|
||||
|
||||
return new Paginator.Builder()
|
||||
.setItemsPerPage(itemsPerPage)
|
||||
.setText(configuration.getHeaderText())
|
||||
.showPageNumbers(ObjectUtils.defaultIfNull(configuration.getShowPageNumbers(), false))
|
||||
.setItems(configuration.getItems().toArray(new String[0]))
|
||||
.useNumberedItems(ObjectUtils.defaultIfNull(configuration.getUseNumberedItems(), false))
|
||||
.setEventWaiter(waiter)
|
||||
.waitOnSinglePage(true)
|
||||
.setTimeout(ObjectUtils.defaultIfNull(configuration.getTimeoutSeconds(), 120L), TimeUnit.SECONDS)
|
||||
.setFinalAction(message -> messageService.deleteMessage(message))
|
||||
@Autowired
|
||||
private ComponentPayloadManagementService componentPayloadManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private PaginatorServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private TemplateServiceBean templateServiceBean;
|
||||
|
||||
@Autowired
|
||||
private SchedulerService schedulerService;
|
||||
|
||||
private static final Map<String, PaginatorInfo> PAGINATORS = new ConcurrentHashMap<>();
|
||||
public static final String PAGINATOR_BUTTON = "PAGINATOR_BUTTON";
|
||||
public static final String PAGINATOR_FOOTER_TEMPLATE_KEY = "paginator_footer";
|
||||
private static final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createPaginatorFromTemplate(String templateKey, Object model, TextChannel textChannel, Long userId) {
|
||||
Long serverId = textChannel.getGuild().getIdLong();
|
||||
String exitButtonId = componentService.generateComponentId(serverId);
|
||||
String startButtonId = componentService.generateComponentId(serverId);
|
||||
String previousButtonId = componentService.generateComponentId(serverId);
|
||||
String nextButtonId = componentService.generateComponentId(serverId);
|
||||
String lastButtonId = componentService.generateComponentId(serverId);
|
||||
PaginatorModel wrapperModel = PaginatorModel
|
||||
.builder()
|
||||
.exitButtonId(exitButtonId)
|
||||
.startButtonId(startButtonId)
|
||||
.previousButtonId(previousButtonId)
|
||||
.nextButtonId(nextButtonId)
|
||||
.lastButtonId(lastButtonId)
|
||||
.innerModel(model)
|
||||
.build();
|
||||
String embedConfig = templateService.renderTemplate(templateKey + "_paginator", wrapperModel, serverId);
|
||||
PaginatorConfiguration configuration = gson.fromJson(embedConfig, PaginatorConfiguration.class);
|
||||
log.info("Setting up paginator in channel {} in server {} with {} pages.", textChannel.getIdLong(),
|
||||
textChannel.getGuild().getIdLong(), configuration.getEmbedConfigs().size());
|
||||
setupFooters(configuration);
|
||||
|
||||
configuration.setPaginatorId(componentService.generateComponentId());
|
||||
configuration.setSinglePage(configuration.getEmbedConfigs().size() < 2);
|
||||
PaginatorButtonPayload buttonPayload = getButtonPayload(configuration, exitButtonId, startButtonId, previousButtonId, nextButtonId, lastButtonId);
|
||||
if(configuration.getRestrictUser() != null && configuration.getRestrictUser()) {
|
||||
buttonPayload.setAllowedUser(userId);
|
||||
}
|
||||
configuration.setExitButton(initializeButton(exitButtonId, buttonPayload));
|
||||
if(!configuration.getSinglePage()) {
|
||||
log.debug("Adding additional buttons for pagination to paginator {}.", configuration.getPaginatorId());
|
||||
configuration.setStartButton(initializeButton(startButtonId, buttonPayload));
|
||||
configuration.setPreviousButton(initializeButton(previousButtonId, buttonPayload));
|
||||
configuration.setNextButton(initializeButton(nextButtonId, buttonPayload));
|
||||
configuration.setLastButton(initializeButton(lastButtonId, buttonPayload));
|
||||
}
|
||||
|
||||
EmbedConfiguration embedConfiguration = configuration.getEmbedConfigs().get(0);
|
||||
MessageToSend messageToSend = templateServiceBean.convertEmbedConfigurationToMessageToSend(embedConfiguration);
|
||||
List<CompletableFuture<Message>> paginatorFutures = channelService.sendMessageToSendToChannel(messageToSend, textChannel);
|
||||
return FutureUtils.toSingleFutureGeneric(paginatorFutures)
|
||||
.thenAccept(unused -> self.setupButtonPayloads(paginatorFutures.get(0).join(), configuration, serverId, buttonPayload));
|
||||
}
|
||||
|
||||
private void setupFooters(PaginatorConfiguration configuration) {
|
||||
for (int i = 0; i < configuration.getEmbedConfigs().size(); i++) {
|
||||
PaginatorFooterModel paginatorModel = PaginatorFooterModel
|
||||
.builder()
|
||||
.page(i + 1)
|
||||
.pageCount(configuration.getEmbedConfigs().size())
|
||||
.build();
|
||||
String footerText = templateService.renderTemplate(PAGINATOR_FOOTER_TEMPLATE_KEY, paginatorModel);
|
||||
EmbedConfiguration embedConfiguration = configuration.getEmbedConfigs().get(i);
|
||||
if(embedConfiguration.getFooter() == null) {
|
||||
embedConfiguration.setFooter(EmbedFooter.builder().text(footerText).build());
|
||||
} else {
|
||||
embedConfiguration.getFooter().setText(footerText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanupPaginatorPayloads(PaginatorButtonPayload configuration) {
|
||||
List<String> payloadIds = getAllPayloadIdsFromPayload(configuration);
|
||||
componentPayloadManagementService.deletePayloads(payloadIds);
|
||||
}
|
||||
|
||||
private List<String> getAllPayloadIdsFromPayload(PaginatorButtonPayload configuration) {
|
||||
List<String> payloadIds = new ArrayList<>(Arrays.asList(configuration.getExitButtonId()));
|
||||
if(!configuration.getSinglePage()) {
|
||||
payloadIds.add(configuration.getStartButtonId());
|
||||
payloadIds.add(configuration.getPreviousButtonId());
|
||||
payloadIds.add(configuration.getNextButtonId());
|
||||
payloadIds.add(configuration.getLastButtonId());
|
||||
}
|
||||
return payloadIds;
|
||||
}
|
||||
|
||||
|
||||
private ButtonConfigModel initializeButton(String buttonId, PaginatorButtonPayload paginatorButtonPayload) {
|
||||
return ButtonConfigModel
|
||||
.builder()
|
||||
.buttonId(buttonId)
|
||||
.buttonPayload(paginatorButtonPayload)
|
||||
.payloadType(PaginatorButtonPayload.class)
|
||||
.origin(PAGINATOR_BUTTON)
|
||||
.build();
|
||||
}
|
||||
|
||||
private int findAppropriateCountPerPage(List<String> items) {
|
||||
int currentMin = Integer.MAX_VALUE;
|
||||
// to be sure, because the paginator adds some characters here and there
|
||||
int carefulMax = MessageEmbed.TEXT_MAX_LENGTH - 50;
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
int count = 0;
|
||||
int length = 0;
|
||||
for (String innerItem : items) {
|
||||
length += innerItem.length();
|
||||
if (length > carefulMax) {
|
||||
currentMin = Math.min(currentMin, count);
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return currentMin;
|
||||
private PaginatorButtonPayload getButtonPayload(PaginatorConfiguration configuration, String exitButtonId,
|
||||
String startButtonId, String previousButtonId,
|
||||
String nextButtonId, String lastButtonId) {
|
||||
return PaginatorButtonPayload
|
||||
.builder()
|
||||
.paginatorId(configuration.getPaginatorId())
|
||||
.exitButtonId(exitButtonId)
|
||||
.startButtonId(startButtonId)
|
||||
.previousButtonId(previousButtonId)
|
||||
.nextButtonId(nextButtonId)
|
||||
.lastButtonId(lastButtonId)
|
||||
.embedConfigs(configuration.getEmbedConfigs())
|
||||
.singlePage(configuration.getSinglePage())
|
||||
.build();
|
||||
}
|
||||
|
||||
public Integer getCurrentPage(String paginatorId) {
|
||||
return PAGINATORS.get(paginatorId).currentPage;
|
||||
}
|
||||
|
||||
public PaginatorInfo getPaginatorInfo(String paginatorId) {
|
||||
return PAGINATORS.get(paginatorId);
|
||||
}
|
||||
|
||||
public void updateCurrentPage(String paginatorId, Integer newPage, String newAccessorId) {
|
||||
try {
|
||||
lock.lock();
|
||||
PaginatorInfo paginatorInfo = PAGINATORS.get(paginatorId);
|
||||
if(paginatorInfo != null) {
|
||||
paginatorInfo.setCurrentPage(newPage);
|
||||
paginatorInfo.setLastAccessor(newAccessorId);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
lock.unlock();
|
||||
log.error("Failed to update current page for paginator {} to page {}", paginatorId, newPage, exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void schedulePaginationDeletion(String paginatorId, String accessorId) {
|
||||
PaginatorServiceBean.PaginatorInfo paginatorInfo = PAGINATORS.get(paginatorId);
|
||||
HashMap<Object, Object> parameters = new HashMap<>();
|
||||
parameters.put("paginatorId", paginatorId);
|
||||
parameters.put("accessorId", accessorId);
|
||||
JobParameters jobParameters = JobParameters
|
||||
.builder()
|
||||
.parameters(parameters)
|
||||
.build();
|
||||
Instant targetDate = Instant.now().plus(paginatorInfo.getTimeoutSeconds(), ChronoUnit.SECONDS);
|
||||
schedulerService.executeJobWithParametersOnce("paginatorCleanupJob", "core", jobParameters, Date.from(targetDate));
|
||||
log.debug("Scheduled job to delete the paginator {} in {} seconds.", paginatorId, paginatorInfo.getTimeoutSeconds());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void setupButtonPayloads(Message paginatorMessage, PaginatorConfiguration configuration, Long serverId, PaginatorButtonPayload payload) {
|
||||
savePayload(configuration.getExitButton(), serverId);
|
||||
if(!configuration.getSinglePage()) {
|
||||
savePayload(configuration.getStartButton(), serverId);
|
||||
savePayload(configuration.getPreviousButton(), serverId);
|
||||
savePayload(configuration.getNextButton(), serverId);
|
||||
savePayload(configuration.getLastButton(), serverId);
|
||||
}
|
||||
|
||||
String accessorId = UUID.randomUUID().toString();
|
||||
|
||||
PaginatorInfo info = PaginatorInfo
|
||||
.builder()
|
||||
.currentPage(0)
|
||||
.serverId(serverId)
|
||||
.channelId(paginatorMessage.getChannel().getIdLong())
|
||||
.messageId(paginatorMessage.getIdLong())
|
||||
.timeoutSeconds(configuration.getTimeoutSeconds())
|
||||
.paginatorId(configuration.getPaginatorId())
|
||||
.payloadIds(getAllPayloadIdsFromPayload(payload))
|
||||
.lastAccessor(accessorId)
|
||||
.build();
|
||||
log.debug("We are using the accessor id {} for paginator {} initially.", accessorId, configuration.getPaginatorId());
|
||||
PAGINATORS.put(configuration.getPaginatorId(), info);
|
||||
|
||||
schedulePaginationDeletion(configuration.getPaginatorId(), accessorId);
|
||||
}
|
||||
|
||||
private void savePayload(ButtonConfigModel model, Long serverId) {
|
||||
componentPayloadManagementService.createPayload(model, serverId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void cleanupPaginator(PaginatorInfo paginatorInfo) {
|
||||
log.info("Cleaning up paginator {} in server {} channel {} message {}.", paginatorInfo.getPaginatorId(),
|
||||
paginatorInfo.getServerId(), paginatorInfo.getChannelId(), paginatorInfo.getMessageId());
|
||||
messageService.deleteMessageInChannelInServer(paginatorInfo.getServerId(), paginatorInfo.getChannelId(), paginatorInfo.getMessageId());
|
||||
componentPayloadManagementService.deletePayloads(paginatorInfo.getPayloadIds());
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public static class PaginatorInfo {
|
||||
@Setter
|
||||
private Integer currentPage;
|
||||
private Long serverId;
|
||||
private Long channelId;
|
||||
private Long messageId;
|
||||
private String paginatorId;
|
||||
@Setter
|
||||
private String lastAccessor;
|
||||
private Long timeoutSeconds;
|
||||
private List<String> payloadIds;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ public class ComponentPayloadManagementServiceBean implements ComponentPayloadMa
|
||||
@Autowired
|
||||
private Gson gson;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public ComponentPayload createPayload(String id, String payload, Class payloadType, String buttonOrigin, AServer server, ComponentType componentType) {
|
||||
ComponentPayload componentPayload = ComponentPayload
|
||||
@@ -43,6 +46,12 @@ public class ComponentPayloadManagementServiceBean implements ComponentPayloadMa
|
||||
return createPayload(buttonConfigModel.getButtonId(), payload, buttonConfigModel.getPayloadType(), buttonConfigModel.getOrigin(), server, ComponentType.BUTTON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentPayload createPayload(ButtonConfigModel buttonConfigModel, Long serverId) {
|
||||
AServer server = serverManagementService.loadOrCreate(serverId);
|
||||
return createPayload(buttonConfigModel, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ComponentPayload> findPayload(String id) {
|
||||
return repository.findById(id);
|
||||
|
||||
@@ -82,6 +82,10 @@ public class TemplateServiceBean implements TemplateService {
|
||||
public MessageToSend renderEmbedTemplate(String key, Object model) {
|
||||
String embedConfig = this.renderTemplate(key + "_embed", model);
|
||||
EmbedConfiguration embedConfiguration = gson.fromJson(embedConfig, EmbedConfiguration.class);
|
||||
return convertEmbedConfigurationToMessageToSend(embedConfiguration);
|
||||
}
|
||||
|
||||
public MessageToSend convertEmbedConfigurationToMessageToSend(EmbedConfiguration embedConfiguration) {
|
||||
List<EmbedBuilder> embedBuilders = new ArrayList<>();
|
||||
embedBuilders.add(new EmbedBuilder());
|
||||
if(embedConfiguration.getMetaConfig() != null &&
|
||||
|
||||
@@ -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>
|
||||
@@ -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="paginatorCleanupJob.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?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="paginator-cleanup-job-insert">
|
||||
<insert tableName="scheduler_job">
|
||||
<column name="name" value="paginatorCleanupJob"/>
|
||||
<column name="group_name" value="core"/>
|
||||
<column name="clazz" value="dev.sheldan.abstracto.core.job.PaginatorCleanupJob"/>
|
||||
<column name="active" value="true"/>
|
||||
<column name="recovery" value="false"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -21,4 +21,5 @@
|
||||
<include file="1.3.5/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.6/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.9/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.10/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -33,6 +33,7 @@ public interface MessageService {
|
||||
CompletableFuture<Message> sendMessageToUser(User user, String text);
|
||||
CompletableFuture<Void> deleteMessageInChannelWithUser(User user, Long messageId);
|
||||
CompletableFuture<Void> editMessageInDMChannel(User user, MessageToSend messageToSend, Long messageId);
|
||||
CompletableFuture<Void> editMessageInChannel(MessageChannel channel, MessageToSend messageToSend, Long messageId);
|
||||
CompletableFuture<Message> loadMessageFromCachedMessage(CachedMessage cachedMessage);
|
||||
CompletableFuture<Message> loadMessage(Long serverId, Long channelId, Long messageId);
|
||||
CompletableFuture<Message> loadMessage(Message message);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
|
||||
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
|
||||
import com.jagrosh.jdautilities.menu.Paginator;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface PaginatorService {
|
||||
Paginator createPaginatorFromTemplate(String templateKey, Object model, EventWaiter waiter, Long serverId);
|
||||
CompletableFuture<Void> createPaginatorFromTemplate(String templateKey, Object model, TextChannel textChannel, Long userId);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.Optional;
|
||||
public interface ComponentPayloadManagementService {
|
||||
ComponentPayload createPayload(String id, String payload, Class payloadType, String buttonOrigin, AServer server, ComponentType type);
|
||||
ComponentPayload createPayload(ButtonConfigModel buttonConfigModel, AServer server);
|
||||
ComponentPayload createPayload(ButtonConfigModel buttonConfigModel, Long serverId);
|
||||
Optional<ComponentPayload> findPayload(String id);
|
||||
List<ComponentPayload> findPayloadsOfOriginInServer(String buttonOrigin, AServer server);
|
||||
void deletePayload(String id);
|
||||
|
||||
@@ -123,6 +123,9 @@ Configuring which role to use for muting::
|
||||
* Usage: `setMuteRole <role>`
|
||||
* Description: Sets the `role` to be used as the role when applying a mute. This role needs to be muting, which means, if you want it to be effective, this role needs to deny `MESSAGE_WRITE`. The bot does not validate nor require the role to actually mute.
|
||||
Only *one* role can be used as a mute role.
|
||||
Showing all mutes::
|
||||
* Usage: `mutes [member]`
|
||||
* Description: Shows all the mutes in a paginated matter with buttons to navigate the pages. If `member` is provided, it will only show mutes for this member.
|
||||
|
||||
=== Logging
|
||||
|
||||
|
||||
Reference in New Issue
Block a user