mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-14 03:45:57 +00:00
[AB-311] adding softban command
This commit is contained in:
@@ -173,13 +173,28 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
|
|||||||
CompletableFutureList<Message> reactionFutureList = new CompletableFutureList<>(reactionMessageFutures);
|
CompletableFutureList<Message> reactionFutureList = new CompletableFutureList<>(reactionMessageFutures);
|
||||||
CompletableFutureList<Message> buttonFutureList = new CompletableFutureList<>(buttonMessageFutures);
|
CompletableFutureList<Message> buttonFutureList = new CompletableFutureList<>(buttonMessageFutures);
|
||||||
return reactionFutureList.getMainFuture()
|
return reactionFutureList.getMainFuture()
|
||||||
.handle((unused, throwable) -> self.removeReactions(reactionFutureList.getObjects()))
|
.handle((unused, throwable) -> {
|
||||||
|
if(throwable != null) {
|
||||||
|
log.warn("Embedded messages reaction message loading failed.", throwable);
|
||||||
|
}
|
||||||
|
return self.removeReactions(reactionFutureList.getObjects());
|
||||||
|
})
|
||||||
.thenCompose(Function.identity())
|
.thenCompose(Function.identity())
|
||||||
.thenCompose(unused -> buttonFutureList.getMainFuture())
|
.thenCompose(unused -> buttonFutureList.getMainFuture())
|
||||||
.handle((unused, throwable) -> self.removeButtons(buttonFutureList.getObjects()))
|
.handle((unused, throwable) -> {
|
||||||
|
if(throwable != null) {
|
||||||
|
log.warn("Embedded messages button message loading failed.", throwable);
|
||||||
|
}
|
||||||
|
return self.removeButtons(buttonFutureList.getObjects());
|
||||||
|
})
|
||||||
// deleting the messages from db regardless of exceptions, at most the reaction remains
|
// deleting the messages from db regardless of exceptions, at most the reaction remains
|
||||||
.thenCompose(Function.identity())
|
.thenCompose(Function.identity())
|
||||||
.whenComplete((unused, throwable) -> self.deleteEmbeddedMessages(embeddedMessagesHandled))
|
.whenComplete((unused, throwable) -> {
|
||||||
|
if(throwable != null) {
|
||||||
|
log.warn("Embedded message button clearing failed.", throwable);
|
||||||
|
}
|
||||||
|
self.deleteEmbeddedMessages(embeddedMessagesHandled);
|
||||||
|
})
|
||||||
.exceptionally(throwable -> {
|
.exceptionally(throwable -> {
|
||||||
log.error("Failed to clean up embedded messages.", throwable);
|
log.error("Failed to clean up embedded messages.", throwable);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.command;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||||
|
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.EffectConfig;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||||
|
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||||
|
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||||
|
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||||
|
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
|
||||||
|
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||||
|
import dev.sheldan.abstracto.moderation.service.BanService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.dv8tion.jda.api.entities.User;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import static dev.sheldan.abstracto.moderation.service.BanService.BAN_EFFECT_KEY;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class SoftBan extends AbstractConditionableCommand {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BanService banService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||||
|
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||||
|
User user = (User) parameters.get(0);
|
||||||
|
Duration delDays = Duration.ofDays(7);
|
||||||
|
if(parameters.size() > 1) {
|
||||||
|
delDays = (Duration) parameters.get(1);
|
||||||
|
}
|
||||||
|
return banService.softBanUser(commandContext.getGuild(), user, delDays)
|
||||||
|
.thenApply(unused -> CommandResult.fromSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandConfiguration getConfiguration() {
|
||||||
|
List<Parameter> parameters = new ArrayList<>();
|
||||||
|
parameters.add(Parameter.builder().name("user").templated(true).type(User.class).build());
|
||||||
|
parameters.add(Parameter.builder().name("delDays").templated(true).type(Duration.class).optional(true).build());
|
||||||
|
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||||
|
List<EffectConfig> effectConfig = Arrays.asList(EffectConfig.builder().position(0).effectKey(BAN_EFFECT_KEY).build());
|
||||||
|
return CommandConfiguration.builder()
|
||||||
|
.name("softBan")
|
||||||
|
.module(ModerationModuleDefinition.MODERATION)
|
||||||
|
.templated(true)
|
||||||
|
.async(true)
|
||||||
|
.effects(effectConfig)
|
||||||
|
.supportsEmbedException(true)
|
||||||
|
.causesReaction(true)
|
||||||
|
.parameters(parameters)
|
||||||
|
.help(helpInfo)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return ModerationFeatureDefinition.MODERATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CommandCondition> getConditions() {
|
||||||
|
List<CommandCondition> conditions = super.getConditions();
|
||||||
|
conditions.add(immuneUserCondition);
|
||||||
|
return conditions;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ import net.dv8tion.jda.api.entities.User;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ public class BanServiceBean implements BanService {
|
|||||||
.commandMessage(message)
|
.commandMessage(message)
|
||||||
.reason(reason)
|
.reason(reason)
|
||||||
.build();
|
.build();
|
||||||
CompletableFuture<Void> banFuture = banUser(member.getGuild(), member.getUser(), reason);
|
CompletableFuture<Void> banFuture = banUser(member.getGuild(), member.getUser(), 0, reason);
|
||||||
CompletableFuture<Void> messageFuture = sendBanLogMessage(banLog, member.getGuild().getIdLong(), BAN_LOG_TEMPLATE);
|
CompletableFuture<Void> messageFuture = sendBanLogMessage(banLog, member.getGuild().getIdLong(), BAN_LOG_TEMPLATE);
|
||||||
return CompletableFuture.allOf(banFuture, messageFuture);
|
return CompletableFuture.allOf(banFuture, messageFuture);
|
||||||
}
|
}
|
||||||
@@ -81,7 +82,7 @@ public class BanServiceBean implements BanService {
|
|||||||
.thenAccept(message1 -> log.info("Notified about not being able to send ban notification in server {} and channel {} based on message {} from user {}."
|
.thenAccept(message1 -> log.info("Notified about not being able to send ban notification in server {} and channel {} based on message {} from user {}."
|
||||||
, message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong(), message.getAuthor().getIdLong()));
|
, message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong(), message.getAuthor().getIdLong()));
|
||||||
}
|
}
|
||||||
CompletableFuture<Void> banFuture = banUser(guild, user, reason);
|
CompletableFuture<Void> banFuture = banUser(guild, user, 0, reason);
|
||||||
CompletableFuture<Void> messageFuture = sendBanLogMessage(banLog, guild.getIdLong(), BAN_LOG_TEMPLATE);
|
CompletableFuture<Void> messageFuture = sendBanLogMessage(banLog, guild.getIdLong(), BAN_LOG_TEMPLATE);
|
||||||
CompletableFuture.allOf(banFuture, messageFuture)
|
CompletableFuture.allOf(banFuture, messageFuture)
|
||||||
.thenAccept(unused1 -> returningFuture.complete(null))
|
.thenAccept(unused1 -> returningFuture.complete(null))
|
||||||
@@ -111,10 +112,29 @@ public class BanServiceBean implements BanService {
|
|||||||
.bannedUser(user)
|
.bannedUser(user)
|
||||||
.unBanningMember(unBanningMember)
|
.unBanningMember(unBanningMember)
|
||||||
.build();
|
.build();
|
||||||
return unBanUser(guild, user)
|
return unbanUser(guild, user)
|
||||||
.thenCompose(unused -> self.sendUnBanLogMessage(banLog, guild.getIdLong(), UN_BAN_LOG_TEMPLATE));
|
.thenCompose(unused -> self.sendUnBanLogMessage(banLog, guild.getIdLong(), UN_BAN_LOG_TEMPLATE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> banUser(Guild guild, User user, Integer deletionDays, String reason) {
|
||||||
|
log.info("Banning user {} in guild {}.", user.getIdLong(), guild.getId());
|
||||||
|
return guild.ban(user, deletionDays, reason).submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> unbanUser(Guild guild, User user) {
|
||||||
|
log.info("Unbanning user {} in guild {}.", user.getIdLong(), guild.getId());
|
||||||
|
return guild.unban(user).submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> softBanUser(Guild guild, User user, Duration delDays) {
|
||||||
|
Long days = delDays.toDays();
|
||||||
|
return banUser(guild, user, days.intValue(), "")
|
||||||
|
.thenCompose(unused -> unbanUser(guild, user));
|
||||||
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> sendBanLogMessage(BanLog banLog, Long guildId, String template) {
|
public CompletableFuture<Void> sendBanLogMessage(BanLog banLog, Long guildId, String template) {
|
||||||
CompletableFuture<Void> completableFuture;
|
CompletableFuture<Void> completableFuture;
|
||||||
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
||||||
@@ -132,14 +152,4 @@ public class BanServiceBean implements BanService {
|
|||||||
completableFuture = FutureUtils.toSingleFutureGeneric(notificationFutures);
|
completableFuture = FutureUtils.toSingleFutureGeneric(notificationFutures);
|
||||||
return completableFuture;
|
return completableFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> banUser(Guild guild, User user, String reason) {
|
|
||||||
log.info("Banning user {} in guild {}.", user.getIdLong(), guild.getId());
|
|
||||||
return guild.ban(user, 0, reason).submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private CompletableFuture<Void> unBanUser(Guild guild, User user) {
|
|
||||||
log.info("Unbanning user {} in guild {}.", user.getIdLong(), guild.getId());
|
|
||||||
return guild.unban(user).submit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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="softBan-command">
|
||||||
|
<insert tableName="command">
|
||||||
|
<column name="name" value="softBan"/>
|
||||||
|
<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>
|
||||||
@@ -10,4 +10,5 @@
|
|||||||
<include file="1.2.11-moderation/collection.xml" relativeToChangelogFile="true"/>
|
<include file="1.2.11-moderation/collection.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="1.2.15/collection.xml" relativeToChangelogFile="true"/>
|
<include file="1.2.15/collection.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="1.2.16/collection.xml" relativeToChangelogFile="true"/>
|
<include file="1.2.16/collection.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="1.3.4/collection.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
@@ -31,36 +31,16 @@ public class BanTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private BanService banService;
|
private BanService banService;
|
||||||
|
|
||||||
@Mock
|
|
||||||
private TemplateService templateService;
|
|
||||||
|
|
||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<Member> banLogModelCaptor;
|
private ArgumentCaptor<Member> banLogModelCaptor;
|
||||||
|
|
||||||
private static final String REASON = "reason";
|
|
||||||
private static final Long SERVER_ID = 1L;
|
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private User bannedMember;
|
private User bannedMember;
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBanWithDefaultReason() {
|
|
||||||
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(bannedMember));
|
|
||||||
when(parameters.getGuild().getIdLong()).thenReturn(SERVER_ID);
|
|
||||||
when(templateService.renderSimpleTemplate(Ban.BAN_DEFAULT_REASON_TEMPLATE, SERVER_ID)).thenReturn(REASON);
|
|
||||||
when(banService.banUser(eq(bannedMember), eq(REASON), banLogModelCaptor.capture(), any(Message.class))).thenReturn(CompletableFuture.completedFuture(null));
|
|
||||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
|
|
||||||
Member banningMember = banLogModelCaptor.getValue();
|
|
||||||
Assert.assertEquals(parameters.getAuthor(), banningMember);
|
|
||||||
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBanWithReason() {
|
public void testBanWithReason() {
|
||||||
String customReason = "reason2";
|
String customReason = "reason2";
|
||||||
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(bannedMember, customReason));
|
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(bannedMember, customReason));
|
||||||
when(parameters.getGuild().getIdLong()).thenReturn(SERVER_ID);
|
|
||||||
when(templateService.renderSimpleTemplate(Ban.BAN_DEFAULT_REASON_TEMPLATE, SERVER_ID)).thenReturn(REASON);
|
|
||||||
when(banService.banUser(eq(bannedMember), eq(customReason), banLogModelCaptor.capture(), any(Message.class))).thenReturn(CompletableFuture.completedFuture(null));
|
when(banService.banUser(eq(bannedMember), eq(customReason), banLogModelCaptor.capture(), any(Message.class))).thenReturn(CompletableFuture.completedFuture(null));
|
||||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
|
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
|
||||||
Member banningMember = banLogModelCaptor.getValue();
|
Member banningMember = banLogModelCaptor.getValue();
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package dev.sheldan.abstracto.moderation.service;
|
package dev.sheldan.abstracto.moderation.service;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public interface BanService {
|
public interface BanService {
|
||||||
@@ -11,4 +13,7 @@ public interface BanService {
|
|||||||
CompletableFuture<Void> banMember(Member member, String reason, Member banningMember, Message message);
|
CompletableFuture<Void> banMember(Member member, String reason, Member banningMember, Message message);
|
||||||
CompletableFuture<Void> banUser(User user, String reason, Member banningMember, Message message);
|
CompletableFuture<Void> banUser(User user, String reason, Member banningMember, Message message);
|
||||||
CompletableFuture<Void> unBanUser(User user, Member unBanningUser);
|
CompletableFuture<Void> unBanUser(User user, Member unBanningUser);
|
||||||
|
CompletableFuture<Void> banUser(Guild guild, User user, Integer deletionDays, String reason);
|
||||||
|
CompletableFuture<Void> unbanUser(Guild guild, User user);
|
||||||
|
CompletableFuture<Void> softBanUser(Guild guild, User user, Duration delDays);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ Purging messages in a channel::
|
|||||||
* Description: Deletes the last `messageCount` messages in the current channel. If a `member` is provided as parameter, only the messages by this member
|
* Description: Deletes the last `messageCount` messages in the current channel. If a `member` is provided as parameter, only the messages by this member
|
||||||
will be deleted. The deletion of this messages will *not* be logged by the logging mechanism. The messages to be deleted need to be from within the last 2 weeks, but there is no limit on how much messages can be deleted besides that.
|
will be deleted. The deletion of this messages will *not* be logged by the logging mechanism. The messages to be deleted need to be from within the last 2 weeks, but there is no limit on how much messages can be deleted besides that.
|
||||||
While the command is ongoing, a status update message will be shown indicating how far the command is. This message will be deleted after the command is done.
|
While the command is ongoing, a status update message will be shown indicating how far the command is. This message will be deleted after the command is done.
|
||||||
|
Deleting all messages and kicking a member::
|
||||||
|
* Usage `softBan <user> [delDays]`
|
||||||
|
* Description: Bans the given `user` and deletes the messages for the given time period in `delDays`. This duration must be in days and can be at most 7 days. When no duration is provided 7 days are used. This command automatically unbans the user afterwards.
|
||||||
|
|
||||||
=== Warning
|
=== Warning
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user