added assignable role place module including: setting up, configuring, deleting commands and documentation

upgraded JDA version to 4.2.0
refactored multiple interfaces to be more convenient/contain more information (reaction added/removed now gets the actual event)
added generic way to check for conditions. these conditions are provided by modules and are loosely connected via condition context and a condition name
added changeable flag to emotes to indicate that they can be updated via setEmote
refactored emote parsing in command parameters, the command parameters will now contain a fake emote
added feature to embed templates for fields to force a new message regardless of the discord limit
added some more functionality to message and channel service regarding field edit/embed sending
introduced the full emote parameter, to have both the emote (if custom) and a fake aemote at hand
refactored some methods to already throw exceptions within the retrieval methods, instead of optionals which need to be dealt outside
changed getEmotes to getEmotesBag to have duplicates of emotes
fixed setEmote to behave correctly with new parameter types
fixed creation of emotes, which previously created additional instances
fixed templating multiple fields handling
refactored command handling to allow async commands, they are the same interface, but configuration dicates whether or not it is async
added generic exception reporting for async commands
refactored a bunch of service methods to be named optional, and the non optional methods throw exceptions in case nothing is found
added a few more customized exceptions
added clearing freemarker internal template cache to clear cache
added feature to skip, not use, embeds if they look to be empty (no fields, no description, no attachment)
added virtual env to gitignore
fixed initial sync of roles un-marking roles as deleted
added some convenience methods to remove reactions from users directly
fixed post command handling in case it is not a templatable instance
fixed exceptions without cause in generic exception model
This commit is contained in:
Sheldan
2020-07-23 02:22:58 +02:00
parent 5317199bf4
commit fd4d784081
201 changed files with 6547 additions and 527 deletions

3
.gitignore vendored
View File

