Skip to content

Commit 900780c

Browse files
committed
JShell javadoc and many minor code improvements
1 parent 7fa5e1e commit 900780c

19 files changed

+277
-64
lines changed

application/src/main/java/org/togetherjava/tjbot/config/JShellConfig.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,43 @@
22

33
import com.linkedin.urls.Url;
44

5+
import org.togetherjava.tjbot.features.utils.RateLimiter;
6+
57
import java.net.MalformedURLException;
68

9+
/**
10+
* JShell config.
11+
*
12+
* @param baseUrl the base url of the JShell REST API
13+
* @param rateLimitWindowSeconds the number of seconds of the {@link RateLimiter rate limiter} for
14+
* jshell commands and code actions
15+
* @param rateLimitRequestsInWindow the number of requests of the {@link RateLimiter rate limiter}
16+
* for jshell commands and code actions
17+
*/
718
public record JShellConfig(String baseUrl, int rateLimitWindowSeconds,
819
int rateLimitRequestsInWindow) {
20+
/**
21+
* Creates a JShell config.
22+
*
23+
* @param baseUrl the base url of the JShell REST API, must be valid
24+
* @param rateLimitWindowSeconds the number of seconds of the {@link RateLimiter rate limiter}
25+
* for jshell commands and code actions, must be higher than 0
26+
* @param rateLimitRequestsInWindow the number of requests of the {@link RateLimiter rate
27+
* limiter} for jshell commands and code actions, must be higher than 0
28+
*/
929
public JShellConfig {
1030
try {
1131
Url.create(baseUrl);
1232
} catch (MalformedURLException e) {
1333
throw new IllegalArgumentException(e);
1434
}
15-
if (rateLimitWindowSeconds <= 0)
35+
if (rateLimitWindowSeconds < 0) {
1636
throw new IllegalArgumentException(
1737
"Illegal rateLimitWindowSeconds : " + rateLimitWindowSeconds);
18-
if (rateLimitRequestsInWindow <= 0)
38+
}
39+
if (rateLimitRequestsInWindow < 0) {
1940
throw new IllegalArgumentException(
2041
"Illegal rateLimitRequestsInWindow : " + rateLimitRequestsInWindow);
42+
}
2143
}
2244
}

application/src/main/java/org/togetherjava/tjbot/features/code/CodeMessageHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public final class CodeMessageHandler extends MessageReceiverAdapter implements
6363

6464
/**
6565
* Creates a new instance.
66+
*
67+
* @param jshellEval the jshell evaluation instance used in the code actions
6668
*/
6769
public CodeMessageHandler(JShellEval jshellEval) {
6870
componentIdInteractor = new ComponentIdInteractor(getInteractionType(), getName());

application/src/main/java/org/togetherjava/tjbot/features/code/EvalCodeCommand.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
import net.dv8tion.jda.api.entities.MessageEmbed;
55

66
import org.togetherjava.tjbot.features.jshell.JShellEval;
7-
import org.togetherjava.tjbot.features.jshell.render.Colors;
87
import org.togetherjava.tjbot.features.utils.CodeFence;
8+
import org.togetherjava.tjbot.features.utils.Colors;
99
import org.togetherjava.tjbot.features.utils.RequestFailedException;
1010

1111
/**
12-
* Evaluates the given code.
12+
* Evaluates the given code with jshell.
13+
* <p>
14+
* It will not work of the code isn't valid java or jshell compatible code.
1315
*/
1416
final class EvalCodeCommand implements CodeAction {
1517
private final JShellEval jshellEval;

application/src/main/java/org/togetherjava/tjbot/features/jshell/JShellCommand.java

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,30 @@
2020
import org.togetherjava.tjbot.features.CommandVisibility;
2121
import org.togetherjava.tjbot.features.SlashCommandAdapter;
2222
import org.togetherjava.tjbot.features.jshell.backend.JShellApi;
23-
import org.togetherjava.tjbot.features.jshell.render.Colors;
23+
import org.togetherjava.tjbot.features.utils.Colors;
24+
import org.togetherjava.tjbot.features.utils.MessageUtils;
2425
import org.togetherjava.tjbot.features.utils.RequestFailedException;
2526

2627
import javax.annotation.Nullable;
2728

2829
import java.util.List;
2930
import java.util.Objects;
3031

32+
/**
33+
* The JShell command, provide functionalities to create JShell sessions, evaluate code, etc.
34+
*/
3135
public class JShellCommand extends SlashCommandAdapter {
32-
private static final String JSHELL_TEXT_INPUT_ID = "jshell";
36+
private static final String TEXT_INPUT_PART_ID = "jshell";
3337
private static final String JSHELL_COMMAND = "jshell";
34-
private static final String JSHELL_VERSION_SUBCOMMAND = "version";
35-
private static final String JSHELL_EVAL_SUBCOMMAND = "eval";
36-
private static final String JSHELL_SNIPPETS_SUBCOMMAND = "snippets";
37-
private static final String JSHELL_CLOSE_SUBCOMMAND = "shutdown";
38-
private static final String JSHELL_STARTUP_SCRIPT_SUBCOMMAND = "startup-script";
39-
private static final String JSHELL_CODE_PARAMETER = "code";
40-
private static final String JSHELL_STARTUP_SCRIPT_PARAMETER = "startup-script";
41-
private static final String JSHELL_USER_PARAMETER = "user";
42-
private static final String JSHELL_INCLUDE_STARTUP_SCRIPT_PARAMETER = "include-startup-script";
38+
private static final String VERSION_SUBCOMMAND = "version";
39+
private static final String EVAL_SUBCOMMAND = "eval";
40+
private static final String SNIPPETS_SUBCOMMAND = "snippets";
41+
private static final String CLOSE_SUBCOMMAND = "shutdown";
42+
private static final String STARTUP_SCRIPT_SUBCOMMAND = "startup-script";
43+
private static final String CODE_PARAMETER = "code";
44+
private static final String STARTUP_SCRIPT_PARAMETER = "startup-script";
45+
private static final String USER_PARAMETER = "user";
46+
private static final String INCLUDE_STARTUP_SCRIPT_PARAMETER = "include-startup-script";
4347

4448
private static final int MIN_MESSAGE_INPUT_LENGTH = 0;
4549
private static final int MAX_MESSAGE_INPUT_LENGTH = TextInput.MAX_VALUE_LENGTH;
@@ -48,51 +52,53 @@ public class JShellCommand extends SlashCommandAdapter {
4852

4953
/**
5054
* Creates an instance of the command.
55+
*
56+
* @param jshellEval the jshell evaluation instance used in the jshell command
5157
*/
5258
public JShellCommand(JShellEval jshellEval) {
53-
super(JSHELL_COMMAND, "JShell as a command.", CommandVisibility.GUILD);
59+
super(JSHELL_COMMAND,
60+
"JShell as a command, a Read–eval–print loop which allows to rapidly and simply execute java code.",
61+
CommandVisibility.GUILD);
5462

5563
this.jshellEval = jshellEval;
5664

5765
getData().addSubcommands(
58-
new SubcommandData(JSHELL_VERSION_SUBCOMMAND, "Get the version of JShell"),
59-
new SubcommandData(JSHELL_EVAL_SUBCOMMAND,
60-
"Evaluate java code in JShell, don't fill the optional parameter to access a bigger input box.")
61-
.addOption(OptionType.STRING, JSHELL_CODE_PARAMETER,
62-
"Code to evaluate. If not supplied, open an inout box.")
63-
.addOption(OptionType.BOOLEAN, JSHELL_STARTUP_SCRIPT_PARAMETER,
66+
new SubcommandData(VERSION_SUBCOMMAND, "Get the version of JShell"),
67+
new SubcommandData(EVAL_SUBCOMMAND,
68+
"Evaluate java code in JShell, submit the command without code for inputting longer, multi-line code.")
69+
.addOption(OptionType.STRING, CODE_PARAMETER,
70+
"Code to evaluate. Leave empty to input longer, multi-line code.")
71+
.addOption(OptionType.BOOLEAN, STARTUP_SCRIPT_PARAMETER,
6472
"If the startup script should be loaded, true by default."),
65-
new SubcommandData(JSHELL_SNIPPETS_SUBCOMMAND,
66-
"Get the evaluated snippets of the user who sent the command, or the user specified user if any.")
67-
.addOption(OptionType.USER, JSHELL_USER_PARAMETER,
68-
"User to get the snippets from. If null, get the snippets of the user who sent the command.")
69-
.addOption(OptionType.BOOLEAN, JSHELL_INCLUDE_STARTUP_SCRIPT_PARAMETER,
73+
new SubcommandData(SNIPPETS_SUBCOMMAND,
74+
"Display your snippets, or the snippets of the specified user if any.")
75+
.addOption(OptionType.USER, USER_PARAMETER,
76+
"User to get the snippets from. If null, get your snippets.")
77+
.addOption(OptionType.BOOLEAN, INCLUDE_STARTUP_SCRIPT_PARAMETER,
7078
"if the startup script should be included, false by default."),
71-
new SubcommandData(JSHELL_CLOSE_SUBCOMMAND, "Close your session."),
72-
new SubcommandData(JSHELL_STARTUP_SCRIPT_SUBCOMMAND,
73-
"Display the startup script."));
79+
new SubcommandData(CLOSE_SUBCOMMAND, "Close your session."),
80+
new SubcommandData(STARTUP_SCRIPT_SUBCOMMAND, "Display the startup script."));
7481
}
7582

7683
@Override
7784
public void onSlashCommand(SlashCommandInteractionEvent event) {
7885
switch (Objects.requireNonNull(event.getSubcommandName())) {
79-
case JSHELL_VERSION_SUBCOMMAND -> handleVersionCommand(event);
80-
case JSHELL_EVAL_SUBCOMMAND -> handleEvalCommand(event);
81-
case JSHELL_SNIPPETS_SUBCOMMAND -> handleSnippetsCommand(event);
82-
case JSHELL_CLOSE_SUBCOMMAND -> handleCloseCommand(event);
83-
case JSHELL_STARTUP_SCRIPT_SUBCOMMAND -> handleStartupScriptCommand(event);
86+
case VERSION_SUBCOMMAND -> handleVersionCommand(event);
87+
case EVAL_SUBCOMMAND -> handleEvalCommand(event);
88+
case SNIPPETS_SUBCOMMAND -> handleSnippetsCommand(event);
89+
case CLOSE_SUBCOMMAND -> handleCloseCommand(event);
90+
case STARTUP_SCRIPT_SUBCOMMAND -> handleStartupScriptCommand(event);
8491
default -> throw new AssertionError(
8592
"Unexpected Subcommand: " + event.getSubcommandName());
8693
}
8794
}
8895

8996
@Override
9097
public void onModalSubmitted(ModalInteractionEvent event, List<String> args) {
91-
ModalMapping mapping =
92-
event.getValue(JSHELL_TEXT_INPUT_ID + "|" + JSHELL_STARTUP_SCRIPT_PARAMETER);
98+
ModalMapping mapping = event.getValue(TEXT_INPUT_PART_ID + "|" + STARTUP_SCRIPT_PARAMETER);
9399
boolean startupScript = mapping != null;
94100
if (mapping == null) {
95-
mapping = event.getValue(JSHELL_TEXT_INPUT_ID);
101+
mapping = event.getValue(TEXT_INPUT_PART_ID);
96102
}
97103
if (mapping != null) {
98104
handleEval(event, event.getUser(), true, mapping.getAsString(), startupScript);
@@ -106,15 +112,14 @@ private void handleVersionCommand(SlashCommandInteractionEvent event) {
106112
System.out.println("Vendor: " + System.getProperty("java.vendor"));
107113
System.out.println("OS: " + System.getProperty("os.name"));
108114
System.out.println("Arch: " + System.getProperty("os.arch"));
109-
System.out.println("```");""";
115+
System.out.println("```");""";
110116
handleEval(event, null, false, code, false);
111117
}
112118

113119
private void handleEvalCommand(SlashCommandInteractionEvent event) {
114-
OptionMapping code = event.getOption(JSHELL_CODE_PARAMETER);
115-
boolean startupScript = event.getOption(JSHELL_STARTUP_SCRIPT_PARAMETER) == null
116-
|| Objects.requireNonNull(event.getOption(JSHELL_STARTUP_SCRIPT_PARAMETER))
117-
.getAsBoolean();
120+
OptionMapping code = event.getOption(CODE_PARAMETER);
121+
boolean startupScript = event.getOption(STARTUP_SCRIPT_PARAMETER) == null
122+
|| Objects.requireNonNull(event.getOption(STARTUP_SCRIPT_PARAMETER)).getAsBoolean();
118123
if (code == null) {
119124
sendEvalModal(event, startupScript);
120125
} else {
@@ -124,8 +129,7 @@ private void handleEvalCommand(SlashCommandInteractionEvent event) {
124129

125130
private void sendEvalModal(SlashCommandInteractionEvent event, boolean startupScript) {
126131
TextInput body = TextInput
127-
.create(JSHELL_TEXT_INPUT_ID
128-
+ (startupScript ? "|" + JSHELL_STARTUP_SCRIPT_PARAMETER : ""),
132+
.create(TEXT_INPUT_PART_ID + (startupScript ? "|" + STARTUP_SCRIPT_PARAMETER : ""),
129133
"Enter code to evaluate.", TextInputStyle.PARAGRAPH)
130134
.setPlaceholder("Put your code here.")
131135
.setRequiredRange(MIN_MESSAGE_INPUT_LENGTH, MAX_MESSAGE_INPUT_LENGTH)
@@ -160,10 +164,10 @@ private void handleEval(IReplyCallback replyCallback, @Nullable User user, boole
160164

161165
private void handleSnippetsCommand(SlashCommandInteractionEvent event) {
162166
event.deferReply().queue(interactionHook -> {
163-
OptionMapping userOption = event.getOption(JSHELL_USER_PARAMETER);
167+
OptionMapping userOption = event.getOption(USER_PARAMETER);
164168
User user = userOption == null ? event.getUser() : userOption.getAsUser();
165169
OptionMapping includeStartupScriptOption =
166-
event.getOption(JSHELL_INCLUDE_STARTUP_SCRIPT_PARAMETER);
170+
event.getOption(INCLUDE_STARTUP_SCRIPT_PARAMETER);
167171
boolean includeStartupScript =
168172
includeStartupScriptOption != null && includeStartupScriptOption.getAsBoolean();
169173
List<String> snippets;
@@ -185,10 +189,7 @@ private void handleSnippetsCommand(SlashCommandInteractionEvent event) {
185189
&& snippets.stream()
186190
.mapToInt(s -> (s + "Snippet 10```java\n```").length())
187191
.sum() < MessageEmbed.EMBED_MAX_LENGTH_BOT - 100
188-
&& snippets.size() <= 25/*
189-
* Max visible embed fields in an embed TODO replace
190-
* with constant
191-
*/) {
192+
&& snippets.size() <= MessageUtils.MAXIMUM_VISIBLE_EMBEDS) {
192193
sendSnippetsAsEmbed(interactionHook, user, snippets);
193194
} else if (snippets.stream()
194195
.mapToInt(s -> (s + "// Snippet 10").getBytes().length)

application/src/main/java/org/togetherjava/tjbot/features/jshell/JShellEval.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
import org.togetherjava.tjbot.config.JShellConfig;
1010
import org.togetherjava.tjbot.features.jshell.backend.JShellApi;
1111
import org.togetherjava.tjbot.features.jshell.backend.dto.JShellResult;
12-
import org.togetherjava.tjbot.features.jshell.render.Colors;
13-
import org.togetherjava.tjbot.features.jshell.render.ResultRenderer;
12+
import org.togetherjava.tjbot.features.utils.Colors;
1413
import org.togetherjava.tjbot.features.utils.RateLimiter;
1514
import org.togetherjava.tjbot.features.utils.RequestFailedException;
1615

@@ -19,12 +18,21 @@
1918
import java.time.Duration;
2019
import java.time.Instant;
2120

21+
/**
22+
* Provides a mid-ground between JDA and JShell API which can be used from many places in the bot,
23+
* including JShell commands and JShell code actions.
24+
*/
2225
public class JShellEval {
2326
private final JShellApi api;
2427

2528
private final ResultRenderer renderer;
2629
private final RateLimiter rateLimiter;
2730

31+
/**
32+
* Creates a JShell evaluation instance
33+
*
34+
* @param config the JShell configuration to use
35+
*/
2836
public JShellEval(JShellConfig config) {
2937
this.api = new JShellApi(new ObjectMapper(), config.baseUrl());
3038
this.renderer = new ResultRenderer();
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.togetherjava.tjbot.features.jshell.render;
1+
package org.togetherjava.tjbot.features.jshell;
22

33
import net.dv8tion.jda.api.EmbedBuilder;
44
import net.dv8tion.jda.api.entities.MessageEmbed;
@@ -12,9 +12,9 @@
1212

1313
import java.awt.Color;
1414

15-
import static org.togetherjava.tjbot.features.jshell.render.Colors.*;
15+
import static org.togetherjava.tjbot.features.utils.Colors.*;
1616

17-
public class ResultRenderer {
17+
class ResultRenderer {
1818

1919
public EmbedBuilder renderToEmbed(@Nullable User originator, @Nullable String originalCode,
2020
boolean partOfSession, JShellResult result, EmbedBuilder builder) {

0 commit comments

Comments
 (0)