forked from MinecraftUtilities/Backend
add mojang api rate limit error
This commit is contained in:
parent
330c3efc78
commit
2e58d9c925
@ -1,6 +1,8 @@
|
|||||||
package cc.fascinated.common;
|
package cc.fascinated.common;
|
||||||
|
|
||||||
|
import cc.fascinated.exception.impl.RateLimitException;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||||
import org.springframework.web.client.HttpClientErrorException;
|
import org.springframework.web.client.HttpClientErrorException;
|
||||||
@ -33,6 +35,9 @@ public class WebRequest {
|
|||||||
if (profile.getStatusCode().isError()) {
|
if (profile.getStatusCode().isError()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (profile.getStatusCode().isSameCodeAs(HttpStatus.TOO_MANY_REQUESTS)) {
|
||||||
|
throw new RateLimitException("Rate limit reached");
|
||||||
|
}
|
||||||
return profile.getBody();
|
return profile.getBody();
|
||||||
} catch (HttpClientErrorException ex) {
|
} catch (HttpClientErrorException ex) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -18,7 +18,7 @@ public class HomeController {
|
|||||||
@RequestMapping(value = "/")
|
@RequestMapping(value = "/")
|
||||||
public String home(Model model) {
|
public String home(Model model) {
|
||||||
model.addAttribute("player_example_url", Config.INSTANCE.getWebPublicUrl() + "/player/" + exampleUuid);
|
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";
|
return "index";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.");
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ public final class CachedMinecraftServer implements Serializable {
|
|||||||
* The cached server.
|
* The cached server.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
private final MinecraftServer value;
|
private final MinecraftServer server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The unix timestamp of when this
|
* The unix timestamp of when this
|
||||||
|
@ -3,27 +3,23 @@ package cc.fascinated.service;
|
|||||||
import cc.fascinated.common.PlayerUtils;
|
import cc.fascinated.common.PlayerUtils;
|
||||||
import cc.fascinated.common.Tuple;
|
import cc.fascinated.common.Tuple;
|
||||||
import cc.fascinated.common.UUIDUtils;
|
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.exception.impl.ResourceNotFoundException;
|
||||||
import cc.fascinated.model.cache.CachedPlayer;
|
import cc.fascinated.model.cache.CachedPlayer;
|
||||||
import cc.fascinated.model.cache.CachedPlayerName;
|
import cc.fascinated.model.cache.CachedPlayerName;
|
||||||
import cc.fascinated.model.mojang.MojangProfile;
|
import cc.fascinated.model.mojang.MojangProfile;
|
||||||
import cc.fascinated.model.mojang.MojangUsernameToUuid;
|
import cc.fascinated.model.mojang.MojangUsernameToUuid;
|
||||||
import cc.fascinated.model.player.Cape;
|
import cc.fascinated.model.player.Cape;
|
||||||
import cc.fascinated.model.player.Player;
|
|
||||||
import cc.fascinated.model.player.Skin;
|
import cc.fascinated.model.player.Skin;
|
||||||
import cc.fascinated.repository.PlayerCacheRepository;
|
import cc.fascinated.repository.PlayerCacheRepository;
|
||||||
import cc.fascinated.repository.PlayerNameCacheRepository;
|
import cc.fascinated.repository.PlayerNameCacheRepository;
|
||||||
import lombok.extern.log4j.Log4j2;
|
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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@Service @Log4j2
|
@Service @Log4j2
|
||||||
public class PlayerService {
|
public class PlayerService {
|
||||||
@ -47,6 +43,7 @@ public class PlayerService {
|
|||||||
* @return the player
|
* @return the player
|
||||||
*/
|
*/
|
||||||
public CachedPlayer getPlayer(String id) {
|
public CachedPlayer getPlayer(String id) {
|
||||||
|
id = id.toUpperCase(); // Convert the id to uppercase to prevent case sensitivity
|
||||||
UUID uuid = PlayerUtils.getUuidFromString(id);
|
UUID uuid = PlayerUtils.getUuidFromString(id);
|
||||||
if (uuid == null) { // If the id is not a valid uuid, get the uuid from the username
|
if (uuid == null) { // If the id is not a valid uuid, get the uuid from the username
|
||||||
uuid = usernameToUuid(id);
|
uuid = usernameToUuid(id);
|
||||||
@ -57,19 +54,23 @@ public class PlayerService {
|
|||||||
return cachedPlayer.get();
|
return cachedPlayer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
MojangProfile mojangProfile = mojangAPIService.getProfile(uuid.toString());
|
try {
|
||||||
Tuple<Skin, Cape> skinAndCape = mojangProfile.getSkinAndCape();
|
MojangProfile mojangProfile = mojangAPIService.getProfile(uuid.toString()); // Get the player profile from Mojang
|
||||||
CachedPlayer player = new CachedPlayer(
|
Tuple<Skin, Cape> skinAndCape = mojangProfile.getSkinAndCape();
|
||||||
uuid,
|
CachedPlayer player = new CachedPlayer(
|
||||||
mojangProfile.getName(),
|
uuid, // Player UUID
|
||||||
skinAndCape.getLeft(), // Skin
|
mojangProfile.getName(), // Player Name
|
||||||
skinAndCape.getRight(), // Cape
|
skinAndCape.getLeft(), // Skin
|
||||||
System.currentTimeMillis()
|
skinAndCape.getRight(), // Cape
|
||||||
);
|
System.currentTimeMillis() // Cache time
|
||||||
|
);
|
||||||
|
|
||||||
playerCacheRepository.save(player);
|
playerCacheRepository.save(player);
|
||||||
player.setCached(-1); // Indicate that the player is not cached
|
player.setCached(-1); // Indicate that the player is not cached
|
||||||
return player;
|
return player;
|
||||||
|
} catch (RateLimitException exception) {
|
||||||
|
throw new MojangAPIRateLimitException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,12 +84,16 @@ public class PlayerService {
|
|||||||
if (cachedPlayerName.isPresent()) {
|
if (cachedPlayerName.isPresent()) {
|
||||||
return cachedPlayerName.get().getUniqueId();
|
return cachedPlayerName.get().getUniqueId();
|
||||||
}
|
}
|
||||||
MojangUsernameToUuid mojangUsernameToUuid = mojangAPIService.getUuidFromUsername(username);
|
try {
|
||||||
if (mojangUsernameToUuid == null) {
|
MojangUsernameToUuid mojangUsernameToUuid = mojangAPIService.getUuidFromUsername(username);
|
||||||
throw new ResourceNotFoundException("Player with username '%s' not found".formatted(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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ public class ServerService {
|
|||||||
public byte[] getServerFavicon(String hostname, int port) {
|
public byte[] getServerFavicon(String hostname, int port) {
|
||||||
String icon = null; // The server base64 icon
|
String icon = null; // The server base64 icon
|
||||||
try {
|
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
|
if (favicon != null) { // Use the server's favicon
|
||||||
icon = favicon.getBase64();
|
icon = favicon.getBase64();
|
||||||
icon = icon.substring(icon.indexOf(",") + 1); // Remove the data type from the server icon
|
icon = icon.substring(icon.indexOf(",") + 1); // Remove the data type from the server icon
|
||||||
|
Loading…
Reference in New Issue
Block a user