Skip to content

Commit 2763a57

Browse files
authored
Merge branch 'Java-Discord:main' into forms-feature
2 parents 385820d + 0c0fbad commit 2763a57

File tree

113 files changed

+13928
-907
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+13928
-907
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ on: [push, pull_request, workflow_dispatch]
88
jobs:
99
build:
1010
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
1113
steps:
1214
- uses: actions/checkout@v4
13-
- name: Set up JDK 17
15+
- name: Set up JDK 25
1416
uses: actions/setup-java@v4
1517
with:
16-
java-version: '17'
18+
java-version: '25'
1719
distribution: 'temurin'
1820
- name: Grant execute permission for gradlew
1921
run: chmod +x gradlew
@@ -23,14 +25,16 @@ jobs:
2325
run: ./gradlew test
2426
publish:
2527
runs-on: ubuntu-latest
28+
permissions:
29+
contents: read
2630
needs: build
2731
if: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch' }}
2832
steps:
2933
- uses: actions/checkout@v4
30-
- name: Set up JDK 21
34+
- name: Set up JDK 25
3135
uses: graalvm/setup-graalvm@v1
3236
with:
33-
java-version: '21'
37+
java-version: '25'
3438
distribution: 'graalvm-community'
3539
- name: Build native-image
3640
run: ./gradlew nativeCompile -Pprod

build.gradle.kts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.*
44
plugins {
55
java
66
id("com.github.johnrengelman.shadow") version "8.1.1"
7-
id("org.springframework.boot") version "3.5.0"
7+
id("org.springframework.boot") version "4.0.1"
88
id("io.spring.dependency-management") version "1.1.7"
9-
id("org.graalvm.buildtools.native") version "0.10.6"
9+
id("org.graalvm.buildtools.native") version "0.11.3"
1010
checkstyle
1111
}
1212

1313
java {
14-
sourceCompatibility = JavaVersion.VERSION_17
15-
targetCompatibility = JavaVersion.VERSION_17
14+
toolchain {
15+
languageVersion = JavaLanguageVersion.of(25)
16+
}
1617
}
1718

