Compare commits
47 Commits
a8558578f2
...
renovate/o
Author | SHA1 | Date | |
---|---|---|---|
9a0b6e1635 | |||
0bc614ce39 | |||
499c54c8cf | |||
41f7ca07b0 | |||
5ec61940ac | |||
6665e8a655 | |||
07562eb94d | |||
a78adf67c7 | |||
fc1f51da75 | |||
c796875d8c | |||
82fb2a3d23 | |||
2e326bb7be | |||
c5bf941c54 | |||
0eb965a26d | |||
5481c9302c | |||
b7834ab389 | |||
bb651bd88b | |||
2b017f9ef7 | |||
d83391de33 | |||
76bef70473 | |||
4aa5b0a90d | |||
6a44618ae9 | |||
146d053af8 | |||
796146c039 | |||
00c83d9ae3 | |||
3bbab24e45 | |||
5034a11e63 | |||
3d11c65678 | |||
fd3da02159 | |||
0bdaefe4a2 | |||
ba167b4e56 | |||
493e7ce4c0 | |||
7f501431b1 | |||
fa92791b56 | |||
6750773640 | |||
cecc6bc94f | |||
20db1c1aff | |||
e62e7f0fc2 | |||
c9ed681204 | |||
c6642e85fe | |||
9dfbd1af47 | |||
c8629e4f27 | |||
a6209c45ff | |||
ee5b1f12d8 | |||
ff79372ead | |||
f0e1490463 | |||
9196ec3578 |
@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
# Setup Java and Maven
|
||||
- name: Set up JDK and Maven
|
||||
uses: s4u/setup-maven-action@v1.12.0
|
||||
uses: s4u/setup-maven-action@v1.14.0
|
||||
with:
|
||||
java-version: ${{ matrix.java-version }}
|
||||
distribution: "zulu"
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM maven:3.9.6-eclipse-temurin-17-alpine
|
||||
FROM maven:3.9.8-eclipse-temurin-17-alpine
|
||||
|
||||
RUN apk --update --upgrade --no-cache add fontconfig ttf-freefont font-noto terminus-font \
|
||||
&& fc-cache -f \
|
||||
|
20
pom.xml
20
pom.xml
@ -17,7 +17,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.2.5</version>
|
||||
<version>3.3.2</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
@ -93,13 +93,13 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.32</version>
|
||||
<version>1.18.34</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10.1</version>
|
||||
<version>2.11.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -122,7 +122,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
<version>5.3.1</version>
|
||||
<version>5.4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@ -133,20 +133,20 @@
|
||||
<dependency>
|
||||
<groupId>io.sentry</groupId>
|
||||
<artifactId>sentry-spring-boot-starter-jakarta</artifactId>
|
||||
<version>7.8.0</version>
|
||||
<version>7.14.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- InfluxDB Metrics -->
|
||||
<dependency>
|
||||
<groupId>com.influxdb</groupId>
|
||||
<artifactId>influxdb-spring</artifactId>
|
||||
<version>7.0.0</version>
|
||||
<version>7.2.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.influxdb</groupId>
|
||||
<artifactId>influxdb-client-java</artifactId>
|
||||
<version>7.0.0</version>
|
||||
<version>7.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- DNS Lookup -->
|
||||
@ -161,7 +161,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.5.0</version>
|
||||
<version>2.6.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
@ -176,7 +176,7 @@
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-archiver</artifactId>
|
||||
<version>4.9.1</version>
|
||||
<version>4.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Tests -->
|
||||
@ -194,7 +194,7 @@
|
||||
<dependency>
|
||||
<groupId>de.flapdoodle.embed</groupId>
|
||||
<artifactId>de.flapdoodle.embed.mongo.spring3x</artifactId>
|
||||
<version>4.12.6</version>
|
||||
<version>4.16.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -16,9 +16,9 @@ import java.util.Objects;
|
||||
@Log4j2(topic = "Main")
|
||||
@SpringBootApplication
|
||||
public class Main {
|
||||
public static final Gson GSON = new GsonBuilder()
|
||||
.setDateFormat("MM-dd-yyyy HH:mm:ss")
|
||||
.create();
|
||||
public static final Gson GSON = new GsonBuilder()
|
||||
.setDateFormat("MM-dd-yyyy HH:mm:ss")
|
||||
.create();
|
||||
public static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
|
||||
|
||||
@SneakyThrows
|
||||
|
@ -22,7 +22,7 @@ public final class AppConfig {
|
||||
private static boolean isRunningTest = true;
|
||||
static {
|
||||
try {
|
||||
Class.forName("org.junit.Test");
|
||||
Class.forName("org.junit.jupiter.engine.JupiterTestEngine");
|
||||
} catch (ClassNotFoundException e) {
|
||||
isRunningTest = false;
|
||||
}
|
||||
|
85
src/main/java/xyz/mcutils/backend/common/MojangServer.java
Normal file
85
src/main/java/xyz/mcutils/backend/common/MojangServer.java
Normal file
@ -0,0 +1,85 @@
|
||||
package xyz.mcutils.backend.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;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Fascinated (fascinated7)
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
public enum MojangServer {
|
||||
SESSION("Session Server", "https://sessionserver.mojang.com"),
|
||||
API("Mojang API", "https://api.mojang.com"),
|
||||
TEXTURES("Textures Server", "https://textures.minecraft.net"),
|
||||
ASSETS("Assets Server", "https://assets.mojang.com"),
|
||||
LIBRARIES("Libraries Server", "https://libraries.minecraft.net"),
|
||||
SERVICES("Minecraft Services", "https://api.minecraftservices.com");
|
||||
|
||||
private static final long STATUS_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
|
||||
|
||||
/**
|
||||
* The name of this server.
|
||||
*/
|
||||
@NonNull private final String name;
|
||||
|
||||
/**
|
||||
* The endpoint of this service.
|
||||
*/
|
||||
@NonNull private final String endpoint;
|
||||
|
||||
/**
|
||||
* Ping this service and get the status of it.
|
||||
*
|
||||
* @return the service status
|
||||
*/
|
||||
@NonNull
|
||||
public Status getStatus() {
|
||||
try {
|
||||
InetAddress address = InetAddress.getByName(endpoint.substring(8));
|
||||
long before = System.currentTimeMillis();
|
||||
if (address.isReachable((int) 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, then 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
|
||||
}
|
||||
}
|
@ -12,23 +12,21 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import xyz.mcutils.backend.model.cache.CachedEndpointStatus;
|
||||
import xyz.mcutils.backend.service.MojangService;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Mojang Controller", description = "The Mojang Controller is used to get information about the Mojang APIs.")
|
||||
@RequestMapping(value = "/mojang/", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Tag(name = "Mojang Controller", description = "The Mojang Controller is used to get information about the Mojang APIs.")
|
||||
public class MojangController {
|
||||
|
||||
@Autowired
|
||||
private MojangService mojangService;
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping(value = "/status")
|
||||
public ResponseEntity<CachedEndpointStatus> getStatus() {
|
||||
CachedEndpointStatus status = mojangService.getMojangApiStatus();
|
||||
|
||||
public ResponseEntity<?> getStatus() {
|
||||
return ResponseEntity.ok()
|
||||
.cacheControl(CacheControl.maxAge(1, TimeUnit.MINUTES).cachePublic())
|
||||
.body(status);
|
||||
.body(Map.of("endpoints", mojangService.getMojangServerStatus()));
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ import xyz.mcutils.backend.service.PlayerService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Player Controller", description = "The Player Controller is used to get information about a player.")
|
||||
@RequestMapping(value = "/player/")
|
||||
@Tag(name = "Player Controller", description = "The Player Controller is used to get information about a player.")
|
||||
public class PlayerController {
|
||||
|
||||
private final PlayerService playerService;
|
||||
|
@ -16,8 +16,8 @@ import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Server Controller", description = "The Server Controller is used to get information about a server.")
|
||||
@RequestMapping(value = "/server/")
|
||||
@Tag(name = "Server Controller", description = "The Server Controller is used to get information about a server.")
|
||||
public class ServerController {
|
||||
|
||||
private final ServerService serverService;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package xyz.mcutils.backend.exception;
|
||||
|
||||
import io.micrometer.common.lang.NonNull;
|
||||
import io.sentry.Sentry;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
@ -39,6 +40,7 @@ public final class ExceptionControllerAdvice {
|
||||
}
|
||||
if (status == null) { // Fallback to 500
|
||||
status = HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
Sentry.captureException(ex); // Capture the exception with Sentry
|
||||
}
|
||||
return new ResponseEntity<>(new ErrorResponse(status, message), status);
|
||||
}
|
||||
|
@ -8,10 +8,13 @@ import lombok.Setter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
import xyz.mcutils.backend.common.CachedResponse;
|
||||
import xyz.mcutils.backend.model.mojang.EndpointStatus;
|
||||
import xyz.mcutils.backend.common.MojangServer;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Setter @Getter @EqualsAndHashCode(callSuper = false)
|
||||
@RedisHash(value = "mojangEndpointStatus", timeToLive = 60L) // 1 minute (in seconds)
|
||||
@ -26,11 +29,21 @@ public class CachedEndpointStatus extends CachedResponse implements Serializable
|
||||
/**
|
||||
* The endpoint cache.
|
||||
*/
|
||||
private final List<EndpointStatus> endpoints;
|
||||
private final List<Map<String, Object>> endpoints;
|
||||
|
||||
public CachedEndpointStatus(@NonNull String id, List<EndpointStatus> endpoints) {
|
||||
public CachedEndpointStatus(@NonNull String id, Map<MojangServer, MojangServer.Status> mojangServers) {
|
||||
super(Cache.defaultCache());
|
||||
this.id = id;
|
||||
this.endpoints = endpoints;
|
||||
this.endpoints = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<MojangServer, MojangServer.Status> entry : mojangServers.entrySet()) {
|
||||
MojangServer server = entry.getKey();
|
||||
|
||||
Map<String, Object> serverStatus = new HashMap<>();
|
||||
serverStatus.put("name", server.getName());
|
||||
serverStatus.put("endpoint", server.getEndpoint());
|
||||
serverStatus.put("status", entry.getValue().name());
|
||||
endpoints.add(serverStatus);
|
||||
}
|
||||
}
|
||||
}
|
@ -58,7 +58,7 @@ public final class BedrockMinecraftServer extends MinecraftServer {
|
||||
Edition edition = Edition.valueOf(split[0]);
|
||||
Version version = new Version(Integer.parseInt(split[2]), split[3]);
|
||||
Players players = new Players(Integer.parseInt(split[4]), Integer.parseInt(split[5]), null);
|
||||
MOTD motd = MOTD.create(split[1] + "\n" + split[7]);
|
||||
MOTD motd = MOTD.create(hostname, Platform.BEDROCK, split[1] + "\n" + split[7]);
|
||||
GameMode gameMode = new GameMode(split[8], split.length > 9 ? Integer.parseInt(split[9]) : -1);
|
||||
return new BedrockMinecraftServer(
|
||||
split[6],
|
||||
|
@ -97,7 +97,7 @@ public final class JavaMinecraftServer extends MinecraftServer {
|
||||
hostname,
|
||||
ip,
|
||||
port,
|
||||
MinecraftServer.MOTD.create(motdString),
|
||||
MinecraftServer.MOTD.create(hostname, Platform.JAVA, motdString),
|
||||
token.getPlayers(),
|
||||
location,
|
||||
records,
|
||||
|
@ -4,6 +4,7 @@ import com.maxmind.geoip2.model.CityResponse;
|
||||
import io.micrometer.common.lang.NonNull;
|
||||
import lombok.*;
|
||||
import xyz.mcutils.backend.common.ColorUtils;
|
||||
import xyz.mcutils.backend.config.Config;
|
||||
import xyz.mcutils.backend.model.dns.DNSRecord;
|
||||
import xyz.mcutils.backend.service.pinger.MinecraftServerPinger;
|
||||
import xyz.mcutils.backend.service.pinger.impl.BedrockMinecraftServerPinger;
|
||||
@ -100,6 +101,11 @@ public class MinecraftServer {
|
||||
*/
|
||||
private final String[] html;
|
||||
|
||||
/**
|
||||
* The URL to the server preview image.
|
||||
*/
|
||||
private final String preview;
|
||||
|
||||
/**
|
||||
* Create a new MOTD from a raw string.
|
||||
*
|
||||
@ -107,12 +113,14 @@ public class MinecraftServer {
|
||||
* @return the new motd
|
||||
*/
|
||||
@NonNull
|
||||
public static MOTD create(@NonNull String raw) {
|
||||
public static MOTD create(@NonNull String hostname, @NonNull Platform platform, @NonNull String raw) {
|
||||
String[] rawLines = raw.split("\n"); // The raw lines
|
||||
return new MOTD(
|
||||
rawLines,
|
||||
Arrays.stream(rawLines).map(ColorUtils::stripColor).toArray(String[]::new),
|
||||
Arrays.stream(rawLines).map(ColorUtils::toHTML).toArray(String[]::new)
|
||||
Arrays.stream(rawLines).map(ColorUtils::toHTML).toArray(String[]::new),
|
||||
Config.INSTANCE.getWebPublicUrl() + "/server/%s/preview/%s".formatted(
|
||||
platform.name().toLowerCase(),hostname)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
package xyz.mcutils.backend.repository.redis;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import xyz.mcutils.backend.model.cache.CachedEndpointStatus;
|
||||
|
||||
/**
|
||||
* A cache repository for {@link CachedEndpointStatus}'s.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
public interface EndpointStatusRepository extends CrudRepository<CachedEndpointStatus, String> { }
|
@ -3,6 +3,7 @@ package xyz.mcutils.backend.service;
|
||||
import com.maxmind.geoip2.DatabaseReader;
|
||||
import com.maxmind.geoip2.exception.GeoIp2Exception;
|
||||
import com.maxmind.geoip2.model.CityResponse;
|
||||
import io.sentry.Sentry;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.codehaus.plexus.archiver.tar.TarGZipUnArchiver;
|
||||
@ -68,7 +69,8 @@ public class MaxMindService {
|
||||
return database.city(InetAddress.getByName(ip));
|
||||
} catch (IOException | GeoIp2Exception e) {
|
||||
log.error("Failed to lookup the GeoIP information for '{}'", ip, e);
|
||||
throw new RuntimeException("Failed to lookup the IP for '%s'".formatted(ip));
|
||||
Sentry.captureException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,26 +9,23 @@ import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.jodah.expiringmap.ExpirationPolicy;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import xyz.mcutils.backend.common.AppConfig;
|
||||
import xyz.mcutils.backend.common.ExpiringSet;
|
||||
import xyz.mcutils.backend.common.MojangServer;
|
||||
import xyz.mcutils.backend.common.WebRequest;
|
||||
import xyz.mcutils.backend.model.cache.CachedEndpointStatus;
|
||||
import xyz.mcutils.backend.model.mojang.EndpointStatus;
|
||||
import xyz.mcutils.backend.model.token.MojangProfileToken;
|
||||
import xyz.mcutils.backend.model.token.MojangUsernameToUuidToken;
|
||||
import xyz.mcutils.backend.repository.redis.EndpointStatusRepository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service @Log4j2(topic = "Mojang Service") @Getter
|
||||
@Service
|
||||
@Log4j2(topic = "Mojang Service")
|
||||
@Getter
|
||||
public class MojangService {
|
||||
|
||||
/**
|
||||
@ -50,19 +47,9 @@ public class MojangService {
|
||||
private static final long FETCH_BLOCKED_SERVERS_INTERVAL = TimeUnit.HOURS.toMillis(1L);
|
||||
|
||||
/**
|
||||
* Information about the Mojang API endpoints.
|
||||
* The interval to fetch the Mojang server status.
|
||||
*/
|
||||
private static final String MOJANG_ENDPOINT_STATUS_KEY = "mojang";
|
||||
private static final List<EndpointStatus> MOJANG_ENDPOINTS = List.of(
|
||||
new EndpointStatus("Minecraft Textures", "textures.minecraft.net"),
|
||||
new EndpointStatus("Minecraft Libraries", "libraries.minecraft.net"),
|
||||
new EndpointStatus("Minecraft Services", "api.minecraftservices.com"),
|
||||
new EndpointStatus("Mojang Assets", "assets.mojang.com"),
|
||||
new EndpointStatus("Mojang API", "api.mojang.com"),
|
||||
new EndpointStatus("Mojang Session Server", "sessionserver.mojang.com"));
|
||||
|
||||
@Autowired
|
||||
private EndpointStatusRepository mojangEndpointStatusRepository;
|
||||
private static final long FETCH_MOJANG_SERVERS_STATUS_INTERVAL = TimeUnit.MINUTES.toMillis(1L);
|
||||
|
||||
/**
|
||||
* A list of banned server hashes provided by Mojang.
|
||||
@ -82,6 +69,11 @@ public class MojangService {
|
||||
*/
|
||||
private final ExpiringSet<String> blockedServersCache = new ExpiringSet<>(ExpirationPolicy.CREATED, 10L, TimeUnit.MINUTES);
|
||||
|
||||
/**
|
||||
* The status of the Mojang API.
|
||||
*/
|
||||
private final List<Map<String, Object>> mojangServerStatus = new ArrayList<>();
|
||||
|
||||
public MojangService() {
|
||||
new Timer().scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
@ -89,6 +81,33 @@ public class MojangService {
|
||||
fetchBlockedServers();
|
||||
}
|
||||
}, 0L, FETCH_BLOCKED_SERVERS_INTERVAL);
|
||||
|
||||
new Timer().scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
log.info("Fetching Mojang Server status...");
|
||||
Map<MojangServer, MojangServer.Status> mojangServers = new HashMap<>();
|
||||
Arrays.stream(MojangServer.values()).parallel().forEach(server -> {
|
||||
log.info("Pinging {}...", server.getEndpoint());
|
||||
MojangServer.Status status = server.getStatus(); // Retrieve the server status
|
||||
log.info("Retrieved status of {}: {}", server.getEndpoint(), status.name());
|
||||
mojangServers.put(server, status); // Cache the server status
|
||||
});
|
||||
|
||||
mojangServerStatus.clear();
|
||||
for (Map.Entry<MojangServer, MojangServer.Status> entry : mojangServers.entrySet()) {
|
||||
MojangServer server = entry.getKey();
|
||||
|
||||
Map<String, Object> serverStatus = new HashMap<>();
|
||||
serverStatus.put("name", server.getName());
|
||||
serverStatus.put("endpoint", server.getEndpoint());
|
||||
serverStatus.put("status", entry.getValue().name());
|
||||
mojangServerStatus.add(serverStatus);
|
||||
}
|
||||
|
||||
log.info("Fetched Mojang Server status for {} endpoints", mojangServers.size());
|
||||
}
|
||||
}, 0L, FETCH_MOJANG_SERVERS_STATUS_INTERVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,6 +126,8 @@ public class MojangService {
|
||||
}
|
||||
bannedServerHashes = Collections.synchronizedList(hashes);
|
||||
log.info("Fetched {} banned server hashes", bannedServerHashes.size());
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to fetch blocked servers from Mojang", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,46 +198,6 @@ public class MojangService {
|
||||
return blocked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of the Mojang APIs.
|
||||
*
|
||||
* @return the status
|
||||
*/
|
||||
public CachedEndpointStatus getMojangApiStatus() {
|
||||
log.info("Getting Mojang API status");
|
||||
Optional<CachedEndpointStatus> endpointStatus = mojangEndpointStatusRepository.findById(MOJANG_ENDPOINT_STATUS_KEY);
|
||||
if (endpointStatus.isPresent() && AppConfig.isProduction()) {
|
||||
log.info("Got cached Mojang API status");
|
||||
return endpointStatus.get();
|
||||
}
|
||||
|
||||
MOJANG_ENDPOINTS.parallelStream().forEach(endpoint -> {
|
||||
try {
|
||||
long start = System.currentTimeMillis();
|
||||
InetAddress address = InetAddress.getByName(endpoint.getHostname());
|
||||
if (address.isReachable((int) TimeUnit.SECONDS.toMillis(4))) { // Check if the endpoint is reachable
|
||||
endpoint.setStatus(EndpointStatus.Status.ONLINE);
|
||||
return;
|
||||
}
|
||||
// Check if the endpoint took too long to respond
|
||||
if (System.currentTimeMillis() - start > TimeUnit.SECONDS.toMillis(2)) {
|
||||
endpoint.setStatus(EndpointStatus.Status.DEGRADED);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
endpoint.setStatus(EndpointStatus.Status.OFFLINE);
|
||||
}
|
||||
});
|
||||
|
||||
log.info("Fetched Mojang API status for {} endpoints", MOJANG_ENDPOINTS.size());
|
||||
CachedEndpointStatus status = new CachedEndpointStatus(
|
||||
MOJANG_ENDPOINT_STATUS_KEY,
|
||||
MOJANG_ENDPOINTS
|
||||
);
|
||||
mojangEndpointStatusRepository.save(status);
|
||||
status.getCache().setCached(false);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Session Server profile of the
|
||||
* player with the given UUID.
|
||||
|
Reference in New Issue
Block a user