Skip to content

Commit 5f12bc7

Browse files
Merge pull request #343 from Java-Discord/dynxsty/api
Internal API Implementation
2 parents 81d1597 + d636094 commit 5f12bc7

31 files changed

+650
-119
lines changed

build.gradle.kts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2+
import com.github.jengelman.gradle.plugins.shadow.transformers.*
3+
14
plugins {
25
java
36
id("com.github.johnrengelman.shadow") version "7.1.2"
7+
id("io.spring.dependency-management") version "1.0.11.RELEASE"
48
checkstyle
59
}
610

@@ -19,12 +23,17 @@ repositories {
1923
}
2024

2125
dependencies {
22-
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
23-
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2")
26+
testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0")
27+
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.9.0")
28+
29+
// DIH4JDA (Interaction Framework) & JDA
30+
implementation("com.github.DynxstyGIT:DIH4JDA:f564af77e9")
31+
implementation("net.dv8tion:JDA:5.0.0-alpha.17") {
32+
exclude(module = "opus-java")
33+
}
2434

25-
// DIH4JDA (Interaction Framework) (includes JDA (jda5.0.0-alpha.17))
26-
implementation("com.github.DenuxPlays:DIH4JDA:7ac2c9c77c")
27-
implementation("org.reflections:reflections:0.10.2")
35+
// Caffeine (Caching Library)
36+
implementation("com.github.ben-manes.caffeine:caffeine:3.1.1")
2837

2938
implementation("com.google.code.gson:gson:2.9.0")
3039
implementation("org.yaml:snakeyaml:1.30")
@@ -52,6 +61,9 @@ dependencies {
5261

5362
// Sentry
5463
implementation("io.sentry:sentry:6.3.0")
64+
65+
// Spring Boot
66+
implementation("org.springframework.boot:spring-boot-starter-web:2.7.0")
5567
}
5668

5769
tasks.withType<Jar> {
@@ -67,6 +79,19 @@ tasks.withType<JavaCompile>().configureEach {
6779
}
6880
tasks.withType<Test>{ useJUnitPlatform() }
6981

82+
tasks.withType<ShadowJar> {
83+
isZip64 = true
84+
// Required for Spring
85+
mergeServiceFiles()
86+
append("META-INF/spring.handlers")
87+
append("META-INF/spring.schemas")
88+
append("META-INF/spring.tooling")
89+
transform(PropertiesFileTransformer().apply {
90+
paths = listOf("META-INF/spring.factories")
91+
mergeStrategy = "append"
92+
})
93+
}
94+
7095
checkstyle {
7196
toolVersion = "9.1"
7297
configDirectory.set(File("checkstyle"))

checkstyle/checkstyle.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ See https://checkstyle.org/ for more information.
6969
<module name="UnnecessarySemicolonInEnumeration"/>
7070
<module name="UnnecessarySemicolonInTryWithResources"/>
7171
<module name="InnerTypeLast"/>
72-
<module name="HideUtilityClassConstructor"/>
7372
<module name="InterfaceIsType"/>
7473
<module name="MutableException"/>
7574
<module name="OneTopLevelClass"/>

src/main/java/net/javadiscord/javabot/Bot.java

Lines changed: 48 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22

33
import com.dynxsty.dih4jda.DIH4JDA;
44
import com.dynxsty.dih4jda.DIH4JDABuilder;
5+
import com.dynxsty.dih4jda.DIH4JDALogger;
6+
import com.dynxsty.dih4jda.interactions.commands.ContextCommand;
57
import com.dynxsty.dih4jda.interactions.commands.RegistrationType;
8+
import com.dynxsty.dih4jda.interactions.commands.SlashCommand;
69
import com.zaxxer.hikari.HikariDataSource;
710
import io.sentry.Sentry;
11+
import lombok.Getter;
812
import lombok.extern.slf4j.Slf4j;
913
import net.dv8tion.jda.api.JDA;
1014
import net.dv8tion.jda.api.JDABuilder;
@@ -29,14 +33,14 @@
2933
import net.javadiscord.javabot.systems.qotw.commands.questions_queue.AddQuestionSubcommand;
3034
import net.javadiscord.javabot.systems.qotw.commands.view.QOTWQuerySubcommand;
3135
import net.javadiscord.javabot.systems.qotw.submissions.SubmissionInteractionManager;
32-
import net.javadiscord.javabot.systems.staff_commands.self_roles.SelfRoleInteractionManager;
3336
import net.javadiscord.javabot.systems.staff_commands.embeds.AddEmbedFieldSubcommand;
3437
import net.javadiscord.javabot.systems.staff_commands.embeds.CreateEmbedSubcommand;
3538
import net.javadiscord.javabot.systems.staff_commands.embeds.EditEmbedSubcommand;
36-
import net.javadiscord.javabot.systems.starboard.StarboardManager;
39+
import net.javadiscord.javabot.systems.staff_commands.self_roles.SelfRoleInteractionManager;
3740
import net.javadiscord.javabot.systems.staff_commands.tags.CustomTagManager;
3841
import net.javadiscord.javabot.systems.staff_commands.tags.commands.CreateCustomTagSubcommand;
3942
import net.javadiscord.javabot.systems.staff_commands.tags.commands.EditCustomTagSubcommand;
43+
import net.javadiscord.javabot.systems.starboard.StarboardManager;
4044
import net.javadiscord.javabot.systems.user_commands.leaderboard.ExperienceLeaderboardSubcommand;
4145
import net.javadiscord.javabot.tasks.MetricsUpdater;
4246
import net.javadiscord.javabot.tasks.PresenceUpdater;
@@ -45,6 +49,11 @@
4549
import net.javadiscord.javabot.util.InteractionUtils;
4650
import org.jetbrains.annotations.NotNull;
4751
import org.quartz.SchedulerException;
52+
import org.springframework.beans.factory.annotation.Autowired;
53+
import org.springframework.boot.SpringApplication;
54+
import org.springframework.boot.autoconfigure.SpringBootApplication;
55+
import org.springframework.context.annotation.ComponentScan;
56+
import org.springframework.context.annotation.FilterType;
4857

4958
import java.nio.file.Path;
5059
import java.time.ZoneOffset;
@@ -59,33 +68,62 @@
5968
* The main class where the bot is initialized.
6069
*/
6170
@Slf4j
71+
@SpringBootApplication
72+
@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {SlashCommand.class, ContextCommand.class}))
6273
public class Bot {
6374

75+
@Getter
6476
private static BotConfig config;
6577

78+
@Getter
6679
private static AutoMod autoMod;
6780

81+
@Getter
6882
private static DIH4JDA dih4jda;
6983

84+
@Getter
7085
private static MessageCache messageCache;
7186

87+
@Getter
7288
private static ServerLockManager serverLockManager;
7389

90+
@Getter
7491
private static CustomTagManager customTagManager;
7592

93+
@Getter
7694
private static HikariDataSource dataSource;
7795

96+
@Getter
7897
private static ScheduledExecutorService asyncPool;
7998

80-
private Bot() {
99+
/**
100+
* The constructor of this class, which also adds all {@link SlashCommand} and
101+
* {@link ContextCommand} to the {@link DIH4JDA} instance.
102+
*
103+
* @param commands The {@link Autowired} list of {@link SlashCommand}s.
104+
* @param contexts The {@link Autowired} list of {@link ContextCommand}s.
105+
*/
106+
@Autowired
107+
public Bot(final List<SlashCommand> commands, final List<ContextCommand> contexts) {
108+
if (!commands.isEmpty()) {
109+
getDih4jda().addSlashCommands(commands.toArray(SlashCommand[]::new));
110+
}
111+
if (!contexts.isEmpty()) {
112+
getDih4jda().addContextCommands(contexts.toArray(ContextCommand[]::new));
113+
}
114+
try {
115+
getDih4jda().registerInteractions();
116+
} catch (ReflectiveOperationException e) {
117+
ExceptionLogger.capture(e, getClass().getSimpleName());
118+
}
81119
}
82120

83121
/**
84122
* The main method that starts the bot. This involves a few steps:
85123
* <ol>
86124
* <li>Setting the time zone to UTC, to keep our sanity when working with times.</li>
87125
* <li>Loading the configuration JSON file.</li>
88-
* <li>Creating and configuring the {@link JDA} instance that enables the bot's Discord connectivity.</li>
126+
* <li>Creating and configuring the {@link JDA} instance that enables the bots' Discord connectivity.</li>
89127
* <li>Initializing the {@link DIH4JDA} instance.</li>
90128
* <li>Adding event listeners to the bot.</li>
91129
* </ol>
@@ -109,8 +147,9 @@ public static void main(String[] args) throws Exception {
109147
.build();
110148
AllowedMentions.setDefaultMentions(EnumSet.of(Message.MentionType.ROLE, Message.MentionType.CHANNEL, Message.MentionType.USER, Message.MentionType.EMOJI));
111149
dih4jda = DIH4JDABuilder.setJDA(jda)
112-
.setCommandsPackage("net.javadiscord.javabot")
113150
.setDefaultCommandType(RegistrationType.GLOBAL)
151+
.disableLogging(DIH4JDALogger.Type.SMART_QUEUE_IGNORED)
152+
.disableAutomaticCommandRegistration()
114153
.build();
115154
customTagManager = new CustomTagManager(jda, dataSource);
116155
messageCache = new MessageCache();
@@ -131,10 +170,11 @@ public static void main(String[] args) throws Exception {
131170
log.error("Could not initialize all scheduled tasks.", e);
132171
jda.shutdown();
133172
}
173+
SpringApplication.run(Bot.class, args);
134174
}
135175

136176
/**
137-
* Adds all the bot's event listeners to the JDA instance, except for
177+
* Adds all the bots' event listeners to the JDA instance, except for
138178
* the {@link AutoMod} instance.
139179
*
140180
* @param jda The JDA bot instance to add listeners to.
@@ -158,7 +198,7 @@ private static void addEventListeners(@NotNull JDA jda, @NotNull DIH4JDA dih4jda
158198
new PingableNameListener(),
159199
new HugListener()
160200
);
161-
dih4jda.addListener(new DIH4JDAListener());
201+
dih4jda.addEventListener(new DIH4JDAListener());
162202
}
163203

164204
private static void addComponentHandler(@NotNull DIH4JDA dih4jda) {
@@ -169,7 +209,7 @@ private static void addComponentHandler(@NotNull DIH4JDA dih4jda) {
169209
List.of("self-role"), new SelfRoleInteractionManager(),
170210
List.of("qotw-submission"), new SubmissionInteractionManager(),
171211
List.of("help-channel", "help-thank"), new HelpChannelInteractionManager(),
172-
List.of("qotw-list-questions"),new QOTWQuerySubcommand()
212+
List.of("qotw-list-questions"), new QOTWQuerySubcommand()
173213
));
174214
dih4jda.addModalHandlers(Map.of(
175215
List.of("qotw-add-question"), new AddQuestionSubcommand(),
@@ -186,80 +226,5 @@ private static void addComponentHandler(@NotNull DIH4JDA dih4jda) {
186226
List.of("qotw-submission-select"), new SubmissionInteractionManager()
187227
));
188228
}
189-
190-
/**
191-
* The set of configuration properties that this bot uses.
192-
*
193-
* @return The {@link BotConfig} which was set in {@link Bot#main(String[])}.
194-
*/
195-
public static BotConfig getConfig() {
196-
return config;
197-
}
198-
199-
/**
200-
* A static reference to the bots' {@link AutoMod} instance.
201-
*
202-
* @return The {@link AutoMod} instance which was created in {@link Bot#main(String[])}.
203-
*/
204-
public static AutoMod getAutoMod() {
205-
return autoMod;
206-
}
207-
208-
/**
209-
* A static reference to the bots' {@link DIH4JDA} instance.
210-
*
211-
* @return The {@link DIH4JDA} instance which was set in {@link Bot#main(String[])}.
212-
*/
213-
public static DIH4JDA getDIH4JDA() {
214-
return dih4jda;
215-
}
216-
217-
/**
218-
* The bots' {@link MessageCache}, which handles logging of deleted and edited messages.
219-
*
220-
* @return The {@link MessageCache} which was initialized in {@link Bot#main(String[])}.
221-
*/
222-
public static MessageCache getMessageCache() {
223-
return messageCache;
224-
}
225-
226-
/**
227-
* A reference to the bots' {@link ServerLockManager}.
228-
*
229-
* @return The {@link ServerLockManager} which was created in {@link Bot#main(String[])}.
230-
*/
231-
public static ServerLockManager getServerLockManager() {
232-
return serverLockManager;
233-
}
234-
235-
/**
236-
* A static reference to the {@link CustomTagManager} which handles and loads all registered Custom Commands.
237-
*
238-
* @return The {@link CustomTagManager} which was created in {@link Bot#main(String[])}.
239-
*/
240-
public static CustomTagManager getCustomTagManager() {
241-
return customTagManager;
242-
}
243-
244-
/**
245-
* A reference to the data source that provides access to the relational
246-
* database that this bot users for certain parts of the application. Use
247-
* this to obtain a connection and perform transactions.
248-
*
249-
* @return The {@link HikariDataSource} which was initialized in {@link Bot#main(String[])}.
250-
*/
251-
public static HikariDataSource getDataSource() {
252-
return dataSource;
253-
}
254-
255-
/**
256-
* A general-purpose thread pool that can be used by the bot to execute
257-
* tasks outside the main event processing thread.
258-
*
259-
* @return The {@link ScheduledExecutorService} which was set in {@link Bot#main(String[])}.
260-
*/
261-
public static ScheduledExecutorService getAsyncPool() {
262-
return asyncPool;
263-
}
264229
}
265230

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package net.javadiscord.javabot.api.exception;
2+
3+
import org.springframework.http.HttpStatus;
4+
5+
/**
6+
* Represents a single API-Error which holds the {@link HttpStatus}, a message and
7+
* an array of errors.
8+
*
9+
* @param status The {@link HttpStatus}.
10+
* @param message The errors' message.
11+
* @param errors An array of additional error notices.
12+
*/
13+
public record ErrorResponse(HttpStatus status, String message, String... errors) {}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package net.javadiscord.javabot.api.exception;
2+
3+
import org.springframework.beans.BeansException;
4+
5+
/**
6+
* An exception which is thrown for invalid JDA entity ids.
7+
*/
8+
public class InternalServerException extends BeansException {
9+
10+
public InternalServerException(String msg, Throwable cause) {
11+
super(msg, cause);
12+
}
13+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package net.javadiscord.javabot.api.exception;
2+
3+
import org.springframework.beans.BeansException;
4+
import org.springframework.lang.Nullable;
5+
6+
/**
7+
* An exception which is thrown for invalid JDA entity ids.
8+
*/
9+
public class InvalidEntityIdException extends BeansException {
10+
@Nullable
11+
private final Class<?> requiredEntity;
12+
13+
public InvalidEntityIdException(Class<?> requiredEntity, String msg) {
14+
super(msg);
15+
this.requiredEntity = requiredEntity;
16+
}
17+
18+
public Class<?> getRequiredEntity() {
19+
return requiredEntity;
20+
}
21+
}

0 commit comments

Comments
 (0)