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

@@ -3,21 +3,20 @@
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>
<artifactId>command-base</artifactId>
<groupId>dev.sheldan.abstracto.command</groupId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>channels</artifactId>
<artifactId>moderation-impl</artifactId>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core-interface</artifactId>
<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

@@ -3,13 +3,12 @@
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>
<artifactId>command-base</artifactId>
<groupId>dev.sheldan.abstracto.command</groupId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>support</artifactId>
<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

@@ -3,19 +3,19 @@
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.command</groupId>
<artifactId>command</artifactId>
<groupId>dev.sheldan.abstracto</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>command-base</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId>
<packaging>pom</packaging>
<modules>
<module>utility</module>
<module>support</module>
<module>channels</module>
<module>moderation-int</module>
<module>moderation-impl</module>
</modules>
<dependencies>
@@ -24,6 +24,11 @@
<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

@@ -3,13 +3,17 @@
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.command</groupId>
<artifactId>command-base</artifactId>
<groupId>dev.sheldan.abstracto</groupId>
<artifactId>abstracto-application</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>utility</artifactId>
<artifactId>abstracto-modules</artifactId>
<packaging>pom</packaging>
<modules>
<module>moderation</module>
</modules>
</project>

View File

@@ -1,11 +1,11 @@
package dev.sheldan.abstracto.command;
import dev.sheldan.abstracto.command.execution.Configuration;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Result;
public interface Command<T> {
Result execute(CommandContext commandContext);
Configuration getConfiguration();
CommandConfiguration getConfiguration();
}

View File