1819
group = "net.discordjug"
@@ -27,22 +28,24 @@ repositories {
2728
dependencies {
2829
testImplementation("org.junit.jupiter:junit-jupiter-api")
2930
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
31+
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
3032
compileOnly("com.google.code.findbugs:jsr305:3.0.2")
3133
compileOnly("org.jetbrains:annotations:26.0.2")
3234

3335
// DIH4JDA (Command Framework) & JDA
34-
implementation("com.github.DynxstyGIT:DIH4JDA:a64b5a9dc5")
35-
implementation("net.dv8tion:JDA:5.5.1") {
36+
implementation("com.github.jasonlessenich:DIH4JDA:1.7.0")
37+
//implementation("xyz.dynxsty:dih4jda:1.7.0")
38+
implementation("net.dv8tion:JDA:6.2.0") {
3639
exclude(module = "opus-java")
3740
}
3841

3942
// Caffeine (Caching Library)
40-
implementation("com.github.ben-manes.caffeine:caffeine:3.2.0")
43+
implementation("com.github.ben-manes.caffeine:caffeine:3.2.2")
4144

4245
implementation("com.google.code.gson:gson:2.13.1")
4346
implementation("org.yaml:snakeyaml:2.4")
4447
implementation("com.google.re2j:re2j:1.8")
45-
implementation("commons-validator:commons-validator:1.9.0")
48+
implementation("commons-validator:commons-validator:1.10.0")
4649

4750
implementation("com.mashape.unirest:unirest-java:1.4.9")
4851

@@ -60,20 +63,16 @@ dependencies {
6063
testAnnotationProcessor("org.projectlombok:lombok:1.18.38")
6164

6265
// Sentry
63-
implementation("io.sentry:sentry:8.13.2")
66+
implementation("io.sentry:sentry:8.20.0")
6467

6568
// Spring
66-
implementation("org.springframework.boot:spring-boot-starter-web")
69+
implementation("org.springframework.boot:spring-boot-starter-webmvc")
6770
implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
6871

6972
//required for registering native hints
7073
implementation("org.jetbrains.kotlin:kotlin-reflect")
71-
}
72-
73-
configurations {
74-
all {
75-
exclude(group = "commons-logging", module = "commons-logging")
76-
}
74+
75+
implementation("org.slf4j:jcl-over-slf4j")
7776
}
7877

7978
tasks.withType<Jar> {
@@ -121,6 +120,7 @@ tasks.processTestAot {
121120
graalvmNative {
122121
binaries {
123122
named("main") {
123+
buildArgs.add("-H:+ForeignAPISupport")//needed for AWT/plotting, see https://bugs.openjdk.org/browse/JDK-8337237
124124
if (hasProperty("prod")) {
125125
buildArgs.add("-O3")
126126
} else {

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public void onApplicationEvent(ApplicationReadyEvent event) {
101101
*/
102102
public static void main(String[] args) throws Exception {
103103
TimeZone.setDefault(TimeZone.getTimeZone(ZoneOffset.UTC));
104-
MessageRequest.setDefaultMentions(EnumSet.of(Message.MentionType.ROLE, Message.MentionType.CHANNEL, Message.MentionType.USER, Message.MentionType.EMOJI));
104+
MessageRequest.setDefaultMentions(EnumSet.of(Message.MentionType.CHANNEL, Message.MentionType.USER, Message.MentionType.EMOJI));
105105
SpringApplication.run(Bot.class, args);
106106
}
107107

src/main/java/net/discordjug/javabot/RuntimeHintsConfiguration.java

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package net.discordjug.javabot;
22

3-
import java.nio.channels.Channel;
4-
53
import club.minnced.discord.webhook.send.WebhookEmbed;
64
import com.zaxxer.hikari.HikariConfig;
75
import net.discordjug.javabot.data.config.BotConfig;
@@ -11,24 +9,14 @@
119
import net.discordjug.javabot.data.config.SystemsConfig.ApiConfig;
1210
import net.discordjug.javabot.data.config.guild.HelpConfig;
1311
import net.discordjug.javabot.data.config.guild.MessageCacheConfig;
12+
import net.discordjug.javabot.data.config.guild.MessageRule;
1413
import net.discordjug.javabot.data.config.guild.MetricsConfig;
1514
import net.discordjug.javabot.data.config.guild.ModerationConfig;
1615
import net.discordjug.javabot.data.config.guild.QOTWConfig;
1716
import net.discordjug.javabot.data.config.guild.ServerLockConfig;
1817
import net.discordjug.javabot.data.config.guild.StarboardConfig;
19-
import net.dv8tion.jda.api.entities.Guild;
20-
import net.dv8tion.jda.api.entities.Member;
21-
import net.dv8tion.jda.api.entities.Role;
22-
import net.dv8tion.jda.api.entities.ScheduledEvent;
23-
import net.dv8tion.jda.api.entities.ThreadMember;
24-
import net.dv8tion.jda.api.entities.User;
25-
import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
26-
import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji;
27-
import net.dv8tion.jda.api.entities.sticker.GuildSticker;
2818
import net.dv8tion.jda.api.hooks.ListenerAdapter;
29-
import net.dv8tion.jda.api.managers.AudioManager;
3019
import net.dv8tion.jda.internal.entities.GuildVoiceStateImpl;
31-
import net.dv8tion.jda.internal.entities.MemberPresenceImpl;
3220
import net.dv8tion.jda.internal.requests.restaction.PermOverrideData;
3321
import org.h2.server.TcpServer;
3422
import org.springframework.aot.hint.MemberCategory;
@@ -47,10 +35,8 @@
4735
@RegisterReflectionForBinding({
4836
//register config classes for reflection
4937
BotConfig.class, GuildConfig.class, GuildConfigItem.class, SystemsConfig.class, ApiConfig.class,
50-
HelpConfig.class, MessageCacheConfig.class, MetricsConfig.class, ModerationConfig.class, QOTWConfig.class, ServerLockConfig.class, StarboardConfig.class,
38+
HelpConfig.class, MessageCacheConfig.class, MetricsConfig.class, ModerationConfig.class, QOTWConfig.class, ServerLockConfig.class, StarboardConfig.class,MessageRule.class, MessageRule.MessageAction.class,
5139

52-
//ensure JDA can create necessary caches
53-
User[].class, Guild[].class, Member[].class, Role[].class, Channel[].class, AudioManager[].class, ScheduledEvent[].class, ThreadMember[].class, ForumTag[].class, RichCustomEmoji[].class, GuildSticker[].class, MemberPresenceImpl[].class,
5440
//needs to be serialized for channel managers etc
5541
PermOverrideData.class,
5642

@@ -77,8 +63,17 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
7763
// caffeine
7864
hints.reflection().registerTypeIfPresent(getClass().getClassLoader(), "com.github.benmanes.caffeine.cache.SSW", MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
7965

66+
try {
67+
// These classes are necessary on X11 but may not be loaded on Wayland when generating native hints
68+
for(Class<?> cl : getClass().getClassLoader().loadClass("sun.font.FontConfigManager").getDeclaredClasses()) {
69+
hints.jni().registerType(cl, MemberCategory.ACCESS_DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
70+
}
71+
} catch (ClassNotFoundException _) {
72+
// FontConfigManager is only supported on Linux
73+
}
74+
8075
for (Class<?> cl : WebhookEmbed.class.getClasses()) {
81-
hints.reflection().registerType(cl, MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_PUBLIC_METHODS);
76+
hints.reflection().registerType(cl, MemberCategory.ACCESS_DECLARED_FIELDS, MemberCategory.INVOKE_PUBLIC_METHODS);
8277
}
8378

8479
hints.reflection().registerType(GuildVoiceStateImpl[].class, MemberCategory.UNSAFE_ALLOCATED);

src/main/java/net/discordjug/javabot/api/TomcatConfig.java

Lines changed: 0 additions & 61 deletions
This file was deleted.

src/main/java/net/discordjug/javabot/data/config/BotConfig.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package net.discordjug.javabot.data.config;
22

3-
import com.google.gson.Gson;
4-
import com.google.gson.GsonBuilder;
53
import com.google.gson.JsonSyntaxException;
64
import lombok.extern.slf4j.Slf4j;
75
import net.discordjug.javabot.util.ExceptionLogger;
6+
import net.discordjug.javabot.util.GsonUtils;
87
import net.dv8tion.jda.api.entities.Guild;
98

109
import org.jetbrains.annotations.NotNull;
@@ -64,11 +63,10 @@ public BotConfig(Path dir) {
6463
}
6564
}
6665
this.guilds = new ConcurrentHashMap<>();
67-
Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
6866
Path systemsFile = dir.resolve(SYSTEMS_FILE);
6967
if (Files.exists(systemsFile)) {
7068
try (BufferedReader reader = Files.newBufferedReader(systemsFile)) {
71-
this.systemsConfig = gson.fromJson(reader, SystemsConfig.class);
69+
this.systemsConfig = GsonUtils.fromJson(reader, SystemsConfig.class);
7270
log.info("Loaded systems config from {}", systemsFile);
7371
} catch (JsonSyntaxException e) {
7472
ExceptionLogger.capture(e, getClass().getSimpleName());
@@ -133,10 +131,9 @@ public SystemsConfig getSystems() {
133131
* Flushes all configuration to the disk.
134132
*/
135133
public void flush() {
136-
Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
137134
Path systemsFile = this.dir.resolve(SYSTEMS_FILE);
138135
try (BufferedWriter writer = Files.newBufferedWriter(systemsFile)) {
139-
gson.toJson(this.systemsConfig, writer);
136+
GsonUtils.toJson(this.systemsConfig, writer);
140137
writer.flush();
141138
} catch (IOException e) {
142139
ExceptionLogger.capture(e, getClass().getSimpleName());

src/main/java/net/discordjug/javabot/data/config/GuildConfig.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package net.discordjug.javabot.data.config;
22

3-
import com.google.gson.Gson;
4-
import com.google.gson.GsonBuilder;
53
import com.google.gson.JsonSyntaxException;
64
import lombok.Data;
75
import lombok.extern.slf4j.Slf4j;
86
import net.discordjug.javabot.data.config.guild.*;
97
import net.discordjug.javabot.util.ExceptionLogger;
8+
import net.discordjug.javabot.util.GsonUtils;
109
import net.discordjug.javabot.util.Pair;
1110
import net.dv8tion.jda.api.entities.Guild;
1211

@@ -70,11 +69,10 @@ public GuildConfig(Guild guild, Path file) {
7069
* @throws UncheckedIOException if an IO error occurs.
7170
*/
7271
public static GuildConfig loadOrCreate(Guild guild, Path file) {
73-
Gson gson = new GsonBuilder().create();
7472
GuildConfig config;
7573
if (Files.exists(file)) {
7674
try (BufferedReader reader = Files.newBufferedReader(file)) {
77-
config = gson.fromJson(reader, GuildConfig.class);
75+
config = GsonUtils.fromJson(reader, GuildConfig.class);
7876
config.setFile(file);
7977
config.setGuild(guild);
8078
log.info("Loaded config from {}", file);
@@ -115,9 +113,8 @@ private void setGuild(Guild guild) {
115113
* Saves this config to its file path.
116114
*/
117115
public synchronized void flush() {
118-
Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
119116
try (BufferedWriter writer = Files.newBufferedWriter(this.file)) {
120-
gson.toJson(this, writer);
117+
GsonUtils.toJson(this, writer);
121118
writer.flush();
122119
} catch (IOException e) {
123120
ExceptionLogger.capture(e, getClass().getSimpleName());
@@ -160,7 +157,10 @@ public void set(String propertyName, String value) throws UnknownPropertyExcepti
160157
Optional<Pair<Field, Object>> result = ReflectionUtils.resolveField(propertyName, this);
161158
result.ifPresent(pair -> {
162159
try {
163-
ReflectionUtils.set(pair.first(), pair.second(), value);
160+
Object updatedField = ReflectionUtils.set(pair.first(), pair.second(), value);
161+
if (updatedField instanceof GuildConfigItem item) {
162+
item.setGuildConfig(this);
163+
}
164164
this.flush();
165165
} catch (IllegalAccessException e) {
166166
ExceptionLogger.capture(e, getClass().getSimpleName());
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package net.discordjug.javabot.data.config;
2+
3+
import java.io.IOException;
4+
import java.util.regex.Pattern;
5+
6+
import com.google.gson.TypeAdapter;
7+
import com.google.gson.stream.JsonReader;
8+
import com.google.gson.stream.JsonToken;
9+
import com.google.gson.stream.JsonWriter;
10+
11+
/**
12+
* A gson {@link TypeAdapter} that allows serializing and deserializing regex {@link Pattern}s.
13+
*/
14+
public class PatternTypeAdapter extends TypeAdapter<Pattern> {
15+
16+
@Override
17+
public void write(JsonWriter writer, Pattern value) throws IOException {
18+
if (value == null) {
19+
writer.nullValue();
20+
return;
21+
}
22+
writer.value(value.toString());
23+
}
24+
25+
@Override
26+
public Pattern read(JsonReader reader) throws IOException {
27+
if (reader.peek() == JsonToken.NULL) {
28+
reader.nextNull();
29+
return null;
30+
}
31+
String value = reader.nextString();
32+
return Pattern.compile(value);
33+
}
34+
35+
}

0 commit comments

Comments
 (0)