Skip to content

Commit 8251074

Browse files
committed
[AB-xxx] adding command to view system configuration per server
adding auto complete to setConfig command key parameter
1 parent 4180a07 commit 8251074

File tree

10 files changed

+310
-0
lines changed

10 files changed

+310
-0
lines changed
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
package dev.sheldan.abstracto.core.commands.config;
2+
3+
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
4+
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
5+
import dev.sheldan.abstracto.core.command.config.HelpInfo;
6+
import dev.sheldan.abstracto.core.command.config.Parameter;
7+
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureDefinition;
8+
import dev.sheldan.abstracto.core.command.execution.CommandResult;
9+
import dev.sheldan.abstracto.core.config.FeatureConfig;
10+
import dev.sheldan.abstracto.core.config.FeatureDefinition;
11+
import dev.sheldan.abstracto.core.exception.ConfigurationKeyNotFoundException;
12+
import dev.sheldan.abstracto.core.interaction.InteractionService;
13+
import dev.sheldan.abstracto.core.interaction.slash.CoreSlashCommandNames;
14+
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
15+
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
16+
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
17+
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
18+
import dev.sheldan.abstracto.core.models.database.AConfig;
19+
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
20+
import dev.sheldan.abstracto.core.models.template.commands.GetConfigModel;
21+
import dev.sheldan.abstracto.core.service.FeatureConfigService;
22+
import dev.sheldan.abstracto.core.service.PaginatorService;
23+
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
24+
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
25+
import java.util.ArrayList;
26+
import java.util.Arrays;
27+
import java.util.Comparator;
28+
import java.util.List;
29+
import java.util.Map;
30+
import java.util.concurrent.CompletableFuture;
31+
import java.util.function.Function;
32+
import java.util.stream.Collectors;
33+
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
34+
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
35+
import org.springframework.beans.factory.annotation.Autowired;
36+
import org.springframework.stereotype.Component;
37+
38+
@Component
39+
public class GetConfig extends AbstractConditionableCommand {
40+
41+
private static final String GET_CONFIG_COMMAND = "getConfig";
42+
private static final String KEY_PARAMETER = "key";
43+
private static final String FEATURE_PARAMETER = "feature";
44+
45+
private static final String GET_CONFIG_RESPONSE_TEMPLATE_KEY = "getConfig_response";
46+
private static final String NO_CONFIGS_TEMPLATE_KEY = "getConfig_no_configs_found";
47+
48+
@Autowired
49+
private SlashCommandParameterService slashCommandParameterService;
50+
51+
@Autowired
52+
private FeatureConfigService featureConfigService;
53+
54+
@Autowired
55+
private SlashCommandAutoCompleteService slashCommandAutoCompleteService;
56+
57+
@Autowired
58+
private DefaultConfigManagementService defaultConfigManagementService;
59+
60+
@Autowired
61+
private ConfigManagementService configManagementService;
62+
63+
@Autowired
64+
private PaginatorService paginatorService;
65+
66+
@Autowired
67+
private InteractionService interactionService;
68+
69+
@Override
70+
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
71+
Long serverId = event.getGuild().getIdLong();
72+
List<GetConfigModel.ConfigValue> configValues;
73+
if(slashCommandParameterService.hasCommandOption(KEY_PARAMETER, event)) {
74+
String key = slashCommandParameterService.getCommandOption(KEY_PARAMETER, event, String.class);
75+
if(!defaultConfigManagementService.configKeyExists(key)) {
76+
throw new ConfigurationKeyNotFoundException(key);
77+
}
78+
79+
GetConfigModel.ConfigValue.ConfigValueBuilder configValueBuilder = GetConfigModel.ConfigValue.builder();
80+
if(configManagementService.configExists(serverId, key)) {
81+
AConfig aConfig = configManagementService.loadConfig(serverId, key);
82+
configValueBuilder
83+
.doubleValue(aConfig.getDoubleValue())
84+
.hasConcreateValue(true)
85+
.longValue(aConfig.getLongValue())
86+
.stringValue(aConfig.getStringValue());
87+
}
88+
SystemConfigProperty defaultConfig = defaultConfigManagementService.getDefaultConfig(key);
89+
GetConfigModel.ConfigValue.ConfigValueBuilder defaultConfigValueBuilder = GetConfigModel
90+
.ConfigValue
91+
.builder()
92+
.stringValue(defaultConfig.getStringValue())
93+
.doubleValue(defaultConfig.getDoubleValue())
94+
.longValue(defaultConfig.getLongValue())
95+
.key(defaultConfig.getName());
96+
configValueBuilder
97+
.key(defaultConfig.getName())
98+
.defaultValue(defaultConfigValueBuilder.build());
99+
configValues = List.of(configValueBuilder.build());
100+
101+
} else if(slashCommandParameterService.hasCommandOption(FEATURE_PARAMETER, event)) {
102+
String featureKey = slashCommandParameterService.getCommandOption(FEATURE_PARAMETER, event, String.class);
103+
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(featureKey);
104+
List<String> configKeys = feature.getRequiredSystemConfigKeys();
105+
configValues = getConfigValuesForKeys(serverId, configKeys);
106+
} else {
107+
List<String> configKeys = defaultConfigManagementService.getConfigKeys();
108+
configValues = getConfigValuesForKeys(serverId, configKeys);
109+
}
110+
111+
if(configValues.isEmpty()) {
112+
return interactionService.replyEmbed(NO_CONFIGS_TEMPLATE_KEY, new Object() , event)
113+
.thenApply(interactionHook -> CommandResult.fromSuccess());
114+
}
115+
116+
configValues = new ArrayList<>(configValues);
117+
configValues.sort(Comparator.comparing(GetConfigModel.ConfigValue::getKey));
118+
GetConfigModel model = GetConfigModel.builder()
119+
.values(configValues)
120+
.build();
121+
122+
return paginatorService.createPaginatorFromTemplate(GET_CONFIG_RESPONSE_TEMPLATE_KEY, model, event)
123+
.thenApply(unused -> CommandResult.fromSuccess());
124+
}
125+
126+
private List<GetConfigModel.ConfigValue> getConfigValuesForKeys(Long serverId, List<String> configKeys) {
127+
Map<String, AConfig> allExistingConfigs = configManagementService
128+
.loadForServer(serverId)
129+
.stream()
130+
.collect(Collectors.toMap(aConfig -> aConfig.getName().toLowerCase(), Function.identity()));
131+
return configKeys.stream().map(key -> {
132+
GetConfigModel.ConfigValue.ConfigValueBuilder configValueBuilder = GetConfigModel.ConfigValue.builder();
133+
if(allExistingConfigs.containsKey(key.toLowerCase())) {
134+
AConfig aConfig = allExistingConfigs.get(key.toLowerCase());
135+
configValueBuilder
136+
.doubleValue(aConfig.getDoubleValue())
137+
.hasConcreateValue(true)
138+
.longValue(aConfig.getLongValue())
139+
.stringValue(aConfig.getStringValue());
140+
}
141+
SystemConfigProperty defaultConfig = defaultConfigManagementService.getDefaultConfig(key);
142+
GetConfigModel.ConfigValue.ConfigValueBuilder defaultConfigValueBuilder = GetConfigModel
143+
.ConfigValue
144+
.builder()
145+
.stringValue(defaultConfig.getStringValue())
146+
.doubleValue(defaultConfig.getDoubleValue())
147+
.longValue(defaultConfig.getLongValue())
148+
.key(defaultConfig.getName());
149+
configValueBuilder
150+
.key(defaultConfig.getName())
151+
.defaultValue(defaultConfigValueBuilder.build());
152+
return configValueBuilder.build();
153+
}).toList();
154+
}
155+
156+
@Override
157+
public List<String> performAutoComplete(CommandAutoCompleteInteractionEvent event) {
158+
String input = event.getFocusedOption().getValue().toLowerCase();
159+
if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), KEY_PARAMETER)) {
160+
return defaultConfigManagementService
161+
.getConfigKeys()
162+
.stream()
163+
.map(String::toLowerCase)
164+
.filter(key -> key.startsWith(input))
165+
.toList();
166+
} else if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), FEATURE_PARAMETER)) {
167+
return featureConfigService.getAllFeatures()
168+
.stream()
169+
.map(String::toLowerCase)
170+
.filter(lowerCase -> lowerCase.startsWith(input))
171+
.toList();
172+
}
173+
return new ArrayList<>();
174+
}
175+
176+
@Override
177+
public CommandConfiguration getConfiguration() {
178+
Parameter keyToGet = Parameter
179+
.builder()
180+
.name(KEY_PARAMETER)
181+
.type(String.class)
182+
.supportsAutoComplete(true)
183+
.templated(true)
184+
.optional(true)
185+
.build();
186+
Parameter featureToGet = Parameter
187+
.builder()
188+
.name(FEATURE_PARAMETER)
189+
.type(String.class)
190+
.supportsAutoComplete(true)
191+
.templated(true)
192+
.optional(true)
193+
.build();
194+
List<Parameter> parameters = Arrays.asList(keyToGet, featureToGet);
195+
HelpInfo helpInfo = HelpInfo
196+
.builder()
197+
.templated(true)
198+
.hasExample(true)
199+
.build();
200+
201+
SlashCommandConfig slashCommandConfig = SlashCommandConfig
202+
.builder()
203+
.enabled(true)
204+
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
205+
.rootCommandName(CoreSlashCommandNames.CONFIG)
206+
.commandName("get")
207+
.build();
208+
209+
return CommandConfiguration.builder()
210+
.name(GET_CONFIG_COMMAND)
211+
.module(ConfigModuleDefinition.CONFIG)
212+
.parameters(parameters)
213+
.slashCommandOnly(true)
214+
.slashCommandConfig(slashCommandConfig)
215+
.templated(true)
216+
.supportsEmbedException(true)
217+
.help(helpInfo)
218+
.causesReaction(true)
219+
.build();
220+
}
221+
222+
@Override
223+
public FeatureDefinition getFeature() {
224+
return CoreFeatureDefinition.CORE_FEATURE;
225+
}
226+
}

abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetConfig.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111
import dev.sheldan.abstracto.core.config.FeatureDefinition;
1212
import dev.sheldan.abstracto.core.interaction.InteractionService;
1313
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
14+
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
1415
import dev.sheldan.abstracto.core.service.ConfigService;
1516
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
17+
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
18+
import java.util.ArrayList;
19+
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
1620
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
1721
import org.springframework.beans.factory.annotation.Autowired;
1822
import org.springframework.stereotype.Component;
@@ -36,6 +40,12 @@ public class SetConfig extends AbstractConditionableCommand {
3640
@Autowired
3741
private InteractionService interactionService;
3842

43+
@Autowired
44+
private SlashCommandAutoCompleteService slashCommandAutoCompleteService;
45+
46+
@Autowired
47+
private DefaultConfigManagementService defaultConfigManagementService;
48+
3949
private static final String RESPONSE_TEMPLATE = "setConfig_response";
4050

4151
@Override
@@ -47,11 +57,26 @@ public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEven
4757
.thenApply(interactionHook -> CommandResult.fromSuccess());
4858
}
4959

60+
@Override
61+
public List<String> performAutoComplete(CommandAutoCompleteInteractionEvent event) {
62+
if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), KEY_PARAMETER)) {
63+
String input = event.getFocusedOption().getValue().toLowerCase();
64+
return defaultConfigManagementService
65+
.getConfigKeys()
66+
.stream()
67+
.map(String::toLowerCase)
68+
.filter(key -> key.startsWith(input))
69+
.toList();
70+
}
71+
return new ArrayList<>();
72+
}
73+
5074
@Override
5175
public CommandConfiguration getConfiguration() {
5276
Parameter keyToChange = Parameter
5377
.builder()
5478
.name(KEY_PARAMETER)
79+
.supportsAutoComplete(true)
5580
.type(String.class)
5681
.templated(true)
5782
.build();

abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/repository/ConfigRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import dev.sheldan.abstracto.core.models.database.AConfig;
44
import dev.sheldan.abstracto.core.models.database.AServer;
5+
import java.util.List;
56
import org.springframework.data.jpa.repository.JpaRepository;
67
import org.springframework.stereotype.Repository;
78

@@ -11,6 +12,7 @@ public interface ConfigRepository extends JpaRepository<AConfig, Long> {
1112

1213
AConfig findAConfigByServerIdAndNameIgnoreCase(Long serverId, String name);
1314
void deleteAConfigByServerId(Long serverId);
15+
List<AConfig> findByServerId(Long serverId);
1416

1517
boolean existsAConfigByServerIdAndNameIgnoreCase(Long serverId, String name);
1618

abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementServiceBean.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dev.sheldan.abstracto.core.models.database.AConfig;
44
import dev.sheldan.abstracto.core.models.database.AServer;
55
import dev.sheldan.abstracto.core.repository.ConfigRepository;
6+
import java.util.List;
67
import lombok.extern.slf4j.Slf4j;
78
import org.springframework.beans.factory.annotation.Autowired;
89
import org.springframework.stereotype.Component;
@@ -98,6 +99,11 @@ public AConfig loadOrCreateIfNotExists(Long serverId, String name, String value)
9899
return config;
99100
}
100101

102+
@Override
103+
public List<AConfig> loadForServer(Long serverId) {
104+
return configRepository.findByServerId(serverId);
105+
}
106+
101107
@Override
102108
public AConfig loadOrCreateIfNotExists(Long serverId, String name, Long value) {
103109
AConfig config = loadConfig(serverId, name);

abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/DefaultConfigManagementServiceBean.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import dev.sheldan.abstracto.core.config.DefaultConfigProperties;
44
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
5+
import java.util.List;
56
import lombok.extern.slf4j.Slf4j;
67
import org.springframework.beans.factory.annotation.Autowired;
78
import org.springframework.stereotype.Component;
@@ -22,4 +23,9 @@ public SystemConfigProperty getDefaultConfig(String key) {
2223
public boolean configKeyExists(String key) {
2324
return defaultConfigProperties.getSystemConfigs().containsKey(key.toLowerCase());
2425
}
26+
27+
@Override
28+
public List<String> getConfigKeys() {
29+
return defaultConfigProperties.getSystemConfigs().keySet().stream().toList();
30+
}
2531
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
2+
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
5+
<property name="coreFeature" value="(SELECT id FROM feature WHERE key = 'core')"/>
6+
<property name="configModule" value="(SELECT id FROM module WHERE name = 'config')"/>
7+
<changeSet author="Sheldan" id="getConfig-command" >
8+
<insert tableName="command">
9+
<column name="name" value="getConfig"/>
10+
<column name="module_id" valueComputed="${configModule}"/>
11+
<column name="feature_id" valueComputed="${coreFeature}"/>
12+
</insert>
13+
</changeSet>
14+
</databaseChangeLog>

abstracto-application/core/core-impl/src/main/resources/migrations/1.6.18/seedData/data.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
55
<include file="channel_group_types.xml" relativeToChangelogFile="true"/>
6+
<include file="command.xml" relativeToChangelogFile="true"/>
67
</databaseChangeLog>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package dev.sheldan.abstracto.core.models.template.commands;
2+
3+
import java.util.List;
4+
import lombok.Builder;
5+
import lombok.Getter;
6+
7+
@Builder
8+
@Getter
9+
public class GetConfigModel {
10+
private List<ConfigValue> values;
11+
12+
13+
@Getter
14+
@Builder
15+
public static class ConfigValue {
16+
private String key;
17+
@Builder.Default
18+
private Boolean hasConcreateValue = false;
19+
private Long longValue;
20+
private String stringValue;
21+
private Double doubleValue;
22+
private ConfigValue defaultValue;
23+
}
24+
25+
}

abstracto-application/core/core-int/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import dev.sheldan.abstracto.core.models.database.AConfig;
44
import dev.sheldan.abstracto.core.models.database.AServer;
5+
import java.util.List;
56

67
public interface ConfigManagementService {
78
AConfig setOrCreateStringValue(Long serverId, String name, String value);
@@ -11,6 +12,7 @@ public interface ConfigManagementService {
1112
AConfig createConfig(Long serverId, String name, Double value);
1213
AConfig createConfig(Long serverId, String name, Long value);
1314
AConfig loadOrCreateIfNotExists(Long serverId, String name, String value);
15+
List<AConfig> loadForServer(Long serverId);
1416
AConfig loadOrCreateIfNotExists(Long serverId, String name, Long value);
1517
AConfig loadOrCreateIfNotExists(Long serverId, String name, Double value);
1618
AConfig loadConfig(Long serverId, String name);

0 commit comments

Comments
 (0)