@@ -7,4 +7,6 @@ import lombok.Getter;
public class HelpInfo {
private String usage;
private String longHelp;
private String longHelpTemplate;
private String usageTemplate;
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.command;
public interface TemplatedException {
String getTemplateName();
Object getTemplateModel();
}

View File

@@ -8,16 +8,17 @@ import lombok.Setter;
import java.util.List;
@Getter @Builder
public class Configuration {
public class CommandConfiguration {
private String name;
private String module;
private String description;
private String descriptionTemplate;
private List<Parameter> parameters;
private boolean causesReaction;
private HelpInfo help;
public long getNecessaryParameterCount(){
return parameters.stream().filter(parameter -> !parameter.isOptional()).count();
public int getNecessaryParameterCount(){
return (int) parameters.stream().filter(parameter -> !parameter.isOptional()).count();
}
}

View File

@@ -3,17 +3,14 @@ package dev.sheldan.abstracto.command.execution;
import lombok.Builder;
import lombok.Getter;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.*;
@Builder
@Getter
public class CommandContext {
private TextChannel channel;
private Guild guild;
private User author;
private Member author;
private Message message;
private CommandTemplateContext commandTemplateContext;
private Parameters parameters;

View File

@@ -9,6 +9,7 @@ import lombok.Setter;
public class Result {
private ResultState result;
private String message;
private Throwable throwable;
public static Result fromSuccess() {
return Result.builder().result(ResultState.SUCCESSFUL).build();
@@ -17,4 +18,8 @@ public class Result {
public static Result fromError(String message){
return Result.builder().result(ResultState.ERROR).message(message).build();
}
public static Result fromError(String message, Throwable throwable) {
return Result.builder().result(ResultState.ERROR).message(message).throwable(throwable).build();
}
}

View File

@@ -1,4 +0,0 @@
package dev.sheldan.abstracto.commands.management.exception;
public class CommandNotFoundException extends RuntimeException {
}

View File

@@ -9,7 +9,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>command-management</artifactId>
<artifactId>command-support</artifactId>
<dependencies>
<dependency>

View File

@@ -2,11 +2,12 @@ package dev.sheldan.abstracto.commands.management;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.Module;
import dev.sheldan.abstracto.command.execution.Configuration;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.meta.CommandRegistry;
import dev.sheldan.abstracto.command.meta.UnParsedCommandParameter;
import dev.sheldan.abstracto.commands.management.exception.CommandNotFoundException;
import dev.sheldan.abstracto.commands.management.exception.InsufficientParametersException;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -24,32 +25,39 @@ public class CommandManager implements CommandRegistry {
@Override
public Command findCommandByParameters(String name, UnParsedCommandParameter unParsedCommandParameter) {
Optional<Command> commandOptional = commands.stream().filter((Command o )-> {
Configuration configuration = o.getConfiguration();
CommandConfiguration commandConfiguration = o.getConfiguration();
if(!commandConfiguration.getName().equals(name)) {
return false;
}
boolean parameterFit;
if(configuration.getParameters() != null){
boolean paramCountFits = unParsedCommandParameter.getParameters().size() >= configuration.getNecessaryParameterCount();
boolean hasRemainderParameter = configuration.getParameters().stream().anyMatch(Parameter::isRemainder);
if(commandConfiguration.getParameters() != null){
boolean paramCountFits = unParsedCommandParameter.getParameters().size() >= commandConfiguration.getNecessaryParameterCount();
boolean hasRemainderParameter = commandConfiguration.getParameters().stream().anyMatch(Parameter::isRemainder);
if(unParsedCommandParameter.getParameters().size() < commandConfiguration.getNecessaryParameterCount()) {
String nextParameterName = commandConfiguration.getParameters().get(commandConfiguration.getNecessaryParameterCount()).getName();
throw new InsufficientParametersException("Insufficient parameters", o, nextParameterName);
}
parameterFit = paramCountFits || hasRemainderParameter;
} else {
parameterFit = unParsedCommandParameter.getParameters().size() == 0;
}
return configuration.getName().equals(name) && parameterFit;
return parameterFit;
}).findFirst();
if(commandOptional.isPresent()){
return commandOptional.get();
}
throw new CommandNotFoundException();
throw new CommandNotFoundException("Command not found.");
}
public Command findCommand(String name) {
Optional<Command> commandOptional = commands.stream().filter((Command o )-> {
Configuration configuration = o.getConfiguration();
return configuration.getName().equals(name);
CommandConfiguration commandConfiguration = o.getConfiguration();
return commandConfiguration.getName().equals(name);
}).findFirst();
if(commandOptional.isPresent()){
return commandOptional.get();
}
throw new CommandNotFoundException();
throw new CommandNotFoundException("Command not found.");
}
@Override

View File

@@ -9,11 +9,13 @@ import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.models.AChannel;
import dev.sheldan.abstracto.core.models.AServer;
import net.dv8tion.jda.api.entities.GuildChannel;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.ArrayList;
@@ -24,10 +26,10 @@ import java.util.List;
public class CommandReceivedHandler extends ListenerAdapter {
@Autowired
private CommandManager manager;
private CommandManager commandManager;
@Autowired
private PostCommandExecution execution;
private List<PostCommandExecution> executions;
@Autowired
private ServerManagementService serverManagementService;
@@ -36,27 +38,42 @@ public class CommandReceivedHandler extends ListenerAdapter {
private ChannelManagementService channelManagementService;
@Override
@Transactional
public void onMessageReceived(@Nonnull MessageReceivedEvent event) {
if(!manager.isCommand(event.getMessage())) {
if(!commandManager.isCommand(event.getMessage())) {
return;
}
if(!event.isFromGuild()) {
return;
}
CommandContext.CommandContextBuilder commandContextBuilder = CommandContext.builder()
.author(event.getMember())
.guild(event.getGuild())
.channel(event.getTextChannel())
.message(event.getMessage())
.jda(event.getJDA())
.commandTemplateContext(buildTemplateParameter(event));
Command foundCommand = null;
try {
List<String> parameters = Arrays.asList(event.getMessage().getContentStripped().split(" "));
UnParsedCommandParameter unparsedParameter = new UnParsedCommandParameter();
unparsedParameter.setParameters(parameters.subList(1, parameters.size()));
String withoutPrefix = parameters.get(0).substring(1);
Command foundCommand = manager.findCommandByParameters(withoutPrefix, unparsedParameter);
foundCommand = commandManager.findCommandByParameters(withoutPrefix, unparsedParameter);
Parameters parsedParameters = getParsedParameters(unparsedParameter, foundCommand, event.getMessage());
CommandContext commandContext = CommandContext.builder()
.author(event.getAuthor())
.guild(event.getGuild())
.channel(event.getTextChannel())
.message(event.getMessage())
.parameters(parsedParameters)
.jda(event.getJDA())
.commandTemplateContext(buildTemplateParameter(event))
.build();
CommandContext commandContext = commandContextBuilder.parameters(parsedParameters).build();
Result result = foundCommand.execute(commandContext);
execution.execute(commandContext, result, foundCommand);
for (PostCommandExecution postCommandExecution : executions) {
postCommandExecution.execute(commandContext, result, foundCommand);
}
} catch (Exception e) {
Result result = Result.fromError(e.getMessage(), e);
CommandContext commandContext = commandContextBuilder.build();
for (PostCommandExecution postCommandExecution : executions) {
postCommandExecution.execute(commandContext, result, foundCommand);
}
}
}
private CommandTemplateContext buildTemplateParameter(MessageReceivedEvent event) {
@@ -68,6 +85,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
public Parameters getParsedParameters(UnParsedCommandParameter unParsedCommandParameter, Command command, Message message){
List<Object> parsedParameters = new ArrayList<>();
int mentionedChannelsCount = 0;
int mentionedUserCount = 0;
for (int i = 0; i < unParsedCommandParameter.getParameters().size(); i++) {
Parameter param = command.getConfiguration().getParameters().get(i);
String value = unParsedCommandParameter.getParameters().get(i);
@@ -78,7 +96,10 @@ public class CommandReceivedHandler extends ListenerAdapter {
} else if(param.getType().equals(GuildChannel.class)){
parsedParameters.add(message.getMentionedChannels().get(mentionedChannelsCount));
mentionedChannelsCount++;
} else{
} else if(param.getType().equals(Member.class)) {
parsedParameters.add(message.getMentionedMembers().get(mentionedUserCount));
mentionedUserCount++;
} else {
parsedParameters.add(value);
}
}

View File

@@ -0,0 +1,20 @@
package dev.sheldan.abstracto.commands.management.exception;
import dev.sheldan.abstracto.command.TemplatedException;
public class CommandNotFoundException extends RuntimeException implements TemplatedException {
public CommandNotFoundException(String s) {
super(s);
}
@Override
public String getTemplateName() {
return "command_not_found";
}
@Override
public Object getTemplateModel() {
return null;
}
}

View File

@@ -0,0 +1,32 @@
package dev.sheldan.abstracto.commands.management.exception;
import dev.sheldan.abstracto.command.TemplatedException;
import dev.sheldan.abstracto.command.Command;
import lombok.Getter;
import java.util.HashMap;
@Getter
public class InsufficientParametersException extends RuntimeException implements TemplatedException {
private Command command;
private String parameterName;
public InsufficientParametersException(String s, Command command, String parameterName) {
super(s);
this.command = command;
this.parameterName = parameterName;
}
@Override
public String getTemplateName() {
return "insufficient_parameters";
}
@Override
public Object getTemplateModel() {
HashMap<String, Object> model = new HashMap<>();
model.put("parameterName", parameterName);
return model;
}
}

View File

@@ -0,0 +1,33 @@
package dev.sheldan.abstracto.commands.management.post;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.PostCommandExecution;
import dev.sheldan.abstracto.command.TemplatedException;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.execution.ResultState;
import dev.sheldan.abstracto.templating.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ExceptionPostExecution implements PostCommandExecution {
@Autowired
private TemplateService templateService;
@Override
public void execute(CommandContext commandContext, Result result, Command command) {
if(result.getResult().equals(ResultState.ERROR)) {
if(result.getThrowable() != null) {
if(result.getThrowable() instanceof TemplatedException) {
TemplatedException exception = (TemplatedException) result.getThrowable();
String text = templateService.renderTemplate(exception.getTemplateName(), exception.getTemplateModel());
commandContext.getChannel().sendMessage(text).queue();
} else {
commandContext.getChannel().sendMessage(result.getMessage()).queue();
}
}
}
}
}

View File

@@ -1,17 +1,23 @@
package dev.sheldan.abstracto.commands.management;
package dev.sheldan.abstracto.commands.management.post;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.PostCommandExecution;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.execution.ResultState;
import org.springframework.stereotype.Service;
@Service
public class ReactionPostExecution implements PostCommandExecution {
@Override
public void execute(CommandContext commandContext, Result result, Command command) {
if(result.getResult().equals(ResultState.ERROR)) {
commandContext.getMessage().addReaction("⚠️").queue();
} else {
if(command.getConfiguration().isCausesReaction()){
commandContext.getMessage().addReaction("").queue();
}
}
}
}

View File

@@ -0,0 +1 @@
Insufficient parameters: ${parameterName} was not found.

View File

@@ -14,8 +14,7 @@
<packaging>pom</packaging>
<modules>
<module>command-int</module>
<module>command-base</module>
<module>command-management</module>
<module>command-support</module>
</modules>

View File

@@ -82,7 +82,7 @@
<dependency>
<groupId>dev.sheldan.abstracto.command</groupId>
<artifactId>command-management</artifactId>
<artifactId>command-support</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>

View File

@@ -1,4 +1,4 @@
package dev.sheldan.abstracto.command.channels;
package dev.sheldan.abstracto.core.commands.channels;
import dev.sheldan.abstracto.command.Module;
import dev.sheldan.abstracto.command.module.ModuleInfo;

View File

@@ -1,12 +1,14 @@
package dev.sheldan.abstracto.command.channels;
package dev.sheldan.abstracto.core.commands.channels;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.execution.Configuration;
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.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.PostTargetManagement;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -16,6 +18,7 @@ import java.util.Arrays;
import java.util.List;
@Service
@Slf4j
public class SetPostTargetCommand implements Command {
@Autowired
@@ -29,21 +32,23 @@ public class SetPostTargetCommand implements Command {
public Result execute(CommandContext commandContext) {
GuildChannel channel = (GuildChannel) commandContext.getParameters().getParameters().get(1);
String targetName = (String) commandContext.getParameters().getParameters().get(0);
postTargetManagement.createOrUpdate(targetName, channel.getIdLong(), channel.getGuild().getIdLong());
Guild guild = channel.getGuild();
postTargetManagement.createOrUpdate(targetName, channel.getIdLong(), guild.getIdLong());
log.info("Setting posttarget {} in {} to {}", targetName, guild.getIdLong(), channel.getId());
return Result.fromSuccess();
}
@Override
public Configuration getConfiguration() {
public CommandConfiguration getConfiguration() {
Parameter channel = Parameter.builder().name("channel").type(GuildChannel.class).description("The channel to post towards").build();
Parameter postTargetName = Parameter.builder().name("name").type(String.class).description("The name of the post target to redirect").build();
List<Parameter> parameters = Arrays.asList(postTargetName, channel);
return Configuration.builder()
return CommandConfiguration.builder()
.name("posttarget")
.module("channels")
.parameters(parameters)
.description("Sets the target of a post done by the bot")
.causesReaction(false)
.causesReaction(true)
.build();
}
}

View File

@@ -1,11 +1,9 @@
package dev.sheldan.abstracto.command.support;
package dev.sheldan.abstracto.core.commands.help;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.CommandHierarchy;
import dev.sheldan.abstracto.command.ModuleRegistry;
import dev.sheldan.abstracto.command.PackedModule;
import dev.sheldan.abstracto.command.*;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.command.module.ModuleInfo;
import dev.sheldan.abstracto.templating.TemplateService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -20,6 +18,9 @@ public class Help implements Command {
@Autowired
private ModuleRegistry registry;
@Autowired
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
CommandHierarchy commandStructure = registry.getDetailedModules();
@@ -57,19 +58,29 @@ public class Help implements Command {
private String getCommand(Command command){
StringBuilder sb = new StringBuilder();
Configuration configuration = command.getConfiguration();
sb.append(String.format("Command: **%s**", configuration.getName()));
CommandConfiguration commandConfiguration = command.getConfiguration();
sb.append(String.format("Command: **%s**", commandConfiguration.getName()));
sb.append("\n");
sb.append(String.format("Description: %s", configuration.getDescription()));
sb.append(String.format("Description: %s", getTemplateOrDefault(commandConfiguration.getDescriptionTemplate(), commandConfiguration.getDescription())));
sb.append("\n");
if(configuration.getHelp() != null){
sb.append(String.format("Usage: %s", configuration.getHelp().getUsage()));
HelpInfo helpObj = commandConfiguration.getHelp();
if(helpObj != null){
sb.append(String.format("Usage: %s", getTemplateOrDefault(helpObj.getUsageTemplate(), helpObj.getUsage())));
sb.append("\n");
sb.append(String.format("Detailed help: %s", getTemplateOrDefault(helpObj.getLongHelpTemplate(), helpObj.getLongHelp())));
sb.append("\n");
sb.append(String.format("Detailed help: %s", configuration.getHelp().getLongHelp()));
}
return sb.toString();
}
private String getTemplateOrDefault(String templateKey, String defaultText) {
if(templateKey == null) {
return defaultText;
} else {
return templateService.renderTemplate(templateKey, null);
}
}
private String getModule(PackedModule module, int depth, boolean recursive){
StringBuilder sb = new StringBuilder();
String intentation = "";
@@ -89,7 +100,7 @@ public class Help implements Command {
}
@Override
public Configuration getConfiguration() {
public CommandConfiguration getConfiguration() {
Parameter moduleOrCommandName = Parameter.builder()
.name("name")
.optional(true)
@@ -97,7 +108,7 @@ public class Help implements Command {
.type(String.class)
.build();
return Configuration.builder()
return CommandConfiguration.builder()
.name("help")
.module("support")
.parameters(Collections.singletonList(moduleOrCommandName))

View File

@@ -1,9 +1,7 @@
package dev.sheldan.abstracto.command.support;
package dev.sheldan.abstracto.core.commands.help;
import dev.sheldan.abstracto.command.Module;
import dev.sheldan.abstracto.command.module.AbstracatoModule;
import dev.sheldan.abstracto.command.module.ModuleInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component

View File

@@ -1,16 +1,15 @@
package dev.sheldan.abstracto.command.utility;
package dev.sheldan.abstracto.core.commands.utility;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.Configuration;
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.command.utility.model.EchoModel;
import dev.sheldan.abstracto.core.commands.utility.model.EchoModel;
import dev.sheldan.abstracto.templating.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@@ -18,13 +17,12 @@ import java.util.List;
@Service
public class Echo implements Command {
private static final String TEMPLATE_NAME = "echo";
private static final String TEMPLATE_NAME = "echo_response";
@Autowired
private TemplateService templateService;
@Override
@Transactional
public Result execute(CommandContext commandContext) {
StringBuilder sb = new StringBuilder();
commandContext.getParameters().getParameters().forEach(o -> {
@@ -36,14 +34,14 @@ public class Echo implements Command {
}
@Override
public Configuration getConfiguration() {
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("input").type(String.class).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().usage("echo <text>").longHelp("Echos back the text put in").build();
return Configuration.builder()
HelpInfo helpInfo = HelpInfo.builder().usageTemplate("echo_usage").longHelpTemplate("echo_long_help").build();
return CommandConfiguration.builder()
.name("echo")
.module("utility")
.description("Echos the input back to the same channel")
.descriptionTemplate("echo_description")
.causesReaction(false)
.parameters(parameters)
.help(helpInfo)

View File

@@ -1,14 +1,13 @@
package dev.sheldan.abstracto.command.utility;
package dev.sheldan.abstracto.core.commands.utility;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.execution.Configuration;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.utility.model.PingModel;
import dev.sheldan.abstracto.core.commands.utility.model.PingModel;
import dev.sheldan.abstracto.templating.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class Ping implements Command {
@@ -19,7 +18,6 @@ public class Ping implements Command {
private TemplateService templateService;
@Override
@Transactional
public Result execute(CommandContext commandContext) {
long ping = commandContext.getJda().getGatewayPing();
PingModel model = PingModel.parentBuilder().parent(commandContext.getCommandTemplateContext()).latency(ping).build();
@@ -29,11 +27,11 @@ public class Ping implements Command {
}
@Override
public Configuration getConfiguration() {
return Configuration.builder()
public CommandConfiguration getConfiguration() {
return CommandConfiguration.builder()
.name("ping")
.module("utility")
.description("Prints the current bot latency to the discord api")
.descriptionTemplate("ping_description")
.causesReaction(false)
.build();
}

View File

@@ -1,4 +1,4 @@
package dev.sheldan.abstracto.command.utility;
package dev.sheldan.abstracto.core.commands.utility;
import dev.sheldan.abstracto.command.Module;
import dev.sheldan.abstracto.command.module.ModuleInfo;

View File

@@ -1,4 +1,4 @@
package dev.sheldan.abstracto.command.utility.model;
package dev.sheldan.abstracto.core.commands.utility.model;
import dev.sheldan.abstracto.command.execution.CommandTemplateContext;

View File

@@ -1,4 +1,4 @@
package dev.sheldan.abstracto.command.utility.model;
package dev.sheldan.abstracto.core.commands.utility.model;
import dev.sheldan.abstracto.command.execution.CommandTemplateContext;
import lombok.Builder;

View File

@@ -1,11 +1,6 @@
package dev.sheldan.abstracto.core.service.management;
package dev.sheldan.abstracto.core.management;
import dev.sheldan.abstracto.core.models.AChannel;
import dev.sheldan.abstracto.core.models.AServer;
import dev.sheldan.abstracto.core.models.PostTarget;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.PostTargetManagement;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.models.*;
import dev.sheldan.abstracto.repository.ServerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -37,6 +32,13 @@ public class ServerManagementServiceBean implements ServerManagementService {
server.getChannels().add(channel);
}
@Override
public AUserInAServer addUserToServer(AServer server, AUser user) {
AUserInAServer aUserInAServer = AUserInAServer.builder().serverReference(server).userReference(user).build();
server.getUsers().add(aUserInAServer);
return aUserInAServer;
}
@Override
public AChannel getPostTarget(Long serverId, String name) {
AServer server = this.loadServer(serverId);

View File

@@ -0,0 +1,63 @@
package dev.sheldan.abstracto.core.management;
import dev.sheldan.abstracto.core.models.AServer;
import dev.sheldan.abstracto.core.models.AUser;
import dev.sheldan.abstracto.core.models.AUserInAServer;
import dev.sheldan.abstracto.repository.UserInServerRepository;
import dev.sheldan.abstracto.repository.UserRepository;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class UserManagementServiceBean implements UserManagementService {
@Autowired
private UserInServerRepository userInServerRepository;
@Autowired
private UserRepository userRepository;
@Autowired
private ServerManagementService serverManagementService;
@Override
public AUserInAServer loadUser(Long userId, Long serverId) {
AUser user = userRepository.getOne(userId);
AServer server = serverManagementService.loadServer(serverId);
return loadUser(user, server);
}
@Override
public AUserInAServer loadUser(AUser user, AServer server) {
return userInServerRepository.findByServerReferenceAndUserReference(server, user);
}
@Override
public AUserInAServer loadUser(Member member) {
AUserInAServer aUserInAServer = this.loadUser(member.getGuild().getIdLong(), member.getIdLong());
if(aUserInAServer == null) {
return this.createUserInServer(member);
}
return null;
}
@Override
public AUserInAServer createUserInServer(Member member) {
AServer server = serverManagementService.loadServer(member.getGuild().getIdLong());
if(!userRepository.existsById(member.getIdLong())) {
this.createUser(member);
}
AUser aUser = userRepository.getOne(member.getIdLong());
return serverManagementService.addUserToServer(server, aUser);
}
@Override
public AUser createUser(Member member) {
AUser aUser = AUser.builder().id(member.getIdLong()).build();
userRepository.save(aUser);
return aUser;
}
}

View File

@@ -12,7 +12,7 @@ import org.springframework.stereotype.Component;
public class ChannelServiceBean implements ChannelService {
@Autowired
private BotService botService;
private Bot botService;
@Override
public void sendTextInAChannel(String text, AChannel channel) {

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.management.PostTargetManagement;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.models.PostTarget;
import lombok.extern.slf4j.Slf4j;
@@ -17,7 +18,10 @@ public class PostTargetServiceBean implements PostTargetService {
private ServerManagementService serverManagementService;
@Autowired
private BotService botService;
private PostTargetManagement postTargetManagement;
@Autowired
private Bot botService;
@Override
public void sendTextInPostTarget(String text, PostTarget target) {
@@ -34,4 +38,14 @@ public class PostTargetServiceBean implements PostTargetService {
log.warn("Incorrect post target configuration: Guild id {} was not found.", target.getServerReference().getId());
}
}
@Override
public void sendTextInPostTarget(String text, String postTargetName, Long serverId) {
PostTarget postTarget = postTargetManagement.getPostTarget(postTargetName, serverId);
if(postTarget != null) {
this.sendTextInPostTarget(text, postTarget);
} else {
log.warn("PostTarget {} in server {} was not found!", postTargetName, serverId);
}
}
}

View File

@@ -28,7 +28,7 @@ import java.util.Set;
public class StartupManager implements Startup {
@Autowired
private BotService service;
private Bot service;
@Autowired
private List<? extends ListenerAdapter> listeners;

View File

@@ -40,16 +40,14 @@ public class JoinLeaveListener extends ListenerAdapter {
@Transactional
public void onGuildMemberJoin(@Nonnull GuildMemberJoinEvent event) {
String text = getRenderedEvent(event.getUser(), USER_JOIN_TEMPLATE);
PostTarget postTarget = postTargetManagement.getPostTarget(PostTarget.JOIN_LOG, event.getGuild().getIdLong());
postTargetService.sendTextInPostTarget(text, postTarget);
postTargetService.sendTextInPostTarget(text, PostTarget.JOIN_LOG, event.getGuild().getIdLong());
}
@Override
@Transactional
public void onGuildMemberLeave(@Nonnull GuildMemberLeaveEvent event) {
String text = getRenderedEvent(event.getUser(), USER_LEAVE_TEMPLATE);
PostTarget postTarget = postTargetManagement.getPostTarget(PostTarget.LEAVE_LOG, event.getGuild().getIdLong());
postTargetService.sendTextInPostTarget(text, postTarget);
postTargetService.sendTextInPostTarget(text, PostTarget.LEAVE_LOG, event.getGuild().getIdLong());
}
@NotNull

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.repository;
import dev.sheldan.abstracto.core.models.AServer;
import dev.sheldan.abstracto.core.models.AUser;
import dev.sheldan.abstracto.core.models.AUserInAServer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserInServerRepository extends JpaRepository<AUserInAServer, Long> {
AUserInAServer findByServerReferenceAndUserReference(AServer serverId, AUser userId);
}

View File

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

View File

@@ -0,0 +1 @@
Echos the input back to the same channel

View File

@@ -1,13 +1,12 @@
package dev.sheldan.abstracto.core.management;
import dev.sheldan.abstracto.core.models.AChannel;
import dev.sheldan.abstracto.core.models.AServer;
import dev.sheldan.abstracto.core.models.PostTarget;
import dev.sheldan.abstracto.core.models.*;
public interface ServerManagementService {
AServer createServer(Long id);
AServer loadServer(Long id);
void addChannelToServer(AServer server, AChannel channel);
AUserInAServer addUserToServer(AServer server, AUser user);
AChannel getPostTarget(Long serverId, String name);
AChannel getPostTarget(Long serverId, PostTarget target);
AChannel getPostTarget(AServer server, PostTarget target);

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.management;
import dev.sheldan.abstracto.core.models.AServer;
import dev.sheldan.abstracto.core.models.AUser;
import dev.sheldan.abstracto.core.models.AUserInAServer;
import net.dv8tion.jda.api.entities.Member;
public interface UserManagementService {
AUserInAServer loadUser(Long userId, Long serverId);
AUserInAServer loadUser(AUser user, AServer server);
AUserInAServer loadUser(Member member);
AUserInAServer createUserInServer(Member member);
AUser createUser(Member member);
}

View File

@@ -11,17 +11,15 @@ import java.util.List;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class AServer implements SnowFlake {
@Id
@Getter @Setter
private Long id;
@Getter
private String name;
@OneToMany(fetch = FetchType.LAZY)
@Getter
@Builder.Default
private List<ARole> roles = new ArrayList<>();
@@ -30,10 +28,15 @@ public class AServer implements SnowFlake {
mappedBy = "server",
cascade = CascadeType.ALL,
orphanRemoval = true)
@Getter
@Builder.Default
private List<AChannel> channels = new ArrayList<>();
@OneToMany(
fetch = FetchType.LAZY,
mappedBy = "serverReference",
cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<AUserInAServer> users;
}

View File

@@ -0,0 +1,24 @@
package dev.sheldan.abstracto.core.models;
import lombok.*;
import javax.persistence.*;
import java.util.List;
@Entity
@Table(name="users")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class AUser {
@Id
private Long id;
@OneToMany(
fetch = FetchType.LAZY,
mappedBy = "userReference",
cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<AUserInAServer> servers;
}

View File

@@ -0,0 +1,22 @@
package dev.sheldan.abstracto.core.models;
import lombok.Builder;
import lombok.Getter;
import javax.persistence.*;
@Entity @Getter @Builder
public class AUserInAServer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userInServerId;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "userReference")
private AUser userReference;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "serverReference")
private AServer serverReference;
}

View File

@@ -35,6 +35,7 @@ public class PostTarget {
public static String JOIN_LOG = "joinlog";
public static String LEAVE_LOG = "leavelog";
public static String WARN_LOG = "warnlog";
public static List<String> AVAILABLE_POST_TARGETS = Arrays.asList(JOIN_LOG, LEAVE_LOG);
public static List<String> AVAILABLE_POST_TARGETS = Arrays.asList(JOIN_LOG, LEAVE_LOG, WARN_LOG);
}

View File

@@ -4,4 +4,5 @@ import dev.sheldan.abstracto.core.models.PostTarget;
public interface PostTargetService {
void sendTextInPostTarget(String text, PostTarget target);
void sendTextInPostTarget(String text, String postTargetName, Long serverId);
}

View File

@@ -49,25 +49,11 @@
<!-- modules containing commands -->
<dependency>
<groupId>dev.sheldan.abstracto.command</groupId>
<artifactId>utility</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation-impl</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.command</groupId>
<artifactId>support</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.command</groupId>
<artifactId>channels</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>

View File

@@ -19,6 +19,7 @@
<module>core</module>
<module>executable</module>
<module>templating</module>
<module>abstracto-modules</module>
</modules>