@@ -23,3 +23,6 @@ target/
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
venv/

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>assignable-roles</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>assignable-roles-impl</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/liquibase.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>assignable-roles-int</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,18 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
<id>liquibase</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<outputDirectory>.</outputDirectory>
<directory>${project.basedir}/src/main/resources/migrations</directory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,52 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class ActivateAssignableRolePlace extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
service.activateAssignableRolePlace(commandContext.getUserInitiatedContext().getServer(), name);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("activateAssignableRolePlace")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,75 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.exceptions.AssignableRoleAlreadyDefinedException;
import dev.sheldan.abstracto.assignableroles.exceptions.AssignableRoleNotUsableException;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.FullEmote;
import dev.sheldan.abstracto.core.models.FullRole;
import dev.sheldan.abstracto.core.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class AddRoleToAssignableRolePost extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Autowired
private RoleService roleService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
FullEmote emote = (FullEmote) parameters.get(1);
String description = (String) parameters.get(2);
FullRole role = (FullRole) parameters.get(3);
if(service.hasAssignableRolePlaceEmote(commandContext.getUserInitiatedContext().getServer(), name, emote.getFakeEmote())) {
throw new AssignableRoleAlreadyDefinedException(emote, name);
}
if(!roleService.canBotInteractWithRole(role.getRole())) {
throw new AssignableRoleNotUsableException(role, commandContext.getGuild());
}
return service.addRoleToAssignableRolePlace(commandContext.getUserInitiatedContext().getServer(), name, role.getRole(), emote, description)
.thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter emote = Parameter.builder().name("emote").type(FullEmote.class).templated(true).build();
Parameter description = Parameter.builder().name("description").type(String.class).templated(true).build();
Parameter role = Parameter.builder().name("role").type(FullRole.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName, emote, description, role);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("addRoleToAssignableRolePlace")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.async(true)
.reportsException(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,18 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.core.command.config.ModuleInfo;
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
public class AssignableRoleModule implements ModuleInterface {
public static final String ASSIGNABLE_ROLES = "assignableRoles";
@Override
public ModuleInfo getInfo() {
return ModuleInfo.builder().name(ASSIGNABLE_ROLES).description("Module containing commands for creating and maintaining assignable role posts.").build();
}
@Override
public String getParentModule() {
return "default";
}
}

View File

@@ -0,0 +1,54 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class ChangeAssignablePlaceDescription extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
String newDescription = (String) parameters.get(1);
service.changeAssignablePlaceDescription(commandContext.getUserInitiatedContext().getServer(), name, newDescription);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter newDescription = Parameter.builder().name("newDescription").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName, newDescription);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("changeAssignablePlaceDescription")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,62 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.AssignableRolePlaceParameterKey;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
public class ChangeAssignableRolePlaceConfig extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
AssignableRolePlaceParameterKey configKey = (AssignableRolePlaceParameterKey) parameters.get(1);
Object parameterValue = parameters.get(2);
return service.changeConfiguration(commandContext.getUserInitiatedContext().getServer(), name, configKey, parameterValue)
.thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter assignableRolePlaceName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter parameterKey = Parameter.builder().name("key").type(AssignableRolePlaceParameterKey.class).templated(true).build();
Parameter parameterValue = Parameter.builder().name("value").type(Object.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(assignableRolePlaceName, parameterKey, parameterValue);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("changeAssignableRolePlaceConfig")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.async(true)
.reportsException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,67 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class CreateAssignableRolePost extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Autowired
private ChannelManagementService channelManagementService;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
MessageChannel channel = (TextChannel) parameters.get(1);
String text = (String) parameters.get(2);
AChannel chosenChannel = channelManagementService.loadChannel(channel.getIdLong());
service.createAssignableRolePlace(commandContext.getUserInitiatedContext().getServer(), name, chosenChannel, text);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter channel = Parameter.builder().name("channel").type(TextChannel.class).templated(true).build();
Parameter text = Parameter.builder().name("text").type(String.class).remainder(true).optional(true).templated(true).build();
List<String> aliases = Arrays.asList("crRPl", "crAssRoPl");
List<Parameter> parameters = Arrays.asList(rolePostName, channel, text);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("createAssignableRolePlace")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.reportsException(true)
.causesReaction(true)
.parameters(parameters)
.aliases(aliases)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,52 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class DeactivateAssignableRolePlace extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
service.deactivateAssignableRolePlace(commandContext.getUserInitiatedContext().getServer(), name);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("deactivateAssignableRolePlace")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,52 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class DeleteAssignableRolePlace extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
service.deleteAssignableRolePlace(commandContext.getUserInitiatedContext().getServer(), name);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("deleteAssignableRolePlace")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,58 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class EditAssignableRolePlaceText extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
String newText = (String) parameters.get(1);
return service.changeText(commandContext.getUserInitiatedContext().getServer(), name, newText).thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter newText = Parameter.builder().name("newText").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName, newText);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("editAssignableRolePlaceText")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.async(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,55 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class MoveAssignableRolePlace extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService placeManagementService;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
TextChannel newChannel = (TextChannel) parameters.get(1);
placeManagementService.moveAssignableRolePlace(commandContext.getUserInitiatedContext().getServer(), name, newChannel);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter channel = Parameter.builder().name("channel").type(TextChannel.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName, channel);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("moveAssignableRolePlace")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,55 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.FullEmote;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class RemoveRoleFromAssignableRolePlace extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
FullEmote emote = (FullEmote) parameters.get(1);
service.removeRoleFromAssignableRolePlace(commandContext.getUserInitiatedContext().getServer(), name, emote);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter emote = Parameter.builder().name("emote").type(FullEmote.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName, emote);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("removeRoleFromAssignableRolePlace")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,63 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.FullEmote;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class SetAssignableRolePosition extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
FullEmote emote = (FullEmote) parameters.get(1);
Integer newPosition = (Integer) parameters.get(2);
if(!service.hasAssignableRolePlaceEmote(commandContext.getUserInitiatedContext().getServer(), name, emote.getFakeEmote())) {
return CommandResult.fromError("Place does not have emote assigned.");
}
if(service.isPositionUsed(commandContext.getUserInitiatedContext().getServer(), name, newPosition)) {
return CommandResult.fromError("Position is already used");
}
service.setEmoteToPosition(commandContext.getUserInitiatedContext().getServer(), name, emote, newPosition);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter emote = Parameter.builder().name("emote").type(FullEmote.class).templated(true).build();
Parameter newPosition = Parameter.builder().name("newPosition").type(Integer.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName, emote, newPosition);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("setAssignableRolePosition")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,61 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.service.ChannelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
public class SetupAssignableRolePlace extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Autowired
private ChannelService channelService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
return service.setupAssignableRolePlace(commandContext.getUserInitiatedContext().getServer(), name)
.thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("setupAssignableRolePlace")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.async(true)
.reportsException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,53 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class ShowAssignableRolePlaceConfig extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
service.showAssignablePlaceConfig(commandContext.getUserInitiatedContext().getServer(), name, commandContext.getChannel());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("showAssignableRolePlaceConfig")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,47 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.CompletableFuture;
@Component
public class ShowAssignableRolePlaces extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
return service.showAllAssignableRolePlaces(commandContext.getUserInitiatedContext().getServer(), commandContext.getChannel())
.thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("showAssignableRolePlaces")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.async(true)
.reportsException(true)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,73 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.exceptions.EmoteNotInAssignableRolePlaceException;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.FullEmote;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.EmoteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class SwapAssignableRolePosition extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Autowired
private EmoteService emoteService;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
FullEmote firstEmote = (FullEmote) parameters.get(1);
FullEmote secondEmote = (FullEmote) parameters.get(2);
AServer server = commandContext.getUserInitiatedContext().getServer();
if(emoteService.compareAEmote(firstEmote.getFakeEmote(), secondEmote.getFakeEmote())) {
return CommandResult.fromError("You cannot swap the same emote");
}
if(!service.hasAssignableRolePlaceEmote(server, name, firstEmote.getFakeEmote())) {
throw new EmoteNotInAssignableRolePlaceException(firstEmote, name);
}
if(!service.hasAssignableRolePlaceEmote(server, name, firstEmote.getFakeEmote())) {
throw new EmoteNotInAssignableRolePlaceException(secondEmote, name);
}
service.swapPositions(server, name, firstEmote, secondEmote);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter firstEmote = Parameter.builder().name("firstEmote").type(FullEmote.class).templated(true).build();
Parameter secondEmote = Parameter.builder().name("secondEmote").type(FullEmote.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName, firstEmote, secondEmote);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("swapAssignableRolePosition")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,52 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class TestAssignableRolePlace extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
service.testAssignableRolePlace(commandContext.getUserInitiatedContext().getServer(), name, commandContext.getChannel());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("testAssignableRolePlace")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,40 @@
package dev.sheldan.abstracto.assignableroles.listener;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlacePost;
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRolePlacePostManagementService;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.listener.MessageDeletedListener;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.core.models.GuildChannelMember;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
@Slf4j
public class AssignablePostDeletedListener implements MessageDeletedListener {
@Autowired
private AssignableRolePlacePostManagementService service;
@Override
public void execute(CachedMessage messageBefore, AServerAChannelAUser authorUser, GuildChannelMember authorMember) {
Optional<AssignableRolePlacePost> messageOptional = service.findByMessageIdOptional(messageBefore.getMessageId());
messageOptional.ifPresent(post -> {
AssignableRolePlace assignablePlace = post.getAssignablePlace();
log.info("Post {} has been deleted in server {} in channel {}, we are removing a post from place {}.", post.getId(), messageBefore.getServerId(), messageBefore.getChannelId(), assignablePlace.getKey());
post.getAssignableRoles().forEach(assignableRole -> assignableRole.setAssignableRolePlacePost(null));
assignablePlace.getMessagePosts().remove(post);
});
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,106 @@
package dev.sheldan.abstracto.assignableroles.listener;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRole;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlacePost;
import dev.sheldan.abstracto.assignableroles.models.database.AssignedRoleUser;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.assignableroles.service.AssignableRoleServiceBean;
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRolePlacePostManagementService;
import dev.sheldan.abstracto.assignableroles.service.management.AssignedRoleUserManagementService;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.listener.ReactedAddedListener;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.EmoteService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.MessageReaction;
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
public class AssignablePostReactionAdded implements ReactedAddedListener {
@Autowired
private AssignableRolePlacePostManagementService service;
@Autowired
private AssignableRoleServiceBean assignableRoleServiceBean;
@Autowired
private EmoteService emoteService;
@Autowired
private AssignableRolePlaceService assignableRolePlaceService;
@Autowired
private AssignedRoleUserManagementService assignedRoleUserManagementService;
@Override
public void executeReactionAdded(CachedMessage message, GuildMessageReactionAddEvent event, AUserInAServer userAdding) {
Optional<AssignableRolePlacePost> messageOptional = service.findByMessageIdOptional(message.getMessageId());
if(messageOptional.isPresent()) {
MessageReaction reaction = event.getReaction();
AssignableRolePlacePost assignablePlacePost = messageOptional.get();
if(reaction.isSelf()) {
log.info("Ignoring self reaction on assignable role post in server {}.", message.getServerId());
return;
}
MessageReaction.ReactionEmote reactionEmote = event.getReactionEmote();
if(assignablePlacePost.getAssignablePlace().getActive()) {
addAppropriateRoles(event, reaction, assignablePlacePost, reactionEmote, userAdding);
} else {
reaction.removeReaction(event.getUser()).submit();
log.trace("Reaction for assignable place {} in sever {} was added, but place is inactive.", assignablePlacePost.getAssignablePlace().getKey(), userAdding.getServerReference().getId());
}
}
}
private void addAppropriateRoles(GuildMessageReactionAddEvent event, MessageReaction reaction, AssignableRolePlacePost assignablePlacePost, MessageReaction.ReactionEmote reactionEmote, AUserInAServer userAdding) {
boolean validReaction = false;
AssignableRolePlace assignableRolePlace = assignablePlacePost.getAssignablePlace();
for (AssignableRole assignableRole : assignablePlacePost.getAssignableRoles()) {
if (emoteService.isReactionEmoteAEmote(reactionEmote, assignableRole.getEmote())) {
CompletableFuture<Void> future;
if(assignableRolePlace.getUniqueRoles()) {
Optional<AssignedRoleUser> byUserInServer = assignedRoleUserManagementService.findByUserInServerOptional(userAdding);
if(byUserInServer.isPresent()){
future = assignableRolePlaceService.removeExistingReactionsAndRoles(assignableRolePlace, byUserInServer.get());
} else {
future = CompletableFuture.completedFuture(null);
}
} else {
future = CompletableFuture.completedFuture(null);
}
Long assignableRoleId = assignableRole.getId();
future.whenComplete((aVoid, throwable) -> {
if(throwable != null) {
log.warn("Failed to remove previous role assignments for {} in server {} at place {}.",
userAdding.getUserReference().getId(), userAdding.getServerReference().getId(), assignablePlacePost.getAssignablePlace().getKey());
}
assignableRoleServiceBean.assignAssignableRoleToUser(assignableRoleId, event.getMember()).exceptionally(innerThrowable -> {
log.error("Failed to add new role assignment.", innerThrowable);
return null;
});
});
validReaction = true;
break;
}
}
if(!validReaction || assignableRolePlace.getAutoRemove()) {
reaction.removeReaction(event.getUser()).submit();
}
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -0,0 +1,63 @@
package dev.sheldan.abstracto.assignableroles.listener;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlacePost;
import dev.sheldan.abstracto.assignableroles.service.AssignableRoleService;
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRolePlacePostManagementService;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.listener.ReactedRemovedListener;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.EmoteService;
import dev.sheldan.abstracto.core.service.RoleService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.MessageReaction;
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionRemoveEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
@Slf4j
public class AssignablePostReactionRemoved implements ReactedRemovedListener {
@Autowired
private AssignableRolePlacePostManagementService service;
@Autowired
private EmoteService emoteService;
@Autowired
private RoleService roleService;
@Autowired
private AssignableRoleService assignableRoleService;
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
@Override
public void executeReactionRemoved(CachedMessage message, GuildMessageReactionRemoveEvent event, AUserInAServer userRemoving) {
Optional<AssignableRolePlacePost> messageOptional = service.findByMessageIdOptional(message.getMessageId());
if(messageOptional.isPresent()) {
MessageReaction.ReactionEmote reactionEmote = event.getReactionEmote();
AssignableRolePlacePost assignablePlacePost = messageOptional.get();
if(assignablePlacePost.getAssignablePlace().getActive()) {
assignablePlacePost.getAssignableRoles().forEach(assignableRole -> {
if(emoteService.isReactionEmoteAEmote(reactionEmote, assignableRole.getEmote())) {
Long assignableRoleId = assignableRole.getId();
assignableRoleService.removeAssignableRoleFromUser(assignableRole, event.getMember()).exceptionally(throwable -> {
log.error("Failed to remove assignable role {} from user {}.", assignableRoleId, event.getMember(), throwable);
return null;
});
}
});
} else {
log.trace("Reaction for assignable place {} in sever {} was added, but place is inactive.", assignablePlacePost.getAssignablePlace().getKey(), userRemoving.getServerReference().getId());
}
}
}
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.assignableroles.repository;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlacePost;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AssignableRolePlacePostRepository extends JpaRepository<AssignableRolePlacePost, Long> {
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.assignableroles.repository;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.core.models.database.AServer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface AssignableRolePlaceRepository extends JpaRepository<AssignableRolePlace, Long> {
boolean existsByServerAndKey(AServer server, String key);
Optional<AssignableRolePlace> findByServerAndKey(AServer server, String key);
List<AssignableRolePlace> findByServer(AServer server);
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.assignableroles.repository;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRole;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AssignableRoleRepository extends JpaRepository<AssignableRole, Long> {
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.assignableroles.repository;
import dev.sheldan.abstracto.assignableroles.models.database.AssignedRoleUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AssignedRoleUserRepository extends JpaRepository<AssignedRoleUser, Long> {
}

View File

@@ -0,0 +1,751 @@
package dev.sheldan.abstracto.assignableroles.service;
import dev.sheldan.abstracto.assignableroles.config.AssignableRolePlaceParameterKey;
import dev.sheldan.abstracto.assignableroles.exceptions.AssignableRolePlaceAlreadyExistsException;
import dev.sheldan.abstracto.assignableroles.exceptions.AssignableRolePlaceChannelDoesNotExist;
import dev.sheldan.abstracto.assignableroles.exceptions.EmoteNotInAssignableRolePlaceException;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRole;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlacePost;
import dev.sheldan.abstracto.assignableroles.models.database.AssignedRoleUser;
import dev.sheldan.abstracto.assignableroles.models.templates.*;
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRoleManagementService;
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRolePlaceManagementService;
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRolePlacePostManagementService;
import dev.sheldan.abstracto.core.command.exception.CommandParameterKeyValueWrongTypeException;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.exception.EmoteNotUsableException;
import dev.sheldan.abstracto.core.models.FullEmote;
import dev.sheldan.abstracto.core.models.database.*;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.EmoteService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.management.*;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.*;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
@Component
@Slf4j
public class AssignableRolePlaceServiceBean implements AssignableRolePlaceService {
public static final String ASSIGNABLE_ROLES_CONFIG_POST_TEMPLATE_KEY = "assignable_roles_config_post";
public static final String ASSIGNABLE_ROLES_POST_TEMPLATE_KEY = "assignable_roles_post";
public static final String ASSIGNABLE_ROLE_PLACES_OVERVIEW_TEMPLATE_KEY = "assignable_role_places_overview";
@Autowired
private AssignableRolePlaceManagementService rolePlaceManagementService;
@Autowired
private AssignableRoleManagementService assignableRoleManagementServiceBean;
@Autowired
private MessageService messageService;
@Autowired
private ChannelService channelService;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private BotService botService;
@Autowired
private EmoteService emoteService;
@Autowired
private AssignableRolePlaceServiceBean self;
@Autowired
private TemplateService templateService;
@Autowired
private EmoteManagementService emoteManagementService;
@Autowired
private AssignableRolePlacePostManagementService postManagementService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private RoleManagementService roleManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private AssignableRoleService roleService;
@Override
public void createAssignableRolePlace(AServer server, String name, AChannel channel, String text) {
if(rolePlaceManagementService.doesPlaceExist(server, name)) {
throw new AssignableRolePlaceAlreadyExistsException(name);
}
rolePlaceManagementService.createPlace(server, name, channel, text);
}
@Override
public boolean hasAssignableRolePlaceEmote(AServer server, String placeName, AEmote emote) {
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByServerAndKey(server, placeName);
return hasAssignableRolePlaceEmote(assignableRolePlace, emote);
}
@Override
public boolean isPositionUsed(AServer server, String placeName, Integer position) {
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByServerAndKey(server, placeName);
return assignableRolePlace.getAssignableRoles().stream().anyMatch(role -> role.getPosition().equals(position));
}
@Override
public CompletableFuture<Void> setEmoteToPosition(AServer server, String placeName, FullEmote emote, Integer position) {
Integer emoteId = emote.getFakeEmote().getId();
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByServerAndKey(server, placeName);
Optional<AssignableRole> emoteOptional = assignableRolePlace.getAssignableRoles().stream().filter(role -> role.getEmote().getId().equals(emoteId)).findFirst();
if(emoteOptional.isPresent()) {
AssignableRole toChange = emoteOptional.get();
toChange.setPosition(position);
}
throw new EmoteNotInAssignableRolePlaceException(emote, placeName);
}
@Override
public boolean hasAssignableRolePlaceEmote(AssignableRolePlace place, AEmote emote) {
for (AssignableRole assignableRole : place.getAssignableRoles()) {
if(emoteService.compareAEmote(assignableRole.getEmote(), emote)) {
return true;
}
}
return false;
}
@Override
public CompletableFuture<Void> addRoleToAssignableRolePlace(AServer server, String placeName, ARole role, FullEmote fakeEmote, String description) {
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByServerAndKey(server, placeName);
Long placeId = assignableRolePlace.getId();
Long roleId = role.getId();
Long serverId = server.getId();
boolean emoteUsable = true;
if(fakeEmote.getEmote() != null) {
// it only may be unusable if its a custom emote
emoteUsable = emoteService.isEmoteUsableByBot(fakeEmote.getEmote()) && fakeEmote.getEmote().isAvailable();
}
if(emoteUsable) {
AEmote createdEmote = emoteManagementService.createEmote(null, fakeEmote.getFakeEmote(), server.getId(), false);
Integer emoteId = createdEmote.getId();
List<AssignableRolePlacePost> existingMessagePosts = assignableRolePlace.getMessagePosts();
existingMessagePosts.sort(Comparator.comparingLong(AssignableRolePlacePost::getId));
createdEmote.setChangeable(false);
if(!assignableRolePlace.getMessagePosts().isEmpty()){
AssignableRolePlacePost latestPost = existingMessagePosts.get(assignableRolePlace.getMessagePosts().size() - 1);
AssignablePostMessage model = prepareAssignablePostMessageModel(assignableRolePlace);
AssignablePostRole newAssignableRole = AssignablePostRole
.builder()
.description(description)
.emote(fakeEmote)
.forceNewMessage(latestPost.getAssignableRoles().size() >= 20)
.build();
model.getRoles().add(newAssignableRole);
MessageToSend messageToSend = templateService.renderEmbedTemplate(ASSIGNABLE_ROLES_POST_TEMPLATE_KEY, model);
// add it to the last currently existing post
Optional<TextChannel> channelOptional = channelService.getTextChannelInGuild(server.getId(), latestPost.getUsedChannel().getId());
if(channelOptional.isPresent()) {
TextChannel textChannel = channelOptional.get();
if(latestPost.getAssignableRoles().size() < 20) {
return addReactionToExistingAssignableRolePlacePost(fakeEmote, description, assignableRolePlace, placeId, roleId, serverId, emoteId, latestPost, messageToSend, textChannel);
} else {
return addNewMessageToAssignableRolePlace(placeName, fakeEmote, description, roleId, serverId, emoteId, messageToSend, textChannel);
}
} else {
throw new ChannelNotFoundException(latestPost.getUsedChannel().getId());
}
} else {
log.info("Added emote to assignable place {} in server {}, but no message post yet.", placeName, serverId);
self.addAssignableRoleInstanceWithoutPost(placeId, roleId, emoteId, description);
}
} else {
throw new EmoteNotUsableException(fakeEmote.getEmote());
}
return CompletableFuture.completedFuture(null);
}
private CompletableFuture<Void> addReactionToExistingAssignableRolePlacePost(FullEmote fakeEmote, String description, AssignableRolePlace assignableRolePlace, Long placeId, Long roleId, Long serverId, Integer emoteId, AssignableRolePlacePost latestPost, MessageToSend messageToSend, TextChannel textChannel) {
return textChannel.retrieveMessageById(latestPost.getId()).submit()
.thenCompose(message -> messageService.addReactionToMessageWithFuture(fakeEmote.getFakeEmote(), serverId, message))
.thenCompose(aVoid -> {
MessageEmbed embedToUse = messageToSend.getEmbeds().get(assignableRolePlace.getMessagePosts().size() - 1);
return channelService.editEmbedMessageInAChannel(embedToUse, textChannel, latestPost.getId());
})
.thenCompose(message -> {
self.addAssignableRoleInstanceWithPost(message.getIdLong(), placeId, roleId, emoteId, description);
return CompletableFuture.completedFuture(null);
});
}
private CompletableFuture<Void> addNewMessageToAssignableRolePlace(String placeName, FullEmote fakeEmote, String description, Long roleId, Long serverId, Integer emoteId, MessageToSend messageToSend, TextChannel textChannel) {
MessageEmbed embedToUse = messageToSend.getEmbeds().get(messageToSend.getEmbeds().size() - 1);
return channelService.sendEmbedToChannel(embedToUse, textChannel)
.thenCompose(message -> messageService.addReactionToMessageWithFuture(fakeEmote.getFakeEmote(), serverId, message).thenAccept(aVoid ->
self.addNewlyCreatedAssignablePlacePost(placeName, description, roleId, serverId, emoteId, textChannel, message)
));
}
@Transactional
public void addNewlyCreatedAssignablePlacePost(String placeName, String description,Long roleId, Long serverId, Integer emoteId, TextChannel textChannel, Message message) {
AChannel loadedChannel = channelManagementService.loadChannel(textChannel.getIdLong());
AServer loadedServer = serverManagementService.loadOrCreate(serverId);
ARole role = roleManagementService.findRole(roleId);
AEmote emote = emoteManagementService.loadEmote(emoteId);
AssignableRolePlace loadedPlace = rolePlaceManagementService.findByServerAndKey(loadedServer, placeName);
AssignableRolePlacePost newPost = AssignableRolePlacePost
.builder()
.id(message.getIdLong())
.usedChannel(loadedChannel)
.assignablePlace(loadedPlace)
.build();
loadedPlace.getMessagePosts().add(newPost);
assignableRoleManagementServiceBean.addRoleToPlace(loadedPlace, emote, role, description, newPost);
}
@Transactional
public void addAssignableRoleInstanceWithPost(Long messageId, Long placeId, Long roleId, Integer emoteId, String description) {
assignableRoleManagementServiceBean.addRoleToPlace(placeId, emoteId, roleId, description, messageId);
}
@Transactional
public void addAssignableRoleInstanceWithoutPost(Long placeId, Long roleId, Integer emoteId, String description) {
assignableRoleManagementServiceBean.addRoleToPlace(placeId, emoteId, roleId, description);
}
@Override
public CompletableFuture<Void> removeRoleFromAssignableRolePlace(AServer server, String placeName, FullEmote emote) {
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByServerAndKey(server, placeName);
for (AssignableRole assignableRole : assignableRolePlace.getAssignableRoles()) {
if(emoteService.compareAEmote(assignableRole.getEmote(), emote.getFakeEmote())) {
return removeRoleFromAssignablePlace(assignableRole, assignableRolePlace).thenAccept(aVoid ->
self.deleteAssignableRoleFromPlace(server.getId(), placeName, assignableRole.getId())
);
}
}
return CompletableFuture.completedFuture(null);
}
@Transactional
public void deleteAssignableRoleFromPlace(Long serverId, String placeName, Long assignableRoleId) {
AServer server = serverManagementService.loadOrCreate(serverId);
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByServerAndKey(server, placeName);
Optional<AssignableRole> roleToRemoveOptional = assignableRolePlace.getAssignableRoles().stream().filter(role -> role.getId().equals(assignableRoleId)).findAny();
roleToRemoveOptional.ifPresent(assignableRole -> {
assignableRolePlace.getAssignableRoles().remove(assignableRole);
assignableRole.setAssignablePlace(null);
});
}
private CompletableFuture<Void> removeRoleFromAssignablePlace(AssignableRole role, AssignableRolePlace assignableRolePlace) {
AssignableRolePlacePost post = role.getAssignableRolePlacePost();
if(post != null) {
AServer server = assignableRolePlace.getServer();
TextChannel textChannel = botService.getTextChannelFromServer(server.getId(), post.getUsedChannel().getId());
List<AssignableRole> assignableRoles = assignableRolePlace.getAssignableRoles();
assignableRoles.sort(Comparator.comparing(AssignableRole::getPosition));
Long messageId = post.getId();
CompletableFuture<Message> fieldEditing = channelService.removeFieldFromMessage(textChannel, messageId, assignableRoles.indexOf(role));
CompletableFuture<Void> reactionRemoval = messageService.clearReactionFromMessageWithFuture(role.getEmote(), assignableRolePlace.getServer().getId(), role.getAssignableRolePlacePost().getUsedChannel().getId(), role.getAssignableRolePlacePost().getId());
return CompletableFuture.allOf(fieldEditing, reactionRemoval);
} else {
// this case comes from the situation in which, the emote was deleted ant he initial post setup failed
log.warn("Reaction {} to remove does not have a post attached. The post needs to be setup again, it is most likely not functioning currently anyway.", role.getEmote().getEmoteId());
return CompletableFuture.completedFuture(null);
}
}
@Override
public CompletableFuture<Void> setupAssignableRolePlace(AServer server, String name) {
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByServerAndKey(server, name);
List<CompletableFuture<Void>> oldPostDeletionFutures = deleteExistingMessagePostsForPlace(assignableRolePlace);
assignableRolePlace.getMessagePosts().clear();
assignableRolePlace.getAssignableRoles().forEach(assignableRole ->
assignableRole.setAssignableRolePlacePost(null)
);
Long serverId = server.getId();
return CompletableFuture.allOf(oldPostDeletionFutures.toArray(new CompletableFuture[0]))
.thenCompose(aVoid -> self.createAssignableRolePlacePosts(serverId, name));
}
@Override
public CompletableFuture<Void> refreshAssignablePlacePosts(AServer server, String name) {
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByServerAndKey(server, name);
return refreshAssignablePlacePosts(assignableRolePlace);
}
@Override
public CompletableFuture<Void> refreshAssignablePlacePosts(AssignableRolePlace place) {
MessageToSend messageToSend = renderAssignablePlacePosts(place);
List<AssignableRolePlacePost> existingMessagePosts = place.getMessagePosts();
existingMessagePosts.sort(Comparator.comparingLong(AssignableRolePlacePost::getId));
AssignableRolePlacePost latestPost = existingMessagePosts.get(place.getMessagePosts().size() - 1);
List<CompletableFuture<Message>> futures = new ArrayList<>();
Optional<TextChannel> channelOptional = channelService.getTextChannelInGuild(place.getServer().getId(), latestPost.getUsedChannel().getId());
if(channelOptional.isPresent()) {
TextChannel textChannel = channelOptional.get();
Iterator<MessageEmbed> iterator = messageToSend.getEmbeds().iterator();
place.getMessagePosts().forEach(post -> {
CompletableFuture<Message> messageCompletableFuture = channelService.editEmbedMessageInAChannel(iterator.next(), textChannel, post.getId());
futures.add(messageCompletableFuture);
});
}
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
}
@Override
public CompletableFuture<Void> refreshTextFromPlace(AssignableRolePlace place) {
List<AssignableRolePlacePost> existingMessagePosts = place.getMessagePosts();
if(!existingMessagePosts.isEmpty()) {
MessageToSend renderedMessage = renderAssignablePlacePosts(place);
existingMessagePosts.sort(Comparator.comparingLong(AssignableRolePlacePost::getId));
AssignableRolePlacePost latestPost = existingMessagePosts.get(0);
Long channelId = latestPost.getUsedChannel().getId();
Optional<TextChannel> channelOptional = channelService.getTextChannelInGuild(place.getServer().getId(), channelId);
if(channelOptional.isPresent()) {
return channelService.editEmbedMessageInAChannel(renderedMessage.getEmbeds().get(0), channelOptional.get(), latestPost.getId()).thenCompose(message -> CompletableFuture.completedFuture(null));
}
throw new ChannelNotFoundException(channelId);
}
return CompletableFuture.completedFuture(null);
}
@Override
public void setAssignablePlaceActiveTo(AServer server, String name, Boolean newValue) {
AssignableRolePlace place = rolePlaceManagementService.findByServerAndKey(server, name);
if(newValue) {
this.activateAssignableRolePlace(place);
} else {
this.deactivateAssignableRolePlace(place);
}
}
private List<CompletableFuture<Void>> deleteExistingMessagePostsForPlace(AssignableRolePlace assignableRolePlace) {
List<CompletableFuture<Void>> oldPostDeletionFutures = new ArrayList<>();
assignableRolePlace.getMessagePosts().forEach(assignableRolePlacePost ->
oldPostDeletionFutures.add(messageService.deleteMessageInChannelInServer(assignableRolePlace.getServer().getId(), assignableRolePlacePost.getUsedChannel().getId(), assignableRolePlacePost.getId()))
);
return oldPostDeletionFutures;
}
@Override
public void deactivateAssignableRolePlace(AServer server, String name) {
setAssignablePlaceActiveTo(server, name, false);
}
@Override
public void deactivateAssignableRolePlace(AssignableRolePlace place) {
place.setActive(false);
log.info("Deactivating assignable role place {} in server {}", place.getId(), place.getServer().getId());
}
@Override
public void activateAssignableRolePlace(AServer server, String name) {
setAssignablePlaceActiveTo(server, name, true);
}
@Override
public void activateAssignableRolePlace(AssignableRolePlace place) {
place.setActive(true);
log.info("Activating assignable role place {} in server {}", place.getId(), place.getServer().getId());
}
@Override
public CompletableFuture<Void> setAssignablePlaceInlineTo(AServer server, String name, Boolean newValue) {
AssignableRolePlace place = rolePlaceManagementService.findByServerAndKey(server, name);
if(newValue) {
return this.inlineAssignableRolePlace(place);
} else {
return this.spreadAssignableRolePlace(place);
}
}
@Override
public CompletableFuture<Void> inlineAssignableRolePlace(AServer server, String name) {
return setAssignablePlaceInlineTo(server, name, true);
}
@Override
public CompletableFuture<Void> inlineAssignableRolePlace(AssignableRolePlace place) {
log.info("Setting assignable role place inline {} in server {} to {}", place.getId(), place.getServer().getId(), true);
place.setInline(true);
return refreshAssignablePlacePosts(place);
}
@Override
public CompletableFuture<Void> spreadAssignableRolePlace(AServer server, String name) {
return setAssignablePlaceInlineTo(server, name, false);
}
@Override
public CompletableFuture<Void> spreadAssignableRolePlace(AssignableRolePlace place) {
log.info("Setting assignable role place inline {} in server {} to {}", place.getId(), place.getServer().getId(), false);
place.setInline(false);
return refreshAssignablePlacePosts(place);
}
@Override
public void setAssignablePlaceUniqueTo(AServer server, String name, Boolean newValue) {
AssignableRolePlace place = rolePlaceManagementService.findByServerAndKey(server, name);
if(newValue) {
this.uniqueAssignableRolePlace(place);
} else {
this.multipleAssignableRolePlace(place);
}
}
@Override
public void uniqueAssignableRolePlace(AServer server, String name) {
setAssignablePlaceInlineTo(server, name, true);
}
@Override
public void uniqueAssignableRolePlace(AssignableRolePlace place) {
log.info("Setting assignable role place uniqueness {} in server {} to {}", place.getId(), place.getServer().getId(), true);
place.setUniqueRoles(true);
}
@Override
public void multipleAssignableRolePlace(AServer server, String name) {
setAssignablePlaceInlineTo(server, name, false);
}
@Override
public void multipleAssignableRolePlace(AssignableRolePlace place) {
log.info("Setting assignable role place uniqueness {} in server {} to {}", place.getId(), place.getServer().getId(), false);
place.setUniqueRoles(false);
}
@Override
public void setAssignablePlaceAutoRemoveTo(AServer server, String name, Boolean newValue) {
AssignableRolePlace place = rolePlaceManagementService.findByServerAndKey(server, name);
if(newValue) {
this.autoRemoveAssignableRolePlace(place);
} else {
this.keepReactionsAssignableRolePlace(place);
}
}
@Override
public void autoRemoveAssignableRolePlace(AServer server, String name) {
setAssignablePlaceAutoRemoveTo(server, name, true);
}
@Override
public void autoRemoveAssignableRolePlace(AssignableRolePlace place) {
log.info("Setting assignable role place auto remove {} in server {} to {}", place.getId(), place.getServer().getId(), true);
place.setAutoRemove(true);
}
@Override
public void keepReactionsAssignableRolePlace(AServer server, String name) {
setAssignablePlaceAutoRemoveTo(server, name, false);
}
@Override
public void keepReactionsAssignableRolePlace(AssignableRolePlace place) {
log.info("Setting assignable role place auto remove {} in server {} to {}", place.getId(), place.getServer().getId(), false);
place.setAutoRemove(false);
}
@Override
public void swapPositions(AServer server, String name, FullEmote firstEmote, FullEmote secondEmote) {
AssignableRolePlace place = rolePlaceManagementService.findByServerAndKey(server, name);
Optional<AssignableRole> firstEmoteOptional = place.getAssignableRoles().stream().filter(role -> emoteService.compareAEmote(role.getEmote(), firstEmote.getFakeEmote())).findFirst();
Optional<AssignableRole> secondEmoteOptional = place.getAssignableRoles().stream().filter(role -> emoteService.compareAEmote(role.getEmote(), secondEmote.getFakeEmote())).findFirst();
if(firstEmoteOptional.isPresent() && secondEmoteOptional.isPresent()) {
AssignableRole firstRole = firstEmoteOptional.get();
AssignableRole secondRole = secondEmoteOptional.get();
int firstPosition = firstRole.getPosition();
firstRole.setPosition(secondRole.getPosition());
secondRole.setPosition(firstPosition);
} else {
if(!firstEmoteOptional.isPresent()) {
throw new EmoteNotInAssignableRolePlaceException(firstEmote, name);
} else {
throw new EmoteNotInAssignableRolePlaceException(secondEmote, name);
}
}
}
@Override
public CompletableFuture<Void> testAssignableRolePlace(AServer server, String name, MessageChannel channel) {
AssignableRolePlace place = rolePlaceManagementService.findByServerAndKey(server, name);
MessageToSend messageToSend = renderAssignablePlacePosts(place);
List<CompletableFuture<Message>> completableFutures = channelService.sendMessageToSendToChannel(messageToSend, channel);
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]));
}
@Override
public void showAssignablePlaceConfig(AServer server, String name, MessageChannel channel) {
AssignableRolePlace place = rolePlaceManagementService.findByServerAndKey(server, name);
List<AssignablePostConfigRole> roles = new ArrayList<>();
Guild guild = botService.getGuildByIdNullable(server.getId());
List<AssignableRole> assignableRoles = place.getAssignableRoles().stream().sorted(Comparator.comparingInt(AssignableRole::getPosition)).collect(Collectors.toList());
for (AssignableRole role : assignableRoles) {
AEmote emoteForRole = role.getEmote();
Emote jdaEmoteForRole = botService.getEmote(emoteForRole).orElse(null);
Role jdaRole = guild.getRoleById(role.getRole().getId());
AssignablePostConfigRole postRole = AssignablePostConfigRole
.builder()
.description(role.getDescription())
.emote(jdaEmoteForRole)
.position(role.getPosition())
.awardedRole(jdaRole)
.build();
roles.add(postRole);
}
AssignableRolePlaceConfig configModel = AssignableRolePlaceConfig
.builder()
.roles(roles)
.place(place)
.build();
channelService.sendEmbedTemplateInChannel(ASSIGNABLE_ROLES_CONFIG_POST_TEMPLATE_KEY, configModel, channel);
}
@Override
public void moveAssignableRolePlace(AServer server, String name, TextChannel newChannel) {
AChannel channel = channelManagementService.loadChannel(newChannel.getIdLong());
rolePlaceManagementService.moveAssignableRolePlace(server, name, channel);
}
@Override
public void changeAssignablePlaceDescription(AServer server, String name, String newDescription) {
rolePlaceManagementService.changeAssignableRolePlaceDescription(server, name, newDescription);
}
@Override
public CompletableFuture<Void> deleteAssignableRolePlace(AServer server, String name) {
AssignableRolePlace place = rolePlaceManagementService.findByServerAndKey(server, name);
rolePlaceManagementService.deleteAssignablePlace(place);
deleteEmotesFromAssignableRolePlace(place);
List<CompletableFuture<Void>> deleteFutures = deleteExistingMessagePostsForPlace(place);
return CompletableFuture.allOf(deleteFutures.toArray(new CompletableFuture[0]));
}
@Override
public CompletableFuture<Void> changeText(AServer server, String name, String newText) {
AssignableRolePlace place = rolePlaceManagementService.findByServerAndKey(server, name);
place.setText(newText);
return refreshTextFromPlace(place);
}
@Override
public CompletableFuture<Void> removeExistingReactionsAndRoles(AssignableRolePlace place, AssignedRoleUser user) {
Member memberInServer = botService.getMemberInServer(user.getUser());
List<CompletableFuture<Void>> futures = new ArrayList<>();
user.getRoles().forEach(assignableRole -> {
futures.add(roleService.removeAssignableRoleFromUser(assignableRole, memberInServer));
AEmote emoteToUseObject = emoteManagementService.loadEmote(assignableRole.getEmote().getId());
AssignableRolePlacePost assignablePlacePost = assignableRole.getAssignableRolePlacePost();
futures.add(messageService.removeReactionOfUserFromMessageWithFuture(emoteToUseObject, place.getServer().getId(),
assignablePlacePost.getUsedChannel().getId(), assignablePlacePost.getId(), memberInServer));
});
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
}
@Override
public CompletableFuture<Void> changeConfiguration(AServer server, String name, AssignableRolePlaceParameterKey keyToChange, Object newValue) {
Boolean booleanValue = BooleanUtils.toBooleanObject(newValue.toString());
if(booleanValue == null) {
throwBooleanParameterKeyException();
}
switch (keyToChange) {
case INLINE:
return setAssignablePlaceInlineTo(server, name, booleanValue);
case AUTOREMOVE:
setAssignablePlaceAutoRemoveTo(server, name, booleanValue);
return CompletableFuture.completedFuture(null);
case UNIQUE:
setAssignablePlaceUniqueTo(server, name, booleanValue);
return CompletableFuture.completedFuture(null);
case ACTIVE:
setAssignablePlaceActiveTo(server, name, booleanValue);
return CompletableFuture.completedFuture(null);
default:
throw new IllegalArgumentException("Illegal assignable role place parameter key was passed.");
}
}
@Override
public CompletableFuture<Void> showAllAssignableRolePlaces(AServer server, MessageChannel channel) {
List<AssignableRolePlace> assignableRolePlaces = rolePlaceManagementService.findAllByServer(server);
AssignablePlaceOverview overViewModel = AssignablePlaceOverview.builder().places(assignableRolePlaces).build();
List<CompletableFuture<Message>> promises = channelService.sendEmbedTemplateInChannel(ASSIGNABLE_ROLE_PLACES_OVERVIEW_TEMPLATE_KEY, overViewModel, channel);
return CompletableFuture.allOf(promises.toArray(new CompletableFuture[0]));
}
private void throwBooleanParameterKeyException() {
throw new CommandParameterKeyValueWrongTypeException(Arrays.asList("yes", "no", "true", "false", "on", "off"));
}
private void deleteEmotesFromAssignableRolePlace(AssignableRolePlace place) {
place.getAssignableRoles().forEach(role ->
emoteManagementService.deleteEmote(role.getEmote())
);
}
private List<CompletableFuture<Message>> sendAssignablePostMessages(AssignableRolePlace place, MessageChannel channel) {
MessageToSend messageToSend = renderAssignablePlacePosts(place);
return channelService.sendMessageToSendToChannel(messageToSend, channel);
}
private MessageToSend renderAssignablePlacePosts(AssignableRolePlace place) {
AssignablePostMessage model = prepareAssignablePostMessageModel(place);
return templateService.renderEmbedTemplate(ASSIGNABLE_ROLES_POST_TEMPLATE_KEY, model);
}
private AssignablePostMessage prepareAssignablePostMessageModel(AssignableRolePlace place) {
List<AssignablePostRole> roles = new ArrayList<>();
List<AssignableRole> rolesToAdd = place.getAssignableRoles().stream().sorted(Comparator.comparingInt(AssignableRole::getPosition)).collect(Collectors.toList());
int maxPosition = 0;
if(!rolesToAdd.isEmpty()) {
maxPosition = rolesToAdd.get(rolesToAdd.size() - 1).getPosition();
Iterator<AssignableRole> rolesToAddIterator = rolesToAdd.iterator();
AssignableRole current = rolesToAddIterator.next();
AssignablePostRole lastAddedRole = null;
for (int position = 0; position < maxPosition + 1; position++) {
boolean legitEntry = current.getPosition().equals(position);
boolean startOfNewMessage = position > 0 && (position % 21) == 0;
if(legitEntry) {
AEmote emoteForRole = current.getEmote();
Emote jdaEmoteForRole = botService.getEmote(emoteForRole).orElse(null);
FullEmote fullEmote = FullEmote.builder().emote(jdaEmoteForRole).fakeEmote(emoteForRole).build();
AssignablePostRole postRole = AssignablePostRole
.builder()
.description(current.getDescription())
.emote(fullEmote)
.position(position)
.forceNewMessage(startOfNewMessage)
.build();
roles.add(postRole);
lastAddedRole = postRole;
if(rolesToAddIterator.hasNext()) {
current = rolesToAddIterator.next();
}
} else if(startOfNewMessage && lastAddedRole != null) {
lastAddedRole.setForceNewMessage(true);
}
}
}
return AssignablePostMessage
.builder()
.roles(roles)
.place(place)
.maxPosition(maxPosition)
.build();
}
@Transactional
public CompletableFuture<Void> createAssignableRolePlacePosts(Long serverId, String name) {
AServer server = serverManagementService.loadOrCreate(serverId);
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByServerAndKey(server, name);
Optional<TextChannel> channelOptional = botService.getTextChannelFromServerOptional(serverId, assignableRolePlace.getChannel().getId());
if(channelOptional.isPresent()) {
MessageChannel channel = channelOptional.get();
List<CompletableFuture<Message>> messageFutures = sendAssignablePostMessages(assignableRolePlace, channel);
return CompletableFuture.allOf(messageFutures.toArray(new CompletableFuture[0]))
.thenCompose(aVoid -> self.addEmotes(messageFutures, name));
} else {
log.warn("Channel to create assignable role post in does not exist.");
throw new AssignableRolePlaceChannelDoesNotExist(assignableRolePlace.getChannel().getId(), name);
}
}
@Transactional
public CompletableFuture<Void> addEmotes(List<CompletableFuture<Message>> assignablePlacePostsMessageFutures, String placeKey) {
try {
Message firstMessage = assignablePlacePostsMessageFutures.get(0).get();
Long serverId = firstMessage.getGuild().getIdLong();
AServer innerServer = serverManagementService.loadOrCreate(serverId);
AssignableRolePlace innerRolePlace = rolePlaceManagementService.findByServerAndKey(innerServer, placeKey);
List<AssignableRole> roleStream = innerRolePlace.getAssignableRoles().stream().sorted(Comparator.comparingInt(AssignableRole::getPosition)).collect(Collectors.toList());
List<CompletableFuture<Void>> reactionFutures = new ArrayList<>();
int usedEmotes = 0;
for (CompletableFuture<Message> messageCompletableFuture : assignablePlacePostsMessageFutures) {
Message sentMessage = messageCompletableFuture.get();
// this uses the actual embed count as a limit, so this relies on fields to be used for description, if this changes, this needs to be changed
MessageEmbed embed = sentMessage.getEmbeds().get(0);
List<AssignableRole> firstRoles = roleStream.subList(usedEmotes, usedEmotes + embed.getFields().size());
usedEmotes += embed.getFields().size();
List<Integer> usedEmoteIds = firstRoles.stream().map(assignableRole -> assignableRole.getEmote().getId()).collect(Collectors.toList());
CompletableFuture<Void> firstMessageFuture = createAssignableRolePlacePost(sentMessage, serverId, usedEmoteIds);
reactionFutures.add(firstMessageFuture);
}
return CompletableFuture.allOf(reactionFutures.toArray(new CompletableFuture[0])).thenCompose(aVoid -> {
self.storeCreatedAssignableRolePlacePosts(placeKey, serverId, assignablePlacePostsMessageFutures);
return CompletableFuture.completedFuture(null);
});
} catch (InterruptedException | ExecutionException e) {
log.error("Failed to process future from sending assignable place posts messages.", e);
throw new AbstractoRunTimeException(e);
}
}
@Transactional
public void storeCreatedAssignableRolePlacePosts(String name, Long serverId, List<CompletableFuture<Message>> futures) {
AServer server = serverManagementService.loadOrCreate(serverId);
AssignableRolePlace updatedPlace = rolePlaceManagementService.findByServerAndKey(server, name);
List<AssignableRole> rolesToAdd = updatedPlace.getAssignableRoles().stream().sorted(Comparator.comparingInt(AssignableRole::getPosition)).collect(Collectors.toList());
int usedEmotes = 0;
for (int i = 0; i < futures.size(); i++) {
CompletableFuture<Message> messageCompletableFuture = futures.get(i);
try {
Message message = messageCompletableFuture.get();
Message sentMessage = messageCompletableFuture.get();
// this uses the actual embed count as a limit, so this relies on fields to be used for description, if this changes, this needs to be changed
MessageEmbed embed = sentMessage.getEmbeds().get(0);
List<AssignableRole> firstRoles = rolesToAdd.subList(usedEmotes, usedEmotes + embed.getFields().size());
usedEmotes += embed.getFields().size();
AssignableRolePlacePost post = AssignableRolePlacePost
.builder()
.id(message.getIdLong())
.usedChannel(updatedPlace.getChannel())
.assignablePlace(updatedPlace)
.build();
firstRoles.forEach(assignableRole ->
assignableRole.setAssignableRolePlacePost(post)
);
updatedPlace.getMessagePosts().add(post);
} catch (Exception e) {
log.error("Failed to get future.", e);
}
}
}
@Transactional
public CompletableFuture<Void> createAssignableRolePlacePost(Message message, Long server, List<Integer> emotesToAdd) {
// TODO might need to guarantee the order
List<CompletableFuture<Void>> futures = new ArrayList<>();
emotesToAdd.forEach(emotesToUse -> {
AEmote emoteToUseObject = emoteManagementService.loadEmote(emotesToUse);
futures.add(messageService.addReactionToMessageWithFuture(emoteToUseObject, server, message));
});
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
}
}

View File

@@ -0,0 +1,69 @@
package dev.sheldan.abstracto.assignableroles.service;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRole;
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRoleManagementServiceBean;
import dev.sheldan.abstracto.assignableroles.service.management.AssignedRoleUserManagementService;
import dev.sheldan.abstracto.assignableroles.service.management.AssignedRoleUserManagementServiceBean;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.RoleService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.concurrent.CompletableFuture;
@Component
public class AssignableRoleServiceBean implements AssignableRoleService {
@Autowired
private RoleService roleService;
@Autowired
private AssignedRoleUserManagementService assignedRoleUserManagementService;
@Autowired
private AssignableRoleManagementServiceBean assignableRoleManagementServiceBean;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private AssignedRoleUserManagementServiceBean assignedRoleUserManagementServiceBean;
@Autowired
private AssignableRoleServiceBean self;
@Override
public CompletableFuture<Void> assignAssignableRoleToUser(Long assignableRoleId, Member toAdd) {
AssignableRole role = assignableRoleManagementServiceBean.getByAssignableRoleId(assignableRoleId);
return roleService.addRoleToMemberFuture(toAdd, role.getRole()).thenApply(aVoid -> {
self.persistRoleAssignment(assignableRoleId, toAdd);
return null;
});
}
@Override
public CompletableFuture<Void> removeAssignableRoleFromUser(AssignableRole assignableRole, Member member) {
Long assignableRoleId = assignableRole.getId();
return roleService.removeRoleFromMemberFuture(member, assignableRole.getRole()).thenApply(aVoid -> {
self.persistRoleRemoval(assignableRoleId, member);
return null;
});
}
@Transactional
public void persistRoleAssignment(Long assignableRoleId, Member member) {
AssignableRole role = assignableRoleManagementServiceBean.getByAssignableRoleId(assignableRoleId);
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(member);
assignedRoleUserManagementServiceBean.addAssignedRoleToUser(role, aUserInAServer);
}
@Transactional
public void persistRoleRemoval(Long assignableRoleId, Member member) {
AssignableRole role = assignableRoleManagementServiceBean.getByAssignableRoleId(assignableRoleId);
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(member);
assignedRoleUserManagementServiceBean.removeAssignedRoleFromUser(role, aUserInAServer);
}
}

View File

@@ -0,0 +1,77 @@
package dev.sheldan.abstracto.assignableroles.service.management;
import dev.sheldan.abstracto.assignableroles.exceptions.AssignableRolePlaceNotFoundException;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRole;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlacePost;
import dev.sheldan.abstracto.assignableroles.repository.AssignableRoleRepository;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AssignableRoleManagementServiceBean implements AssignableRoleManagementService {
@Autowired
private AssignableRolePlaceManagementService rolePlaceManagementService;
@Autowired
private EmoteManagementService emoteManagementService;
@Autowired
private RoleManagementService roleManagementService;
@Autowired
private AssignableRolePlacePostManagementService postManagementService;
@Autowired
private AssignableRoleRepository repository;
@Override
public AssignableRole addRoleToPlace(AssignableRolePlace place, AEmote emote, ARole role, String description, AssignableRolePlacePost post) {
Integer maxPosition = place.getAssignableRoles().stream().map(AssignableRole::getPosition).max(Integer::compareTo).orElse(0);
if(!place.getAssignableRoles().isEmpty()) {
maxPosition += 1;
}
AssignableRole roleToAdd = AssignableRole
.builder()
.assignablePlace(place)
.emote(emote)
.role(role)
.requiredLevel(0)
.position(maxPosition)
.description(description)
.assignableRolePlacePost(post)
.build();
place.getAssignableRoles().add(roleToAdd);
return roleToAdd;
}
@Override
public AssignableRole addRoleToPlace(Long placeId, Integer emoteId, Long roleId, String description, Long messageId) {
AssignableRolePlace place = rolePlaceManagementService.findByPlaceId(placeId).orElseThrow(() -> new AssignableRolePlaceNotFoundException(placeId));
AEmote emote = emoteManagementService.loadEmote(emoteId);
ARole role = roleManagementService.findRole(roleId);
AssignableRolePlacePost post = postManagementService.findByMessageId(messageId);
AssignableRole assignableRole = addRoleToPlace(place, emote, role, description, post);
post.getAssignableRoles().add(assignableRole);
return assignableRole;
}
@Override
public AssignableRole addRoleToPlace(Long placeId, Integer emoteId, Long roleId, String description) {
AssignableRolePlace place = rolePlaceManagementService.findByPlaceId(placeId).orElseThrow(() -> new AssignableRolePlaceNotFoundException(placeId));
AEmote emote = emoteManagementService.loadEmote(emoteId);
ARole role = roleManagementService.findRole(roleId);
return addRoleToPlace(place, emote, role, description, null);
}
@Override
public AssignableRole getByAssignableRoleId(Long assignableRoleId) {
return repository.findById(assignableRoleId).orElseThrow(() -> new AbstractoRunTimeException("Assignable role not found"));
}
}

View File

@@ -0,0 +1,72 @@
package dev.sheldan.abstracto.assignableroles.service.management;
import dev.sheldan.abstracto.assignableroles.exceptions.AssignableRolePlaceNotFoundException;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.repository.AssignableRolePlaceRepository;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
public class AssignableRolePlaceManagementServiceBean implements AssignableRolePlaceManagementService {
@Autowired
private AssignableRolePlaceRepository repository;
@Override
public AssignableRolePlace createPlace(AServer server, String name, AChannel channel, String text) {
AssignableRolePlace place = AssignableRolePlace
.builder()
.channel(channel)
.server(server)
.text(text)
.key(name)
.build();
repository.save(place);
return place;
}
@Override
public boolean doesPlaceExist(AServer server, String name) {
return repository.existsByServerAndKey(server, name);
}
@Override
public AssignableRolePlace findByServerAndKey(AServer server, String name) {
// todo use other exception or adapt exception
return repository.findByServerAndKey(server, name).orElseThrow(() -> new AssignableRolePlaceNotFoundException(0L));
}
@Override
public Optional<AssignableRolePlace> findByPlaceId(Long id) {
return repository.findById(id);
}
@Override
public void moveAssignableRolePlace(AServer server, String name, AChannel newChannel) {
AssignableRolePlace assignablePlaceToChange = findByServerAndKey(server, name);
assignablePlaceToChange.setChannel(newChannel);
}
@Override
public void changeAssignableRolePlaceDescription(AServer server, String name, String newDescription) {
AssignableRolePlace assignablePlaceToChange = findByServerAndKey(server, name);
assignablePlaceToChange.setText(newDescription);
}
@Override
public void deleteAssignablePlace(AssignableRolePlace toDelete) {
repository.delete(toDelete);
}
@Override
public List<AssignableRolePlace> findAllByServer(AServer server) {
return repository.findByServer(server);
}
}

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.assignableroles.service.management;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlacePost;
import dev.sheldan.abstracto.assignableroles.exceptions.AssignablePlacePostNotFoundException;
import dev.sheldan.abstracto.assignableroles.repository.AssignableRolePlacePostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class AssignableRolePlacePostManagementServiceBean implements AssignableRolePlacePostManagementService {
@Autowired
private AssignableRolePlacePostRepository repository;
@Override
public Optional<AssignableRolePlacePost> findByMessageIdOptional(Long messageId) {
return repository.findById(messageId);
}
@Override
public AssignableRolePlacePost findByMessageId(Long messageId) {
return findByMessageIdOptional(messageId).orElseThrow(() -> new AssignablePlacePostNotFoundException(messageId));
}
}

View File

@@ -0,0 +1,54 @@
package dev.sheldan.abstracto.assignableroles.service.management;
import dev.sheldan.abstracto.assignableroles.exceptions.AssignedUserNotFoundException;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRole;
import dev.sheldan.abstracto.assignableroles.models.database.AssignedRoleUser;
import dev.sheldan.abstracto.assignableroles.repository.AssignedRoleUserRepository;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class AssignedRoleUserManagementServiceBean implements AssignedRoleUserManagementService {
@Autowired
private AssignedRoleUserRepository repository;
@Override
public void addAssignedRoleToUser(AssignableRole assignableRole, AUserInAServer aUserInAServer) {
Optional<AssignedRoleUser> optional = findByUserInServerOptional(aUserInAServer);
AssignedRoleUser user = optional.orElseGet(() -> createAssignedRoleUser(aUserInAServer));
assignableRole.getAssignedUsers().add(user);
user.getRoles().add(assignableRole);
}
@Override
public void removeAssignedRoleFromUser(AssignableRole assignableRole, AUserInAServer aUserInAServer) {
AssignedRoleUser user = findByUserInServer(aUserInAServer);
assignableRole.getAssignedUsers().remove(user);
user.getRoles().remove(assignableRole);
}
@Override
public AssignedRoleUser createAssignedRoleUser(AUserInAServer aUserInAServer) {
AssignedRoleUser newUser = AssignedRoleUser.builder().user(aUserInAServer).id(aUserInAServer.getUserInServerId()).build();
return repository.save(newUser);
}
@Override
public boolean doesAssignedRoleUserExist(AUserInAServer aUserInAServer) {
return repository.existsById(aUserInAServer.getUserInServerId());
}
@Override
public Optional<AssignedRoleUser> findByUserInServerOptional(AUserInAServer aUserInAServer) {
return repository.findById(aUserInAServer.getUserInServerId());
}
@Override
public AssignedRoleUser findByUserInServer(AUserInAServer aUserInAServer) {
return findByUserInServerOptional(aUserInAServer).orElseThrow(() -> new AssignedUserNotFoundException(aUserInAServer));
}
}

View File

@@ -0,0 +1,111 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="experienceModule" value="(SELECT id FROM module WHERE name = 'assignableRoles')"/>
<property name="experienceFeature" value="(SELECT id FROM feature WHERE key = 'assignableRole')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="assignable_roles-commands">
<insert tableName="command">
<column name="name" value="addRoleToAssignableRolePlace"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="setupAssignableRolePlace"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="activateAssignableRolePlace"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="deactivateAssignableRolePlace"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="removeRoleFromAssignableRolePlace"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="changeAssignableRolePlaceConfig"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="setAssignableRolePosition"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="swapAssignableRolePosition"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="testAssignableRolePlace"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="deleteAssignableRolePlace"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="createAssignableRolePlace"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="changeAssignablePlaceDescription"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="showAssignableRolePlaceConfig"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="editAssignableRolePlaceText"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="moveAssignableRolePlace"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="showAssignableRolePlaces"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,13 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,18 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="assignableFeature" value="(SELECT id FROM feature WHERE key = 'assignableRole')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="assignableRole_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${assignableFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,16 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="assignable_role-feature-insertion">
<insert tableName="feature">
<column name="key" value="assignableRole"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,16 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="assignable_role-module-insertion">
<insert tableName="module">
<column name="name" value="assignableRoles"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,50 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="assignable_role-table">
<createTable tableName="assignable_role">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="assignable_role_pkey"/>
</column>
<column name="emote_id" type="INTEGER">
<constraints nullable="false"/>
</column>
<column name="role_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="assignable_place_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="assignable_role_place_post_id" type="BIGINT">
<constraints nullable="true"/>
</column>
<column name="description" type="VARCHAR(255)"/>
<column name="required_level" type="INTEGER"/>
<column name="position" type="INTEGER"/>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
</changeSet>
<changeSet author="Sheldan" id="assignable_role-fk_assignable_role_emote">
<addForeignKeyConstraint baseColumnNames="emote_id" baseTableName="assignable_role" constraintName="fk_assignable_role_emote" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="emote" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="assignable_role-fk_assignable_role_role">
<addForeignKeyConstraint baseColumnNames="role_id" baseTableName="assignable_role" constraintName="fk_assignable_role_role" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="role" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="assignable_role-fk_assignable_role_place">
<addForeignKeyConstraint baseColumnNames="assignable_place_id" baseTableName="assignable_role" constraintName="fk_assignable_role_place" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="assignable_role_place" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="assignable_role-fk_assignable_role_post">
<addForeignKeyConstraint baseColumnNames="assignable_role_place_post_id" baseTableName="assignable_role" constraintName="fk_assignable_role_post" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="assignable_role_place_post" validate="true"/>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,39 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="assignable_role_place-table">
<createTable tableName="assignable_role_place">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="assignable_role_place_pkey"/>
</column>
<column name="channel_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="key" type="VARCHAR(255)"/>
<column name="text" type="VARCHAR(255)"/>
<column name="active" type="BOOLEAN"/>
<column name="inline" type="BOOLEAN"/>
<column name="unique_roles" type="BOOLEAN"/>
<column name="auto_remove" type="BOOLEAN"/>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
</changeSet>
<changeSet author="Sheldan" id="assignable_role_place-fk_assignable_role_place_channel">
<addForeignKeyConstraint baseColumnNames="channel_id" baseTableName="assignable_role_place" constraintName="fk_assignable_role_place_channel" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="channel" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="assignable_role_place-fk_assignable_role_place_server">
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="assignable_role_place" constraintName="fk_assignable_role_place_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,33 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="assignable_role_place_post-table">
<createTable tableName="assignable_role_place_post">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="assignable_role_place_post_pkey"/>
</column>
<column name="assignable_place_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="channel_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
</changeSet>
<changeSet author="Sheldan" id="assignable_role_place_post-fk_assignable_role_place_post_place_id">
<addForeignKeyConstraint baseColumnNames="assignable_place_id" baseTableName="assignable_role_place_post" constraintName="fk_assignable_role_place_post_place_id" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="assignable_role_place" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="assignable_role_place_post-fk_assignable_role_place_post_channel">
<addForeignKeyConstraint baseColumnNames="channel_id" baseTableName="assignable_role_place_post" constraintName="fk_assignable_role_place_post_channel" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="channel" validate="true"/>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,38 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="assigned_role_user-table">
<createTable tableName="assigned_role_user">
<column name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="assigned_role_user_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
</changeSet>
<changeSet author="Sheldan" id="assigned_role_in_user-table">
<createTable tableName="assigned_role_in_user">
<column name="assigned_role_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="user_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<changeSet author="Sheldan" id="assigned_role_in_user-fk_assigned_role_in_user_assignable_role">
<addForeignKeyConstraint baseColumnNames="assigned_role_id" baseTableName="assigned_role_in_user" constraintName="fk_assigned_role_in_user_assignable_role" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="assignable_role" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="assigned_role_in_user-fk_assigned_role_in_user_assigned_user">
<addForeignKeyConstraint baseColumnNames="user_id" baseTableName="assigned_role_in_user" constraintName="fk_assigned_role_in_user_assigned_user" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="assigned_role_user" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="assigned_role_user-fk_assigned_role_user_user">
<addForeignKeyConstraint baseColumnNames="id" baseTableName="assigned_role_user" constraintName="fk_assigned_role_user_user" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="auser" validate="true"/>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,13 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="assignable_role_place.xml" relativeToChangelogFile="true"/>
<include file="assignable_role_place_post.xml" relativeToChangelogFile="true"/>
<include file="assignable_role.xml" relativeToChangelogFile="true"/>
<include file="assigned_role_user.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,11 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../dbchangelog-3.8.xsd" >
<include file="assignableRoles-tables/tables.xml" relativeToChangelogFile="true"/>
<include file="assignableRoles-seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog-3.8.xsd" >
<include file="1.0-assignableRoles/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

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

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.assignableroles.config;
import dev.sheldan.abstracto.core.command.execution.CommandParameterKey;
import lombok.Getter;
@Getter
public enum AssignableRolePlaceParameterKey implements CommandParameterKey {
INLINE, UNIQUE, AUTOREMOVE, ACTIVE
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.assignableroles.config.features;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.stereotype.Component;
@Component
public class AssignableFeatureConfig implements FeatureConfig {
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

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

View File

@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.assignableroles.exceptions;
import dev.sheldan.abstracto.assignableroles.models.exception.AssignableRolePlacePostNotFoundModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.templating.Templatable;
public class AssignablePlacePostNotFoundException extends AbstractoRunTimeException implements Templatable {
private final AssignableRolePlacePostNotFoundModel model;
public AssignablePlacePostNotFoundException(Long messageId) {
super("Assignable place post not found.");
this.model = AssignableRolePlacePostNotFoundModel.builder().messageId(messageId).build();
}
@Override
public String getTemplateName() {
return "assignable_role_place_post_not_found_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.assignableroles.exceptions;
import dev.sheldan.abstracto.assignableroles.models.exception.AssignableRoleAlreadyDefinedModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.FullEmote;
import dev.sheldan.abstracto.templating.Templatable;
public class AssignableRoleAlreadyDefinedException extends AbstractoRunTimeException implements Templatable {
private final AssignableRoleAlreadyDefinedModel model;
public AssignableRoleAlreadyDefinedException(FullEmote emote, String placeName) {
super("Assignable role already assigned");
this.model = AssignableRoleAlreadyDefinedModel.builder().emote(emote).placeName(placeName).build();
}
@Override
public String getTemplateName() {
return "assignable_role_place_emote_already_defined_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.assignableroles.exceptions;
import dev.sheldan.abstracto.assignableroles.models.exception.AssignableRoleNotUsableModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.FullRole;
import dev.sheldan.abstracto.templating.Templatable;
import net.dv8tion.jda.api.entities.Guild;
public class AssignableRoleNotUsableException extends AbstractoRunTimeException implements Templatable {
private final AssignableRoleNotUsableModel model;
public AssignableRoleNotUsableException(FullRole role, Guild guild) {
super("Role is not usable as assignable role");
this.model = AssignableRoleNotUsableModel.builder().role(role).guild(guild).build();
}
@Override
public String getTemplateName() {
return "assignable_role_place_role_not_usable_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.assignableroles.exceptions;
import dev.sheldan.abstracto.assignableroles.models.exception.AssignableRolePlaceAlreadyExistsModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.templating.Templatable;
public class AssignableRolePlaceAlreadyExistsException extends AbstractoRunTimeException implements Templatable {
private final AssignableRolePlaceAlreadyExistsModel model;
public AssignableRolePlaceAlreadyExistsException(String name) {
super("Assignable role place already exists");
this.model = AssignableRolePlaceAlreadyExistsModel.builder().name(name).build();
}
@Override
public String getTemplateName() {
return "assignable_role_place_exists_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.assignableroles.exceptions;
import dev.sheldan.abstracto.assignableroles.models.exception.AssignableRolePlaceChannelDoesNotExistModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.templating.Templatable;
public class AssignableRolePlaceChannelDoesNotExist extends AbstractoRunTimeException implements Templatable {
private final AssignableRolePlaceChannelDoesNotExistModel model;
public AssignableRolePlaceChannelDoesNotExist(Long channelId, String placeName) {
super("Assignable role place channel does not exist");
this.model = AssignableRolePlaceChannelDoesNotExistModel.builder().channelId(channelId).placeName(placeName).build();
}
@Override
public String getTemplateName() {
return "assignable_role_place_channel_does_not_exist_exception";
}
@Override
public Object getTemplateModel() {
return this.model;
}
}

View File

@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.assignableroles.exceptions;
import dev.sheldan.abstracto.assignableroles.models.exception.AssignableRolePlaceNotFoundModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.templating.Templatable;
public class AssignableRolePlaceNotFoundException extends AbstractoRunTimeException implements Templatable {
private final AssignableRolePlaceNotFoundModel model;
public AssignableRolePlaceNotFoundException(Long placeId) {
super("Assignable role place not found");
this.model = AssignableRolePlaceNotFoundModel.builder().placeId(placeId).build();
}
@Override
public String getTemplateName() {
return "assignable_role_place_not_found_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.assignableroles.exceptions;
import dev.sheldan.abstracto.assignableroles.models.exception.AssignedUserNotFoundModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.templating.Templatable;
public class AssignedUserNotFoundException extends AbstractoRunTimeException implements Templatable {
private final AssignedUserNotFoundModel model;
public AssignedUserNotFoundException(AUserInAServer userInAServer) {
super("Assigned user was not found");
this.model = AssignedUserNotFoundModel.builder().aUserInAServer(userInAServer).build();
}
@Override
public String getTemplateName() {
return "assignable_role_place_assigned_user_not_found_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.assignableroles.exceptions;
import dev.sheldan.abstracto.assignableroles.models.exception.EmoteNotInAssignableRolePlaceModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.FullEmote;
import dev.sheldan.abstracto.templating.Templatable;
public class EmoteNotInAssignableRolePlaceException extends AbstractoRunTimeException implements Templatable {
private final EmoteNotInAssignableRolePlaceModel model;
public EmoteNotInAssignableRolePlaceException(FullEmote emote, String placeName) {
super("Emote not found in assignable role place");
this.model = EmoteNotInAssignableRolePlaceModel.builder().emote(emote).placeName(placeName).build();
}
@Override
public String getTemplateName() {
return "emote_not_in_assignable_role_place_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,73 @@
package dev.sheldan.abstracto.assignableroles.models.database;
import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.models.database.ARole;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name="assignable_role")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class AssignableRole {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "emote_id")
private AEmote emote;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "role_id", nullable = false)
private ARole role;
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@Getter
@Setter
@JoinColumn(name = "assignable_place_id", nullable = false)
private AssignableRolePlace assignablePlace;
@Getter
@Setter
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "assignable_role_place_post_id")
private AssignableRolePlacePost assignableRolePlacePost;
@Getter
@Setter
@ManyToMany(mappedBy = "roles")
@Builder.Default
private List<AssignedRoleUser> assignedUsers = new ArrayList<>();
private String description;
private Integer requiredLevel;
private Integer position;
@Column(name = "created")
private Instant created;
@PrePersist
private void onInsert() {
this.created = Instant.now();
}
@Column(name = "updated")
private Instant updated;
@PreUpdate
private void onUpdate() {
this.updated = Instant.now();
}
}

View File

@@ -0,0 +1,88 @@
package dev.sheldan.abstracto.assignableroles.models.database;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name="assignable_role_place")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class AssignableRolePlace {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne
@JoinColumn(name="channel_id")
private AChannel channel;
@OneToOne
@JoinColumn(name="server_id")
private AServer server;
private String key;
@OneToMany(
fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
orphanRemoval = true,
mappedBy = "assignablePlace"
)
@Builder.Default
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private List<AssignableRolePlacePost> messagePosts = new ArrayList<>();
@OneToMany(
fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
orphanRemoval = true,
mappedBy = "assignablePlace"
)
@Builder.Default
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private List<AssignableRole> assignableRoles = new ArrayList<>();
private String text;
@Builder.Default
private Boolean active = true;
@Builder.Default
private Boolean inline = false;
@Builder.Default
private Boolean uniqueRoles = false;
@Builder.Default
private Boolean autoRemove = false;
@Column(name = "created")
private Instant created;
@PrePersist
private void onInsert() {
this.created = Instant.now();
}
@Column(name = "updated")
private Instant updated;
@PreUpdate
private void onUpdate() {
this.updated = Instant.now();
}
}

View File

@@ -0,0 +1,51 @@
package dev.sheldan.abstracto.assignableroles.models.database;
import dev.sheldan.abstracto.core.models.database.AChannel;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name="assignable_role_place_post")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class AssignableRolePlacePost {
@Id
private Long id;
@ManyToOne
@JoinColumn(name = "channel_id")
private AChannel usedChannel;
@Column(name = "created")
private Instant created;
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@Getter
@Setter
@JoinColumn(name = "assignable_place_id", nullable = false)
private AssignableRolePlace assignablePlace;
@OneToMany(
fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
mappedBy = "assignableRolePlacePost")
@Builder.Default
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private List<AssignableRole> assignableRoles = new ArrayList<>();
@PrePersist
private void onInsert() {
this.created = Instant.now();
}
}

View File

@@ -0,0 +1,46 @@
package dev.sheldan.abstracto.assignableroles.models.database;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name="assigned_role_user")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class AssignedRoleUser {
@Id
private Long id;
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@PrimaryKeyJoinColumn
private AUserInAServer user;
@ManyToMany
@JoinTable(
name = "assigned_role_in_user",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "assigned_role_id"))
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Builder.Default
private List<AssignableRole> roles = new ArrayList<>();
@Column(name = "created")
private Instant created;
@PrePersist
private void onInsert() {
this.created = Instant.now();
}
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.assignableroles.models.exception;
import dev.sheldan.abstracto.core.models.FullEmote;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@Builder
public class AssignableRoleAlreadyDefinedModel implements Serializable {
private FullEmote emote;
private String placeName;
}

View File

@@ -0,0 +1,17 @@
package dev.sheldan.abstracto.assignableroles.models.exception;
import dev.sheldan.abstracto.core.models.FullRole;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Guild;
import java.io.Serializable;
@Getter
@Setter
@Builder
public class AssignableRoleNotUsableModel implements Serializable {
private FullRole role;
private Guild guild;
}

View File

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

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.assignableroles.models.exception;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@Builder
public class AssignableRolePlaceChannelDoesNotExistModel implements Serializable {
private Long channelId;
private String placeName;
}

View File

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

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.assignableroles.models.exception;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class AssignableRolePlaceNotFoundModel {
private Long placeId;
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.assignableroles.models.exception;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@Builder
public class AssignableRolePlacePostNotFoundModel implements Serializable {
private Long messageId;
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.assignableroles.models.exception;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class AssignedUserNotFoundModel {
private AUserInAServer aUserInAServer;
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.assignableroles.models.exception;
import dev.sheldan.abstracto.core.models.FullEmote;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@Builder
public class EmoteNotInAssignableRolePlaceModel implements Serializable {
private FullEmote emote;
private String placeName;
}

View File

@@ -0,0 +1,17 @@
package dev.sheldan.abstracto.assignableroles.models.templates;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
@Builder
public class AssignablePlaceOverview {
@Builder.Default
private List<AssignableRolePlace> places = new ArrayList<>();
}

View File

@@ -0,0 +1,21 @@
package dev.sheldan.abstracto.assignableroles.models.templates;
import dev.sheldan.abstracto.core.models.database.ARole;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.Role;
@Getter
@Setter
@Builder
public class AssignablePostConfigRole {
private Emote emote;
private String description;
private Integer position;
private Boolean inline;
private ARole role;
private Role awardedRole;
}

View File

@@ -0,0 +1,17 @@
package dev.sheldan.abstracto.assignableroles.models.templates;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@Builder
public class AssignablePostMessage {
private AssignableRolePlace place;
private List<AssignablePostRole> roles;
private Integer maxPosition;
}

View File

@@ -0,0 +1,19 @@
package dev.sheldan.abstracto.assignableroles.models.templates;
import dev.sheldan.abstracto.core.models.FullEmote;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class AssignablePostRole {
private FullEmote emote;
private String description;
private Integer position;
@Builder.Default
private Boolean forceNewMessage = false;
private Boolean inline;
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.assignableroles.models.templates;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@Builder
public class AssignableRolePlaceConfig {
private AssignableRolePlace place;
private List<AssignablePostConfigRole> roles;
}

View File

@@ -0,0 +1,66 @@
package dev.sheldan.abstracto.assignableroles.service;
import dev.sheldan.abstracto.assignableroles.config.AssignableRolePlaceParameterKey;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.models.database.AssignedRoleUser;
import dev.sheldan.abstracto.core.models.FullEmote;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.TextChannel;
import java.util.concurrent.CompletableFuture;
public interface AssignableRolePlaceService {
void createAssignableRolePlace(AServer server, String name, AChannel channel, String text);
boolean hasAssignableRolePlaceEmote(AServer server, String placeName, AEmote emote);
boolean hasAssignableRolePlaceEmote(AssignableRolePlace place, AEmote emote);
boolean isPositionUsed(AServer server, String placeName, Integer position);
CompletableFuture<Void> setEmoteToPosition(AServer server, String placeName, FullEmote emote, Integer position);
CompletableFuture<Void> addRoleToAssignableRolePlace(AServer server, String placeName, ARole role, FullEmote emote, String description);
CompletableFuture<Void> removeRoleFromAssignableRolePlace(AServer server, String placeName, FullEmote emote);
CompletableFuture<Void> setupAssignableRolePlace(AServer server, String name);
CompletableFuture<Void> refreshAssignablePlacePosts(AServer server, String name);
CompletableFuture<Void> refreshAssignablePlacePosts(AssignableRolePlace place);
CompletableFuture<Void> refreshTextFromPlace(AssignableRolePlace place);
void setAssignablePlaceActiveTo(AServer server, String name, Boolean newValue);
void activateAssignableRolePlace(AServer server, String name);
void activateAssignableRolePlace(AssignableRolePlace place);
void deactivateAssignableRolePlace(AServer server, String name);
void deactivateAssignableRolePlace(AssignableRolePlace place);
// inline attribute
CompletableFuture<Void> setAssignablePlaceInlineTo(AServer server, String name, Boolean newValue);
CompletableFuture<Void> inlineAssignableRolePlace(AServer server, String name);
CompletableFuture<Void> inlineAssignableRolePlace(AssignableRolePlace place);
CompletableFuture<Void> spreadAssignableRolePlace(AServer server, String name);
CompletableFuture<Void> spreadAssignableRolePlace(AssignableRolePlace place);
// unique attribute
void setAssignablePlaceUniqueTo(AServer server, String name, Boolean newValue);
void uniqueAssignableRolePlace(AServer server, String name);
void uniqueAssignableRolePlace(AssignableRolePlace place);
void multipleAssignableRolePlace(AServer server, String name);
void multipleAssignableRolePlace(AssignableRolePlace place);
// auto remove attribute
void setAssignablePlaceAutoRemoveTo(AServer server, String name, Boolean newValue);
void autoRemoveAssignableRolePlace(AServer server, String name);
void autoRemoveAssignableRolePlace(AssignableRolePlace place);
void keepReactionsAssignableRolePlace(AServer server, String name);
void keepReactionsAssignableRolePlace(AssignableRolePlace place);
void swapPositions(AServer server, String name, FullEmote firstEmote, FullEmote secondEmote);
CompletableFuture<Void> testAssignableRolePlace(AServer server, String name, MessageChannel channel);
void showAssignablePlaceConfig(AServer server, String name, MessageChannel channel);
void moveAssignableRolePlace(AServer server, String name, TextChannel newChannel);
void changeAssignablePlaceDescription(AServer server, String name, String newDescription);
CompletableFuture<Void> deleteAssignableRolePlace(AServer server, String name);
CompletableFuture<Void> changeText(AServer server, String name, String newText);
CompletableFuture<Void> removeExistingReactionsAndRoles(AssignableRolePlace place, AssignedRoleUser user);
CompletableFuture<Void> changeConfiguration(AServer server, String name, AssignableRolePlaceParameterKey keyToChange, Object newValue);
CompletableFuture<Void> showAllAssignableRolePlaces(AServer server, MessageChannel channel);
}

View File

@@ -0,0 +1,11 @@
package dev.sheldan.abstracto.assignableroles.service;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRole;
import net.dv8tion.jda.api.entities.Member;
import java.util.concurrent.CompletableFuture;
public interface AssignableRoleService {
CompletableFuture<Void> assignAssignableRoleToUser(Long assignableRoleId, Member toAdd);
CompletableFuture<Void> removeAssignableRoleFromUser(AssignableRole assignableRole, Member member);
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.assignableroles.service.management;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRole;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlacePost;
import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.models.database.ARole;
public interface AssignableRoleManagementService {
AssignableRole addRoleToPlace(AssignableRolePlace place, AEmote emote, ARole role, String description, AssignableRolePlacePost post);
AssignableRole addRoleToPlace(Long placeId, Integer emoteId, Long roleId, String description, Long messageId);
AssignableRole addRoleToPlace(Long placeId, Integer emoteId, Long roleId, String description);
AssignableRole getByAssignableRoleId(Long assignableRoleId);
}

View File

@@ -0,0 +1,20 @@
package dev.sheldan.abstracto.assignableroles.service.management;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import java.util.List;
import java.util.Optional;
public interface AssignableRolePlaceManagementService {
AssignableRolePlace createPlace(AServer server, String name, AChannel channel, String text);
boolean doesPlaceExist(AServer server, String name);
AssignableRolePlace findByServerAndKey(AServer server, String name);
Optional<AssignableRolePlace> findByPlaceId(Long id);
void moveAssignableRolePlace(AServer server, String name, AChannel newChannel);
void changeAssignableRolePlaceDescription(AServer server, String name, String newDescription);
void deleteAssignablePlace(AssignableRolePlace place);
List<AssignableRolePlace> findAllByServer(AServer server);
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.assignableroles.service.management;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlacePost;
import java.util.Optional;
public interface AssignableRolePlacePostManagementService {
Optional<AssignableRolePlacePost> findByMessageIdOptional(Long messageId);
AssignableRolePlacePost findByMessageId(Long messageId);
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.assignableroles.service.management;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRole;
import dev.sheldan.abstracto.assignableroles.models.database.AssignedRoleUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import java.util.Optional;
public interface AssignedRoleUserManagementService {
void addAssignedRoleToUser(AssignableRole assignableRole, AUserInAServer aUserInAServer);
void removeAssignedRoleFromUser(AssignableRole assignableRole, AUserInAServer aUserInAServer);
AssignedRoleUser createAssignedRoleUser(AUserInAServer aUserInAServer);
boolean doesAssignedRoleUserExist(AUserInAServer aUserInAServer);
Optional<AssignedRoleUser> findByUserInServerOptional(AUserInAServer aUserInAServer);
AssignedRoleUser findByUserInServer(AUserInAServer aUserInAServer);
}

View File

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

View File

@@ -0,0 +1,56 @@
package dev.sheldan.abstracto.experience.service.condition;
import dev.sheldan.abstracto.core.models.ConditionContext;
import dev.sheldan.abstracto.core.models.ConditionContextInstance;
import dev.sheldan.abstracto.core.models.ConditionContextVariable;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.SystemCondition;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Optional;
@Component
public class HasLevelCondition implements SystemCondition {
public static final String USER_ID_VARIABLE = "userId";
public static final String LEVEL_VARIABLE = "level";
@Autowired
private UserExperienceManagementService userExperienceManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Override
public boolean checkCondition(ConditionContextInstance conditionContext) {
HashMap<String, Object> parameters = conditionContext.getParameters();
Long userId = (Long) parameters.get(USER_ID_VARIABLE);
Integer level = (Integer) parameters.get(LEVEL_VARIABLE);
Optional<AUserInAServer> userInServerOptional = userInServerManagementService.loadUser(userId);
if(userInServerOptional.isPresent()) {
AUserInAServer userInServer = userInServerOptional.get();
AUserExperience user = userExperienceManagementService.findUserInServer(userInServer);
return user.getCurrentLevel() != null && user.getCurrentLevel().getLevel() >= level;
}
return false;
}
@Override
public String getConditionName() {
return "HAS_LEVEL";
}
@Override
public ConditionContext getExpectedContext() {
ConditionContextVariable userIdVariable = ConditionContextVariable.builder().name(USER_ID_VARIABLE).type(Long.class).build();
ConditionContextVariable levelVariable = ConditionContextVariable.builder().name(LEVEL_VARIABLE).type(Integer.class).build();
return ConditionContext.builder().expectedVariables(Arrays.asList(userIdVariable, levelVariable)).build();
}
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
import dev.sheldan.abstracto.core.models.context.ServerContext;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.PostTargetService;
@@ -52,7 +52,7 @@ public class BanServiceBean implements BanService {
banUser(guildByIdOptional.get(), userId, reason);
} else {
log.warn("Guild {} not found. Not able to ban user {}", guildId, userId);
throw new GuildException(guildId);
throw new GuildNotFoundException(guildId);
}
}

View File

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
import dev.sheldan.abstracto.core.models.FullUser;
import dev.sheldan.abstracto.core.models.database.AChannel;
@@ -157,8 +156,7 @@ public class MuteServiceBean implements MuteService {
AServerAChannelMessage origin = null;
if(message != null) {
long channelId = message.getChannel().getIdLong();
Optional<AChannel> channelOpt = channelManagementService.loadChannel(channelId);
AChannel channel = channelOpt.orElseThrow(() -> new ChannelNotFoundException(channelId, userInServerBeingMuted.getServerReference().getId()));
AChannel channel = channelManagementService.loadChannel(channelId);
origin = AServerAChannelMessage
.builder()
.channel(channel)

View File

@@ -35,12 +35,12 @@ public class SlowModeServiceBean implements SlowModeService {
@Override
public void setSlowMode(AChannel channel, Duration duration) {
Optional<TextChannel> textChannelOptional = botService.getTextChannelFromServer(channel.getServer().getId(), channel.getId());
Optional<TextChannel> textChannelOptional = botService.getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
if(textChannelOptional.isPresent()) {
TextChannel textChannel = textChannelOptional.get();
this.setSlowMode(textChannel, duration);
} else {
throw new ChannelNotFoundException(channel.getId(), channel.getServer().getId());
throw new ChannelNotFoundException(channel.getId());
}
}
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
import dev.sheldan.abstracto.core.models.context.ServerContext;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.PostTargetService;
@@ -73,7 +73,7 @@ public class BanServiceBeanTest {
verify(postTargetService, times(1)).sendEmbedInPostTarget(mockedMessage, ModerationPostTarget.BAN_LOG, serverId);
}
@Test(expected = GuildException.class)
@Test(expected = GuildNotFoundException.class)
public void tryToBanInNonExistentGuild() {
Long userId = 8L;
Long serverId = 5L;

View File

@@ -347,7 +347,7 @@ public class MuteServiceBeanTest {
when(cause.getChannel()).thenReturn(channel);
when(muteRoleManagementService.muteRoleForServerExists(server)).thenReturn(true);
when(muteRoleManagementService.retrieveMuteRoleForServer(server)).thenReturn(muteRole);
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(Optional.of(aChannel));
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(aChannel);
Mute createdMute = Mute.builder().id(muteId).build();
when(muteManagementService.createMute(eq(userBeingMuted), eq(userMuting), eq(REASON), eq(unMuteDate), any(AServerAChannelMessage.class))).thenReturn(createdMute);
when(templateService.renderTemplate(eq(MuteServiceBean.MUTE_NOTIFICATION_TEMPLATE), any(MuteNotification.class))).thenReturn(NOTIFICATION_TEXT);

View File

@@ -58,7 +58,7 @@ public class SlowModeServiceBeanTest {
when(channelManager.setSlowmode(anyInt())).thenReturn(returnedManager);
when(channel.getGuild()).thenReturn(guild);
when(channel.getManager()).thenReturn(channelManager);
when(botService.getTextChannelFromServer(server.getId(), aChannel.getId())).thenReturn(Optional.of(channel));
when(botService.getTextChannelFromServerOptional(server.getId(), aChannel.getId())).thenReturn(Optional.of(channel));
testUnit.setSlowMode(aChannel, duration);
verify(channelManager, times(1)).setSlowmode((int)duration.getSeconds());
}
@@ -84,7 +84,7 @@ public class SlowModeServiceBeanTest {
AServer server = MockUtils.getServer();
AChannel aChannel = MockUtils.getTextChannel(server, 5L);
Duration duration = Duration.ofMinutes(5);
when(botService.getTextChannelFromServer(server.getId(), aChannel.getId())).thenReturn(Optional.empty());
when(botService.getTextChannelFromServerOptional(server.getId(), aChannel.getId())).thenReturn(Optional.empty());
testUnit.setSlowMode(aChannel, duration);
}
}

View File

@@ -49,7 +49,7 @@ public class ModMailMessageServiceBean implements ModMailMessageService {
// the opening of a private channel is a rest operation it itself, so we need
// to create the promises here already, else the list is empty for example
modMailMessages.forEach(modMailMessage -> messageFutures.add(new CompletableFuture<>()));
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServer(thread.getServer().getId(), thread.getChannel().getId());
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServerOptional(thread.getServer().getId(), thread.getChannel().getId());
if(textChannelFromServer.isPresent()) {
TextChannel modMailThread = textChannelFromServer.get();
botService.getInstance().openPrivateChannelById(thread.getUser().getUserReference().getId()).queue(privateChannel -> {

View File

@@ -313,7 +313,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Override
public void relayMessageToModMailThread(ModMailThread modMailThread, Message message) {
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServer(modMailThread.getServer().getId(), modMailThread.getChannel().getId());
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServerOptional(modMailThread.getServer().getId(), modMailThread.getChannel().getId());
if(textChannelFromServer.isPresent()) {
TextChannel textChannel = textChannelFromServer.get();
self.sendUserReply(textChannel, modMailThread, message);

View File

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.modmail.service.management;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
@@ -26,8 +25,7 @@ public class ModMailThreadManagementServiceBean implements ModMailThreadManageme
@Override
public ModMailThread getByChannelId(Long channelId) {
Optional<AChannel> channelOpt = channelManagementService.loadChannel(channelId);
AChannel channel = channelOpt.orElseThrow(() -> new ChannelNotFoundException(channelId, 0L));
AChannel channel = channelManagementService.loadChannel(channelId);
return getByChannel(channel);
}

View File

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.modmail.setup;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.interactive.*;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import dev.sheldan.abstracto.core.models.FeatureValidationResult;
@@ -25,7 +24,6 @@ import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
@@ -86,59 +84,54 @@ public class ModMailCategorySetupBean implements ModMailCategorySetup {
model.setCategory(category);
}
String messageText = templateService.renderTemplate(messageTemplateKey, model);
Optional<AChannel> channel = channelManagementService.loadChannel(user.getChannelId());
AChannel channel = channelManagementService.loadChannel(user.getChannelId());
CompletableFuture<SetupStepResult> future = new CompletableFuture<>();
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId());
// very odd case, if the channel the command was executed in, was not found in the database.
if(channel.isPresent()) {
Runnable finalAction = getTimeoutRunnable(user.getGuildId(), user.getChannelId());
Consumer<MessageReceivedEvent> configAction = (MessageReceivedEvent event) -> {
try {
Runnable finalAction = getTimeoutRunnable(user.getGuildId(), user.getChannelId());
Consumer<MessageReceivedEvent> configAction = (MessageReceivedEvent event) -> {
try {
SetupStepResult result;
Message message = event.getMessage();
// this checks whether or not the user wanted to cancel the setup
if(checkForExit(message)) {
result = SetupStepResult.fromCancelled();
SetupStepResult result;
Message message = event.getMessage();
// this checks whether or not the user wanted to cancel the setup
if(checkForExit(message)) {
result = SetupStepResult.fromCancelled();
} else {
String messageContent = event.getMessage().getContentRaw();
// directly parse the long from the message, for *now*, only the category ID is supported
Long categoryId = Long.parseLong(messageContent);
Guild guild = botService.getGuildByIdNullable(user.getGuildId());
FeatureValidationResult featureValidationResult = FeatureValidationResult.builder().validationResult(true).build();
// directly validate whether or not the given category ID is a valid value
modMailFeatureValidator.validateModMailCategory(featureValidationResult, guild, categoryId);
if(Boolean.TRUE.equals(featureValidationResult.getValidationResult())) {
ModMailCategoryDelayedActionConfig build = ModMailCategoryDelayedActionConfig
.builder()
.serverId(user.getGuildId())
.category(guild.getCategoryById(categoryId))
.categoryId(categoryId)
.build();
List<DelayedActionConfig> delayedSteps = Arrays.asList(build);
result = SetupStepResult
.builder()
.result(SetupStepResultType.SUCCESS)
.delayedActionConfigList(delayedSteps)
.build();
} else {
String messageContent = event.getMessage().getContentRaw();
// directly parse the long from the message, for *now*, only the category ID is supported
Long categoryId = Long.parseLong(messageContent);
Guild guild = botService.getGuildByIdNullable(user.getGuildId());
FeatureValidationResult featureValidationResult = FeatureValidationResult.builder().validationResult(true).build();
// directly validate whether or not the given category ID is a valid value
modMailFeatureValidator.validateModMailCategory(featureValidationResult, guild, categoryId);
if(Boolean.TRUE.equals(featureValidationResult.getValidationResult())) {
ModMailCategoryDelayedActionConfig build = ModMailCategoryDelayedActionConfig
.builder()
.serverId(user.getGuildId())
.category(guild.getCategoryById(categoryId))
.categoryId(categoryId)
.build();
List<DelayedActionConfig> delayedSteps = Arrays.asList(build);
result = SetupStepResult
.builder()
.result(SetupStepResultType.SUCCESS)
.delayedActionConfigList(delayedSteps)
.build();
} else {
// exceptions this exception is used to effectively fail the setup step
throw new InvalidCategoryException();
}
// exceptions this exception is used to effectively fail the setup step
throw new InvalidCategoryException();
}
future.complete(result);
} catch (Exception e) {
log.error("Failed to handle mod mail category step.", e);
future.completeExceptionally(new SetupStepException(e));
}
};
interactiveService.createMessageWithResponse(messageText, aUserInAServer, channel.get(), parameter.getPreviousMessageId(), configAction, finalAction);
} else {
future.completeExceptionally(new ChannelNotFoundException(user.getGuildId(), user.getChannelId()));
}
future.complete(result);
} catch (Exception e) {
log.error("Failed to handle mod mail category step.", e);
future.completeExceptionally(new SetupStepException(e));
}
};
interactiveService.createMessageWithResponse(messageText, aUserInAServer, channel, parameter.getPreviousMessageId(), configAction, finalAction);
return future;
}

View File

@@ -16,6 +16,7 @@
<module>utility</module>
<module>experience-tracking</module>
<module>modmail</module>
<module>assignable-roles</module>
</modules>

View File

@@ -15,6 +15,7 @@ import dev.sheldan.abstracto.utility.service.management.MessageEmbedPostManageme
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.MessageReaction;
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -40,13 +41,13 @@ public class MessageEmbedRemovalReactionListener implements ReactedAddedListener
@Override
public void executeReactionAdded(CachedMessage message, MessageReaction reaction, AUserInAServer userAdding) {
public void executeReactionAdded(CachedMessage message, GuildMessageReactionAddEvent event, AUserInAServer userAdding) {
Long guildId = message.getServerId();
AEmote aEmote = emoteService.getEmoteOrFakeEmote(REMOVAL_EMOTE, guildId);
MessageReaction.ReactionEmote reactionEmote = reaction.getReactionEmote();
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(REMOVAL_EMOTE, guildId);
MessageReaction.ReactionEmote reactionEmote = event.getReactionEmote();
Optional<Emote> emoteInGuild = botService.getEmote(guildId, aEmote);
log.trace("Removing embed in message {} in channel {} in server {} because of a user reaction.", message.getMessageId(), message.getChannelId(), message.getServerId());
if(emoteService.isReactionEmoteAEmote(reactionEmote, aEmote, emoteInGuild.orElse(null))) {
if(emoteService.isReactionEmoteAEmote(reactionEmote, aEmote)) {
Optional<EmbeddedMessage> embeddedMessageOptional = messageEmbedPostManagementService.findEmbeddedPostByMessageId(message.getMessageId());
if(embeddedMessageOptional.isPresent()) {
EmbeddedMessage embeddedMessage = embeddedMessageOptional.get();

View File

@@ -18,8 +18,9 @@ import dev.sheldan.abstracto.utility.service.StarboardService;
import dev.sheldan.abstracto.utility.service.management.StarboardPostManagementService;
import dev.sheldan.abstracto.utility.service.management.StarboardPostReactorManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.MessageReaction;
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent;
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionRemoveEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -59,15 +60,14 @@ public class StarboardListener implements ReactedAddedListener, ReactedRemovedLi
@Override
@Transactional
public void executeReactionAdded(CachedMessage message, MessageReaction addedReaction, AUserInAServer userAdding) {
public void executeReactionAdded(CachedMessage message, GuildMessageReactionAddEvent addedReaction, AUserInAServer userAdding) {
if(userAdding.getUserReference().getId().equals(message.getAuthorId())) {
return;
}
Long guildId = message.getServerId();
AEmote aEmote = emoteService.getEmoteOrFakeEmote(STAR_EMOTE, guildId);
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(STAR_EMOTE, guildId);
MessageReaction.ReactionEmote reactionEmote = addedReaction.getReactionEmote();
Optional<Emote> emoteInGuild = botService.getEmote(guildId, aEmote);
if(emoteService.isReactionEmoteAEmote(reactionEmote, aEmote, emoteInGuild.orElse(null))) {
if(emoteService.isReactionEmoteAEmote(reactionEmote, aEmote)) {
log.trace("User {} in server {} reacted with star to put a message {} on starboard.", userAdding.getUserReference().getId(), userAdding.getServerReference().getId(), message.getMessageId());
Optional<CachedReaction> reactionOptional = emoteService.getReactionFromMessageByEmote(message, aEmote);
handleStarboardPostChange(message, reactionOptional.orElse(null), userAdding, true);
@@ -122,15 +122,14 @@ public class StarboardListener implements ReactedAddedListener, ReactedRemovedLi
@Override
@Transactional
public void executeReactionRemoved(CachedMessage message, MessageReaction removedReaction, AUserInAServer userRemoving) {
public void executeReactionRemoved(CachedMessage message, GuildMessageReactionRemoveEvent removedReaction, AUserInAServer userRemoving) {
if(message.getAuthorId().equals(userRemoving.getUserReference().getId())) {
return;
}
Long guildId = message.getServerId();
AEmote aEmote = emoteService.getEmoteOrFakeEmote(STAR_EMOTE, guildId);
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(STAR_EMOTE, guildId);
MessageReaction.ReactionEmote reactionEmote = removedReaction.getReactionEmote();
Optional<Emote> emoteInGuild = botService.getEmote(guildId, aEmote);
if(emoteService.isReactionEmoteAEmote(reactionEmote, aEmote, emoteInGuild.orElse(null))) {
if(emoteService.isReactionEmoteAEmote(reactionEmote, aEmote)) {
log.trace("User {} in server {} removed star reaction from message {} on starboard.",
userRemoving.getUserReference().getId(), userRemoving.getServerReference().getId(), message.getMessageId());
Optional<CachedReaction> reactionOptional = emoteService.getReactionFromMessageByEmote(message, aEmote);

View File

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.models.template.listener.MessageEmbeddedModel;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
@@ -144,13 +143,12 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
}
private MessageEmbeddedModel buildTemplateParameter(Message message, CachedMessage embeddedMessage) {
Optional<AChannel> channelOpt = channelManagementService.loadChannel(message.getChannel().getIdLong());
AServer server = serverManagementService.loadOrCreate(message.getGuild().getIdLong());
AUserInAServer user = userInServerManagementService.loadUser(message.getMember());
Member author = botService.getMemberInServer(embeddedMessage.getServerId(), embeddedMessage.getAuthorId());
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServer(embeddedMessage.getServerId(), embeddedMessage.getChannelId());
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServerOptional(embeddedMessage.getServerId(), embeddedMessage.getChannelId());
TextChannel sourceChannel = textChannelFromServer.orElse(null);
AChannel channel = channelOpt.orElseThrow(() -> new ChannelNotFoundException(message.getChannel().getIdLong(), server.getId()));
AChannel channel = channelManagementService.loadChannel(message.getChannel().getIdLong());
return MessageEmbeddedModel
.builder()
.channel(channel)

View File

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
@@ -64,7 +63,7 @@ public class RemindServiceBean implements ReminderService {
@Override
public Reminder createReminderInForUser(AUserInAServer user, String remindText, Duration remindIn, Message message) {
AChannel channel = channelManagementService.loadChannel(message.getChannel().getIdLong()).orElseThrow(() -> new ChannelNotFoundException(message.getChannel().getIdLong(), message.getGuild().getIdLong()));
AChannel channel = channelManagementService.loadChannel(message.getChannel().getIdLong());
AServerAChannelAUser aServerAChannelAUser = AServerAChannelAUser
.builder()
.user(user.getUserReference())
@@ -109,7 +108,7 @@ public class RemindServiceBean implements ReminderService {
log.info("Executing reminder {}.", reminderId);
Optional<Guild> guildToAnswerIn = botService.getGuildById(server.getId());
if(guildToAnswerIn.isPresent()) {
Optional<TextChannel> channelToAnswerIn = botService.getTextChannelFromServer(server.getId(), channel.getId());
Optional<TextChannel> channelToAnswerIn = botService.getTextChannelFromServerOptional(server.getId(), channel.getId());
// only send the message if the channel still exists, if not, only set the reminder to reminded.
if(channelToAnswerIn.isPresent()) {
AUser userReference = reminderToRemindFor.getRemindedUser().getUserReference();

View File

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.exception.UserInServerNotFoundException;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
@@ -105,7 +104,7 @@ public class StarboardServiceBean implements StarboardService {
public void persistPost(CachedMessage message, List<Long> userExceptAuthorIds, List<CompletableFuture<Message>> completableFutures, Long starboardChannelId, Long starredUserId, Long userReactingId) {
AUserInAServer innerStarredUser = userInServerManagementService.loadUser(starredUserId).orElseThrow(() -> new UserInServerNotFoundException(starredUserId));
try {
AChannel starboardChannel = channelManagementService.loadChannel(starboardChannelId).orElseThrow(() -> new ChannelNotFoundException(starboardChannelId, message.getServerId()));
AChannel starboardChannel = channelManagementService.loadChannel(starboardChannelId);
Message message1 = completableFutures.get(0).get();
AServerAChannelMessage aServerAChannelMessage = AServerAChannelMessage
.builder()
@@ -129,7 +128,7 @@ public class StarboardServiceBean implements StarboardService {
private StarboardPostModel buildStarboardPostModel(CachedMessage message, Integer starCount) {
Member member = botService.getMemberInServer(message.getServerId(), message.getAuthorId());
Optional<TextChannel> channel = botService.getTextChannelFromServer(message.getServerId(), message.getChannelId());
Optional<TextChannel> channel = botService.getTextChannelFromServerOptional(message.getServerId(), message.getChannelId());
Optional<Guild> guild = botService.getGuildById(message.getServerId());
AChannel aChannel = AChannel.builder().id(message.getChannelId()).build();
AUser user = AUser.builder().id(message.getAuthorId()).build();

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