add mojang api rate limit error
All checks were successful
ci / deploy (push) Successful in 1m14s

This commit is contained in:
Lee 2024-04-10 09:30:35 +01:00
parent 330c3efc78
commit 2e58d9c925
7 changed files with 58 additions and 27 deletions

View File

@ -1,6 +1,8 @@
package cc.fascinated.common;
import cc.fascinated.exception.impl.RateLimitException;
import lombok.experimental.UtilityClass;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.HttpClientErrorException;
@ -33,6 +35,9 @@ public class WebRequest {
if (profile.getStatusCode().isError()) {
return null;
}
if (profile.getStatusCode().isSameCodeAs(HttpStatus.TOO_MANY_REQUESTS)) {
throw new RateLimitException("Rate limit reached");
}
return profile.getBody();
} catch (HttpClientErrorException ex) {
return null;

View File

@ -18,7 +18,7 @@ public class HomeController {
@RequestMapping(value = "/")
public String home(Model model) {
model.addAttribute("player_example_url", Config.INSTANCE.getWebPublicUrl() + "/player/" + exampleUuid);
model.addAttribute("java_server_example_url", Config.INSTANCE.getWebPublicUrl() + "/java/play.hypixel.net");
model.addAttribute("java_server_example_url", Config.INSTANCE.getWebPublicUrl() + "/server/java/play.hypixel.net");
return "index";
}
}

View File

@ -0,0 +1,9 @@
package cc.fascinated.exception.impl;
public class MojangAPIRateLimitException extends RateLimitException {
public MojangAPIRateLimitException() {
super("Mojang API rate limit exceeded. Please try again later.");
}
}

View File

@ -0,0 +1,12 @@
package cc.fascinated.exception.impl;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.TOO_MANY_REQUESTS)
public class RateLimitException extends RuntimeException {
public RateLimitException(String message) {
super(message);
}
}

View File

@ -24,7 +24,7 @@ public final class CachedMinecraftServer implements Serializable {
* The cached server.
*/
@NonNull
private final MinecraftServer value;
private final MinecraftServer server;
/**
* The unix timestamp of when this

View File

@ -3,27 +3,23 @@ package cc.fascinated.service;
import cc.fascinated.common.PlayerUtils;
import cc.fascinated.common.Tuple;
import cc.fascinated.common.UUIDUtils;
import cc.fascinated.exception.impl.BadRequestException;
import cc.fascinated.exception.impl.MojangAPIRateLimitException;
import cc.fascinated.exception.impl.RateLimitException;
import cc.fascinated.exception.impl.ResourceNotFoundException;
import cc.fascinated.model.cache.CachedPlayer;
import cc.fascinated.model.cache.CachedPlayerName;
import cc.fascinated.model.mojang.MojangProfile;
import cc.fascinated.model.mojang.MojangUsernameToUuid;
import cc.fascinated.model.player.Cape;
import cc.fascinated.model.player.Player;
import cc.fascinated.model.player.Skin;
import cc.fascinated.repository.PlayerCacheRepository;
import cc.fascinated.repository.PlayerNameCacheRepository;
import lombok.extern.log4j.Log4j2;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Service @Log4j2
public class PlayerService {
@ -47,6 +43,7 @@ public class PlayerService {
* @return the player
*/
public CachedPlayer getPlayer(String id) {
id = id.toUpperCase(); // Convert the id to uppercase to prevent case sensitivity
UUID uuid = PlayerUtils.getUuidFromString(id);
if (uuid == null) { // If the id is not a valid uuid, get the uuid from the username
uuid = usernameToUuid(id);
@ -57,19 +54,23 @@ public class PlayerService {
return cachedPlayer.get();
}
MojangProfile mojangProfile = mojangAPIService.getProfile(uuid.toString());
Tuple<Skin, Cape> skinAndCape = mojangProfile.getSkinAndCape();
CachedPlayer player = new CachedPlayer(
uuid,
mojangProfile.getName(),
skinAndCape.getLeft(), // Skin
skinAndCape.getRight(), // Cape
System.currentTimeMillis()
);
try {
MojangProfile mojangProfile = mojangAPIService.getProfile(uuid.toString()); // Get the player profile from Mojang
Tuple<Skin, Cape> skinAndCape = mojangProfile.getSkinAndCape();
CachedPlayer player = new CachedPlayer(
uuid, // Player UUID
mojangProfile.getName(), // Player Name
skinAndCape.getLeft(), // Skin
skinAndCape.getRight(), // Cape
System.currentTimeMillis() // Cache time
);
playerCacheRepository.save(player);
player.setCached(-1); // Indicate that the player is not cached
return player;
playerCacheRepository.save(player);
player.setCached(-1); // Indicate that the player is not cached
return player;
} catch (RateLimitException exception) {
throw new MojangAPIRateLimitException();
}
}
/**
@ -83,12 +84,16 @@ public class PlayerService {
if (cachedPlayerName.isPresent()) {
return cachedPlayerName.get().getUniqueId();
}
MojangUsernameToUuid mojangUsernameToUuid = mojangAPIService.getUuidFromUsername(username);
if (mojangUsernameToUuid == null) {
throw new ResourceNotFoundException("Player with username '%s' not found".formatted(username));
try {
MojangUsernameToUuid mojangUsernameToUuid = mojangAPIService.getUuidFromUsername(username);
if (mojangUsernameToUuid == null) {
throw new ResourceNotFoundException("Player with username '%s' not found".formatted(username));
}
UUID uuid = UUIDUtils.addDashes(mojangUsernameToUuid.getId());
playerNameCacheRepository.save(new CachedPlayerName(username, uuid));
return uuid;
} catch (RateLimitException exception) {
throw new MojangAPIRateLimitException();
}
UUID uuid = UUIDUtils.addDashes(mojangUsernameToUuid.getId());
playerNameCacheRepository.save(new CachedPlayerName(username, uuid));
return uuid;
}
}

View File

@ -73,7 +73,7 @@ public class ServerService {
public byte[] getServerFavicon(String hostname, int port) {
String icon = null; // The server base64 icon
try {
JavaMinecraftServer.Favicon favicon = ((JavaMinecraftServer) getServer(MinecraftServer.Platform.JAVA.name(), hostname, port).getValue()).getFavicon();
JavaMinecraftServer.Favicon favicon = ((JavaMinecraftServer) getServer(MinecraftServer.Platform.JAVA.name(), hostname, port).getServer()).getFavicon();
if (favicon != null) { // Use the server's favicon
icon = favicon.getBase64();
icon = icon.substring(icon.indexOf(",") + 1); // Remove the data type from the server icon