[AB-xx] improving scheduling interface

moving renaming module to int
removing duplicated starboard feature validator
sonar fixes
This commit is contained in:
Sheldan
2021-03-08 01:27:50 +01:00
parent 9c6333281b
commit 66061b7719
424 changed files with 95 additions and 154 deletions

View File

@@ -0,0 +1,54 @@
<?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.core</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>core-int</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
</dependency>
<dependency>
<groupId>com.jagrosh</groupId>
<artifactId>jda-utilities-menu</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.core;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.config.FeatureMode;
import java.util.Collections;
import java.util.List;
public interface FeatureAware {
FeatureEnum getFeature();
default List<FeatureMode> getFeatureModeLimitations() { return Collections.emptyList();}
}

View File

@@ -0,0 +1,5 @@
package dev.sheldan.abstracto.core;
public interface Prioritized {
Integer getPriority();
}

View File

@@ -0,0 +1,21 @@
package dev.sheldan.abstracto.core.command;
import dev.sheldan.abstracto.core.command.config.ModuleInfo;
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
import org.springframework.stereotype.Component;
@Component
public class UtilityModuleInterface implements ModuleInterface {
public static final String UTILITY = "utility";
@Override
public ModuleInfo getInfo() {
return ModuleInfo.builder().name(UTILITY).templated(true).build();
}
@Override
public String getParentModule() {
return "default";
}
}

View File

