Compare commits
18 Commits
bb651bd88b
...
master
Author | SHA1 | Date | |
---|---|---|---|
0bc614ce39 | |||
499c54c8cf | |||
41f7ca07b0 | |||
5ec61940ac | |||
6665e8a655 | |||
07562eb94d | |||
a78adf67c7 | |||
fc1f51da75 | |||
c796875d8c | |||
82fb2a3d23 | |||
2e326bb7be | |||
c5bf941c54 | |||
0eb965a26d | |||
5481c9302c | |||
b7834ab389 | |||
d83391de33 | |||
76bef70473 | |||
4aa5b0a90d |
10
pom.xml
10
pom.xml
@ -17,7 +17,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>3.3.1</version>
|
<version>3.3.2</version>
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@ -133,20 +133,20 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.sentry</groupId>
|
<groupId>io.sentry</groupId>
|
||||||
<artifactId>sentry-spring-boot-starter-jakarta</artifactId>
|
<artifactId>sentry-spring-boot-starter-jakarta</artifactId>
|
||||||
<version>7.11.0</version>
|
<version>7.14.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- InfluxDB Metrics -->
|
<!-- InfluxDB Metrics -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.influxdb</groupId>
|
<groupId>com.influxdb</groupId>
|
||||||
<artifactId>influxdb-spring</artifactId>
|
<artifactId>influxdb-spring</artifactId>
|
||||||
<version>7.1.0</version>
|
<version>7.2.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.influxdb</groupId>
|
<groupId>com.influxdb</groupId>
|
||||||
<artifactId>influxdb-client-java</artifactId>
|
<artifactId>influxdb-client-java</artifactId>
|
||||||
<version>7.1.0</version>
|
<version>7.2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- DNS Lookup -->
|
<!-- DNS Lookup -->
|
||||||
@ -194,7 +194,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.flapdoodle.embed</groupId>
|
<groupId>de.flapdoodle.embed</groupId>
|
||||||
<artifactId>de.flapdoodle.embed.mongo.spring3x</artifactId>
|
<artifactId>de.flapdoodle.embed.mongo.spring3x</artifactId>
|
||||||
<version>4.15.0</version>
|
<version>4.16.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -24,7 +24,7 @@ public enum MojangServer {
|
|||||||
LIBRARIES("Libraries Server", "https://libraries.minecraft.net"),
|
LIBRARIES("Libraries Server", "https://libraries.minecraft.net"),
|
||||||
SERVICES("Minecraft Services", "https://api.minecraftservices.com");
|
SERVICES("Minecraft Services", "https://api.minecraftservices.com");
|
||||||
|
|
||||||
private static final long STATUS_TIMEOUT = TimeUnit.SECONDS.toMillis(4);
|
private static final long STATUS_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of this server.
|
* The name of this server.
|
||||||
@ -58,7 +58,7 @@ public enum MojangServer {
|
|||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
// We can safely ignore any errors, we're simply checking
|
// We can safely ignore any errors, we're simply checking
|
||||||
// if the host is reachable, if it's not, it's offline.
|
// if the host is reachable, if it's not, then it's offline.
|
||||||
}
|
}
|
||||||
return Status.OFFLINE;
|
return Status.OFFLINE;
|
||||||
}
|
}
|
||||||
|
@ -12,25 +12,21 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
import xyz.mcutils.backend.model.cache.CachedEndpointStatus;
|
import xyz.mcutils.backend.model.cache.CachedEndpointStatus;
|
||||||
import xyz.mcutils.backend.service.MojangService;
|
import xyz.mcutils.backend.service.MojangService;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@RestController
|
@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)
|
@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 {
|
public class MojangController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MojangService mojangService;
|
private MojangService mojangService;
|
||||||
|
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@GetMapping(value = "/status")
|
@GetMapping(value = "/status")
|
||||||
public ResponseEntity<?> getStatus() {
|
public ResponseEntity<?> getStatus() {
|
||||||
CachedEndpointStatus status = mojangService.getMojangApiStatus();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.cacheControl(CacheControl.maxAge(1, TimeUnit.MINUTES).cachePublic())
|
.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;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@Tag(name = "Player Controller", description = "The Player Controller is used to get information about a player.")
|
|
||||||
@RequestMapping(value = "/player/")
|
@RequestMapping(value = "/player/")
|
||||||
|
@Tag(name = "Player Controller", description = "The Player Controller is used to get information about a player.")
|
||||||
public class PlayerController {
|
public class PlayerController {
|
||||||
|
|
||||||
private final PlayerService playerService;
|
private final PlayerService playerService;
|
||||||
|
@ -16,8 +16,8 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@Tag(name = "Server Controller", description = "The Server Controller is used to get information about a server.")
|
|
||||||
@RequestMapping(value = "/server/")
|
@RequestMapping(value = "/server/")
|
||||||
|
@Tag(name = "Server Controller", description = "The Server Controller is used to get information about a server.")
|
||||||
public class ServerController {
|
public class ServerController {
|
||||||
|
|
||||||
private final ServerService serverService;
|
private final ServerService serverService;
|
||||||
|
@ -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> { }
|
|
@ -9,16 +9,12 @@ import lombok.Getter;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import net.jodah.expiringmap.ExpirationPolicy;
|
import net.jodah.expiringmap.ExpirationPolicy;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import xyz.mcutils.backend.common.AppConfig;
|
|
||||||
import xyz.mcutils.backend.common.ExpiringSet;
|
import xyz.mcutils.backend.common.ExpiringSet;
|
||||||
import xyz.mcutils.backend.common.MojangServer;
|
import xyz.mcutils.backend.common.MojangServer;
|
||||||
import xyz.mcutils.backend.common.WebRequest;
|
import xyz.mcutils.backend.common.WebRequest;
|
||||||
import xyz.mcutils.backend.model.cache.CachedEndpointStatus;
|
|
||||||
import xyz.mcutils.backend.model.token.MojangProfileToken;
|
import xyz.mcutils.backend.model.token.MojangProfileToken;
|
||||||
import xyz.mcutils.backend.model.token.MojangUsernameToUuidToken;
|
import xyz.mcutils.backend.model.token.MojangUsernameToUuidToken;
|
||||||
import xyz.mcutils.backend.repository.redis.EndpointStatusRepository;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -27,7 +23,9 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Service @Log4j2(topic = "Mojang Service") @Getter
|
@Service
|
||||||
|
@Log4j2(topic = "Mojang Service")
|
||||||
|
@Getter
|
||||||
public class MojangService {
|
public class MojangService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,8 +46,10 @@ public class MojangService {
|
|||||||
*/
|
*/
|
||||||
private static final long FETCH_BLOCKED_SERVERS_INTERVAL = TimeUnit.HOURS.toMillis(1L);
|
private static final long FETCH_BLOCKED_SERVERS_INTERVAL = TimeUnit.HOURS.toMillis(1L);
|
||||||
|
|
||||||
@Autowired
|
/**
|
||||||
private EndpointStatusRepository mojangEndpointStatusRepository;
|
* The interval to fetch the Mojang server status.
|
||||||
|
*/
|
||||||
|
private static final long FETCH_MOJANG_SERVERS_STATUS_INTERVAL = TimeUnit.MINUTES.toMillis(1L);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of banned server hashes provided by Mojang.
|
* A list of banned server hashes provided by Mojang.
|
||||||
@ -69,6 +69,11 @@ public class MojangService {
|
|||||||
*/
|
*/
|
||||||
private final ExpiringSet<String> blockedServersCache = new ExpiringSet<>(ExpirationPolicy.CREATED, 10L, TimeUnit.MINUTES);
|
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() {
|
public MojangService() {
|
||||||
new Timer().scheduleAtFixedRate(new TimerTask() {
|
new Timer().scheduleAtFixedRate(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
@ -76,6 +81,33 @@ public class MojangService {
|
|||||||
fetchBlockedServers();
|
fetchBlockedServers();
|
||||||
}
|
}
|
||||||
}, 0L, FETCH_BLOCKED_SERVERS_INTERVAL);
|
}, 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,37 +198,6 @@ public class MojangService {
|
|||||||
return blocked;
|
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-servers-status");
|
|
||||||
if (endpointStatus.isPresent() && AppConfig.isProduction()) {
|
|
||||||
log.info("Got cached Mojang API status");
|
|
||||||
return endpointStatus.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
});
|
|
||||||
|
|
||||||
log.info("Fetched Mojang API status for {} endpoints", mojangServers.size());
|
|
||||||
CachedEndpointStatus status = new CachedEndpointStatus(
|
|
||||||
"mojang-servers-status",
|
|
||||||
mojangServers
|
|
||||||
);
|
|
||||||
mojangEndpointStatusRepository.save(status);
|
|
||||||
status.getCache().setCached(false);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Session Server profile of the
|
* Gets the Session Server profile of the
|
||||||
* player with the given UUID.
|
* player with the given UUID.
|
||||||
|
Reference in New Issue
Block a user