diff --git a/pom.xml b/pom.xml
index f1df3f4..93674a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,7 @@
me.braydon
RESTfulMC
1.0.0
+ A simple, yet useful RESTful API for Minecraft utilizing Springboot.
@@ -31,6 +32,19 @@
org.springframework.boot
spring-boot-maven-plugin
+
+
+ build-info
+
+ build-info
+
+
+
+ ${project.description}
+
+
+
+
diff --git a/src/main/java/me/braydon/mc/RESTfulMC.java b/src/main/java/me/braydon/mc/RESTfulMC.java
index 75a9992..413d2d1 100644
--- a/src/main/java/me/braydon/mc/RESTfulMC.java
+++ b/src/main/java/me/braydon/mc/RESTfulMC.java
@@ -23,13 +23,6 @@
*/
package me.braydon.mc;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import io.swagger.v3.oas.annotations.OpenAPIDefinition;
-import io.swagger.v3.oas.annotations.info.Contact;
-import io.swagger.v3.oas.annotations.info.Info;
-import io.swagger.v3.oas.annotations.info.License;
-import io.swagger.v3.oas.annotations.servers.Server;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@@ -47,18 +40,7 @@ import java.util.Objects;
*/
@SpringBootApplication(exclude = { JacksonAutoConfiguration.class })
@Slf4j(topic = "RESTfulMC")
-@OpenAPIDefinition(info = @Info(
- title = "RESTfulMC",
- description = "A simple, yet useful RESTful API for Minecraft utilizing Springboot.",
- version = "1.0.0",
- contact = @Contact(name = "Braydon (Rainnny)", url = "https://rainnny.club", email = "braydonrainnny@gmail.com"),
- license = @License(name = "MIT License", url = "https://opensource.org/license/MIT")
-), servers = @Server(url = "https://mc.rainnny.club", description = "Production Server"))
public class RESTfulMC {
- public static final Gson GSON = new GsonBuilder()
- .setDateFormat("MM-dd-yyyy HH:mm:ss")
- .create();
-
@SneakyThrows
public static void main(@NonNull String[] args) {
// Handle loading of our configuration file
diff --git a/src/main/java/me/braydon/mc/common/DNSUtils.java b/src/main/java/me/braydon/mc/common/DNSUtils.java
index ae23a72..1b60125 100644
--- a/src/main/java/me/braydon/mc/common/DNSUtils.java
+++ b/src/main/java/me/braydon/mc/common/DNSUtils.java
@@ -40,10 +40,11 @@ public final class DNSUtils {
private static final String SRV_QUERY_PREFIX = "_minecraft._tcp.%s";
/**
- * Resolve the hostname to an {@link InetSocketAddress}.
+ * Get the resolved address and port of the
+ * given hostname by resolving the SRV records.
*
* @param hostname the hostname to resolve
- * @return the resolved {@link InetSocketAddress}
+ * @return the resolved address and port, null if none
*/
@SneakyThrows
public static InetSocketAddress resolveSRV(@NonNull String hostname) {
@@ -61,6 +62,13 @@ public final class DNSUtils {
return host == null ? null : new InetSocketAddress(host, port);
}
+ /**
+ * Get the resolved address of the given
+ * hostname by resolving the A records.
+ *
+ * @param hostname the hostname to resolve
+ * @return the resolved address, null if none
+ */
@SneakyThrows
public static InetAddress resolveA(@NonNull String hostname) {
Record[] records = new Lookup(hostname, Type.A).run(); // Resolve A records
diff --git a/src/main/java/me/braydon/mc/common/web/JsonWebRequest.java b/src/main/java/me/braydon/mc/common/web/JsonWebRequest.java
index 95a8469..df44d41 100644
--- a/src/main/java/me/braydon/mc/common/web/JsonWebRequest.java
+++ b/src/main/java/me/braydon/mc/common/web/JsonWebRequest.java
@@ -27,7 +27,7 @@ import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
-import me.braydon.mc.RESTfulMC;
+import me.braydon.mc.config.AppConfig;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
@@ -118,7 +118,7 @@ public final class JsonWebRequest {
throw new IOException("Failed to make a %s request to %s: %s".formatted(method.name(), endpoint, status));
}
// Return with the response as the type
- return RESTfulMC.GSON.fromJson(response.body(), responseType);
+ return AppConfig.GSON.fromJson(response.body(), responseType);
} catch (Exception ex) {
if (!(ex instanceof JsonWebException)) {
throw new JsonWebException(status, ex);
diff --git a/src/main/java/me/braydon/mc/config/AppConfig.java b/src/main/java/me/braydon/mc/config/AppConfig.java
index 86cb96f..34e7e15 100644
--- a/src/main/java/me/braydon/mc/config/AppConfig.java
+++ b/src/main/java/me/braydon/mc/config/AppConfig.java
@@ -23,10 +23,26 @@
*/
package me.braydon.mc.config;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.License;
+import io.swagger.v3.oas.models.servers.Server;
import jakarta.annotation.PostConstruct;
import lombok.Getter;
+import lombok.NonNull;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.info.BuildProperties;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.GsonHttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.List;
/**
* The configuration for the app.
@@ -34,14 +50,70 @@ import org.springframework.context.annotation.Configuration;
* @author Braydon
*/
@Configuration @Getter
-public class AppConfig {
+public class AppConfig implements WebMvcConfigurer {
public static AppConfig INSTANCE;
+ public static final Gson GSON = new GsonBuilder()
+ .setDateFormat("MM-dd-yyyy HH:mm:ss")
+ .create();
@Value("${server.publicUrl}")
private String serverPublicUrl;
+ /**
+ * The build properties of the
+ * app, null if the app is not built.
+ */
+ private final BuildProperties buildProperties;
+
+ @Autowired
+ public AppConfig(BuildProperties buildProperties) {
+ this.buildProperties = buildProperties;
+ }
+
@PostConstruct
public void onInitialize() {
INSTANCE = this;
}
+
+ /**
+ * Define the OpenAI specification for this app.
+ *
+ * @return the specification
+ */
+ @Bean @NonNull
+ public OpenAPI defineOpenAPI() {
+ Info info = new Info();
+ info.setTitle("RESTfulMC");
+ info.setVersion(buildProperties == null ? "N/A" : buildProperties.getVersion());
+ info.setDescription(buildProperties == null ? "N/A" : buildProperties.get("description"));
+ info.setContact(new Contact().name("Braydon (Rainnny)").url("https://rainnny.club").email("braydonrainnny@gmail.com"));
+ info.setLicense(new License().name("MIT License").url("https://opensource.org/licenses/MIT"));
+
+ return new OpenAPI()
+ .info(info)
+ .addServersItem(new Server().url(serverPublicUrl).description("The public server URL"));
+ }
+
+ /**
+ * Configure the default HTTP
+ * message converters to use Gson.
+ *
+ * @param converters the converters
+ */
+ @Override
+ public void configureMessageConverters(@NonNull List> converters) {
+ GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter();
+ gsonHttpMessageConverter.setGson(gson());
+ converters.add(gsonHttpMessageConverter);
+ }
+
+ /**
+ * Our custom Gson instance to use.
+ *
+ * @return the Gson instance
+ */
+ @Bean @NonNull
+ public Gson gson() {
+ return GSON;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/me/braydon/mc/config/WebMvcConfig.java b/src/main/java/me/braydon/mc/config/WebMvcConfig.java
deleted file mode 100644
index dbeab90..0000000
--- a/src/main/java/me/braydon/mc/config/WebMvcConfig.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2024 Braydon (Rainnny).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package me.braydon.mc.config;
-
-import com.google.gson.Gson;
-import me.braydon.mc.RESTfulMC;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.converter.json.GsonHttpMessageConverter;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-import java.util.List;
-
-/**
- * @author Braydon
- */
-@Configuration
-public class WebMvcConfig implements WebMvcConfigurer {
- @Override
- public void configureMessageConverters(List> converters) {
- GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter();
- gsonHttpMessageConverter.setGson(gson());
- converters.add(gsonHttpMessageConverter);
- }
-
- @Bean
- public Gson gson() {
- return RESTfulMC.GSON;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java b/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java
index 2050493..e88e713 100644
--- a/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java
+++ b/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java
@@ -25,7 +25,6 @@ package me.braydon.mc.model.server;
import com.google.gson.annotations.SerializedName;
import lombok.*;
-import me.braydon.mc.RESTfulMC;
import me.braydon.mc.common.JavaMinecraftVersion;
import me.braydon.mc.config.AppConfig;
import me.braydon.mc.model.MinecraftServer;
@@ -104,7 +103,7 @@ public final class JavaMinecraftServer extends MinecraftServer {
public static JavaMinecraftServer create(@NonNull String hostname, String ip, int port, @NonNull JavaServerStatusToken token) {
String motdString = token.getDescription() instanceof String ? (String) token.getDescription() : null;
if (motdString == null) { // Not a string motd, convert from Json
- motdString = new TextComponent(ComponentSerializer.parse(RESTfulMC.GSON.toJson(token.getDescription()))).toLegacyText();
+ motdString = new TextComponent(ComponentSerializer.parse(AppConfig.GSON.toJson(token.getDescription()))).toLegacyText();
}
return new JavaMinecraftServer(hostname, ip, port, token.getVersion().detailedCopy(), token.getPlayers(),
MOTD.create(motdString), Favicon.create(token.getFavicon(), hostname), token.getModInfo(),
diff --git a/src/main/java/me/braydon/mc/model/token/MojangProfileToken.java b/src/main/java/me/braydon/mc/model/token/MojangProfileToken.java
index adb8231..d3da2f8 100644
--- a/src/main/java/me/braydon/mc/model/token/MojangProfileToken.java
+++ b/src/main/java/me/braydon/mc/model/token/MojangProfileToken.java
@@ -25,8 +25,8 @@ package me.braydon.mc.model.token;
import com.google.gson.JsonObject;
import lombok.*;
-import me.braydon.mc.RESTfulMC;
import me.braydon.mc.common.Tuple;
+import me.braydon.mc.config.AppConfig;
import me.braydon.mc.model.Cape;
import me.braydon.mc.model.ProfileAction;
import me.braydon.mc.model.Skin;
@@ -71,7 +71,7 @@ public final class MojangProfileToken {
if (textures == null) { // No profile textures
return new Tuple<>();
}
- JsonObject jsonObject = RESTfulMC.GSON.fromJson(textures.getDecodedValue(), JsonObject.class); // Get the Json object
+ JsonObject jsonObject = AppConfig.GSON.fromJson(textures.getDecodedValue(), JsonObject.class); // Get the Json object
JsonObject texturesJsonObject = jsonObject.getAsJsonObject("textures"); // Get the textures object
// Return the tuple containing the skin and cape
diff --git a/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java b/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java
index 0817bd3..a06684b 100644
--- a/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java
+++ b/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java
@@ -25,10 +25,10 @@ package me.braydon.mc.service.pinger.impl;
import lombok.NonNull;
import lombok.extern.log4j.Log4j2;
-import me.braydon.mc.RESTfulMC;
import me.braydon.mc.common.DNSUtils;
import me.braydon.mc.common.packet.impl.java.JavaPacketHandshakingInSetProtocol;
import me.braydon.mc.common.packet.impl.java.JavaPacketStatusInStart;
+import me.braydon.mc.config.AppConfig;
import me.braydon.mc.exception.impl.BadRequestException;
import me.braydon.mc.exception.impl.ResourceNotFoundException;
import me.braydon.mc.model.server.JavaMinecraftServer;
@@ -86,7 +86,7 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger