Skip to content
This repository was archived by the owner on Dec 1, 2021. It is now read-only.

Commit c40b4e8

Browse files
committed
Added more response infrastructure and implemented a purge command.
1 parent 160e6ee commit c40b4e8

File tree

12 files changed

+235
-27
lines changed

12 files changed

+235
-27
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package net.javadiscord.javabot2.command;
2+
3+
import lombok.Getter;
4+
import org.javacord.api.interaction.callback.InteractionImmediateResponseBuilder;
5+
6+
import java.util.function.Supplier;
7+
8+
/**
9+
* An exception which can be thrown so that the bot can respond with a well
10+
* formatted error or warning response, while still allowing you to take
11+
* advantage of throwing an exception up the call stack.
12+
*/
13+
public class ResponseException extends Exception {
14+
@Getter
15+
private final InteractionImmediateResponseBuilder responseBuilder;
16+
17+
public ResponseException(InteractionImmediateResponseBuilder responseBuilder) {
18+
this.responseBuilder = responseBuilder;
19+
}
20+
21+
public static Supplier<ResponseException> warning(String message) {
22+
return () -> new ResponseException(Responses.deferredWarningBuilder().message(message).build());
23+
}
24+
25+
public static Supplier<ResponseException> error(String message) {
26+
return () -> new ResponseException(Responses.deferredErrorBuilder().message(message).build());
27+
}
28+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package net.javadiscord.javabot2.command;
2+
3+
import org.javacord.api.entity.message.MessageFlag;
4+
import org.javacord.api.entity.message.embed.EmbedBuilder;
5+
import org.javacord.api.event.interaction.SlashCommandCreateEvent;
6+
import org.javacord.api.interaction.InteractionBase;
7+
import org.javacord.api.interaction.callback.InteractionImmediateResponseBuilder;
8+
import org.javacord.api.interaction.callback.InteractionOriginalResponseUpdater;
9+
10+
import java.awt.*;
11+
import java.util.concurrent.CompletableFuture;
12+
13+
/**
14+
* Provides methods for standardized replies to interaction events.
15+
*/
16+
public class Responses {
17+
public static InteractionImmediateResponseBuilder success(InteractionBase interaction, String title, String message) {
18+
return reply(interaction, title, message, Color.GREEN, true);
19+
}
20+
21+
public static ResponseBuilder successBuilder(InteractionBase interaction) {
22+
return new ResponseBuilder(interaction, Color.GREEN).title("Success");
23+
}
24+
25+
public static ResponseBuilder successBuilder(SlashCommandCreateEvent event) {
26+
return successBuilder(event.getSlashCommandInteraction());
27+
}
28+
29+
public static InteractionImmediateResponseBuilder info(InteractionBase interaction, String title, String message) {
30+
return reply(interaction, title, message, Color.BLUE, true);
31+
}
32+
33+
public static ResponseBuilder infoBuilder(InteractionBase interaction) {
34+
return new ResponseBuilder(interaction, Color.BLUE).title("Info");
35+
}
36+
37+
public static ResponseBuilder infoBuilder(SlashCommandCreateEvent event) {
38+
return infoBuilder(event.getSlashCommandInteraction());
39+
}
40+
41+
public static InteractionImmediateResponseBuilder warning(InteractionBase interaction, String title, String message) {
42+
return reply(interaction, title, message, Color.ORANGE, true);
43+
}
44+
45+
public static InteractionImmediateResponseBuilder warning(InteractionBase interaction, String message) {
46+
return warning(interaction, "Warning", message);
47+
}
48+
49+
public static ResponseBuilder warningBuilder(InteractionBase interaction) {
50+
return new ResponseBuilder(interaction, Color.ORANGE).title("Warning");
51+
}
52+
53+
public static ResponseBuilder warningBuilder(SlashCommandCreateEvent event) {
54+
return warningBuilder(event.getSlashCommandInteraction());
55+
}
56+
57+
public static ResponseBuilder deferredWarningBuilder() {
58+
return new ResponseBuilder(Color.ORANGE).title("Warning");
59+
}
60+
61+
public static InteractionImmediateResponseBuilder error(InteractionBase interaction, String message) {
62+
return reply(interaction, "An Error Occurred", message, Color.RED, true);
63+
}
64+
65+
public static ResponseBuilder errorBuilder(InteractionBase interaction) {
66+
return new ResponseBuilder(interaction, Color.RED).title("An Error Occurred");
67+
}
68+
69+
public static ResponseBuilder errorBuilder(SlashCommandCreateEvent event) {
70+
return errorBuilder(event.getSlashCommandInteraction());
71+
}
72+
73+
public static ResponseBuilder deferredErrorBuilder() {
74+
return new ResponseBuilder(Color.RED).title("An Error Occurred");
75+
}
76+
77+
private static InteractionImmediateResponseBuilder reply(
78+
InteractionBase interaction,
79+
String title,
80+
String message,
81+
Color color,
82+
boolean ephemeral
83+
) {
84+
var responder = interaction.createImmediateResponder()
85+
.addEmbed(new EmbedBuilder()
86+
.setTitle(title)
87+
.setColor(color)
88+
.setTimestampToNow()
89+
.setDescription(message));
90+
if (ephemeral) {
91+
responder.setFlags(MessageFlag.EPHEMERAL);
92+
}
93+
return responder;
94+
}
95+
96+
/**
97+
* A builder that's used to construct a response using a fluent interface.
98+
*/
99+
public static class ResponseBuilder {
100+
private InteractionBase interaction;
101+
private String title = null;
102+
private String message = null;
103+
private final Color color;
104+
private boolean ephemeral = true;
105+
106+
private ResponseBuilder(InteractionBase interaction, Color color) {
107+
this.interaction = interaction;
108+
this.color = color;
109+
}
110+
111+
private ResponseBuilder(Color color) {
112+
this(null, color);
113+
}
114+
115+
public ResponseBuilder title(String title) {
116+
this.title = title;
117+
return this;
118+
}
119+
120+
public ResponseBuilder message(String message) {
121+
this.message = message;
122+
return this;
123+
}
124+
125+
public ResponseBuilder makePublic() {
126+
this.ephemeral = false;
127+
return this;
128+
}
129+
130+
public InteractionImmediateResponseBuilder build() {
131+
return reply(interaction, title, message, color, ephemeral);
132+
}
133+
134+
public InteractionImmediateResponseBuilder build(InteractionBase interaction) {
135+
this.interaction = interaction;
136+
return build();
137+
}
138+
139+
public CompletableFuture<InteractionOriginalResponseUpdater> respond(InteractionBase interaction) {
140+
this.interaction = interaction;
141+
return build().respond();
142+
}
143+
144+
public CompletableFuture<InteractionOriginalResponseUpdater> respond() {
145+
return this.build().respond();
146+
}
147+
}
148+
}

src/main/java/net/javadiscord/javabot2/command/SlashCommandHandler.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
import org.javacord.api.interaction.SlashCommandInteraction;
44
import org.javacord.api.interaction.callback.InteractionImmediateResponseBuilder;
55

6+
/**
7+
* An interface that should be implemented by any class that is defined as a
8+
* handler in any command configuration file.
9+
*/
610
public interface SlashCommandHandler {
711
InteractionImmediateResponseBuilder handle(SlashCommandInteraction interaction) throws Exception;
812
}

src/main/java/net/javadiscord/javabot2/command/SlashCommandListener.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package net.javadiscord.javabot2.command;
22

33
import lombok.extern.slf4j.Slf4j;
4+
import net.javadiscord.javabot2.command.data.CommandConfig;
5+
import net.javadiscord.javabot2.command.data.CommandDataLoader;
46
import org.javacord.api.DiscordApi;
5-
import org.javacord.api.entity.message.MessageFlag;
67
import org.javacord.api.event.interaction.SlashCommandCreateEvent;
78
import org.javacord.api.interaction.ServerSlashCommandPermissionsBuilder;
89
import org.javacord.api.interaction.SlashCommandBuilder;
@@ -21,6 +22,13 @@
2122
public final class SlashCommandListener implements SlashCommandCreateListener {
2223
private final Map<Long, SlashCommandHandler> commandHandlers = new HashMap<>();
2324

25+
/**
26+
* Constructs a new slash command listener using the given Discord api, and
27+
* loads commands from configuration YAML files according to the list of
28+
* resources.
29+
* @param api The Discord api to use.
30+
* @param resources The list of classpath resources to load commands from.
31+
*/
2432
public SlashCommandListener(DiscordApi api, String... resources) {
2533
registerSlashCommands(api, resources)
2634
.thenAcceptAsync(commandHandlers::putAll);
@@ -32,17 +40,18 @@ public void onSlashCommandCreate(SlashCommandCreateEvent event) {
3240
if (handler != null) {
3341
try {
3442
handler.handle(event.getSlashCommandInteraction()).respond();
43+
} catch (ResponseException e) {
44+
e.getResponseBuilder().respond();
3545
} catch (Exception e) {
3646
log.error("An error occurred while handling a slash command.", e);
37-
event.getSlashCommandInteraction().createImmediateResponder()
38-
.setFlags(MessageFlag.EPHEMERAL)
39-
.append("An error occurred.")
47+
Responses.errorBuilder(event)
48+
.message("An error occurred while executing the command.")
4049
.respond();
4150
}
4251
} else {
43-
event.getSlashCommandInteraction().createImmediateResponder()
44-
.setFlags(MessageFlag.EPHEMERAL)
45-
.append("There is no associated handler for this command. Please contact an administrator if this error persists.")
52+
Responses.warningBuilder(event)
53+
.title("No Handler")
54+
.message("There is no associated handler for this command. Please contact an administrator if this error persists.")
4655
.respond();
4756
}
4857
}

src/main/java/net/javadiscord/javabot2/command/CommandConfig.java renamed to src/main/java/net/javadiscord/javabot2/command/data/CommandConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package net.javadiscord.javabot2.command;
1+
package net.javadiscord.javabot2.command.data;
22

33
import lombok.Data;
44
import org.javacord.api.interaction.SlashCommandBuilder;

src/main/java/net/javadiscord/javabot2/command/CommandDataLoader.java renamed to src/main/java/net/javadiscord/javabot2/command/data/CommandDataLoader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package net.javadiscord.javabot2.command;
1+
package net.javadiscord.javabot2.command.data;
22

33
import org.yaml.snakeyaml.Yaml;
44

src/main/java/net/javadiscord/javabot2/command/CommandPrivilegeConfig.java renamed to src/main/java/net/javadiscord/javabot2/command/data/CommandPrivilegeConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package net.javadiscord.javabot2.command;
1+
package net.javadiscord.javabot2.command.data;
22

33
import lombok.Data;
44
import lombok.extern.slf4j.Slf4j;

src/main/java/net/javadiscord/javabot2/command/OptionConfig.java renamed to src/main/java/net/javadiscord/javabot2/command/data/OptionConfig.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
package net.javadiscord.javabot2.command;
1+
package net.javadiscord.javabot2.command.data;
22

33
import lombok.Data;
44
import org.javacord.api.interaction.SlashCommandOptionBuilder;
5+
import org.javacord.api.interaction.SlashCommandOptionChoiceBuilder;
56
import org.javacord.api.interaction.SlashCommandOptionType;
67

78
/**
@@ -16,12 +17,11 @@ public class OptionConfig {
1617
private boolean required;
1718

1819
public SlashCommandOptionBuilder toData() {
19-
var builder = new SlashCommandOptionBuilder()
20+
return new SlashCommandOptionBuilder()
2021
.setType(SlashCommandOptionType.valueOf(this.type.toUpperCase()))
2122
.setName(this.name)
2223
.setDescription(this.description)
2324
.setRequired(this.required);
24-
return builder;
2525
}
2626

2727
@Override

src/main/java/net/javadiscord/javabot2/command/SubCommandConfig.java renamed to src/main/java/net/javadiscord/javabot2/command/data/SubCommandConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package net.javadiscord.javabot2.command;
1+
package net.javadiscord.javabot2.command.data;
22

33
import lombok.Data;
44
import org.javacord.api.interaction.SlashCommandOptionBuilder;

src/main/java/net/javadiscord/javabot2/command/SubCommandGroupConfig.java renamed to src/main/java/net/javadiscord/javabot2/command/data/SubCommandGroupConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package net.javadiscord.javabot2.command;
1+
package net.javadiscord.javabot2.command.data;
22

33
import lombok.Data;
44
import org.javacord.api.interaction.SlashCommandOptionBuilder;

0 commit comments

Comments
 (0)