[AB-128] adding command cooldowns on server/channel group and member level

fixing channel group names being made lower case before storing
changing channel group deleted to be sync instead
refactoring exceptions and adding exception message to a few
fixing channel group incorrect type using the wrong template
showing more information in list channel groups command
allowing commands to be in any channel group
adding concept of channel group types not allowing channels/commands to be in multiple of the same type
adding structure to retrieve information about channel groups
adding ability to disable channel groups
changing loading of member parameter handler to not use cache
This commit is contained in:
Sheldan
2021-04-19 00:25:42 +02:00
parent d540ad80a8
commit 49a9598062
127 changed files with 2325 additions and 189 deletions

View File

@@ -32,10 +32,14 @@ public abstract class AbstractConditionableCommand implements ConditionalCommand
@Autowired
private AdminModeCondition adminModeCondition;
@Autowired
private CommandCoolDownCondition coolDownCondition;
@Override
public List<CommandCondition> getConditions() {
return new ArrayList<>(Arrays.asList(adminModeCondition, featureEnabledCondition, commandDisabledCondition, commandDisallowedCondition, featureModeCondition));
return new ArrayList<>(Arrays.asList(adminModeCondition, featureEnabledCondition, commandDisabledCondition,
commandDisallowedCondition, featureModeCondition, coolDownCondition));
}
protected void checkParameters(CommandContext context) {

View File

@@ -0,0 +1,36 @@
package dev.sheldan.abstracto.core.command.condition;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.condition.detail.CommandCoolDownDetail;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CoolDownCheckResult;
import dev.sheldan.abstracto.core.command.service.CommandCoolDownService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Duration;
@Component
public class CommandCoolDownCondition implements CommandCondition {
@Autowired
private CommandCoolDownService commandCoolDownService;
@Override
public ConditionResult shouldExecute(CommandContext commandContext, Command command) {
commandCoolDownService.takeLock();
try {
CoolDownCheckResult result = commandCoolDownService.allowedToExecuteCommand(command, commandContext);
if(result.getCanExecute()) {
return ConditionResult.builder().result(true).build();
} else {
if(result.getExecuteIn().compareTo(Duration.ofSeconds(1)) < 0) {
result.setExecuteIn(Duration.ofSeconds(1));
}
return ConditionResult.builder().result(false).conditionDetail(new CommandCoolDownDetail(result)).build();
}
} finally {
commandCoolDownService.releaseLock();
}
}
}

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.execution.CoolDownCheckResult;
import dev.sheldan.abstracto.core.command.model.condition.CommandCoolDownDetailModel;
public class CommandCoolDownDetail implements ConditionDetail {
private final CommandCoolDownDetailModel model;
public CommandCoolDownDetail(CoolDownCheckResult result) {
this.model = CommandCoolDownDetailModel.builder().reason(result).build();
}
@Override
public String getTemplateName() {
return "command_cool_down_detail";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -32,6 +32,8 @@ public class CommandConfiguration {
private boolean templated = false;
private HelpInfo help;
private CommandCoolDownConfig coolDownConfig;
public int getNecessaryParameterCount(){
return (int) parameters.stream().filter(parameter -> !parameter.isOptional()).count();
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.core.command.config;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.time.Duration;
@Getter
@Setter
@Builder
public class CommandCoolDownConfig {
private Duration serverCoolDown;
private Duration channelCoolDown;
private Duration memberCoolDown;
}

View File

@@ -14,7 +14,7 @@ public class ChannelGroupIncorrectTypeException extends AbstractoRunTimeExceptio
}
@Override
public String getTemplateName() {
return "channel_group_not_found_exception";
return "channel_group_incorrect_type_exception";
}
@Override

View File

@@ -9,6 +9,7 @@ public class CommandAliasAlreadyExistsException extends AbstractoRunTimeExceptio
private final CommandAliasAlreadyExistsModel model;
public CommandAliasAlreadyExistsException(String existingCommand) {
super("Command alias already exists.");
this.model = CommandAliasAlreadyExistsModel
.builder()
.existingCommand(existingCommand)

View File

@@ -2,11 +2,13 @@ package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class CommandAliasDoesNotExistsException extends AbstractoRunTimeException implements Templatable {
public CommandAliasDoesNotExistsException() {
super("Command Alias does not exist.");
}
@Override
public String getTemplateName() {
return "command_in_server_alias_not_exists_exists_exception";

View File

@@ -9,6 +9,7 @@ public class CommandAliasHidesCommandException extends AbstractoRunTimeException
private final CommandAliasHidesCommandModel model;
public CommandAliasHidesCommandException(String existingCommand) {
super("Command alias hides existing command");
this.model = CommandAliasHidesCommandModel
.builder()
.existingCommand(existingCommand)

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 CommandNotFoundInGroupException extends AbstractoRunTimeException implements Templatable {
public CommandNotFoundInGroupException() {
super("Command was not found in given group.");
}
@Override
public String getTemplateName() {
return "command_not_found_in_group_exception";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -17,6 +17,7 @@ public class CommandParameterValidationException extends AbstractoRunTimeExcepti
private final CommandParameterValidationExceptionModel model;
public CommandParameterValidationException(List<ValidatorParam> validatorParams, String template, Parameter parameter) {
super("Command parameter failed to validate.");
this.model = CommandParameterValidationExceptionModel
.builder()
.validationTemplate(template)

View File

@@ -12,7 +12,12 @@ public class IncorrectFeatureModeException extends AbstractoRunTimeException imp
private final IncorrectFeatureModeModel model;
public IncorrectFeatureModeException(FeatureDefinition featureDefinition, List<FeatureMode> requiredModes) {
this.model = IncorrectFeatureModeModel.builder().featureDefinition(featureDefinition).requiredModes(requiredModes).build();
super("Incorrect feature mode.");
this.model = IncorrectFeatureModeModel
.builder()
.featureDefinition(featureDefinition)
.requiredModes(requiredModes)
.build();
}
@Override

View File

@@ -11,7 +11,11 @@ public class IncorrectParameterException extends AbstractoRunTimeException imple
public IncorrectParameterException(Command command, String parameterName) {
super("Incorrect parameter given for parameter");
this.model = IncorrectParameterExceptionModel.builder().parameterName(parameterName).command(command).build();
this.model = IncorrectParameterExceptionModel
.builder()
.parameterName(parameterName)
.command(command)
.build();
}
@Override

View File

@@ -0,0 +1,54 @@
package dev.sheldan.abstracto.core.command.execution;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.time.Duration;
@Getter
@Setter
@Builder
public class CoolDownCheckResult {
private Duration executeIn;
private Boolean canExecute;
private CoolDownReason reason;
public static CoolDownCheckResult getServerCoolDown(Duration duration) {
return CoolDownCheckResult
.builder()
.canExecute(false)
.reason(CoolDownReason.SERVER)
.executeIn(duration)
.build();
}
public static CoolDownCheckResult getChannelGroupCoolDown(Duration duration) {
return CoolDownCheckResult
.builder()
.canExecute(false)
.reason(CoolDownReason.CHANNEL_GROUP)
.executeIn(duration)
.build();
}
public static CoolDownCheckResult getMemberCoolDown(Duration duration) {
return CoolDownCheckResult
.builder()
.canExecute(false)
.reason(CoolDownReason.MEMBER)
.executeIn(duration)
.build();
}
public static CoolDownCheckResult noCoolDown() {
return CoolDownCheckResult
.builder()
.canExecute(true)
.build();
}
}
enum CoolDownReason {
SERVER, CHANNEL_GROUP, MEMBER
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.command.model.condition;
import dev.sheldan.abstracto.core.command.execution.CoolDownCheckResult;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@Builder
public class CommandCoolDownDetailModel implements Serializable {
private CoolDownCheckResult reason;
}

View File

@@ -61,6 +61,9 @@ public class ACommandInAServer implements Serializable {
@Column(name = "updated")
private Instant updated;
@Column(name = "cool_down")
private Long coolDown;
}

View File

@@ -0,0 +1,31 @@
package dev.sheldan.abstracto.core.command.model.database;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import lombok.*;
import javax.persistence.*;
import java.time.Instant;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "command_disabled_channel_group")
@Getter
@Setter
@EqualsAndHashCode
public class CommandDisabledChannelGroup {
@Id
@Column(name = "id")
private Long id;
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@PrimaryKeyJoinColumn
private AChannelGroup channelGroup;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -0,0 +1,37 @@
package dev.sheldan.abstracto.core.command.model.database;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import lombok.*;
import javax.persistence.*;
import java.time.Instant;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "cool_down_channel_group")
@Getter
@Setter
@EqualsAndHashCode
public class CoolDownChannelGroup {
@Id
@Column(name = "id")
private Long id;
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@PrimaryKeyJoinColumn
private AChannelGroup channelGroup;
@Column(name = "channel_cool_down")
private Long channelCoolDown;
@Column(name = "member_cool_down")
private Long memberCoolDown;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -0,0 +1,39 @@
package dev.sheldan.abstracto.core.command.service;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CoolDownCheckResult;
import dev.sheldan.abstracto.core.command.model.database.ACommand;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import dev.sheldan.abstracto.core.models.ServerIdChannelId;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import java.time.Duration;
public interface CommandCoolDownService {
/**
* Acquires the lock which should be used when accessing the runtime storage
*/
void takeLock();
/**
* Releases the lock which should be used then accessing the runtime storage
*/
void releaseLock();
CoolDownCheckResult allowedToExecuteCommand(Command command, CommandContext context);
Duration getServerCoolDownForCommand(Command command, Long serverId);
Duration getServerCoolDownForCommand(ACommand aCommand, Command command, Long serverId);
Duration getChannelGroupCoolDownForCommand(Command command, ServerIdChannelId serverIdChannelId);
Duration getChannelGroupCoolDownForCommand(ACommand aCommand, Command command, ServerIdChannelId serverIdChannelId);
Duration getMemberCoolDownForCommand(Command command, ServerIdChannelId serverIdChannelId);
Duration getMemberCoolDownForCommand(ACommand aCommand, Command command, ServerIdChannelId serverIdChannelId);
void addServerCoolDown(Command command, Long serverId);
void addServerCoolDown(Command command, Long serverId, boolean takeLock);
void addChannelCoolDown(Command command, ServerIdChannelId context);
void addChannelCoolDown(Command command, ServerIdChannelId context, boolean takeLock);
void addMemberCoolDown(Command command, AServerChannelUserId context);
void addMemberCoolDown(Command command, AServerChannelUserId context, boolean takeLock);
void updateCoolDowns(Command command, CommandContext context);
void setCoolDownConfigForChannelGroup(AChannelGroup aChannelGroup, Duration groupCoolDown, Duration memberCoolDown);
void clearCoolDownsForServer(Long serverId);
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.service;
public interface CommandDisabledService {
void disableCommandInChannelGroup(String commandName, String channelGroupName, Long serverId);
void enableCommandInChannelGroup(String commandName, String channelGroupName, Long serverId);
}

View File

@@ -8,7 +8,11 @@ import java.util.List;
public interface ChannelGroupCommandManagementService {
void setCommandInGroupTo(ACommand command, AChannelGroup group, Boolean enabled);
void addCommandToGroup(ACommand command, AChannelGroup group);
void removeCommandFromGroup(ACommand command, AChannelGroup group);
AChannelGroupCommand createCommandInGroup(ACommand command, AChannelGroup group);
AChannelGroupCommand getChannelGroupCommand(ACommand command, AChannelGroup group);
List<AChannelGroupCommand> getAllGroupCommandsForCommand(ACommand command);
List<AChannelGroupCommand> getAllGroupCommandsForCommandInGroups(ACommand command, List<AChannelGroup> groups);
List<AChannelGroupCommand> getAllGroupCommandsForCommandWithType(ACommand command, String channelGroupType);
}

View File

@@ -9,7 +9,11 @@ public class CategoryNotFoundException extends AbstractoRunTimeException impleme
public CategoryNotFoundException(Long categoryId, Long guildId) {
super("Category not found");
this.model = CategoryNotFoundExceptionModel.builder().categoryId(categoryId).guildId(guildId).build();
this.model = CategoryNotFoundExceptionModel
.builder()
.categoryId(categoryId)
.guildId(guildId)
.build();
}
@Override

View File

@@ -10,7 +10,11 @@ public class ChannelGroupTypeNotFound extends AbstractoRunTimeException implemen
private final ChannelGroupTypeNotFoundExceptionModel model;
public ChannelGroupTypeNotFound(List<String> channelGroupTypeKeys) {
this.model = ChannelGroupTypeNotFoundExceptionModel.builder().availableGroupTypeKeys(channelGroupTypeKeys).build();
super("Channel group type not found.");
this.model = ChannelGroupTypeNotFoundExceptionModel
.builder()
.availableGroupTypeKeys(channelGroupTypeKeys)
.build();
}
@Override

View File

@@ -0,0 +1,27 @@
package dev.sheldan.abstracto.core.exception;
import dev.sheldan.abstracto.core.models.exception.ChannelInMultipleChannelGroupsExceptionModel;
import dev.sheldan.abstracto.core.templating.Templatable;
public class ChannelInMultipleChannelGroupsException extends AbstractoRunTimeException implements Templatable {
private final ChannelInMultipleChannelGroupsExceptionModel model;
public ChannelInMultipleChannelGroupsException(String channelGroupName) {
super("Channel is already in another group of this type.");
this.model = ChannelInMultipleChannelGroupsExceptionModel
.builder()
.channelGroupName(channelGroupName)
.build();
}
@Override
public String getTemplateName() {
return "channel_in_multiple_channel_groups_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -9,7 +9,10 @@ public class ChannelNotFoundException extends AbstractoRunTimeException implemen
public ChannelNotFoundException(Long channelId) {
super("Channel not found in database");
this.model = ChannelNotFoundExceptionModel.builder().channelId(channelId).build();
this.model = ChannelNotFoundExceptionModel
.builder()
.channelId(channelId)
.build();
}
@Override

View File

@@ -9,7 +9,10 @@ public class ChannelNotInGuildException extends AbstractoRunTimeException implem
public ChannelNotInGuildException(Long channelId) {
super("Channel not found in guild");
this.model = ChannelNotFoundExceptionModel.builder().channelId(channelId).build();
this.model = ChannelNotFoundExceptionModel
.builder()
.channelId(channelId)
.build();
}
@Override

View File

@@ -0,0 +1,27 @@
package dev.sheldan.abstracto.core.exception;
import dev.sheldan.abstracto.core.models.exception.CommandInMultipleChannelGroupsExceptionModel;
import dev.sheldan.abstracto.core.templating.Templatable;
public class CommandInMultipleChannelGroupsException extends AbstractoRunTimeException implements Templatable {
private final CommandInMultipleChannelGroupsExceptionModel model;
public CommandInMultipleChannelGroupsException(String channelGroupName) {
super("Command is already in another group of this type.");
this.model = CommandInMultipleChannelGroupsExceptionModel
.builder()
.channelGroupName(channelGroupName)
.build();
}
@Override
public String getTemplateName() {
return "command_in_multiple_channel_groups_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -9,7 +9,10 @@ public class ConfigurationKeyNotFoundException extends AbstractoRunTimeException
public ConfigurationKeyNotFoundException(String key) {
super("Configuration key not found");
this.model = ConfigurationKeyNotFoundExceptionModel.builder().key(key).build();
this.model = ConfigurationKeyNotFoundExceptionModel
.builder()
.key(key)
.build();
}
@Override

View File

@@ -10,7 +10,10 @@ public class ConfiguredEmoteNotUsableException extends AbstractoRunTimeException
public ConfiguredEmoteNotUsableException(AEmote emote) {
super("Emote was configured in database, but is not usable by the bot anymore.");
this.model = EmoteConfiguredButNotUsableExceptionModel.builder().emote(emote).build();
this.model = EmoteConfiguredButNotUsableExceptionModel
.builder()
.emote(emote)
.build();
}
@Override

View File

@@ -12,7 +12,11 @@ public class DurationFormatException extends AbstractoRunTimeException implement
public DurationFormatException(String wrongFormat, List<String> validFormats) {
super("Duration format exception ");
this.model = DurationFormatExceptionModel.builder().invalidFormat(wrongFormat).validFormats(validFormats).build();
this.model = DurationFormatExceptionModel
.builder()
.invalidFormat(wrongFormat)
.validFormats(validFormats)
.build();
}
@Override

View File

@@ -9,7 +9,10 @@ public class EmoteNotDefinedException extends AbstractoRunTimeException implemen
public EmoteNotDefinedException(String key) {
super(String.format("Emote %s not defined", key));
this.model = EmoteNotDefinedExceptionModel.builder().emoteKey(key).build();
this.model = EmoteNotDefinedExceptionModel
.builder()
.emoteKey(key)
.build();
}
@Override

View File

@@ -11,7 +11,11 @@ public class EmoteNotFoundException extends AbstractoRunTimeException implements
public EmoteNotFoundException(String key, List<String> availableEmotes) {
super("Emote not found");
this.model = EmoteNotFoundExceptionModel.builder().emoteKey(key).available(availableEmotes).build();
this.model = EmoteNotFoundExceptionModel
.builder()
.emoteKey(key)
.available(availableEmotes)
.build();
}
@Override

View File

@@ -9,7 +9,10 @@ public class EmoteNotFoundInDbException extends AbstractoRunTimeException implem
public EmoteNotFoundInDbException(Integer emoteId) {
super("Emote not found in database");
this.model = EmoteNotFoundInDbExceptionModel.builder().emoteId(emoteId).build();
this.model = EmoteNotFoundInDbExceptionModel
.builder()
.emoteId(emoteId)
.build();
}
@Override

View File

@@ -9,7 +9,10 @@ public class EmoteNotInServerException extends AbstractoRunTimeException impleme
public EmoteNotInServerException(Long emoteId) {
super("Emote not available in server");
this.model = EmoteNotInServerExceptionModel.builder().emoteId(emoteId).build();
this.model = EmoteNotInServerExceptionModel
.builder()
.emoteId(emoteId)
.build();
}
@Override

View File

@@ -10,7 +10,10 @@ public class EmoteNotUsableException extends AbstractoRunTimeException implement
public EmoteNotUsableException(Emote emote) {
super(String.format("Emote %s not usable by bot.", emote.getId()));
this.model = EmoteNotUsableExceptionModel.builder().emote(emote).build();
this.model = EmoteNotUsableExceptionModel
.builder()
.emote(emote)
.build();
}
@Override

View File

@@ -11,7 +11,11 @@ public class FeatureModeNotFoundException extends AbstractoRunTimeException impl
public FeatureModeNotFoundException(String featureMode, List<String> availableModes) {
super("Feature mode not found.");
this.model = FeatureModeNotFoundExceptionModel.builder().availableModes(availableModes).featureMode(featureMode).build();
this.model = FeatureModeNotFoundExceptionModel
.builder()
.availableModes(availableModes)
.featureMode(featureMode)
.build();
}
@Override

View File

@@ -11,8 +11,11 @@ public class FeatureNotFoundException extends AbstractoRunTimeException implemen
public FeatureNotFoundException(String feature, List<String> availableFeatures) {
super("Feature not found.");
this.model = FeatureNotFoundExceptionModel.builder().featureName(feature).availableFeatures(availableFeatures).build();
this.model = FeatureNotFoundExceptionModel
.builder()
.featureName(feature)
.availableFeatures(availableFeatures)
.build();
}
@Override

View File

@@ -8,7 +8,10 @@ public class GuildNotFoundException extends AbstractoRunTimeException implements
public GuildNotFoundException(Long guildId) {
super("Guild not found");
this.model = GuildNotFoundExceptionModel.builder().guildId(guildId).build();
this.model = GuildNotFoundExceptionModel
.builder()
.guildId(guildId)
.build();
}
@Override

View File

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

View File

@@ -9,7 +9,10 @@ public class PostTargetNotFoundException extends AbstractoRunTimeException imple
public PostTargetNotFoundException(String key) {
super("Post target not found");
this.model = PostTargetNotFoundExceptionModel.builder().postTargetKey(key).build();
this.model = PostTargetNotFoundExceptionModel
.builder()
.postTargetKey(key)
.build();
}
@Override

View File

@@ -11,7 +11,11 @@ public class PostTargetNotValidException extends AbstractoRunTimeException imple
public PostTargetNotValidException(String key, List<String> available) {
super("Given post target was not in the list of valid post targets");
this.model = PostTargetNotValidExceptionModel.builder().availableTargets(available).postTargetKey(key).build();
this.model = PostTargetNotValidExceptionModel
.builder()
.availableTargets(available)
.postTargetKey(key)
.build();
}
@Override

View File

@@ -3,6 +3,11 @@ package dev.sheldan.abstracto.core.exception;
import dev.sheldan.abstracto.core.templating.Templatable;
public class ProfanityGroupExistsException extends AbstractoRunTimeException implements Templatable {
public ProfanityGroupExistsException() {
super("Profanity group already exists.");
}
@Override
public String getTemplateName() {
return "profanity_group_exists_exception";

View File

@@ -3,6 +3,11 @@ package dev.sheldan.abstracto.core.exception;
import dev.sheldan.abstracto.core.templating.Templatable;
public class ProfanityGroupNotFoundException extends AbstractoRunTimeException implements Templatable {
public ProfanityGroupNotFoundException() {
super("Profanity group not found.");
}
@Override
public String getTemplateName() {
return "profanity_group_not_found_exception";

View File

@@ -3,6 +3,11 @@ package dev.sheldan.abstracto.core.exception;
import dev.sheldan.abstracto.core.templating.Templatable;
public class ProfanityRegexExistsException extends AbstractoRunTimeException implements Templatable {
public ProfanityRegexExistsException() {
super("Profanity regex already exists.");
}
@Override
public String getTemplateName() {
return "profanity_regex_exists_exception";

View File

@@ -3,6 +3,11 @@ package dev.sheldan.abstracto.core.exception;
import dev.sheldan.abstracto.core.templating.Templatable;
public class ProfanityRegexNotFoundException extends AbstractoRunTimeException implements Templatable {
public ProfanityRegexNotFoundException() {
super("Profanity regex not found.");
}
@Override
public String getTemplateName() {
return "profanity_regex_not_found_exception";

View File

@@ -3,6 +3,11 @@ package dev.sheldan.abstracto.core.exception;
import dev.sheldan.abstracto.core.templating.Templatable;
public class UnknownMentionTypeException extends AbstractoRunTimeException implements Templatable {
public UnknownMentionTypeException() {
super("Unknown mention type");
}
@Override
public String getTemplateName() {
return "unknown_mention_type_exception";

View File

@@ -4,5 +4,5 @@ import dev.sheldan.abstracto.core.listener.AbstractoListener;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.models.listener.ChannelGroupDeletedListenerModel;
public interface AsyncChannelGroupDeletedListener extends AbstractoListener<ChannelGroupDeletedListenerModel, DefaultListenerResult> {
public interface ChannelGroupDeletedListener extends AbstractoListener<ChannelGroupDeletedListenerModel, DefaultListenerResult> {
}

View File

@@ -11,4 +11,12 @@ public class AServerChannelUserId {
private Long guildId;
private Long channelId;
private Long userId;
public ServerIdChannelId toServerChannelId() {
return ServerIdChannelId.
builder()
.serverId(guildId)
.channelId(channelId)
.build();
}
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.core.models;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class ServerIdChannelId {
private Long serverId;
private Long channelId;
}

View File

@@ -33,7 +33,7 @@ public class AChannelGroup implements Serializable {
@JoinColumn(name = "group_type_id")
private ChannelGroupType channelGroupType;
@OneToMany(mappedBy = "group", fetch = FetchType.LAZY)
@OneToMany(mappedBy = "group", fetch = FetchType.LAZY, orphanRemoval = true)
private List<AChannelGroupCommand> channelGroupCommands;
@Column(name = "created")
@@ -49,5 +49,8 @@ public class AChannelGroup implements Serializable {
inverseJoinColumns = @JoinColumn(name = "channel_id"))
private List<AChannel> channels;
@Column(name = "enabled")
private Boolean enabled;
}

View File

@@ -28,4 +28,10 @@ public class ChannelGroupType {
@Column(name = "updated")
private Instant updated;
@Column(name = "allows_channel_in_multiple")
private Boolean allowsChannelsInMultiple;
@Column(name = "allows_commands_in_multiple")
private Boolean allowsCommandsInMultiple;
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.core.models.exception;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class ChannelInMultipleChannelGroupsExceptionModel {
private String channelGroupName;
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.core.models.exception;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class CommandInMultipleChannelGroupsExceptionModel {
private String channelGroupName;
}

View File

@@ -0,0 +1,4 @@
package dev.sheldan.abstracto.core.models.provider;
public interface ChannelGroupInformation extends ProviderInformation {
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.core.models.provider;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class ChannelGroupInformationRequest implements InformationRequest {
private Long channelGroupId;
private String channelGroupType;
}

View File

@@ -0,0 +1,30 @@
package dev.sheldan.abstracto.core.models.provider;
import dev.sheldan.abstracto.core.models.template.provider.CoolDownChannelInformationModel;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.time.Duration;
@Setter
@Getter
@Builder
public class CoolDownChannelInformation implements ChannelGroupInformation {
private Long channelCoolDown;
private Long memberCoolDown;
@Override
public String getTemplateName() {
return "channel_group_provider_cool_down_display";
}
@Override
public Object getTemplateModel() {
return CoolDownChannelInformationModel
.builder()
.channelCoolDown(Duration.ofSeconds(this.channelCoolDown))
.memberCoolDown(Duration.ofSeconds(this.memberCoolDown))
.build();
}
}

View File

@@ -0,0 +1,4 @@
package dev.sheldan.abstracto.core.models.provider;
public interface InformationRequest {
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.models.provider;
import dev.sheldan.abstracto.core.templating.Templatable;
public interface ProviderInformation extends Templatable {
}

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.core.models.template.commands;
import dev.sheldan.abstracto.core.models.provider.ChannelGroupInformation;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -12,5 +13,7 @@ import java.util.List;
public class ChannelGroupModel {
private String name;
private String typeKey;
private Boolean enabled;
private List<ChannelGroupChannelModel> channels;
private ChannelGroupInformation channelGroupInformation;
}

View File

@@ -1,6 +1,7 @@
package dev.sheldan.abstracto.core.models.template.commands.help;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.CommandCoolDownConfig;
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
import lombok.Getter;
import lombok.Setter;
@@ -19,4 +20,5 @@ public class HelpCommandDetailsModel extends UserInitiatedServerContext {
private List<Role> allowedRoles;
private List<Role> immuneRoles;
private Boolean restricted;
private CommandCoolDownConfig cooldowns;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.models.template.provider;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.time.Duration;
@Getter
@Setter
@Builder
public class CoolDownChannelInformationModel {
private Duration channelCoolDown;
private Duration memberCoolDown;
}

View File

@@ -0,0 +1,5 @@
package dev.sheldan.abstracto.core.provider;
public interface ChannelGroupInformationProvider extends InformationProvider {
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.core.provider;
import dev.sheldan.abstracto.core.models.provider.InformationRequest;
import dev.sheldan.abstracto.core.models.provider.ProviderInformation;
public interface InformationProvider {
<R extends InformationRequest> boolean handlesRequest(R informationRequest);
<I extends ProviderInformation, R extends InformationRequest> I retrieveInformation(R informationRequest);
}

View File

@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
import dev.sheldan.abstracto.core.models.template.commands.ChannelGroupModel;
import net.dv8tion.jda.api.entities.TextChannel;
import java.util.List;
@@ -16,8 +17,11 @@ public interface ChannelGroupService {
void removeChannelFromChannelGroup(String channelGroupName, TextChannel textChannel);
void removeChannelFromChannelGroup(String channelGroupName, Long channelId, Long serverId);
void removeChannelFromChannelGroup(String channelGroupName, AChannel channel);
void disableCommandInChannelGroup(String commandName, String channelGroupName, Long serverId);
void enableCommandInChannelGroup(String commandName, String channelGroupName, Long serverId);
void addCommandToChannelGroup(String commandName, String channelGroupName, Long serverId);
void removeCommandFromChannelGroup(String commandName, String channelGroupName, Long serverId);
void disableChannelGroup(String channelGroupName, Long serverId);
void enableChannelGroup(String channelGroupName, Long serverId);
boolean doesGroupExist(String groupName, Long serverId);
List<AChannelGroup> getChannelGroupsOfChannelWithType(AChannel channel, String groupTypeKey);
List<ChannelGroupModel> convertAChannelGroupToChannelGroupChannel(List<AChannelGroup> channelGroups);
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.command.model.database.CommandDisabledChannelGroup;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
public interface CommandDisabledChannelGroupManagementService {
CommandDisabledChannelGroup createCommandDisabledChannelGroup(AChannelGroup channelGroup);
void deleteCommandDisabledChannelGroup(AChannelGroup channelGroup);
CommandDisabledChannelGroup findViaChannelGroup(AChannelGroup channelGroup);
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.command.model.database.CoolDownChannelGroup;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
public interface CoolDownChannelGroupManagementService {
CoolDownChannelGroup createCoolDownChannelGroup(AChannelGroup aChannelGroup);
CoolDownChannelGroup findByChannelGroupId(Long channelGroupId);
void deleteCoolDownChannelGroup(AChannelGroup aChannelGroup);
}