added warn and ban command

changed command context to be a member instead of user, commands are only supported within guilds
added custom exception templating for the error message
added error message in case the parameters for a command were too little
added support for templates on command help descriptions
added post execution to be executed to print exception messages
refactored command handling to be able to support exceptions
added user and userInServer management
This commit is contained in:
Sheldan
2020-03-18 18:21:06 +01:00
parent 167bbb0f8b
commit bd848d31d3
82 changed files with 913 additions and 151 deletions

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>moderation-impl</artifactId>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation-int</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,66 @@
package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.moderation.Moderation;
import dev.sheldan.abstracto.moderation.models.BanLog;
import dev.sheldan.abstracto.moderation.models.WarnLog;
import dev.sheldan.abstracto.moderation.service.BanService;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Member;
import org.hibernate.sql.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
@Slf4j
public class Ban implements Command {
@Autowired
private BanService banService;
@Autowired
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
String defaultReason = templateService.renderTemplate("ban_default_reason", null);
String reason = parameters.size() == 2 ? (String) parameters.get(1) : defaultReason;
banService.banMember(member, reason);
BanLog banLogModel = BanLog
.parentBuilder()
.commandTemplateContext(commandContext.getCommandTemplateContext())
.bannedUser(member)
.banningUser(commandContext.getAuthor())
.reason(reason)
.build();
banService.sendBanLog(banLogModel);
return Result.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("user").type(Member.class).optional(false).build());
parameters.add(Parameter.builder().name("reason").type(String.class).optional(false).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().usageTemplate("ban_usage").longHelpTemplate("ban_long_help").build();
return CommandConfiguration.builder()
.name("ban")
.module(Moderation.MODERATION)
.descriptionTemplate("ban_help_description")
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
}

View File

