mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-21 21:41:30 +00:00
[AB-196] adding confirmation requirement to various commands
refactoring command received handler in order to re-use when confirmation has been given removing reaction from showSuggestion and remind command adding log message for message deleted message, in case the member left all commands from now on must work without the member field from the message, as this is not available when retrieving the message
This commit is contained in:
@@ -50,6 +50,7 @@ public class DeleteAssignableRolePlace extends AbstractConditionableCommand {
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.async(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -66,6 +66,7 @@ public class SetExpRole extends AbstractConditionableCommand {
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.requiresConfirmation(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
|
||||
@@ -52,6 +52,7 @@ public class SyncRoles extends AbstractConditionableCommand {
|
||||
.module(ExperienceModuleDefinition.EXPERIENCE)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -67,6 +67,7 @@ public class UnSetExpRole extends AbstractConditionableCommand {
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.causesReaction(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -51,6 +51,7 @@ public class RemoveTrackedInviteLinks extends AbstractConditionableCommand {
|
||||
.module(InviteFilterModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -65,7 +65,10 @@ public class MessageDeleteLogListener implements AsyncMessageDeletedListener {
|
||||
CachedMessage message = model.getCachedMessage();
|
||||
memberService.getMemberInServerAsync(model.getServerId(), message.getAuthor().getAuthorId()).thenAccept(member ->
|
||||
self.executeListener(message, member)
|
||||
);
|
||||
).exceptionally(throwable -> {
|
||||
log.warn("Could not retrieve member {} for message deleted event in guild {}.", message.getAuthor().getAuthorId(), model.getServerId(), throwable);
|
||||
return null;
|
||||
});
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ public class DecayAllWarnings extends AbstractConditionableCommand {
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -43,6 +43,7 @@ public class DecayWarnings extends AbstractConditionableCommand {
|
||||
.name("decayWarnings")
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.requiresConfirmation(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
|
||||
@@ -54,7 +54,7 @@ public class AnonReply extends AbstractConditionableCommand {
|
||||
ModMailThread thread = modMailThreadManagementService.getByChannel(channel);
|
||||
Long threadId = thread.getId();
|
||||
return memberService.getMemberInServerAsync(thread.getUser()).thenCompose(member ->
|
||||
modMailThreadService.relayMessageToDm(threadId, text, commandContext.getMessage(), true, commandContext.getChannel(), commandContext.getUndoActions(), member)
|
||||
modMailThreadService.loadExecutingMemberAndRelay(threadId, text, commandContext.getMessage(), true, member)
|
||||
).thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class Reply extends AbstractConditionableCommand {
|
||||
ModMailThread thread = modMailThreadManagementService.getByChannel(channel);
|
||||
Long threadId = thread.getId();
|
||||
return memberService.getMemberInServerAsync(thread.getUser()).thenCompose(member ->
|
||||
modMailThreadService.relayMessageToDm(threadId, text, commandContext.getMessage(), false, commandContext.getChannel(), commandContext.getUndoActions(), member)
|
||||
modMailThreadService.loadExecutingMemberAndRelay(threadId, text, commandContext.getMessage(), false, member)
|
||||
).thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
|
||||
@@ -553,8 +553,14 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CompletableFuture<Void> relayMessageToDm(Long modmailThreadId, String text, Message replyCommandMessage, boolean anonymous, MessageChannel feedBack, List<UndoActionInstance> undoActions, Member targetMember) {
|
||||
public CompletableFuture<Void> loadExecutingMemberAndRelay(Long modmailThreadId, String text, Message replyCommandMessage, boolean anonymous, Member targetMember) {
|
||||
log.info("Relaying message {} to user {} in modmail thread {} on server {}.", replyCommandMessage.getId(), targetMember.getId(), modmailThreadId, targetMember.getGuild().getId());
|
||||
return memberService.getMemberInServerAsync(replyCommandMessage.getGuild().getIdLong(), replyCommandMessage.getAuthor().getIdLong())
|
||||
.thenCompose(executingMember -> self.relayMessageToDm(modmailThreadId, text, replyCommandMessage, anonymous, targetMember, executingMember));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> relayMessageToDm(Long modmailThreadId, String text, Message replyCommandMessage, boolean anonymous, Member targetMember, Member executingMember) {
|
||||
metricService.incrementCounter(MDOMAIL_THREAD_MESSAGE_SENT);
|
||||
ModMailThread modMailThread = modMailThreadManagementService.getById(modmailThreadId);
|
||||
FullUserInServer fullThreadUser = FullUserInServer
|
||||
@@ -573,7 +579,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
log.debug("Message is sent anonymous.");
|
||||
modMailModeratorReplyModelBuilder.moderator(memberService.getBotInGuild(modMailThread.getServer()));
|
||||
} else {
|
||||
modMailModeratorReplyModelBuilder.moderator(replyCommandMessage.getMember());
|
||||
modMailModeratorReplyModelBuilder.moderator(executingMember);
|
||||
}
|
||||
ModMailModeratorReplyModel modMailUserReplyModel = modMailModeratorReplyModelBuilder.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(MODMAIL_STAFF_MESSAGE_TEMPLATE_KEY, modMailUserReplyModel, modMailThread.getServer().getId());
|
||||
|
||||
@@ -67,12 +67,10 @@ public interface ModMailThreadService {
|
||||
* @param text The parsed text of the reply
|
||||
* @param message The pure {@link Message} containing the command which caused the reply
|
||||
* @param anonymous Whether or nor the message should be send anonymous
|
||||
* @param feedBack The {@link MessageChannel} in which feedback about possible exceptions should be sent to
|
||||
* @param undoActions A list of {@link dev.sheldan.abstracto.core.models.UndoAction actions} to be undone in case the operation fails. This list will be filled in the method.
|
||||
* @param targetMember The {@link Member} the {@link ModMailThread} is about.
|
||||
* @return A {@link CompletableFuture future} which completes when the message has been relayed to the DM
|
||||
*/
|
||||
CompletableFuture<Void> relayMessageToDm(Long threadId, String text, Message message, boolean anonymous, MessageChannel feedBack, List<UndoActionInstance> undoActions, Member targetMember);
|
||||
CompletableFuture<Void> loadExecutingMemberAndRelay(Long threadId, String text, Message message, boolean anonymous, Member targetMember);
|
||||
|
||||
/**
|
||||
* Closes the mod mail thread which means: deletes the {@link net.dv8tion.jda.api.entities.TextChannel} associated with the mod mail thread,
|
||||
|
||||
@@ -70,7 +70,7 @@ public class Remind extends AbstractConditionableCommand {
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
|
||||
@@ -109,7 +109,10 @@ public class RemindServiceBean implements ReminderService {
|
||||
} else {
|
||||
HashMap<Object, Object> parameters = new HashMap<>();
|
||||
parameters.put("reminderId", reminder.getId().toString());
|
||||
JobParameters jobParameters = JobParameters.builder().parameters(parameters).build();
|
||||
JobParameters jobParameters = JobParameters
|
||||
.builder()
|
||||
.parameters(parameters)
|
||||
.build();
|
||||
String triggerKey = schedulerService.executeJobWithParametersOnce("reminderJob", "utility", jobParameters, Date.from(reminder.getTargetDate()));
|
||||
log.info("Starting scheduled job with trigger {} to execute reminder {}.", triggerKey, reminder.getId());
|
||||
reminder.setJobTriggerKey(triggerKey);
|
||||
|
||||
@@ -50,6 +50,7 @@ public class PurgeImagePosts extends AbstractConditionableCommand {
|
||||
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
|
||||
.templated(true)
|
||||
.async(false)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -50,6 +50,7 @@ public class PurgeReposts extends AbstractConditionableCommand {
|
||||
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
|
||||
.templated(true)
|
||||
.async(false)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -51,6 +51,7 @@ public class DeleteTrackedEmote extends AbstractConditionableCommand {
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.requiresConfirmation(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
|
||||
@@ -60,6 +60,7 @@ public class PurgeEmoteStats extends AbstractConditionableCommand {
|
||||
.module(EmoteTrackingModuleDefinition.EMOTE_TRACKING)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.requiresConfirmation(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -41,6 +41,7 @@ public class ResetEmoteStats extends AbstractConditionableCommand {
|
||||
.module(EmoteTrackingModuleDefinition.EMOTE_TRACKING)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.requiresConfirmation(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -58,7 +58,7 @@ public class ShowSuggestion extends AbstractConditionableCommand {
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
|
||||
@@ -114,7 +114,13 @@ public class SuggestionServiceBean implements SuggestionService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createSuggestionMessage(Message commandMessage, String text) {
|
||||
Member suggester = commandMessage.getMember();
|
||||
// it is done that way, because we cannot always be sure, that the message containsn the member
|
||||
return memberService.getMemberInServerAsync(commandMessage.getGuild().getIdLong(), commandMessage.getAuthor().getIdLong())
|
||||
.thenCompose(suggester -> self.createMessageWithSuggester(commandMessage, text, suggester));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> createMessageWithSuggester(Message commandMessage, String text, Member suggester) {
|
||||
Long serverId = suggester.getGuild().getIdLong();
|
||||
AServer server = serverManagementService.loadServer(serverId);
|
||||
AUserInAServer userSuggester = userInServerManagementService.loadOrCreateUser(suggester);
|
||||
@@ -126,7 +132,7 @@ public class SuggestionServiceBean implements SuggestionService {
|
||||
.state(SuggestionState.NEW)
|
||||
.serverId(serverId)
|
||||
.message(commandMessage)
|
||||
.member(commandMessage.getMember())
|
||||
.member(suggester)
|
||||
.suggesterUser(userSuggester)
|
||||
.useButtons(useButtons)
|
||||
.suggester(suggester.getUser())
|
||||
@@ -210,22 +216,24 @@ public class SuggestionServiceBean implements SuggestionService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> acceptSuggestion(Long suggestionId, Message commandMessage, String text) {
|
||||
return memberService.getMemberInServerAsync(commandMessage.getGuild().getIdLong(), commandMessage.getAuthor().getIdLong())
|
||||
.thenCompose(member -> self.setSuggestionToFinalState(member, suggestionId, commandMessage, text, SuggestionState.ACCEPTED));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> setSuggestionToFinalState(Member executingMember, Long suggestionId, Message commandMessage, String text, SuggestionState state) {
|
||||
Long serverId = commandMessage.getGuild().getIdLong();
|
||||
Suggestion suggestion = suggestionManagementService.getSuggestion(serverId, suggestionId);
|
||||
suggestionManagementService.setSuggestionState(suggestion, SuggestionState.ACCEPTED);
|
||||
suggestionManagementService.setSuggestionState(suggestion, state);
|
||||
cancelSuggestionReminder(suggestion);
|
||||
log.info("Accepting suggestion {} in server {}.", suggestionId, suggestion.getServer().getId());
|
||||
return updateSuggestion(commandMessage.getMember(), text, suggestion);
|
||||
log.info("Setting suggestion {} in server {} to state {}", suggestionId, suggestion.getServer().getId(), state);
|
||||
return updateSuggestion(executingMember, text, suggestion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> vetoSuggestion(Long suggestionId, Message commandMessage, String text) {
|
||||
Long serverId = commandMessage.getGuild().getIdLong();
|
||||
Suggestion suggestion = suggestionManagementService.getSuggestion(serverId, suggestionId);
|
||||
suggestionManagementService.setSuggestionState(suggestion, SuggestionState.VETOED);
|
||||
cancelSuggestionReminder(suggestion);
|
||||
log.info("Vetoing suggestion {} in server {}.", suggestionId, suggestion.getServer().getId());
|
||||
return updateSuggestion(commandMessage.getMember(), text, suggestion);
|
||||
return memberService.getMemberInServerAsync(commandMessage.getGuild().getIdLong(), commandMessage.getAuthor().getIdLong())
|
||||
.thenCompose(member -> self.setSuggestionToFinalState(member, suggestionId, commandMessage, text, SuggestionState.VETOED));
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> updateSuggestion(Member memberExecutingCommand, String reason, Suggestion suggestion) {
|
||||
@@ -293,12 +301,8 @@ public class SuggestionServiceBean implements SuggestionService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> rejectSuggestion(Long suggestionId, Message commandMessage, String text) {
|
||||
Long serverId = commandMessage.getGuild().getIdLong();
|
||||
Suggestion suggestion = suggestionManagementService.getSuggestion(serverId, suggestionId);
|
||||
suggestionManagementService.setSuggestionState(suggestion, SuggestionState.REJECTED);
|
||||
cancelSuggestionReminder(suggestion);
|
||||
log.info("Rejecting suggestion {} in server {}.", suggestionId, suggestion.getServer().getId());
|
||||
return updateSuggestion(commandMessage.getMember(), text, suggestion);
|
||||
return memberService.getMemberInServerAsync(commandMessage.getGuild().getIdLong(), commandMessage.getAuthor().getIdLong())
|
||||
.thenCompose(member -> self.setSuggestionToFinalState(member, suggestionId, commandMessage, text, SuggestionState.REJECTED));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
package dev.sheldan.abstracto.suggestion.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
@@ -16,10 +12,8 @@ import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureMode;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionPostTarget;
|
||||
import dev.sheldan.abstracto.suggestion.exception.SuggestionNotFoundException;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.Suggestion;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.SuggestionState;
|
||||
import dev.sheldan.abstracto.suggestion.model.template.SuggestionLog;
|
||||
import dev.sheldan.abstracto.suggestion.model.template.SuggestionUpdateModel;
|
||||
import dev.sheldan.abstracto.suggestion.service.management.SuggestionManagementService;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import org.junit.Test;
|
||||
@@ -113,17 +107,12 @@ public class SuggestionServiceBeanTest {
|
||||
public void testCreateSuggestionMessage() {
|
||||
String suggestionText = "text";
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
|
||||
MessageToSend messageToSend = Mockito.mock(MessageToSend.class);
|
||||
when(templateService.renderEmbedTemplate(eq(SuggestionServiceBean.SUGGESTION_CREATION_TEMPLATE), any(SuggestionLog.class), eq(SERVER_ID))).thenReturn(messageToSend);
|
||||
Message suggestionMessage = Mockito.mock(Message.class);
|
||||
when(counterService.getNextCounterValue(server, SuggestionServiceBean.SUGGESTION_COUNTER_KEY)).thenReturn(SUGGESTION_ID);
|
||||
List<CompletableFuture<Message>> postingFutures = Arrays.asList(CompletableFuture.completedFuture(suggestionMessage));
|
||||
when(postTargetService.sendEmbedInPostTarget(messageToSend, SuggestionPostTarget.SUGGESTION, SERVER_ID)).thenReturn(postingFutures);
|
||||
when(message.getMember()).thenReturn(member);
|
||||
when(member.getGuild()).thenReturn(guild);
|
||||
when(member.getIdLong()).thenReturn(SUGGESTER_ID);
|
||||
when(message.getAuthor()).thenReturn(suggesterUser);
|
||||
when(message.getGuild()).thenReturn(guild);
|
||||
when(suggesterUser.getIdLong()).thenReturn(SUGGESTER_ID);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, SUGGESTER_ID)).thenReturn(CompletableFuture.completedFuture(member));
|
||||
testUnit.createSuggestionMessage(message, suggestionText);
|
||||
verify(self).createMessageWithSuggester(message, suggestionText, member);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -139,20 +128,26 @@ public class SuggestionServiceBeanTest {
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = SuggestionNotFoundException.class)
|
||||
@Test
|
||||
public void testAcceptNotExistingSuggestion() {
|
||||
when(suggestionManagementService.getSuggestion(SERVER_ID, SUGGESTION_ID)).thenThrow(new SuggestionNotFoundException(SUGGESTION_ID));
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
when(message.getGuild()).thenReturn(guild);
|
||||
when(message.getAuthor()).thenReturn(suggesterUser);
|
||||
when(suggesterUser.getIdLong()).thenReturn(SUGGESTER_ID);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, SUGGESTER_ID)).thenReturn(CompletableFuture.completedFuture(member));
|
||||
testUnit.acceptSuggestion(SUGGESTION_ID, message, CLOSING_TEXT);
|
||||
verify(self).setSuggestionToFinalState(member, SUGGESTION_ID, message, CLOSING_TEXT, SuggestionState.ACCEPTED);
|
||||
}
|
||||
|
||||
@Test(expected = SuggestionNotFoundException.class)
|
||||
@Test
|
||||
public void testRejectNotExistingSuggestion() {
|
||||
when(suggestionManagementService.getSuggestion(SERVER_ID, SUGGESTION_ID)).thenThrow(new SuggestionNotFoundException(SUGGESTION_ID));
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
when(message.getGuild()).thenReturn(guild);
|
||||
when(message.getAuthor()).thenReturn(suggesterUser);
|
||||
when(suggesterUser.getIdLong()).thenReturn(SUGGESTER_ID);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, SUGGESTER_ID)).thenReturn(CompletableFuture.completedFuture(member));
|
||||
testUnit.rejectSuggestion(SUGGESTION_ID, message, CLOSING_TEXT);
|
||||
verify(self).setSuggestionToFinalState(member, SUGGESTION_ID, message, CLOSING_TEXT, SuggestionState.REJECTED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user