mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-22 07:38:09 +00:00
[AB-xxx] adding sticky roles module
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
<module>remind</module>
|
||||
<module>suggestion</module>
|
||||
<module>repost-detection</module>
|
||||
<module>sticky-roles</module>
|
||||
<module>webservices</module>
|
||||
<module>logging</module>
|
||||
<module>invite-filter</module>
|
||||
|
||||
@@ -9,11 +9,6 @@
|
||||
|
||||
<artifactId>remind-impl</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
<module>repost-detection-impl</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
|
||||
@@ -9,9 +9,4 @@
|
||||
|
||||
<artifactId>repost-detection-int</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
26
abstracto-application/abstracto-modules/sticky-roles/pom.xml
Normal file
26
abstracto-application/abstracto-modules/sticky-roles/pom.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?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>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.25-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>sticky-roles</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>sticky-roles-int</module>
|
||||
<module>sticky-roles-impl</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>sticky-roles</artifactId>
|
||||
<version>1.5.25-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>sticky-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>sticky-roles-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,103 @@
|
||||
package dev.sheldan.abstracto.stickyroles.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
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.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesFeatureDefinition;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesSlashCommandNames;
|
||||
import dev.sheldan.abstracto.stickyroles.service.StickyRoleService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
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 ConfigureStickyRole extends AbstractConditionableCommand {
|
||||
|
||||
private static final String COMMAND_NAME = "configureStickyRole";
|
||||
private static final String STICKY_PARAMETER_NAME = "sticky";
|
||||
private static final String ROLE_PARAMETER_NAME = "role";
|
||||
private static final String RESPONSE_TEMPLATE = "configureStickyRole_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private StickyRoleService stickyRoleService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Boolean newState = slashCommandParameterService.getCommandOption(STICKY_PARAMETER_NAME, event, Boolean.class);
|
||||
Role role = slashCommandParameterService.getCommandOption(ROLE_PARAMETER_NAME, event, Role.class);
|
||||
stickyRoleService.setRoleStickiness(role, newState);
|
||||
return interactionService.replyEmbed(RESPONSE_TEMPLATE, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter roleParameter = Parameter
|
||||
.builder()
|
||||
.name(ROLE_PARAMETER_NAME)
|
||||
.type(Role.class)
|
||||
.optional(false)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
Parameter stateParameter = Parameter
|
||||
.builder()
|
||||
.name(STICKY_PARAMETER_NAME)
|
||||
.type(Boolean.class)
|
||||
.optional(false)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(roleParameter, stateParameter);
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(StickyRolesSlashCommandNames.STICKY_ROLES)
|
||||
.commandName("configure")
|
||||
.build();
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name(COMMAND_NAME)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.parameters(parameters)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StickyRolesFeatureDefinition.STICKY_ROLES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package dev.sheldan.abstracto.stickyroles.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
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.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.models.template.display.RoleDisplay;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesFeatureDefinition;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesSlashCommandNames;
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRole;
|
||||
import dev.sheldan.abstracto.stickyroles.model.template.StickyRoleDisplayModel;
|
||||
import dev.sheldan.abstracto.stickyroles.model.template.StickyRolesDisplayModel;
|
||||
import dev.sheldan.abstracto.stickyroles.service.StickyRoleService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ShowStickyRoles extends AbstractConditionableCommand {
|
||||
|
||||
private static final String COMMAND_NAME = "showStickyRoles";
|
||||
private static final String RESPONSE_TEMPLATE = "showStickyRoles_response";
|
||||
|
||||
@Autowired
|
||||
private StickyRoleService stickyRoleService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
List<StickyRole> stickyRoles = stickyRoleService.getStickyRolesForServer(event.getGuild());
|
||||
log.info("Showing sticky role config for {} roles in server {}.", stickyRoles.size(), event.getGuild().getIdLong());
|
||||
StickyRolesDisplayModel model = getModel(stickyRoles);
|
||||
return interactionService.replyEmbed(RESPONSE_TEMPLATE, model, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
private StickyRolesDisplayModel getModel(List<StickyRole> stickyRoles) {
|
||||
List<StickyRoleDisplayModel> displayRoles = stickyRoles
|
||||
.stream()
|
||||
.map(stickyRole -> StickyRoleDisplayModel
|
||||
.builder()
|
||||
.roleDisplay(RoleDisplay.fromARole(stickyRole.getRole()))
|
||||
.sticky(stickyRole.getSticky())
|
||||
.build())
|
||||
.toList();
|
||||
return StickyRolesDisplayModel
|
||||
.builder()
|
||||
.roles(displayRoles)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(StickyRolesSlashCommandNames.STICKY_ROLES)
|
||||
.commandName("show")
|
||||
.build();
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name(COMMAND_NAME)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StickyRolesFeatureDefinition.STICKY_ROLES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package dev.sheldan.abstracto.stickyroles.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
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.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRoleFeatureMode;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesFeatureDefinition;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesSlashCommandNames;
|
||||
import dev.sheldan.abstracto.stickyroles.service.StickyRoleService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
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 ToggleStickiness extends AbstractConditionableCommand {
|
||||
|
||||
private static final String COMMAND_NAME = "toggleStickiness";
|
||||
private static final String RESPONSE_TEMPLATE = "toggleStickiness_response";
|
||||
|
||||
private static final String STICKY_PARAMETER_NAME = "sticky";
|
||||
|
||||
@Autowired
|
||||
private StickyRoleService stickyRoleService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Member targetMember = event.getMember();
|
||||
Boolean newState = slashCommandParameterService.getCommandOption(STICKY_PARAMETER_NAME, event, Boolean.class);
|
||||
stickyRoleService.setStickiness(targetMember, newState);
|
||||
return interactionService.replyEmbed(RESPONSE_TEMPLATE, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter stateParameter = Parameter
|
||||
.builder()
|
||||
.name(STICKY_PARAMETER_NAME)
|
||||
.type(Boolean.class)
|
||||
.optional(false)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(StickyRolesSlashCommandNames.STICKY_ROLES_PUBLIC)
|
||||
.commandName("toggle")
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(stateParameter);
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name(COMMAND_NAME)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.parameters(parameters)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StickyRolesFeatureDefinition.STICKY_ROLES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(StickyRoleFeatureMode.ALLOW_SELF_MANAGEMENT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package dev.sheldan.abstracto.stickyroles.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
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.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.service.UserService;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesFeatureDefinition;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesSlashCommandNames;
|
||||
import dev.sheldan.abstracto.stickyroles.service.StickyRoleService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ToggleStickinessManagement extends AbstractConditionableCommand {
|
||||
|
||||
private static final String COMMAND_NAME = "toggleStickinessManagement";
|
||||
private static final String RESPONSE_TEMPLATE = "toggleStickinessManagement_response";
|
||||
|
||||
private static final String MEMBER_PARAMETER_NAME = "member";
|
||||
private static final String STICKY_PARAMETER_NAME = "sticky";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private StickyRoleService stickyRoleService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private ToggleStickinessManagement self;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Boolean newState = slashCommandParameterService.getCommandOption(STICKY_PARAMETER_NAME, event, Boolean.class);
|
||||
if(slashCommandParameterService.hasCommandOptionWithFullType(MEMBER_PARAMETER_NAME, event, OptionType.USER)) {
|
||||
Member targetMember = slashCommandParameterService.getCommandOption(MEMBER_PARAMETER_NAME, event, User.class, Member.class);
|
||||
stickyRoleService.setStickiness(targetMember, newState);
|
||||
return interactionService.replyEmbed(RESPONSE_TEMPLATE, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
} else {
|
||||
String userIdStr = slashCommandParameterService.getCommandOption(MEMBER_PARAMETER_NAME, event, User.class, String.class);
|
||||
Long userId = Long.parseLong(userIdStr);
|
||||
return userService.retrieveUserForId(userId).thenCompose(user -> {
|
||||
self.callService(event, user, newState);
|
||||
return interactionService.replyEmbed(RESPONSE_TEMPLATE, event);
|
||||
}).thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void callService(SlashCommandInteractionEvent event, User user, Boolean newState) {
|
||||
stickyRoleService.setStickiness(user, event.getGuild(), newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter memberParameter = Parameter
|
||||
.builder()
|
||||
.name(MEMBER_PARAMETER_NAME)
|
||||
.type(User.class)
|
||||
.optional(false)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
|
||||
Parameter stateParameter = Parameter
|
||||
.builder()
|
||||
.name(STICKY_PARAMETER_NAME)
|
||||
.type(Boolean.class)
|
||||
.optional(false)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(StickyRolesSlashCommandNames.STICKY_ROLES)
|
||||
.commandName("manage")
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(memberParameter, stateParameter);
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name(COMMAND_NAME)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.parameters(parameters)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StickyRolesFeatureDefinition.STICKY_ROLES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.abstracto.stickyroles.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:stickyRoles-config.properties")
|
||||
public class StickyRolesConfig {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.sheldan.abstracto.stickyroles.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncUpdatePendingListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberUpdatePendingModel;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesFeatureDefinition;
|
||||
import dev.sheldan.abstracto.stickyroles.service.StickyRoleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class StickyRolesJoinListener implements AsyncUpdatePendingListener {
|
||||
|
||||
@Autowired
|
||||
private StickyRoleService stickyRoleService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MemberUpdatePendingModel model) {
|
||||
stickyRoleService.handleJoin(model.getMember());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StickyRolesFeatureDefinition.STICKY_ROLES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package dev.sheldan.abstracto.stickyroles.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncLeaveListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberLeaveModel;
|
||||
import dev.sheldan.abstracto.stickyroles.config.StickyRolesFeatureDefinition;
|
||||
import dev.sheldan.abstracto.stickyroles.service.StickyRoleService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StickyRolesLeaveListener implements AsyncLeaveListener {
|
||||
|
||||
@Autowired
|
||||
private StickyRoleService stickyRoleService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MemberLeaveModel model) {
|
||||
if(model.getMember() != null) {
|
||||
stickyRoleService.handleLeave(model.getMember());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
} else {
|
||||
log.warn("Member object was not found for storing sticky roles for user {} in server {}.", model.getLeavingUser().getUserId(), model.getServerId());
|
||||
}
|
||||
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StickyRolesFeatureDefinition.STICKY_ROLES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.abstracto.stickyroles.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRole;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface StickyRoleRepository extends JpaRepository<StickyRole, Long> {
|
||||
List<StickyRole> findStickyRoleByServer(AServer server);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.abstracto.stickyroles.repository;
|
||||
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRoleUser;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface StickyRoleUserRepository extends JpaRepository<StickyRoleUser, Long> {
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package dev.sheldan.abstracto.stickyroles.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.RoleService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRole;
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRoleUser;
|
||||
import dev.sheldan.abstracto.stickyroles.service.management.StickyRoleManagementService;
|
||||
import dev.sheldan.abstracto.stickyroles.service.management.StickyRoleUserManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StickyRoleServiceBean implements StickyRoleService {
|
||||
|
||||
@Autowired
|
||||
private StickyRoleManagementService stickyRoleManagementService;
|
||||
|
||||
@Autowired
|
||||
private StickyRoleUserManagementService stickyRoleUserManagementService;
|
||||
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public void setRoleStickiness(Role role, Boolean stickiness) {
|
||||
StickyRole stickyRole = stickyRoleManagementService.getOrCreateStickyRole(role);
|
||||
log.info("Setting stickiness of role {} in server {} to {}", role.getIdLong(), role.getGuild().getIdLong(), stickiness);
|
||||
stickyRole.setSticky(stickiness);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStickiness(Member member, Boolean stickiness) {
|
||||
StickyRoleUser user = stickyRoleUserManagementService.getOrCreateStickyRoleUser(member);
|
||||
user.setSticky(stickiness);
|
||||
log.info("Setting stickiness of member {} in server {} to {}", member.getIdLong(), member.getGuild().getIdLong(), stickiness);
|
||||
if(!stickiness) {
|
||||
clearStickyRolesForUser(user);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStickiness(User user, Guild guild, Boolean stickiness) {
|
||||
StickyRoleUser stickyUser = stickyRoleUserManagementService.getOrCreateStickyRoleUser(guild.getIdLong(), user.getIdLong());
|
||||
stickyUser.setSticky(stickiness);
|
||||
log.info("Setting stickiness of member {} in server {} to {}", user.getIdLong(), guild.getIdLong(), stickiness);
|
||||
if(!stickiness) {
|
||||
clearStickyRolesForUser(stickyUser);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLeave(Member member) {
|
||||
log.info("Handling user leave of member {} from server {} regarding sticky roles.", member.getIdLong(), member.getGuild().getIdLong());
|
||||
StickyRoleUser user = stickyRoleUserManagementService.getOrCreateStickyRoleUser(member);
|
||||
clearStickyRolesForUser(user);
|
||||
if(user.getSticky()) {
|
||||
List<Role> memberRoles = member.getRoles();
|
||||
log.info("Member was marked as sticky - storing {} roles.", memberRoles.size());
|
||||
Set<Long> memberRoleIds = memberRoles
|
||||
.stream()
|
||||
.map(ISnowflake::getIdLong)
|
||||
.collect(Collectors.toSet());
|
||||
List<StickyRole> existingStickyRolesOfUser = stickyRoleManagementService.getRoles(new ArrayList<>(memberRoleIds));
|
||||
Set<Long> existingStickyRoleIdsOfUser = existingStickyRolesOfUser
|
||||
.stream()
|
||||
.map(StickyRole::getId)
|
||||
.collect(Collectors.toSet());
|
||||
memberRoleIds.removeAll(existingStickyRoleIdsOfUser);
|
||||
List<StickyRole> newStickyRoles = memberRoleIds
|
||||
.stream()
|
||||
.map(rid -> stickyRoleManagementService.createStickyRole(rid))
|
||||
.toList();
|
||||
log.debug("Creating {} new roles.", newStickyRoles.size());
|
||||
List<StickyRole> stickyRolesOfUser = new ArrayList<>(existingStickyRolesOfUser);
|
||||
stickyRolesOfUser.addAll(newStickyRoles);
|
||||
stickyRolesOfUser.forEach(stickyRole -> {
|
||||
stickyRole.getUsers().add(user);
|
||||
});
|
||||
user.setRoles(stickyRolesOfUser);
|
||||
}
|
||||
}
|
||||
|
||||
private static void clearStickyRolesForUser(StickyRoleUser user) {
|
||||
log.debug("Clearing sticky roles for user {}", user.getId());
|
||||
user.getRoles().forEach(stickyRole -> {
|
||||
stickyRole.getUsers().remove(user);
|
||||
});
|
||||
user.getRoles().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJoin(Member member) {
|
||||
log.info("Handling server join for member {} in server {} regarding sticky roles.", member.getIdLong(), member.getGuild().getIdLong());
|
||||
StickyRoleUser user = stickyRoleUserManagementService.getOrCreateStickyRoleUser(member);
|
||||
if(user.getSticky()) {
|
||||
List<Long> rolesToAdd = user
|
||||
.getRoles()
|
||||
.stream()
|
||||
.filter(StickyRole::getSticky)
|
||||
.filter(r -> Boolean.FALSE.equals(r.getRole().getDeleted()))
|
||||
.map(StickyRole::getId)
|
||||
.toList();
|
||||
log.info("Adding {} roles to user {} in server {}", rolesToAdd.size(), member.getIdLong(), member.getGuild().getIdLong());
|
||||
roleService.updateRolesIds(member, new ArrayList<>(), rolesToAdd).thenAccept(unused -> {
|
||||
log.info("Successfully added {} roles to user {} in server {}", rolesToAdd.size(), member.getIdLong(), member.getGuild().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to add {} roles to user {} in server {}", rolesToAdd.size(), member.getIdLong(), member.getGuild().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
log.info("Not re-applying roles for member {} in server {} as they opted out.", member.getIdLong(), member.getGuild().getIdLong());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StickyRole> getStickyRolesForServer(Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild);
|
||||
return stickyRoleManagementService.getStickyRolesForServer(server);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.sheldan.abstracto.stickyroles.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRole;
|
||||
import dev.sheldan.abstracto.stickyroles.repository.StickyRoleRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class StickyRoleManagementServieBean implements StickyRoleManagementService {
|
||||
|
||||
@Autowired
|
||||
private StickyRoleRepository stickyRoleRepository;
|
||||
|
||||
@Autowired
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
|
||||
@Override
|
||||
public StickyRole getOrCreateStickyRole(Long roleId) {
|
||||
Optional<StickyRole> existingRole = stickyRoleRepository.findById(roleId);
|
||||
return existingRole.orElseGet(() -> createStickyRole(roleId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public StickyRole createStickyRole(Long roleId) {
|
||||
ARole aRole = roleManagementService.findRole(roleId);
|
||||
StickyRole role = StickyRole
|
||||
.builder()
|
||||
.id(roleId)
|
||||
.sticky(StickyRoleManagementService.DEFAULT_STICKINESS)
|
||||
.role(aRole)
|
||||
.server(aRole.getServer())
|
||||
.build();
|
||||
return stickyRoleRepository.save(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StickyRole> createStickyRoles(List<Long> roleIds) {
|
||||
return roleIds
|
||||
.stream()
|
||||
.map(this::createStickyRole)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StickyRole> getRoles(List<Long> roleIds) {
|
||||
return stickyRoleRepository.findAllById(roleIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StickyRole> getStickyRolesForServer(AServer server) {
|
||||
return stickyRoleRepository.findStickyRoleByServer(server);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.sheldan.abstracto.stickyroles.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRoleUser;
|
||||
import dev.sheldan.abstracto.stickyroles.repository.StickyRoleUserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class StickyRoleUserManagementServiceBean implements StickyRoleUserManagementService {
|
||||
|
||||
@Autowired
|
||||
private StickyRoleUserRepository repository;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Override
|
||||
public StickyRoleUser getOrCreateStickyRoleUser(Long serverId, Long userId) {
|
||||
ServerUser serverUser = ServerUser
|
||||
.builder()
|
||||
.userId(userId)
|
||||
.serverId(serverId)
|
||||
.build();
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(serverUser);
|
||||
return repository.findById(userInAServer.getUserInServerId()).orElseGet(() -> createStickyroleUser(userInAServer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public StickyRoleUser createStickyroleUser(Long serverId, Long userId) {
|
||||
ServerUser serverUser = ServerUser
|
||||
.builder()
|
||||
.userId(userId)
|
||||
.serverId(serverId)
|
||||
.build();
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(serverUser);
|
||||
return createStickyroleUser(userInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StickyRoleUser createStickyroleUser(AUserInAServer userInAServer) {
|
||||
StickyRoleUser stickyRoleUser = StickyRoleUser
|
||||
.builder()
|
||||
.user(userInAServer)
|
||||
.server(userInAServer.getServerReference())
|
||||
.id(userInAServer.getUserInServerId())
|
||||
.sticky(true)
|
||||
.build();
|
||||
return repository.save(stickyRoleUser);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd" >
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd" >
|
||||
|
||||
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<property name="stickyRolesFeature" value="(SELECT id FROM feature WHERE key = 'stickyRoles')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="stickyRole-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="configureStickyRole"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${stickyRolesFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="toggleStickiness"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${stickyRolesFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="showStickyRoles"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${stickyRolesFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="toggleStickinessManagement"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${stickyRolesFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd" >
|
||||
|
||||
<include file="feature.xml" relativeToChangelogFile="true"/>
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd" >
|
||||
|
||||
<changeSet author="Sheldan" id="stickyRoles_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="stickyRoles"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd" >
|
||||
|
||||
<changeSet author="Sheldan" id="sticky_role-table">
|
||||
<createTable tableName="sticky_role">
|
||||
<column name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_sticky_role"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="sticky" type="BOOLEAN" defaultValue="true">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="id" baseTableName="sticky_role" constraintName="fk_sticky_role_role"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="role" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="sticky_role" constraintName="fk_sticky_role_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS sticky_role_update_trigger ON sticky_role;
|
||||
CREATE TRIGGER sticky_role_update_trigger BEFORE UPDATE ON sticky_role FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS sticky_role_insert_trigger ON sticky_role;
|
||||
CREATE TRIGGER sticky_role_insert_trigger BEFORE INSERT ON sticky_role FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd" >
|
||||
|
||||
<changeSet author="Sheldan" id="sticky_role_user-table">
|
||||
<createTable tableName="sticky_role_user">
|
||||
<column name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_sticky_role_user"/>
|
||||
</column>
|
||||
<column name="sticky" type="BOOLEAN" defaultValue="true">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="id" baseTableName="sticky_role_user" constraintName="fk_sticky_role_user_user"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="sticky_role_user"
|
||||
constraintName="fk_sticky_role_user_server" deferrable="false" initiallyDeferred="false"
|
||||
onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server"
|
||||
validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS sticky_role_user_update_trigger ON sticky_role_user;
|
||||
CREATE TRIGGER sticky_role_user_update_trigger BEFORE UPDATE ON sticky_role_user FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS sticky_role_user_insert_trigger ON sticky_role_user;
|
||||
CREATE TRIGGER sticky_role_user_insert_trigger BEFORE INSERT ON sticky_role_user FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="Sheldan" id="sticky_role_user_mapping-table">
|
||||
<createTable tableName="sticky_role_user_mapping">
|
||||
<column name="role_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="user_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="role_id" baseTableName="sticky_role_user_mapping" constraintName="fk_sticky_role_user_mapping_role"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="sticky_role" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="user_id" baseTableName="sticky_role_user_mapping" constraintName="fk_sticky_role_user_mapping_user"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="sticky_role_user" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS sticky_role_user_mapping_update_trigger ON sticky_role_user_mapping;
|
||||
CREATE TRIGGER sticky_role_user_mapping_update_trigger BEFORE UPDATE ON sticky_role_user_mapping FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS sticky_role_user_mapping_insert_trigger ON sticky_role_user_mapping;
|
||||
CREATE TRIGGER sticky_role_user_mapping_insert_trigger BEFORE INSERT ON sticky_role_user_mapping FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd" >
|
||||
|
||||
<include file="sticky_role.xml" relativeToChangelogFile="true"/>
|
||||
<include file="sticky_role_user.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd" >
|
||||
<include file="1.5.25/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,6 @@
|
||||
abstracto.featureFlags.stickyRoles.featureName=stickyRoles
|
||||
abstracto.featureFlags.stickyRoles.enabled=false
|
||||
|
||||
abstracto.featureModes.allowSelfManagement.featureName=stickyRoles
|
||||
abstracto.featureModes.allowSelfManagement.mode=allowSelfManagement
|
||||
abstracto.featureModes.allowSelfManagement.enabled=false
|
||||
@@ -0,0 +1,15 @@
|
||||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>sticky-roles</artifactId>
|
||||
<version>1.5.25-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>sticky-roles-int</artifactId>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.stickyroles.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum StickyRoleFeatureMode implements FeatureMode {
|
||||
ALLOW_SELF_MANAGEMENT("allowSelfManagement");
|
||||
|
||||
private final String key;
|
||||
|
||||
StickyRoleFeatureMode(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package dev.sheldan.abstracto.stickyroles.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class StickyRolesFeatureConfig implements FeatureConfig {
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StickyRolesFeatureDefinition.STICKY_ROLES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getAvailableModes() {
|
||||
return Arrays.asList(StickyRoleFeatureMode.ALLOW_SELF_MANAGEMENT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.stickyroles.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum StickyRolesFeatureDefinition implements FeatureDefinition {
|
||||
STICKY_ROLES("stickyRoles");
|
||||
|
||||
private String key;
|
||||
|
||||
StickyRolesFeatureDefinition(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.abstracto.stickyroles.config;
|
||||
|
||||
public class StickyRolesSlashCommandNames {
|
||||
public static final String STICKY_ROLES = "stickyroles";
|
||||
public static final String STICKY_ROLES_PUBLIC = "stickyrolespublic";
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dev.sheldan.abstracto.stickyroles.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="sticky_role")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class StickyRole {
|
||||
@Id
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* Reference to the actual {@link ARole} being maintained
|
||||
*/
|
||||
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
|
||||
@PrimaryKeyJoinColumn
|
||||
private ARole role;
|
||||
|
||||
@Column(name = "sticky", nullable = false)
|
||||
private Boolean sticky;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "sticky_role_user_mapping",
|
||||
joinColumns = @JoinColumn(name = "role_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "user_id"))
|
||||
@Builder.Default
|
||||
private List<StickyRoleUser> users = new ArrayList<>();
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.sheldan.abstracto.stickyroles.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "sticky_role_user")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class StickyRoleUser {
|
||||
/**
|
||||
* The ID of the {@link AUserInAServer user} which is represented by this object
|
||||
*/
|
||||
@Id
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* The {@link AUserInAServer user} which is represented by this object
|
||||
*/
|
||||
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
|
||||
@PrimaryKeyJoinColumn
|
||||
private AUserInAServer user;
|
||||
|
||||
@Column(name = "sticky")
|
||||
private Boolean sticky;
|
||||
|
||||
@ManyToMany(mappedBy = "users")
|
||||
@Builder.Default
|
||||
private List<StickyRole> roles = new ArrayList<>();
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.sheldan.abstracto.stickyroles.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.display.RoleDisplay;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class StickyRoleDisplayModel {
|
||||
private RoleDisplay roleDisplay;
|
||||
private Boolean sticky;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.sheldan.abstracto.stickyroles.model.template;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class StickyRolesDisplayModel {
|
||||
private List<StickyRoleDisplayModel> roles;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.sheldan.abstracto.stickyroles.service;
|
||||
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRole;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface StickyRoleService {
|
||||
default void ignoreRoleFromStickyRoles(Role role) {
|
||||
setRoleStickiness(role, false);
|
||||
}
|
||||
default void addRoleToStickyRoles(Role role) {
|
||||
setRoleStickiness(role, true);
|
||||
}
|
||||
void setRoleStickiness(Role role, Boolean stickiness);
|
||||
|
||||
void setStickiness(Member member, Boolean newState);
|
||||
void setStickiness(User user, Guild guild, Boolean newState);
|
||||
|
||||
void handleLeave(Member member);
|
||||
|
||||
void handleJoin(Member member);
|
||||
|
||||
List<StickyRole> getStickyRolesForServer(Guild guild);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.abstracto.stickyroles.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRole;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface StickyRoleManagementService {
|
||||
default StickyRole getOrCreateStickyRole(Role role) {
|
||||
return getOrCreateStickyRole(role.getIdLong());
|
||||
}
|
||||
StickyRole getOrCreateStickyRole(Long roleId);
|
||||
|
||||
StickyRole createStickyRole(Long roleId);
|
||||
List<StickyRole> createStickyRoles(List<Long> roleIds);
|
||||
List<StickyRole> getRoles(List<Long> roleIds);
|
||||
|
||||
List<StickyRole> getStickyRolesForServer(AServer server);
|
||||
|
||||
Boolean DEFAULT_STICKINESS = true;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.abstracto.stickyroles.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.stickyroles.model.database.StickyRoleUser;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
public interface StickyRoleUserManagementService {
|
||||
default StickyRoleUser getOrCreateStickyRoleUser(Member member) {
|
||||
return getOrCreateStickyRoleUser(member.getGuild().getIdLong(), member.getIdLong());
|
||||
}
|
||||
StickyRoleUser getOrCreateStickyRoleUser(Long serverId, Long userId);
|
||||
StickyRoleUser createStickyroleUser(Long serverId, Long userId);
|
||||
StickyRoleUser createStickyroleUser(AUserInAServer userInAServer);
|
||||
}
|
||||
@@ -30,6 +30,12 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>sticky-roles-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation-int</artifactId>
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class CommandManager implements CommandRegistry {
|
||||
@@ -54,7 +53,7 @@ public class CommandManager implements CommandRegistry {
|
||||
@Override
|
||||
public Optional<Command> findCommandByParameters(String name, UnParsedCommandParameter unParsedCommandParameter, Long serverId) {
|
||||
Optional<Command> commandOptional = commands.stream().filter(getCommandByNameAndParameterPredicate(name, unParsedCommandParameter, serverId)).findFirst();
|
||||
if(!commandOptional.isPresent()) {
|
||||
if(commandOptional.isEmpty()) {
|
||||
commandOptional = getCommandViaAliasAndParameter(name, unParsedCommandParameter, serverId);
|
||||
}
|
||||
return commandOptional;
|
||||
@@ -139,7 +138,7 @@ public class CommandManager implements CommandRegistry {
|
||||
.getDependentFeatures()
|
||||
.stream()
|
||||
.map(s -> featureConfigService.getFeatureEnum(s))
|
||||
.collect(Collectors.toList());
|
||||
.toList();
|
||||
boolean required = false;
|
||||
for (FeatureDefinition featureDefinition : featureDefinitions) {
|
||||
if(featureFlagService.getFeatureFlagValue(featureDefinition, serverId)) {
|
||||
|
||||
@@ -46,6 +46,7 @@ public class AsyncLeaveListenerBean extends ListenerAdapter {
|
||||
.build();
|
||||
return MemberLeaveModel
|
||||
.builder()
|
||||
.member(event.getMember())
|
||||
.leavingUser(serverUser)
|
||||
.user(event.getUser())
|
||||
.build();
|
||||
|
||||
@@ -10,7 +10,7 @@ public class FeatureNotFoundException extends AbstractoRunTimeException implemen
|
||||
private final FeatureNotFoundExceptionModel model;
|
||||
|
||||
public FeatureNotFoundException(String feature, List<String> availableFeatures) {
|
||||
super("Feature not found.");
|
||||
super(String.format("Feature %s not found.", feature));
|
||||
this.model = FeatureNotFoundExceptionModel
|
||||
.builder()
|
||||
.featureName(feature)
|
||||
|
||||
@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
|
||||
@Getter
|
||||
@@ -13,6 +14,7 @@ import net.dv8tion.jda.api.entities.User;
|
||||
public class MemberLeaveModel implements FeatureAwareListenerModel {
|
||||
private ServerUser leavingUser;
|
||||
private User user;
|
||||
private Member member;
|
||||
@Override
|
||||
public Long getServerId() {
|
||||
return leavingUser.getServerId();
|
||||
|
||||
Reference in New Issue
Block a user