@@ -0,0 +1,69 @@
package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.moderation.Moderation;
import dev.sheldan.abstracto.moderation.models.WarnLog;
import dev.sheldan.abstracto.moderation.models.Warning;
import dev.sheldan.abstracto.moderation.service.WarnService;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
@Slf4j
public class Warn implements Command {
@Autowired
private UserManagementService userManagementService;
@Autowired
private WarnService warnService;
@Autowired
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
String defaultReason = templateService.renderTemplate("warn_default_reason", null);
String reason = parameters.size() == 2 ? (String) parameters.get(1) : defaultReason;
Warning warning = warnService.warnUser(member, commandContext.getAuthor(), reason);
WarnLog warnLogModel = WarnLog
.parentBuilder()
.commandTemplateContext(commandContext.getCommandTemplateContext())
.warnedUser(member)
.warningUser(commandContext.getAuthor())
.warning(warning)
.build();
warnService.sendWarnLog(warnLogModel);
return Result.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("user").type(Member.class).optional(false).build());
parameters.add(Parameter.builder().name("reason").type(String.class).optional(true).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().usageTemplate("warn_usage").longHelpTemplate("long_help").build();
return CommandConfiguration.builder()
.name("warn")
.module(Moderation.MODERATION)
.descriptionTemplate("warn_help_description")
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.moderation.repository;
import dev.sheldan.abstracto.moderation.models.Warning;
import org.springframework.data.jpa.repository.JpaRepository;
public interface WarnRepository extends JpaRepository<Warning, Long> {
}

View File

@@ -0,0 +1,44 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.PostTarget;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.moderation.models.BanLog;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class BanServiceBean implements BanService {
public static final String BAN_LOG_TEMPLATE = "ban_log";
@Autowired
private Bot bot;
@Autowired
private TemplateService templateService;
@Autowired
private PostTargetService postTargetService;
@Override
public void banMember(Member member, String reason) {
Guild guild = bot.getInstance().getGuildById(member.getGuild().getIdLong());
if(guild != null) {
log.info("Banning user {} in guild {}.", member.getId(), guild.getIdLong());
guild.ban(member, 0, reason).queue();
} else {
log.warn("Guild id {} from member was not found.", member.getGuild().getIdLong());
}
}
@Override
public void sendBanLog(BanLog banLog) {
String warnLogMessage = templateService.renderTemplate(BAN_LOG_TEMPLATE, banLog);
postTargetService.sendTextInPostTarget(warnLogMessage, PostTarget.WARN_LOG, banLog.getServer().getId());
}
}

View File

@@ -0,0 +1,88 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.AServer;
import dev.sheldan.abstracto.core.models.AUser;
import dev.sheldan.abstracto.moderation.models.WarnLog;
import dev.sheldan.abstracto.moderation.models.WarnNotification;
import dev.sheldan.abstracto.moderation.models.Warning;
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.models.AUserInAServer;
import dev.sheldan.abstracto.core.models.PostTarget;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class WarnServiceBean implements WarnService {
@Autowired
private UserManagementService userManagementService;
@Autowired
private WarnManagementService warnManagementService;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private PostTargetService postTargetService;
@Autowired
private TemplateService templateService;
@Autowired
private Bot bot;
private static final String WARN_LOG_TEMPLATE = "warn_log";
private static final String WARN_NOTIFICATION_TEMPLATE = "warn_notification";
@Override
public Warning warnUser(AUserInAServer warnedAUserInAServer, AUserInAServer warningAUserInAServer, String reason) {
AUser warningAUser = warningAUserInAServer.getUserReference();
AUser warnedAUser = warnedAUserInAServer.getUserReference();
AServer serverOfWarning = warnedAUserInAServer.getServerReference();
log.info("User {} is warning {} in server {} because of {}", warningAUser.getId(), warnedAUser.getId(), serverOfWarning.getId(), reason);
Warning warning = warnManagementService.createWarning(warnedAUserInAServer, warningAUserInAServer, reason);
JDA instance = bot.getInstance();
User userBeingWarned = instance.getUserById(warnedAUser.getId());
Guild guildById = instance.getGuildById(serverOfWarning.getId());
String guildName = "<defaultName>";
if(guildById != null) {
guildName = guildById.getName();
}
WarnNotification warnNotification = WarnNotification.builder().warning(warning).serverName(guildName).build();
if(userBeingWarned != null) {
String warnLogMessage = templateService.renderTemplate(WARN_NOTIFICATION_TEMPLATE, warnNotification);
userBeingWarned.openPrivateChannel().queue(privateChannel -> {
log.info("Messaging user {} about warn {}", warnedAUser.getId(), warning.getId());
privateChannel.sendMessage(warnLogMessage).queue();
});
} else {
log.warn("Unable to find user {} in guild {} to warn.", warnedAUser.getId(), serverOfWarning.getId());
}
return warning;
}
@Override
public Warning warnUser(Member warnedMember, Member warningMember, String reason) {
AUserInAServer warnedAUser = userManagementService.loadUser(warnedMember);
AUserInAServer warningAUser = userManagementService.loadUser(warningMember);
return this.warnUser(warnedAUser, warningAUser, reason);
}
@Override
public void sendWarnLog(WarnLog warnLogModel) {
String warnLogMessage = templateService.renderTemplate(WARN_LOG_TEMPLATE, warnLogModel);
postTargetService.sendTextInPostTarget(warnLogMessage, PostTarget.WARN_LOG, warnLogModel.getServer().getId());
}
}

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.moderation.service.management;
import dev.sheldan.abstracto.moderation.models.Warning;
import dev.sheldan.abstracto.moderation.repository.WarnRepository;
import dev.sheldan.abstracto.core.models.AUserInAServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Instant;
@Component
public class WarnManagementServiceBean implements WarnManagementService {
@Autowired
private WarnRepository warnRepository;
@Override
public Warning createWarning(AUserInAServer warnedAUser, AUserInAServer warningAUser, String reason) {
Warning warning = Warning.builder()
.reason(reason)
.warnedUser(warnedAUser)
.warningUser(warningAUser)
.warnDate(Instant.now())
.build();
warnRepository.save(warning);
return warning;
}
}

View File

@@ -0,0 +1 @@
User ${bannedUser.effectiveName} (${bannedUser.asMention}) has been banned with reason ${reason}.

View File

@@ -0,0 +1 @@
You were banned from the server ${serverName} for the following reason: ${warning.reason}.

View File

@@ -0,0 +1 @@
User ${warnedUser.effectiveName} (${warnedUser.asMention}) has been warned with reason ${warning.reason}.

View File

@@ -0,0 +1 @@
You were warned on the server ${serverName} for the following reason: ${warning.reason}.

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>moderation-int</artifactId>
</project>

View File

@@ -0,0 +1,21 @@
package dev.sheldan.abstracto.moderation;
import dev.sheldan.abstracto.command.Module;
import dev.sheldan.abstracto.command.module.ModuleInfo;
import org.springframework.stereotype.Component;
@Component
public class Moderation implements Module {
public static final String MODERATION = "moderation";
@Override
public ModuleInfo getInfo() {
return ModuleInfo.builder().name(MODERATION).description("Utilities to moderate the server").build();
}
@Override
public String getParentModule() {
return "default";
}
}

View File

@@ -0,0 +1,22 @@
package dev.sheldan.abstracto.moderation.models;
import dev.sheldan.abstracto.command.execution.CommandTemplateContext;
import lombok.Builder;
import lombok.Getter;
import net.dv8tion.jda.api.entities.Member;
@Getter
public class BanLog extends CommandTemplateContext {
private String reason;
private Member banningUser;
private Member bannedUser;
@Builder(builderMethodName = "parentBuilder")
public BanLog(CommandTemplateContext commandTemplateContext, Member bannedUser, Member banningUser, String reason) {
super(commandTemplateContext);
this.bannedUser = bannedUser;
this.banningUser = banningUser;
this.reason = reason;
}
}

View File

@@ -0,0 +1,23 @@
package dev.sheldan.abstracto.moderation.models;
import dev.sheldan.abstracto.command.execution.CommandTemplateContext;
import lombok.Builder;
import lombok.Getter;
import net.dv8tion.jda.api.entities.Member;
@Getter
public class WarnLog extends CommandTemplateContext {
private Warning warning;
private Member warnedUser;
private Member warningUser;
@Builder(builderMethodName = "parentBuilder")
public WarnLog(CommandTemplateContext commandTemplateContext, Warning warning, Member warnedUser, Member warningUser) {
super(commandTemplateContext);
this.warning = warning;
this.warnedUser = warnedUser;
this.warningUser = warningUser;
}
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.moderation.models;
import lombok.Builder;
import lombok.Value;
@Value @Builder
public class WarnNotification {
private Warning warning;
private String serverName;
}

View File

@@ -0,0 +1,47 @@
package dev.sheldan.abstracto.moderation.models;
import dev.sheldan.abstracto.core.models.AUserInAServer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.Instant;
@Entity
@Table(name="warning")
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Warning {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Getter
private Long id;
@Getter
@ManyToOne
@JoinColumn(name = "warnedUserId")
private AUserInAServer warnedUser;
@Getter
@ManyToOne
@JoinColumn(name = "warningUserId")
private AUserInAServer warningUser;
@Getter
private String reason;
@Getter
private Instant warnDate;
@Getter
private Boolean decayed;
@Getter
private Instant decayDate;
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.moderation.models.BanLog;
import net.dv8tion.jda.api.entities.Member;
public interface BanService {
void banMember(Member member, String reason);
void sendBanLog(BanLog banLog);
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.moderation.models.WarnLog;
import dev.sheldan.abstracto.moderation.models.Warning;
import dev.sheldan.abstracto.core.models.AUserInAServer;
import net.dv8tion.jda.api.entities.Member;
public interface WarnService {
Warning warnUser(AUserInAServer warnedAUser, AUserInAServer warningAUser, String reason);
Warning warnUser(Member warnedUser, Member warningUser, String reason);
void sendWarnLog(WarnLog warnLogModel);
}

View File

@@ -0,0 +1,8 @@
package dev.sheldan.abstracto.moderation.service.management;
import dev.sheldan.abstracto.moderation.models.Warning;
import dev.sheldan.abstracto.core.models.AUserInAServer;
public interface WarnManagementService {
Warning createWarning(AUserInAServer warnedAUser, AUserInAServer warningAUser, String reason);
}

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId>
<packaging>pom</packaging>
<modules>
<module>moderation-int</module>
<module>moderation-impl</module>
</modules>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.command</groupId>
<artifactId>command-int</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core-interface</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto</groupId>
<artifactId>abstracto-application</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>abstracto-modules</artifactId>
<packaging>pom</packaging>
<modules>
<module>moderation</module>
</modules>
</project>