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

Feature/jshell #870

Merged
merged 9 commits into from
Aug 11, 2023
Merged
5 changes: 5 additions & 0 deletions application/config.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,9 @@
"logErrorChannelWebhook": "<put_your_webhook_here>",
"openaiApiKey": "<check pins in #tjbot_discussion for the key>",
"sourceCodeBaseUrl": "<https://github.com/<your_account_here>/<your_repo_here>/blob/master/application/src/main/java/>"
"jshell": {
"baseUrl": "<put_jshell_rest_api_url_here>",
"rateLimitWindowSeconds": 10,
"rateLimitRequestsInWindow": 3
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public final class Config {
private final String logErrorChannelWebhook;
private final String openaiApiKey;
private final String sourceCodeBaseUrl;
private final JShellConfig jshell;

@SuppressWarnings("ConstructorWithTooManyParameters")
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
Expand Down Expand Up @@ -74,7 +75,8 @@ private Config(@JsonProperty(value = "token", required = true) String token,
@JsonProperty(value = "logErrorChannelWebhook",
required = true) String logErrorChannelWebhook,
@JsonProperty(value = "openaiApiKey", required = true) String openaiApiKey,
@JsonProperty(value = "sourceCodeBaseUrl", required = true) String sourceCodeBaseUrl) {
@JsonProperty(value = "sourceCodeBaseUrl", required = true) String sourceCodeBaseUrl,
@JsonProperty(value = "jshell", required = true) JShellConfig jshell) {
this.token = Objects.requireNonNull(token);
this.gistApiKey = Objects.requireNonNull(gistApiKey);
this.databasePath = Objects.requireNonNull(databasePath);
Expand All @@ -99,6 +101,7 @@ private Config(@JsonProperty(value = "token", required = true) String token,
this.logErrorChannelWebhook = Objects.requireNonNull(logErrorChannelWebhook);
this.openaiApiKey = Objects.requireNonNull(openaiApiKey);
this.sourceCodeBaseUrl = Objects.requireNonNull(sourceCodeBaseUrl);
this.jshell = Objects.requireNonNull(jshell);
}

/**
Expand Down Expand Up @@ -330,4 +333,13 @@ public String getOpenaiApiKey() {
public String getSourceCodeBaseUrl() {
return sourceCodeBaseUrl;
}

/**
* The configuration about jshell REST API and command/code action settings.
*
* @return the jshell configuration
*/
public JShellConfig getJshell() {
return jshell;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.togetherjava.tjbot.config;


import org.togetherjava.tjbot.features.utils.RateLimiter;

import java.util.Objects;

/**
* JShell config.
*
* @param baseUrl the base url of the JShell REST API
* @param rateLimitWindowSeconds the number of seconds of the {@link RateLimiter rate limiter} for
* jshell commands and code actions
* @param rateLimitRequestsInWindow the number of requests of the {@link RateLimiter rate limiter}
* for jshell commands and code actions
*/
public record JShellConfig(String baseUrl, int rateLimitWindowSeconds,
int rateLimitRequestsInWindow) {
/**
* Creates a JShell config.
*
* @param baseUrl the base url of the JShell REST API, must be not null
* @param rateLimitWindowSeconds the number of seconds of the {@link RateLimiter rate limiter}
* for jshell commands and code actions, must be higher than 0
* @param rateLimitRequestsInWindow the number of requests of the {@link RateLimiter rate
* limiter} for jshell commands and code actions, must be higher than 0
SquidXTV marked this conversation as resolved.
Show resolved Hide resolved
*/
public JShellConfig {
Objects.requireNonNull(baseUrl);
if (rateLimitWindowSeconds < 0) {
throw new IllegalArgumentException(
"Illegal rateLimitWindowSeconds : " + rateLimitWindowSeconds);
}
if (rateLimitRequestsInWindow < 0) {
throw new IllegalArgumentException(
"Illegal rateLimitRequestsInWindow : " + rateLimitRequestsInWindow);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
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;
import org.togetherjava.tjbot.features.mediaonly.MediaOnlyChannelListener;
Expand Down Expand Up @@ -67,13 +69,15 @@ private Features() {
* @return a collection of all features
*/
public static Collection<Feature> createFeatures(JDA jda, Database database, Config config) {
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);
HelpSystemHelper helpSystemHelper = new HelpSystemHelper(config, database);
CodeMessageHandler codeMessageHandler = new CodeMessageHandler();
CodeMessageHandler codeMessageHandler = new CodeMessageHandler(jshellEval);
ChatGptService chatGptService = new ChatGptService(config);

// NOTE The system can add special system relevant commands also by itself,
Expand Down Expand Up @@ -143,6 +147,7 @@ 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.togetherjava.tjbot.features.UserInteractor;
import org.togetherjava.tjbot.features.componentids.ComponentIdGenerator;
import org.togetherjava.tjbot.features.componentids.ComponentIdInteractor;
import org.togetherjava.tjbot.features.jshell.JShellEval;
import org.togetherjava.tjbot.features.utils.CodeFence;
import org.togetherjava.tjbot.features.utils.MessageUtils;

Expand Down Expand Up @@ -62,11 +63,14 @@ public final class CodeMessageHandler extends MessageReceiverAdapter implements

/**
* Creates a new instance.
*
* @param jshellEval used to execute java code and build visual result
*/
public CodeMessageHandler() {
public CodeMessageHandler(JShellEval jshellEval) {
componentIdInteractor = new ComponentIdInteractor(getInteractionType(), getName());

List<CodeAction> codeActions = List.of(new FormatCodeCommand());
List<CodeAction> codeActions =
List.of(new FormatCodeCommand(), new EvalCodeCommand(jshellEval));

labelToCodeAction = codeActions.stream()
.collect(Collectors.toMap(CodeAction::getLabel, Function.identity(), (x, y) -> y,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.togetherjava.tjbot.features.code;

import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;

import org.togetherjava.tjbot.features.jshell.JShellEval;
import org.togetherjava.tjbot.features.utils.CodeFence;
import org.togetherjava.tjbot.features.utils.Colors;
import org.togetherjava.tjbot.features.utils.ConnectionFailedException;
import org.togetherjava.tjbot.features.utils.RequestFailedException;

/**
* Evaluates the given code with jshell.
* <p>
* It will not work of the code isn't valid java or jshell compatible code.
*/
final class EvalCodeCommand implements CodeAction {
private final JShellEval jshellEval;

EvalCodeCommand(JShellEval jshellEval) {
this.jshellEval = jshellEval;
}

@Override
public String getLabel() {
return "Run code";
}

@Override
public MessageEmbed apply(CodeFence codeFence) {
if (codeFence.code().isEmpty()) {
return new EmbedBuilder().setColor(Colors.ERROR_COLOR)
.setDescription("There is nothing to evaluate")
.build();
}
try {
return jshellEval.evaluateAndRespond(null, codeFence.code(), false, false);
} catch (RequestFailedException | ConnectionFailedException e) {
return new EmbedBuilder().setColor(Colors.ERROR_COLOR)
.setDescription("Request failed: " + e.getMessage())
.build();
}
}

}
Loading
Loading