Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamically enable features with config file #886

Merged
merged 1 commit into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions application/config.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,11 @@
"pruneMemberAmount": 7,
"inactivateAfterDays": 90,
"recentlyJoinedDays": 4
},
"feature_blacklist": {
"normal": [
],
"special": [
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public final class Config {
private final String sourceCodeBaseUrl;
private final JShellConfig jshell;
private final HelperPruneConfig helperPruneConfig;
private final FeatureBlacklistConfig featureBlacklistConfig;

@SuppressWarnings("ConstructorWithTooManyParameters")
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
Expand Down Expand Up @@ -79,7 +80,9 @@ private Config(@JsonProperty(value = "token", required = true) String token,
@JsonProperty(value = "sourceCodeBaseUrl", required = true) String sourceCodeBaseUrl,
@JsonProperty(value = "jshell", required = true) JShellConfig jshell,
@JsonProperty(value = "helperPruneConfig",
required = true) HelperPruneConfig helperPruneConfig) {
required = true) HelperPruneConfig helperPruneConfig,
@JsonProperty(value = "featureBlacklist",
required = true) FeatureBlacklistConfig featureBlacklistConfig) {
this.token = Objects.requireNonNull(token);
this.gistApiKey = Objects.requireNonNull(gistApiKey);
this.databasePath = Objects.requireNonNull(databasePath);
Expand All @@ -106,6 +109,7 @@ private Config(@JsonProperty(value = "token", required = true) String token,
this.sourceCodeBaseUrl = Objects.requireNonNull(sourceCodeBaseUrl);
this.jshell = Objects.requireNonNull(jshell);
this.helperPruneConfig = Objects.requireNonNull(helperPruneConfig);
this.featureBlacklistConfig = Objects.requireNonNull(featureBlacklistConfig);
}

/**
Expand Down Expand Up @@ -355,4 +359,13 @@ public JShellConfig getJshell() {
public HelperPruneConfig getHelperPruneConfig() {
return helperPruneConfig;
}

/**
* The configuration of blacklisted features.
*
* @return configuration of blacklisted features
*/
public FeatureBlacklistConfig getFeatureBlacklistConfig() {
return featureBlacklistConfig;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.togetherjava.tjbot.config;

import com.fasterxml.jackson.annotation.JsonCreator;

import java.util.Set;

/**
* Blacklist of features, use {@link FeatureBlacklist#isEnabled(T)} to test if a feature is enabled.
Zabuzard marked this conversation as resolved.
Show resolved Hide resolved
* If a feature is blacklisted, it won't be enabled by the bot, and so will be ignored.
*
* @param <T> the type of the feature identifier
Zabuzard marked this conversation as resolved.
Show resolved Hide resolved
*/
public class FeatureBlacklist<T> {
private final Set<T> featureIdentifierBlacklist;

/**
* Creates a feature blacklist
*
* @param featureIdentifierBlacklist a set of identifiers which are blacklisted
*/
@JsonCreator
public FeatureBlacklist(Set<T> featureIdentifierBlacklist) {
this.featureIdentifierBlacklist = Set.copyOf(featureIdentifierBlacklist);
}

/**
* Returns if a feature is enabled or not.
*
* @param featureId the identifier of the feature
* @return true if a feature is enabled, false otherwise
*/
public boolean isEnabled(T featureId) {
return !featureIdentifierBlacklist.contains(featureId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.togetherjava.tjbot.config;

import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.Objects;

/**
* Configuration of the feature blacklist, any feature present here will be disabled.
*
* @param normal the normal features, which are present in
* {@link org.togetherjava.tjbot.features.Features}
* @param special the special features, which require special code
*/
public record FeatureBlacklistConfig(
@JsonProperty(value = "normal", required = true) FeatureBlacklist<Class<?>> normal,
@JsonProperty(value = "special", required = true) FeatureBlacklist<String> special) {

/**
* Creates a FeatureBlacklistConfig.
*
* @param normal the list of normal features, must be not null
* @param special the list of special features, must be not null
*/
public FeatureBlacklistConfig {
Objects.requireNonNull(normal);
Objects.requireNonNull(special);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import net.dv8tion.jda.api.JDA;

import org.togetherjava.tjbot.config.Config;
import org.togetherjava.tjbot.config.FeatureBlacklist;
import org.togetherjava.tjbot.config.FeatureBlacklistConfig;
import org.togetherjava.tjbot.db.Database;
import org.togetherjava.tjbot.features.basic.PingCommand;
import org.togetherjava.tjbot.features.basic.RoleSelectCommand;
Expand All @@ -19,6 +21,7 @@
import org.togetherjava.tjbot.features.code.CodeMessageManualDetection;
import org.togetherjava.tjbot.features.filesharing.FileSharingMessageListener;
import org.togetherjava.tjbot.features.help.*;
import org.togetherjava.tjbot.features.jshell.JShellCommand;
import org.togetherjava.tjbot.features.jshell.JShellEval;
import org.togetherjava.tjbot.features.mathcommands.TeXCommand;
import org.togetherjava.tjbot.features.mathcommands.wolframalpha.WolframAlphaCommand;
Expand Down Expand Up @@ -73,14 +76,16 @@ private Features() {
* @return a collection of all features
*/
public static Collection<Feature> createFeatures(JDA jda, Database database, Config config) {
FeatureBlacklistConfig blacklistConfig = config.getFeatureBlacklistConfig();
JShellEval jshellEval = new JShellEval(config.getJshell());

TagSystem tagSystem = new TagSystem(database);
BookmarksSystem bookmarksSystem = new BookmarksSystem(config, database);
ModerationActionsStore actionsStore = new ModerationActionsStore(database);
ModAuditLogWriter modAuditLogWriter = new ModAuditLogWriter(config);
ScamHistoryStore scamHistoryStore = new ScamHistoryStore(database);
CodeMessageHandler codeMessageHandler = new CodeMessageHandler(jshellEval);
CodeMessageHandler codeMessageHandler =
new CodeMessageHandler(blacklistConfig.special(), jshellEval);
ChatGptService chatGptService = new ChatGptService(config);
HelpSystemHelper helpSystemHelper = new HelpSystemHelper(config, database, chatGptService);

Expand Down Expand Up @@ -151,7 +156,9 @@ public static Collection<Feature> createFeatures(JDA jda, Database database, Con
features.add(new ReportCommand(config));
features.add(new BookmarksCommand(bookmarksSystem));
features.add(new ChatGptCommand(chatGptService));
// features.add(new JShellCommand(jshellEval));
return features;
features.add(new JShellCommand(jshellEval));

FeatureBlacklist<Class<?>> blacklist = blacklistConfig.normal();
return features.stream().filter(f -> blacklist.isEnabled(f.getClass())).toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.togetherjava.tjbot.config.FeatureBlacklist;
import org.togetherjava.tjbot.features.MessageReceiverAdapter;
import org.togetherjava.tjbot.features.UserInteractionType;
import org.togetherjava.tjbot.features.UserInteractor;
Expand All @@ -30,6 +31,7 @@
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* Handles code in registered messages and offers code actions to the user, such as formatting their
Expand Down Expand Up @@ -63,14 +65,18 @@ public final class CodeMessageHandler extends MessageReceiverAdapter implements

/**
* Creates a new instance.
*
*
* @param blacklist the feature blacklist, used to test if certain code actions should be
* disabled
* @param jshellEval used to execute java code and build visual result
*/
public CodeMessageHandler(JShellEval jshellEval) {
public CodeMessageHandler(FeatureBlacklist<String> blacklist, JShellEval jshellEval) {
componentIdInteractor = new ComponentIdInteractor(getInteractionType(), getName());

List<CodeAction> codeActions =
List.of(new FormatCodeCommand()/* , new EvalCodeCommand(jshellEval) */);
Stream.of(new FormatCodeCommand(), new EvalCodeCommand(jshellEval))
.filter(a -> blacklist.isEnabled(a.getClass().getSimpleName()))
.toList();

labelToCodeAction = codeActions.stream()
.collect(Collectors.toMap(CodeAction::getLabel, Function.identity(), (x, y) -> y,
Expand Down
Loading