Add Mojang status route
All checks were successful
Deploy App / docker (ubuntu-latest, 2.44.0, 17, 3.8.5) (push) Successful in 1m35s
All checks were successful
Deploy App / docker (ubuntu-latest, 2.44.0, 17, 3.8.5) (push) Successful in 1m35s
This commit is contained in:
parent
6d112ac658
commit
6c6b9349f2
101
src/main/java/me/braydon/mc/common/MojangServer.java
Normal file
101
src/main/java/me/braydon/mc/common/MojangServer.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* 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.common;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a service provided by Mojang.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor @Getter @ToString
|
||||||
|
public enum MojangServer {
|
||||||
|
SESSION("https://sessionserver.mojang.com"),
|
||||||
|
API("https://api.mojang.com"),
|
||||||
|
TEXTURES("https://textures.minecraft.net"),
|
||||||
|
ASSETS("https://assets.mojang.com"),
|
||||||
|
LIBRARIES("https://libraries.minecraft.net");
|
||||||
|
|
||||||
|
private static final int STATUS_TIMEOUT = 7000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The endpoint of this service.
|
||||||
|
*/
|
||||||
|
@NonNull private final String endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the status of this service.
|
||||||
|
*
|
||||||
|
* @return the service status
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Status getStatus() {
|
||||||
|
try {
|
||||||
|
InetAddress address = InetAddress.getByName(endpoint.substring(8));
|
||||||
|
long before = System.currentTimeMillis();
|
||||||
|
if (address.isReachable(STATUS_TIMEOUT)) {
|
||||||
|
// The time it took to reach the host is 75% of
|
||||||
|
// the timeout, consider it to be degraded.
|
||||||
|
if ((System.currentTimeMillis() - before) > STATUS_TIMEOUT * 0.75D) {
|
||||||
|
return Status.DEGRADED;
|
||||||
|
}
|
||||||
|
return Status.ONLINE;
|
||||||
|
}
|
||||||
|
} catch (UnknownHostException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// We can safely ignore any errors, we're simply checking
|
||||||
|
// if the host is reachable, if it's not, it's offline.
|
||||||
|
}
|
||||||
|
return Status.OFFLINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status of a service.
|
||||||
|
*/
|
||||||
|
public enum Status {
|
||||||
|
/**
|
||||||
|
* The service is online and accessible.
|
||||||
|
*/
|
||||||
|
ONLINE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service is online, but is experiencing degraded performance.
|
||||||
|
*/
|
||||||
|
DEGRADED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service is offline and inaccessible.
|
||||||
|
*/
|
||||||
|
OFFLINE
|
||||||
|
}
|
||||||
|
}
|
78
src/main/java/me/braydon/mc/controller/MojangController.java
Normal file
78
src/main/java/me/braydon/mc/controller/MojangController.java
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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.controller;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import me.braydon.mc.common.MojangServer;
|
||||||
|
import me.braydon.mc.exception.impl.BadRequestException;
|
||||||
|
import me.braydon.mc.service.MojangService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The controller for handling
|
||||||
|
* Mojang related requests.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(value = "/mojang", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
@Log4j2(topic = "Mojang Controller")
|
||||||
|
@Tag(name = "Mojang Controller", description = "The controller for handling Mojang related requests.")
|
||||||
|
public final class MojangController {
|
||||||
|
/**
|
||||||
|
* The Mojang service to use.
|
||||||
|
*/
|
||||||
|
@NonNull private final MojangService mojangService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public MojangController(@NonNull MojangService mojangService) {
|
||||||
|
this.mojangService = mojangService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GET route to get the status of Mojang servers.
|
||||||
|
*
|
||||||
|
* @return the status response
|
||||||
|
*/
|
||||||
|
@GetMapping("/status")
|
||||||
|
@ResponseBody
|
||||||
|
public ResponseEntity<Map<String, String>> getStatus() throws BadRequestException {
|
||||||
|
Map<String, String> response = new HashMap<>();
|
||||||
|
for (Map.Entry<MojangServer, MojangServer.Status> entry : mojangService.getMojangServerStatuses().entrySet()) {
|
||||||
|
response.put(entry.getKey().getEndpoint(), entry.getValue().name());
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
}
|
||||||
|
}
|
@ -50,7 +50,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
@Tag(name = "Player Controller", description = "The controller for handling player related requests.")
|
@Tag(name = "Player Controller", description = "The controller for handling player related requests.")
|
||||||
public final class PlayerController {
|
public final class PlayerController {
|
||||||
/**
|
/**
|
||||||
* The Mojang service to use for player information.
|
* The Mojang service to use.
|
||||||
*/
|
*/
|
||||||
@NonNull private final MojangService mojangService;
|
@NonNull private final MojangService mojangService;
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ import java.util.Map;
|
|||||||
@Tag(name = "Server Controller", description = "The controller for handling server related requests.")
|
@Tag(name = "Server Controller", description = "The controller for handling server related requests.")
|
||||||
public final class ServerController {
|
public final class ServerController {
|
||||||
/**
|
/**
|
||||||
* The Mojang service to use for server information.
|
* The Mojang service to use.
|
||||||
*/
|
*/
|
||||||
@NonNull private final MojangService mojangService;
|
@NonNull private final MojangService mojangService;
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import com.google.common.base.Splitter;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
@ -77,11 +78,9 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@Service
|
@Service
|
||||||
@Log4j2(topic = "Mojang Service")
|
@Log4j2(topic = "Mojang Service")
|
||||||
public final class MojangService {
|
public final class MojangService {
|
||||||
private static final String SESSION_SERVER_ENDPOINT = "https://sessionserver.mojang.com";
|
private static final String UUID_TO_PROFILE = MojangServer.SESSION.getEndpoint() + "/session/minecraft/profile/%s";
|
||||||
private static final String API_ENDPOINT = "https://api.mojang.com";
|
private static final String USERNAME_TO_UUID = MojangServer.API.getEndpoint() + "/users/profiles/minecraft/%s";
|
||||||
private static final String UUID_TO_PROFILE = SESSION_SERVER_ENDPOINT + "/session/minecraft/profile/%s";
|
private static final String FETCH_BLOCKED_SERVERS = MojangServer.SESSION.getEndpoint() + "/blockedservers";
|
||||||
private static final String USERNAME_TO_UUID = API_ENDPOINT + "/users/profiles/minecraft/%s";
|
|
||||||
private static final String FETCH_BLOCKED_SERVERS = SESSION_SERVER_ENDPOINT + "/blockedservers";
|
|
||||||
|
|
||||||
private static final int DEFAULT_PART_TEXTURE_SIZE = 128;
|
private static final int DEFAULT_PART_TEXTURE_SIZE = 128;
|
||||||
private static final int MAX_PART_TEXTURE_SIZE = 512;
|
private static final int MAX_PART_TEXTURE_SIZE = 512;
|
||||||
@ -102,7 +101,7 @@ public final class MojangService {
|
|||||||
@NonNull private final PlayerCacheRepository playerCache;
|
@NonNull private final PlayerCacheRepository playerCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cache repository for {@link Skin.Part}'s.
|
* The cache repository for {@link ISkinPart}'s.
|
||||||
*/
|
*/
|
||||||
@NonNull private final SkinPartTextureCacheRepository skinPartTextureCache;
|
@NonNull private final SkinPartTextureCacheRepository skinPartTextureCache;
|
||||||
|
|
||||||
@ -111,6 +110,11 @@ public final class MojangService {
|
|||||||
*/
|
*/
|
||||||
@NonNull private final MinecraftServerCacheRepository minecraftServerCache;
|
@NonNull private final MinecraftServerCacheRepository minecraftServerCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapped statuses for {@link MojangServer}'s.
|
||||||
|
*/
|
||||||
|
@Getter private final Map<MojangServer, MojangServer.Status> mojangServerStatuses = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of banned server hashes provided by Mojang.
|
* A list of banned server hashes provided by Mojang.
|
||||||
* <p>
|
* <p>
|
||||||
@ -140,6 +144,15 @@ public final class MojangService {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
|
// Schedule a task to fetch statuses
|
||||||
|
// of Mojang servers every few minutes
|
||||||
|
new Timer().scheduleAtFixedRate(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
fetchMojangServerStatuses();
|
||||||
|
}
|
||||||
|
}, 0L, 60L * 3L * 1000L);
|
||||||
|
|
||||||
// Schedule a task to fetch blocked
|
// Schedule a task to fetch blocked
|
||||||
// servers from Mojang every 15 minutes.
|
// servers from Mojang every 15 minutes.
|
||||||
new Timer().scheduleAtFixedRate(new TimerTask() {
|
new Timer().scheduleAtFixedRate(new TimerTask() {
|
||||||
@ -501,6 +514,22 @@ public final class MojangService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the statuses of {@link MojangServer}'s.
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
private void fetchMojangServerStatuses() {
|
||||||
|
log.info("Checking Mojang server statuses...");
|
||||||
|
long before = System.currentTimeMillis();
|
||||||
|
for (MojangServer server : MojangServer.values()) {
|
||||||
|
log.info("Pinging {}...", server.getEndpoint());
|
||||||
|
MojangServer.Status status = server.getStatus(); // Retrieve the server status
|
||||||
|
log.info("Retrieved status of {}: {}", server.getEndpoint(), status.name());
|
||||||
|
mojangServerStatuses.put(server, status); // Cache the server status
|
||||||
|
}
|
||||||
|
log.info("Mojang server status check took {}ms", System.currentTimeMillis() - before);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a list of blocked servers from Mojang.
|
* Fetch a list of blocked servers from Mojang.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user