@@ -0,0 +1,68 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Component
public abstract class AbstractConditionableCommand implements ConditionalCommand {
@Autowired
protected FeatureEnabledCondition featureEnabledCondition;
@Autowired
protected CommandDisabledCondition commandDisabledCondition;
@Autowired
protected CommandDisallowedCondition commandDisallowedCondition;
@Autowired
protected ImmuneUserCondition immuneUserCondition;
@Autowired
private FeatureModeCondition featureModeCondition;
@Override
public List<CommandCondition> getConditions() {
return new ArrayList<>(Arrays.asList(featureEnabledCondition, commandDisabledCondition, commandDisallowedCondition, featureModeCondition));
}
protected void checkParameters(CommandContext context) {
List<Parameter> parameters = getConfiguration().getParameters();
for (int i = 0; i < parameters.size(); i++) {
Parameter parameter = parameters.get(i);
Class desiredType = parameter.getType();
if(!parameter.isOptional()) {
checkMandatoryExp(context, i, parameter, desiredType);
} else {
checkOptionalParameter(context, i, parameter, desiredType);
}
}
}
private void checkOptionalParameter(CommandContext context, int i, Parameter parameter, Class desiredType) {
if(context.getParameters() != null && context.getParameters().getParameters() != null && context.getParameters().getParameters().size() >= i) {
boolean parameterIsPresent = i < context.getParameters().getParameters().size();
if(parameterIsPresent && !desiredType.isInstance(context.getParameters().getParameters().get(i))) {
throw new IncorrectParameterTypeException(this, desiredType, parameter.getName());
}
}
}
private void checkMandatoryExp(CommandContext context, int i, Parameter parameter, Class desiredType) {
if(context.getParameters() == null || context.getParameters().getParameters() == null || context.getParameters().getParameters().isEmpty() || i >= context.getParameters().getParameters().size()) {
throw new InsufficientParametersException(this, parameter.getName());
}
if(!desiredType.isInstance(context.getParameters().getParameters().get(i))) {
throw new IncorrectParameterTypeException(this, desiredType, parameter.getName());
}
}
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
public interface CommandCondition {
ConditionResult shouldExecute(CommandContext commandContext, Command command);
}

View File

@@ -0,0 +1,30 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.condition.detail.CommandDisabledDetail;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.models.database.ACommand;
import dev.sheldan.abstracto.core.command.service.ChannelGroupCommandService;
import dev.sheldan.abstracto.core.command.service.management.CommandManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CommandDisabledCondition implements CommandCondition {
@Autowired
private ChannelGroupCommandService channelGroupCommandService;
@Autowired
private CommandManagementService commandManagementService;
@Override
public ConditionResult shouldExecute(CommandContext context, Command command) {
ACommand acommand = commandManagementService.findCommandByName(command.getConfiguration().getName());
Boolean commandEnabled = channelGroupCommandService.isCommandEnabled(acommand, context.getUserInitiatedContext().getMessageChannel().getIdLong());
if(!commandEnabled) {
return ConditionResult.builder().result(false).conditionDetail(new CommandDisabledDetail()).build();
}
return ConditionResult.builder().result(true).build();
}
}

View File

@@ -0,0 +1,52 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.condition.detail.InsufficientPermissionConditionDetail;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.models.database.ACommand;
import dev.sheldan.abstracto.core.command.models.database.ACommandInAServer;
import dev.sheldan.abstracto.core.command.service.management.CommandInServerManagementService;
import dev.sheldan.abstracto.core.command.service.management.CommandManagementService;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.service.RoleService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Slf4j
public class CommandDisallowedCondition implements CommandCondition {
@Autowired
private CommandInServerManagementService commandInServerManagementService;
@Autowired
private CommandManagementService commandService;
@Autowired
private RoleService roleService;
@Override
public ConditionResult shouldExecute(CommandContext context, Command command) {
ACommand aCommand = commandService.findCommandByName(command.getConfiguration().getName());
ACommandInAServer commandForServer = commandInServerManagementService.getCommandForServer(aCommand, context.getUserInitiatedContext().getGuild().getIdLong());
if(Boolean.FALSE.equals(commandForServer.getRestricted())) {
return ConditionResult.builder().result(true).build();
}
for (ARole role : commandForServer.getAllowedRoles()) {
Member author = context.getAuthor();
if (roleService.memberHasRole(author, role)) {
log.trace("Member {} is able to execute restricted command {}, because of role {}.", author.getIdLong(), aCommand.getName(), role.getId());
return ConditionResult.builder().result(true).build();
}
}
List<Role> allowedRoles = roleService.getRolesFromGuild(commandForServer.getAllowedRoles());
InsufficientPermissionConditionDetail exception = new InsufficientPermissionConditionDetail(allowedRoles);
return ConditionResult.builder().result(false).conditionDetail(exception).build();
}
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.templating.Templatable;
public interface ConditionDetail extends Templatable {
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.command.condition;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class ConditionResult {
private boolean result;
private String reason;
private ConditionDetail conditionDetail;
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.command.Command;
import java.util.List;
public interface ConditionalCommand extends Command {
List<CommandCondition> getConditions();
}

View File

@@ -0,0 +1,37 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.condition.detail.FeatureDisabledConditionDetail;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class FeatureEnabledCondition implements CommandCondition {
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureFlagService featureFlagService;
@Override
public ConditionResult shouldExecute(CommandContext context, Command command) {
FeatureEnum feature = command.getFeature();
boolean featureFlagValue = true;
if(feature != null) {
featureFlagValue = featureFlagService.getFeatureFlagValue(feature, context.getGuild().getIdLong());
if(!featureFlagValue) {
log.trace("Feature {} is disabled, disallows command {} to be executed in guild {}.", feature.getKey(), command.getConfiguration().getName(), context.getGuild().getId());
FeatureDisabledConditionDetail exception = new FeatureDisabledConditionDetail(featureConfigService.getFeatureDisplayForFeature(command.getFeature()));
return ConditionResult.builder().result(false).conditionDetail(exception).build();
}
}
return ConditionResult.builder().result(true).build();
}
}

View File

@@ -0,0 +1,38 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.condition.detail.IncorrectFeatureModeConditionDetail;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class FeatureModeCondition implements CommandCondition {
@Autowired
private FeatureModeService modeService;
@Override
public ConditionResult shouldExecute(CommandContext context, Command command) {
if(!command.getFeatureModeLimitations().isEmpty()){
FeatureEnum feature = command.getFeature();
if(feature != null) {
for (FeatureMode featureModeLimitation : command.getFeatureModeLimitations()) {
if(modeService.featureModeActive(feature, context.getUserInitiatedContext().getGuild().getIdLong(), featureModeLimitation)) {
return ConditionResult.builder().result(true).build();
}
}
return ConditionResult
.builder()
.result(false)
.conditionDetail(new IncorrectFeatureModeConditionDetail(feature, command.getFeatureModeLimitations()))
.build();
}
}
return ConditionResult.builder().result(true).build();
}
}

View File

@@ -0,0 +1,53 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.condition.detail.ImmuneUserConditionDetail;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.models.database.ACommand;
import dev.sheldan.abstracto.core.command.models.database.ACommandInAServer;
import dev.sheldan.abstracto.core.command.service.management.CommandInServerManagementService;
import dev.sheldan.abstracto.core.command.service.management.CommandManagementService;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.service.RoleService;
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.Optional;
@Component
@Slf4j
public class ImmuneUserCondition implements CommandCondition {
@Autowired
private CommandInServerManagementService commandInServerManagementService;
@Autowired
private CommandManagementService commandService;
@Autowired
private RoleService roleService;
@Override
public ConditionResult shouldExecute(CommandContext context, Command command) {
ACommand aCommand = commandService.findCommandByName(command.getConfiguration().getName());
ACommandInAServer commandForServer = commandInServerManagementService.getCommandForServer(aCommand, context.getUserInitiatedContext().getGuild().getIdLong());
Optional<Member> any = context.getParameters().getParameters().stream().filter(o -> o instanceof Member).map(this::toMember).findAny();
if(any.isPresent()) {
Member member = any.get();
for (ARole role : commandForServer.getImmuneRoles()) {
if (roleService.memberHasRole(member, role)) {
log.trace("Member {} is immune against command {}, because of role {}.", member.getIdLong(), aCommand.getName(), role.getId());
ImmuneUserConditionDetail exception = new ImmuneUserConditionDetail(roleService.getRoleFromGuild(role));
return ConditionResult.builder().result(false).conditionDetail(exception).build();
}
}
}
return ConditionResult.builder().result(true).build();
}
private Member toMember(Object o) {
return (Member) o;
}
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.core.command.condition.detail;
import dev.sheldan.abstracto.core.command.condition.ConditionDetail;
public class CommandDisabledDetail implements ConditionDetail {
@Override
public String getTemplateName() {
return "command_disabled_condition";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.core.command.condition.detail;
import dev.sheldan.abstracto.core.command.condition.ConditionDetail;
import dev.sheldan.abstracto.core.command.models.condition.FeatureDisabledConditionDetailModel;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FeatureDisabledConditionDetail implements ConditionDetail {
private final FeatureDisabledConditionDetailModel model;
public FeatureDisabledConditionDetail(FeatureConfig featureConfig) {
this.model = FeatureDisabledConditionDetailModel.builder().featureConfig(featureConfig).build();
}
@Override
public String getTemplateName() {
return "feature_disabled_condition";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,24 @@
package dev.sheldan.abstracto.core.command.condition.detail;
import dev.sheldan.abstracto.core.command.condition.ConditionDetail;
import dev.sheldan.abstracto.core.command.models.condition.ImmuneUserConditionDetailModel;
import net.dv8tion.jda.api.entities.Role;
public class ImmuneUserConditionDetail implements ConditionDetail {
private final ImmuneUserConditionDetailModel model;
public ImmuneUserConditionDetail(Role role) {
this.model = ImmuneUserConditionDetailModel.builder().role(role).build();
}
@Override
public String getTemplateName() {
return "immune_role_condition";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.core.command.condition.detail;
import dev.sheldan.abstracto.core.command.condition.ConditionDetail;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.core.models.exception.IncorrectFeatureModeModel;
import java.util.List;
public class IncorrectFeatureModeConditionDetail implements ConditionDetail {
private final IncorrectFeatureModeModel model;
public IncorrectFeatureModeConditionDetail(FeatureEnum featureEnum, List<FeatureMode> requiredModes) {
this.model = IncorrectFeatureModeModel.builder().featureEnum(featureEnum).requiredModes(requiredModes).build();
}
@Override
public String getTemplateName() {
return "incorrect_feature_mode_condition";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.core.command.condition.detail;
import dev.sheldan.abstracto.core.command.condition.ConditionDetail;
import dev.sheldan.abstracto.core.command.models.condition.InsufficientPermissionCondtionDetailModel;
import net.dv8tion.jda.api.entities.Role;
import java.util.List;
public class InsufficientPermissionConditionDetail implements ConditionDetail {
private final InsufficientPermissionCondtionDetailModel model;
public InsufficientPermissionConditionDetail(List<Role> allowedRoles) {
this.model = InsufficientPermissionCondtionDetailModel.builder().allowedRoles(allowedRoles).build();
}
@Override
public String getTemplateName() {
return "insufficient_role_condition";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.core.command.config;
import org.springframework.stereotype.Component;
@Component
public class AbstractoModuleInterface implements ModuleInterface {
@Override
public ModuleInfo getInfo() {
return ModuleInfo.builder().name("default").templated(true).build();
}
@Override
public String getParentModule() {
return null;
}
}

View File

@@ -0,0 +1,38 @@
package dev.sheldan.abstracto.core.command.config;
import lombok.Builder;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
@Getter @Builder
public class CommandConfiguration {
private String name;
private String module;
private String description;
@Builder.Default
private boolean async = false;
@Builder.Default
private boolean supportsEmbedException = false;
@Builder.Default
private List<Parameter> parameters = new ArrayList<>();
@Builder.Default
private List<String> aliases = new ArrayList<>();
@Builder.Default
private boolean causesReaction = false;
@Builder.Default
private boolean templated = false;
private HelpInfo help;
public int getNecessaryParameterCount(){
return (int) parameters.stream().filter(parameter -> !parameter.isOptional()).count();
}
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.command.config;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class HelpInfo {
private String longHelp;
private String example;
@Builder.Default
private boolean hasExample = false;
@Builder.Default
private boolean templated = false;
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.core.command.config;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class ModuleInfo {
private String name;
private String description;
private Boolean templated;
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.config;
public interface ModuleInterface {
ModuleInfo getInfo();
String getParentModule();
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.core.command.config;
import dev.sheldan.abstracto.core.command.Command;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
@Builder
@Getter
public class PackedModule {
private ModuleInterface moduleInterface;
private PackedModule parentModule;
private List<PackedModule> subModules;
private List<Command> commands;
}

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.core.command.config;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
@Builder
public class Parameter implements Serializable {
private String name;
private Class type;
private String description;
@Builder.Default
private boolean optional = false;
@Builder.Default
private boolean remainder = false;
@Builder.Default
private boolean isListParam = false;
@Builder.Default
private Boolean templated = false;
@Builder.Default
private List<ParameterValidator> validators = new ArrayList<>();
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.core.command.config;
import dev.sheldan.abstracto.core.command.config.validator.ValidatorParam;
import dev.sheldan.abstracto.core.templating.Templatable;
import java.util.List;
public interface ParameterValidator extends Templatable {
boolean validate(Object value);
List<ValidatorParam> getParameters();
String getExceptionTemplateName();
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.core.command.config;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
@Builder
public class Parameters {
@Getter
private List<Object> parameters;
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.core.command.config;
import dev.sheldan.abstracto.core.command.Command;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Builder
@Setter
@Getter
public class SingleLevelPackedModule {
private ModuleInterface moduleInterface;
private List<Command> commands;
}

View File

@@ -0,0 +1,22 @@
package dev.sheldan.abstracto.core.command.config.features;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class CoreFeature implements FeatureConfig {
@Override
public FeatureEnum getFeature() {
return CoreFeatures.CORE_FEATURE;
}
@Override
public List<String> getRequiredEmotes() {
return Arrays.asList("warnReaction", "successReaction");
}
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.command.config.features;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import lombok.Getter;
@Getter
public enum CoreFeatures implements FeatureEnum {
CORE_FEATURE("core");
private String key;
CoreFeatures(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,55 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Getter
@Setter
@Builder
public class MaxIntegerValueValidator implements ParameterValidator {
private Long maxValue;
@Override
public boolean validate(Object value) {
if(value == null) {
throw new IllegalArgumentException("Object to validate must not be null");
}
if(!(value instanceof Long)) {
throw new ValidatorConfigException("Incorrect value passed to max value validator.");
}
SingleNumberValidatorParam param = (SingleNumberValidatorParam) getParameters().get(0);
Long longValue = (Long) value;
return longValue <= param.getNumber();
}
@Override
public List<ValidatorParam> getParameters() {
SingleNumberValidatorParam param = SingleNumberValidatorParam
.builder()
.number(maxValue)
.build();
return Arrays.asList(param);
}
@Override
public String getExceptionTemplateName() {
return "command_parameter_validation_value_too_large";
}
@Override
public String getTemplateName() {
return "max_integer_value_validation_description";
}
@Override
public Object getTemplateModel() {
return getParameters().get(0);
}
}

View File

@@ -0,0 +1,63 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Getter
@Setter
@Builder
public class MaxStringLengthValidator implements ParameterValidator {
private Long maxLength;
@Override
public boolean validate(Object value) {
if(value == null) {
throw new IllegalArgumentException("Object to validate must not be null");
}
if(!(value instanceof String)) {
throw new ValidatorConfigException("Incorrect value passed to max string length validator.");
}
SingleNumberValidatorParam param = (SingleNumberValidatorParam) getParameters().get(0);
String stringValue = (String) value;
return stringValue.length() <= param.getNumber();
}
@Override
public List<ValidatorParam> getParameters() {
SingleNumberValidatorParam param = SingleNumberValidatorParam
.builder()
.number(maxLength)
.build();
return Arrays.asList(param);
}
@Override
public String getExceptionTemplateName() {
return "command_parameter_validation_string_too_long";
}
public static MaxStringLengthValidator max(Long number) {
return MaxStringLengthValidator
.builder()
.maxLength(number)
.build();
}
@Override
public String getTemplateName() {
return "max_string_length_validation_description";
}
@Override
public Object getTemplateModel() {
return getParameters().get(0);
}
}

View File

@@ -0,0 +1,70 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Getter
@Setter
@Builder
public class MinIntegerValueValidator implements ParameterValidator {
private Long minValue;
@Override
public boolean validate(Object value) {
if(value == null) {
throw new IllegalArgumentException("Object to validate must not be null");
}
boolean isLong = value instanceof Long;
boolean isInteger = value instanceof Integer;
if(!isLong && !isInteger) {
throw new ValidatorConfigException("Incorrect value passed to max value validator.");
}
SingleNumberValidatorParam param = (SingleNumberValidatorParam) getParameters().get(0);
if(isLong) {
Long longValue = (Long) value;
return longValue >= param.getNumber();
} else {
Integer integerValue = (Integer) value;
return integerValue >= param.getNumber();
}
}
@Override
public List<ValidatorParam> getParameters() {
SingleNumberValidatorParam param = SingleNumberValidatorParam
.builder()
.number(minValue)
.build();
return Arrays.asList(param);
}
public static MinIntegerValueValidator min(Long number) {
return MinIntegerValueValidator
.builder()
.minValue(number)
.build();
}
@Override
public String getExceptionTemplateName() {
return "command_parameter_validation_value_too_small";
}
@Override
public String getTemplateName() {
return "min_integer_value_validation_description";
}
@Override
public Object getTemplateModel() {
return getParameters().get(0);
}
}

View File

@@ -0,0 +1,55 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Getter
@Setter
@Builder
public class MinStringLengthValidator implements ParameterValidator {
private Long minLength;
@Override
public boolean validate(Object value) {
if(value == null) {
throw new IllegalArgumentException("Object to validate must not be null");
}
if(!(value instanceof String)) {
throw new ValidatorConfigException("Incorrect value passed to min string length validator.");
}
SingleNumberValidatorParam param = (SingleNumberValidatorParam) getParameters().get(0);
String stringValue = (String) value;
return stringValue.length() >= param.getNumber();
}
@Override
public List<ValidatorParam> getParameters() {
SingleNumberValidatorParam param = SingleNumberValidatorParam
.builder()
.number(minLength)
.build();
return Arrays.asList(param);
}
@Override
public String getExceptionTemplateName() {
return "command_parameter_validation_string_too_short";
}
@Override
public String getTemplateName() {
return "min_string_length_validation_description";
}
@Override
public Object getTemplateModel() {
return getParameters().get(0);
}
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.core.command.config.validator;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class SingleNumberValidatorParam implements ValidatorParam {
private Long number;
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.config.validator;
import java.io.Serializable;
public interface ValidatorParam extends Serializable {
}

View File

@@ -0,0 +1,30 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
public class AbstractoTemplatedException extends AbstractoRunTimeException implements Templatable {
private final String templateKey;
public AbstractoTemplatedException(String message, String templateKey) {
super(message);
this.templateKey = templateKey;
}
public AbstractoTemplatedException(String message, String templateKey, Throwable cause) {
super(message, cause);
this.templateKey = templateKey;
}
@Override
public String getTemplateName() {
return templateKey;
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -0,0 +1,27 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.command.models.exception.ChannelAlreadyInChannelGroupExceptionModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.templating.Templatable;
public class ChannelAlreadyInChannelGroupException extends AbstractoRunTimeException implements Templatable {
private final ChannelAlreadyInChannelGroupExceptionModel model;
public ChannelAlreadyInChannelGroupException(AChannel channel, AChannelGroup group) {
super("Channel is already part of channel group");
this.model = ChannelAlreadyInChannelGroupExceptionModel.builder().channel(channel).channelGroup(group).build();
}
@Override
public String getTemplateName() {
return "channel_already_in_channel_group_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.command.models.exception.ChannelGroupExistsExceptionModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
public class ChannelGroupExistsException extends AbstractoRunTimeException implements Templatable {
private final ChannelGroupExistsExceptionModel model;
public ChannelGroupExistsException(String name) {
super("Channel group already exists");
this.model = ChannelGroupExistsExceptionModel.builder().name(name).build();
}
@Override
public String getTemplateName() {
return "channel_group_exists_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.command.models.exception.ChannelGroupNotFoundExceptionModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
import java.util.List;
public class ChannelGroupNotFoundException extends AbstractoRunTimeException implements Templatable {
private final ChannelGroupNotFoundExceptionModel model;
public ChannelGroupNotFoundException(String key, List<String> available) {
super("Channel group not found");
this.model = ChannelGroupNotFoundExceptionModel.builder().name(key).available(available).build();
}
@Override
public String getTemplateName() {
return "channel_group_not_found_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,27 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.command.models.exception.ChannelNotInChannelGroupExceptionModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.templating.Templatable;
public class ChannelNotInChannelGroupException extends AbstractoRunTimeException implements Templatable {
private final ChannelNotInChannelGroupExceptionModel model;
public ChannelNotInChannelGroupException(AChannel channel, AChannelGroup group) {
super("Channel is already part of channel group");
this.model = ChannelNotInChannelGroupExceptionModel.builder().channel(channel).channelGroup(group).build();
}
@Override
public String getTemplateName() {
return "channel_not_in_channel_group_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,20 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
public class CommandNotFoundException extends AbstractoRunTimeException implements Templatable {
public CommandNotFoundException() {
super("Command not found");
}
@Override
public String getTemplateName() {
return "command_not_found_exception";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -0,0 +1,37 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.validator.ValidatorParam;
import dev.sheldan.abstracto.core.command.models.exception.CommandParameterValidationExceptionModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class CommandParameterValidationException extends AbstractoRunTimeException implements Templatable {
private final CommandParameterValidationExceptionModel model;
public CommandParameterValidationException(List<ValidatorParam> validatorParams, String template, Parameter parameter) {
this.model = CommandParameterValidationExceptionModel
.builder()
.validationTemplate(template)
.validatorParams(validatorParams)
.parameter(parameter)
.build();
}
@Override
public String getTemplateName() {
return "command_parameter_validation_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,27 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.exception.IncorrectFeatureModeModel;
import dev.sheldan.abstracto.core.templating.Templatable;
import java.util.List;
public class IncorrectFeatureModeException extends AbstractoRunTimeException implements Templatable {
private final IncorrectFeatureModeModel model;
public IncorrectFeatureModeException(FeatureEnum featureEnum, List<FeatureMode> requiredModes) {
this.model = IncorrectFeatureModeModel.builder().featureEnum(featureEnum).requiredModes(requiredModes).build();
}
@Override
public String getTemplateName() {
return "incorrect_feature_mode_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.models.exception.IncorrectParameterExceptionModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
public class IncorrectParameterException extends AbstractoRunTimeException implements Templatable {
private final IncorrectParameterExceptionModel model;
public IncorrectParameterException(Command command, String parameterName) {
super("Incorrect parameter given for parameter");
this.model = IncorrectParameterExceptionModel.builder().parameterName(parameterName).command(command).build();
}
@Override
public String getTemplateName() {
return "incorrect_parameters_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,11 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
public class IncorrectParameterTypeException extends AbstractoRunTimeException {
public IncorrectParameterTypeException(Command command, Class clazz, String parameterName) {
super(String.format("Incorrect parameter given for parameter. Expected %s for parameter %s in command %s.", clazz.getName(), parameterName, command.getConfiguration().getName()));
}
}

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.models.exception.InsufficientParametersExceptionModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
public class InsufficientParametersException extends AbstractoRunTimeException implements Templatable {
private final InsufficientParametersExceptionModel model;
public InsufficientParametersException(Command command, String parameterName) {
super("Insufficient parameters given for command");
this.model = InsufficientParametersExceptionModel.builder().command(command).parameterName(parameterName).build();
}
@Override
public String getTemplateName() {
return "insufficient_parameters_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,21 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
public class NoAttachmentFoundException extends AbstractoRunTimeException implements Templatable {
public NoAttachmentFoundException() {
super("No attachment was found in the message.");
}
@Override
public String getTemplateName() {
return "attachment_not_found_exception";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
public class ValidatorConfigException extends AbstractoRunTimeException {
public ValidatorConfigException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,29 @@
package dev.sheldan.abstracto.core.command.execution;
import dev.sheldan.abstracto.core.command.config.Parameters;
import dev.sheldan.abstracto.core.models.UndoActionInstance;
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
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.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import java.util.List;
@Builder
@Getter
@Setter
public class CommandContext {
private TextChannel channel;
private Guild guild;
private Member author;
private Message message;
private UserInitiatedServerContext userInitiatedContext;
private Parameters parameters;
private JDA jda;
private List<UndoActionInstance> undoActions;
}

View File

@@ -0,0 +1,22 @@
package dev.sheldan.abstracto.core.command.execution;
import dev.sheldan.abstracto.core.command.exception.CommandParameterKeyValueWrongTypeException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public interface CommandParameterKey {
static <T extends Enum<T>> T getEnumFromKey(Class<T> clazz, String key) {
try {
if(clazz != null && key != null ) {
return Enum.valueOf(clazz, key.trim().toUpperCase());
}
} catch (IllegalArgumentException e) {
List<T> ts = Arrays.asList(clazz.getEnumConstants());
List<String> keys = ts.stream().map(Enum::toString).map(String::toLowerCase).collect(Collectors.toList());
throw new CommandParameterKeyValueWrongTypeException(keys);
}
throw new IllegalArgumentException("Clazz and key must not be null");
}
}

View File

@@ -0,0 +1,45 @@
package dev.sheldan.abstracto.core.command.execution;
import dev.sheldan.abstracto.core.command.condition.ConditionResult;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class CommandResult {
private ResultState result;
private String message;
private Throwable throwable;
private ConditionResult conditionResult;
public static CommandResult fromSuccess() {
return CommandResult.builder().result(ResultState.SUCCESSFUL).build();
}
public static CommandResult fromSelfDestruct() {
return CommandResult.builder().result(ResultState.SELF_DESTRUCT).build();
}
public static CommandResult fromReportedError() {
return CommandResult.builder().result(ResultState.REPORTED_ERROR).build();
}
public static CommandResult fromError(String message){
return CommandResult.builder().result(ResultState.ERROR).message(message).build();
}
public static CommandResult fromError(String message, Throwable throwable) {
return CommandResult.builder().result(ResultState.ERROR).message(message).throwable(throwable).build();
}
public static CommandResult fromIgnored() {
return CommandResult.builder().result(ResultState.IGNORED).build();
}
public static CommandResult fromCondition(ConditionResult result) {
return CommandResult.builder().conditionResult(result).result(ResultState.CONDITION).build();
}
}

View File

@@ -0,0 +1,51 @@
package dev.sheldan.abstracto.core.command.execution;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.context.SlimUserInitiatedServerContext;
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@Slf4j
public class ContextConverter {
private ContextConverter() {
}
public static <T extends UserInitiatedServerContext> UserInitiatedServerContext fromCommandContext(CommandContext commandContext, Class<T> clazz) {
Method m = null;
try {
m = clazz.getMethod("builder");
UserInitiatedServerContext.UserInitiatedServerContextBuilder<?, ?> builder = (UserInitiatedServerContext.UserInitiatedServerContextBuilder) m.invoke(null, null);
return builder
.member(commandContext.getAuthor())
.guild(commandContext.getGuild())
.message(commandContext.getMessage())
.messageChannel(commandContext.getChannel())
.build();
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
log.error("Failed to execute builder method", e);
}
throw new AbstractoRunTimeException("Failed to create UserInitiatedServerContext from CommandContext.");
}
public static <T extends SlimUserInitiatedServerContext> SlimUserInitiatedServerContext slimFromCommandContext(CommandContext commandContext, Class<T> clazz) {
Method m = null;
try {
m = clazz.getMethod("builder");
SlimUserInitiatedServerContext.SlimUserInitiatedServerContextBuilder<?, ?> builder = (SlimUserInitiatedServerContext.SlimUserInitiatedServerContextBuilder) m.invoke(null, null);
return builder
.member(commandContext.getAuthor())
.guild(commandContext.getGuild())
.message(commandContext.getMessage())
.channel(commandContext.getChannel())
.build();
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
log.error("Failed to execute builder method", e);
}
throw new AbstractoRunTimeException("Failed to create SlimUserInitiatedServerContext from CommandContext");
}
}

View File

@@ -0,0 +1,5 @@
package dev.sheldan.abstracto.core.command.execution;
public enum ParameterPieceType {
STRING, ATTACHMENT
}

View File

@@ -0,0 +1,5 @@
package dev.sheldan.abstracto.core.command.execution;
public enum ResultState {
ERROR, SUCCESSFUL, IGNORED, CONDITION, SELF_DESTRUCT, REPORTED_ERROR
}

View File

@@ -0,0 +1,41 @@
package dev.sheldan.abstracto.core.command.execution;
import lombok.Getter;
import net.dv8tion.jda.api.entities.Message;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Getter
public class UnParsedCommandParameter {
private static Pattern SPLIT_REGEX = Pattern.compile("\"([^\"]*)\"|(\\S+)");
public UnParsedCommandParameter(String parameters, Message message) {
this.parameters = new ArrayList<>();
Matcher m = SPLIT_REGEX.matcher(parameters);
boolean skippedCommand = false;
while (m.find()) {
if(!skippedCommand) {
skippedCommand = true;
continue;
}
if (m.group(1) != null) {
String group = m.group(1);
if(!group.equals("")) {
this.parameters.add(UnparsedCommandParameterPiece.builder().value(group).build());
}
} else {
String group = m.group(2);
if(!group.equals("")) {
this.parameters.add(UnparsedCommandParameterPiece.builder().value(group).build());
}
}
}
message.getAttachments().forEach(attachment ->
this.parameters.add(UnparsedCommandParameterPiece.builder().value(attachment).type(ParameterPieceType.ATTACHMENT).build()));
}
private List<UnparsedCommandParameterPiece> parameters;
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.command.execution;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class UnparsedCommandParameterPiece {
private Object value;
@Builder.Default
private ParameterPieceType type = ParameterPieceType.STRING;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import net.dv8tion.jda.api.entities.Message;
import java.util.concurrent.CompletableFuture;
public interface CommandParameterHandler {
boolean handles(Class clazz);
default boolean async() { return false; }
default Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { return new Object();}
default CompletableFuture<Object> handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { return CompletableFuture.completedFuture(null); }
Integer getPriority();
}

View File

@@ -0,0 +1,19 @@
package dev.sheldan.abstracto.core.command.handler;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.TextChannel;
import java.util.Iterator;
@Getter
@AllArgsConstructor
public class CommandParameterIterators {
private Iterator<TextChannel> channelIterator;
private Iterator<Emote> emoteIterator;
private Iterator<Member> memberIterator;
private Iterator<Role> roleIterator;
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface AChannelParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface AEmoteParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface ARoleParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface AUserInAServerParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface BooleanParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface ChannelGroupParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface ChannelGroupTypeParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface CommandKeyParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface DoubleParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface DurationParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface EmoteParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface FileParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface FullEmoteParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface FullRoleParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,8 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface IntegerParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface LongParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface MemberParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface RoleParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.command.handler.provided;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
public interface TextChannelParameterHandler extends CommandParameterHandler {
}

View File

@@ -0,0 +1,5 @@
package dev.sheldan.abstracto.core.command.models;
public enum TableLocks {
CHANNELS, USER_IN_SERVER, USER
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.command.models.condition;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Setter
@Getter
@Builder
public class FeatureDisabledConditionDetailModel implements Serializable {
private FeatureConfig featureConfig;
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.core.command.models.condition;
import dev.sheldan.abstracto.core.command.condition.ConditionDetail;
import dev.sheldan.abstracto.core.models.GuildChannelMember;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class GenericConditionModel {
private GuildChannelMember guildChannelMember;
private ConditionDetail conditionDetail;
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.core.command.models.condition;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Role;
@Getter
@Setter
@Builder
public class ImmuneUserConditionDetailModel {
private Role role;
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.command.models.condition;
import lombok.Builder;
import lombok.Getter;
import net.dv8tion.jda.api.entities.Role;
import java.io.Serializable;
import java.util.List;
@Getter
@Builder
public class InsufficientPermissionCondtionDetailModel implements Serializable {
private transient List<Role> allowedRoles;
}

View File

@@ -0,0 +1,46 @@
package dev.sheldan.abstracto.core.command.models.database;
import dev.sheldan.abstracto.core.models.database.AChannelGroupCommand;
import dev.sheldan.abstracto.core.models.database.AFeature;
import lombok.*;
import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
import java.util.List;
@Entity
@Table(name = "command")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@EqualsAndHashCode
public class ACommand implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "module_id", nullable = false)
private AModule module;
@OneToMany(mappedBy = "command", fetch = FetchType.LAZY)
private List<AChannelGroupCommand> channelGroupCommands;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "feature_id", nullable = false)
private AFeature feature;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -0,0 +1,64 @@
package dev.sheldan.abstracto.core.command.models.database;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import lombok.*;
import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
import java.util.List;
@Entity(name = "command_in_server")
@Getter
@Builder
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class ACommandInAServer implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "command_in_server_id")
private Long commandInServerId;
@OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "command_id", nullable = false)
private ACommand commandReference;
@OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "server_id", nullable = false)
private AServer serverReference;
@ManyToMany
@JoinTable(
name = "command_in_server_allowed_role",
joinColumns = @JoinColumn(name = "command_in_server_id", referencedColumnName = "command_in_server_id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
@Getter
private List<ARole> allowedRoles;
@ManyToMany
@JoinTable(
name = "command_in_server_immune_role",
joinColumns = @JoinColumn(name = "command_in_server_id", referencedColumnName = "command_in_server_id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
@Getter
private List<ARole> immuneRoles;
@Getter
@Setter
@Column(name = "restricted")
private Boolean restricted;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -0,0 +1,40 @@
package dev.sheldan.abstracto.core.command.models.database;
import lombok.*;
import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "module")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@EqualsAndHashCode
public class AModule implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(
fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
orphanRemoval = true, mappedBy = "module")
@Builder.Default
private List<ACommand> commands = new ArrayList<>();
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.command.models.exception;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import lombok.Builder;
import lombok.Getter;
import java.io.Serializable;
@Getter
@Builder
public class ChannelAlreadyInChannelGroupExceptionModel implements Serializable {
private AChannel channel;
private AChannelGroup channelGroup;
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.core.command.models.exception;
import lombok.Builder;
import lombok.Getter;
import java.io.Serializable;
@Getter
@Builder
public class ChannelGroupExistsExceptionModel implements Serializable {
private String name;
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.core.command.models.exception;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
@Getter
@Setter
@Builder
public class ChannelGroupNotFoundExceptionModel implements Serializable {
private String name;
private List<String> available;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.command.models.exception;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import lombok.Builder;
import lombok.Getter;
import java.io.Serializable;
@Getter
@Builder
public class ChannelNotInChannelGroupExceptionModel implements Serializable {
private AChannel channel;
private AChannelGroup channelGroup;
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.command.models.exception;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@Builder
public class CommandParameterKeyValueWrongTypeExceptionModel {
private List<String> expectedValues;
}

View File

@@ -0,0 +1,19 @@
package dev.sheldan.abstracto.core.command.models.exception;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.validator.ValidatorParam;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
@Getter
@Setter
@Builder
public class CommandParameterValidationExceptionModel implements Serializable {
private List<ValidatorParam> validatorParams;
private String validationTemplate;
private Parameter parameter;
}

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.core.command.models.exception;
import dev.sheldan.abstracto.core.models.FullUser;
import dev.sheldan.abstracto.core.models.FullUserInServer;
import dev.sheldan.abstracto.core.templating.Templatable;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class GenericExceptionModel {
private FullUserInServer user;
private FullUser fullUser;
private Throwable throwable;
public Templatable getTemplate() {
Throwable current = throwable;
while(!(current instanceof Templatable) && (current.getCause() != null && !current.getCause().equals(current))) {
current = current.getCause();
}
if(current instanceof Templatable) {
return (Templatable) current;
}
return null;
}
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.command.models.exception;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Builder
public class IncorrectFeatureModeMessage {
private FeatureConfig featureConfig;
private Command command;
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.command.models.exception;
import dev.sheldan.abstracto.core.command.Command;
import lombok.Builder;
import lombok.Getter;
import java.io.Serializable;
@Getter
@Builder
public class IncorrectParameterExceptionModel implements Serializable {
private final transient Command command;
private final String parameterName;
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.core.command.models.exception;
import dev.sheldan.abstracto.core.command.Command;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@Builder
public class InsufficientParametersExceptionModel implements Serializable {
private final transient Command command;
private final String parameterName;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.command.models.exception;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Role;
import java.util.List;
@Setter
@Getter
@Builder
public class InsufficientPermissionMessage {
private List<Role> allowedRoles;
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.core.command.service;
import dev.sheldan.abstracto.core.command.models.database.ACommand;
import dev.sheldan.abstracto.core.models.database.AChannel;
public interface ChannelGroupCommandService {
Boolean isCommandEnabled(ACommand command, AChannel channel);
Boolean isCommandEnabled(ACommand command, Long channelId);
}

View File

@@ -0,0 +1,20 @@
package dev.sheldan.abstracto.core.command.service;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
import net.dv8tion.jda.api.entities.Message;
import java.util.List;
public interface CommandRegistry {
Command findCommandByParameters(String name, UnParsedCommandParameter context);
Command findCommand(String message);
List<Command> getAllCommands();
List<Command> getAllCommandsFromModule(ModuleInterface module);
boolean isCommand(Message message);
boolean commandExists(String name);
Command getCommandByName(String name);
String getCommandName(String input, Long serverId);
}

Some files were not shown because too many files have changed in this diff Show More