Allow for Java user profiles to be signed
All checks were successful
Deploy App / docker (ubuntu-latest, 2.44.0, 17, 3.8.5) (push) Successful in 1m27s
All checks were successful
Deploy App / docker (ubuntu-latest, 2.44.0, 17, 3.8.5) (push) Successful in 1m27s
This commit is contained in:
parent
655ee50a21
commit
a03bac8f1d
@ -63,6 +63,7 @@ public final class PlayerController {
|
||||
* A GET route to get a player by their username or UUID.
|
||||
*
|
||||
* @param query the query to search for the player by
|
||||
* @param signed whether the profile is signed
|
||||
* @return the player response
|
||||
* @throws BadRequestException if the UUID or username is invalid
|
||||
* @throws ResourceNotFoundException if the player is not found
|
||||
@ -71,9 +72,10 @@ public final class PlayerController {
|
||||
@GetMapping("/{query}")
|
||||
@ResponseBody
|
||||
public ResponseEntity<CachedPlayer> getPlayer(
|
||||
@Parameter(description = "The player username or UUID to get", example = "Rainnny") @PathVariable @NonNull String query
|
||||
@Parameter(description = "The player username or UUID to get", example = "Rainnny") @PathVariable @NonNull String query,
|
||||
@Parameter(description = "Whether the profile is signed by Mojang") @RequestParam(required = false) boolean signed
|
||||
) throws BadRequestException, ResourceNotFoundException, MojangRateLimitException {
|
||||
return ResponseEntity.ofNullable(mojangService.getPlayer(query));
|
||||
return ResponseEntity.ofNullable(mojangService.getPlayer(query, signed));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,6 @@ package me.braydon.mc.model;
|
||||
import lombok.*;
|
||||
import me.braydon.mc.model.skin.Skin;
|
||||
import me.braydon.mc.model.token.MojangProfileToken;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@ -40,7 +39,7 @@ public class Player {
|
||||
/**
|
||||
* The unique id of this player.
|
||||
*/
|
||||
@Id @EqualsAndHashCode.Include @NonNull private final UUID uniqueId;
|
||||
@EqualsAndHashCode.Include @NonNull private final UUID uniqueId;
|
||||
|
||||
/**
|
||||
* The username of this player.
|
||||
|
@ -38,7 +38,7 @@ import java.io.Serializable;
|
||||
@RedisHash(value = "server", timeToLive = 60L) // 1 minute (in seconds)
|
||||
public final class CachedMinecraftServer implements Serializable {
|
||||
/**
|
||||
* The id of this cached server.
|
||||
* The id of this cache element.
|
||||
*/
|
||||
@Id @JsonIgnore @NonNull private final String id;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
package me.braydon.mc.model.cache;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
@ -32,6 +33,7 @@ import me.braydon.mc.model.Player;
|
||||
import me.braydon.mc.model.ProfileAction;
|
||||
import me.braydon.mc.model.skin.Skin;
|
||||
import me.braydon.mc.model.token.MojangProfileToken;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -46,16 +48,26 @@ import java.util.UUID;
|
||||
@ToString(callSuper = true)
|
||||
@RedisHash(value = "player", timeToLive = 60L * 60L) // 1 hour (in seconds)
|
||||
public final class CachedPlayer extends Player implements Serializable {
|
||||
/**
|
||||
* The id of this cache element.
|
||||
* <p>
|
||||
* This ID is in the given format:
|
||||
* player:<uniqueId>-<signed>
|
||||
* </p>
|
||||
*/
|
||||
@Id @NonNull @JsonIgnore private final String cacheId;
|
||||
|
||||
/**
|
||||
* The unix timestamp of when this
|
||||
* player was cached, -1 if not cached.
|
||||
*/
|
||||
private long cached;
|
||||
|
||||
public CachedPlayer(@NonNull UUID uniqueId, @NonNull String username, @NonNull Skin skin, Cape cape,
|
||||
@NonNull MojangProfileToken.ProfileProperty[] properties, ProfileAction[] profileActions,
|
||||
public CachedPlayer(@NonNull String cacheId, @NonNull UUID uniqueId, @NonNull String username, @NonNull Skin skin,
|
||||
Cape cape, @NonNull MojangProfileToken.ProfileProperty[] properties, ProfileAction[] profileActions,
|
||||
long cached) {
|
||||
super(uniqueId, username, skin, cape, properties, profileActions);
|
||||
this.cacheId = cacheId;
|
||||
this.cached = cached;
|
||||
}
|
||||
}
|
@ -26,11 +26,9 @@ package me.braydon.mc.repository;
|
||||
import me.braydon.mc.model.cache.CachedPlayer;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A cache repository for {@link CachedPlayer}'s.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
public interface PlayerCacheRepository extends CrudRepository<CachedPlayer, UUID> { }
|
||||
public interface PlayerCacheRepository extends CrudRepository<CachedPlayer, String> { }
|
@ -214,7 +214,7 @@ public final class MojangService {
|
||||
Skin skin = null; // The target skin to get the skin part of
|
||||
long before = System.currentTimeMillis();
|
||||
try {
|
||||
CachedPlayer player = getPlayer(query); // Retrieve the player
|
||||
CachedPlayer player = getPlayer(query, false); // Retrieve the player
|
||||
skin = player.getSkin(); // Use the player's skin
|
||||
} catch (Exception ignored) {
|
||||
// Simply ignore, and fallback to the default skin
|
||||
@ -245,13 +245,14 @@ public final class MojangService {
|
||||
* </p>
|
||||
*
|
||||
* @param query the query to search for the player by
|
||||
* @param signed whether the profile is signed
|
||||
* @return the player
|
||||
* @throws BadRequestException if the UUID or username is invalid
|
||||
* @throws ResourceNotFoundException if the player is not found
|
||||
* @throws MojangRateLimitException if the Mojang API rate limit is reached
|
||||
*/
|
||||
@NonNull
|
||||
public CachedPlayer getPlayer(@NonNull String query) throws BadRequestException, ResourceNotFoundException, MojangRateLimitException {
|
||||
public CachedPlayer getPlayer(@NonNull String query, boolean signed) throws BadRequestException, ResourceNotFoundException, MojangRateLimitException {
|
||||
log.info("Requesting player with query: {}", query);
|
||||
|
||||
UUID uuid; // The player UUID to lookup
|
||||
@ -270,10 +271,11 @@ public final class MojangService {
|
||||
uuid = usernameToUUID(query);
|
||||
log.info("Found UUID for username {}: {}", query, uuid);
|
||||
}
|
||||
String cacheId = "%s-%s".formatted(uuid, signed); // The cache id of the player
|
||||
|
||||
// Check the cache for the player
|
||||
// and return it if it's present
|
||||
Optional<CachedPlayer> cached = playerCache.findById(uuid);
|
||||
Optional<CachedPlayer> cached = playerCache.findById(cacheId);
|
||||
if (cached.isPresent()) { // Respond with the cache if present
|
||||
log.info("Found player in cache: {}", uuid);
|
||||
return cached.get();
|
||||
@ -283,14 +285,13 @@ public final class MojangService {
|
||||
// the player profile by their UUID
|
||||
try {
|
||||
log.info("Retrieving player profile for UUID: {}", uuid);
|
||||
MojangProfileToken token = JsonWebRequest.makeRequest(
|
||||
UUID_TO_PROFILE.formatted(uuid), HttpMethod.GET
|
||||
).execute(MojangProfileToken.class);
|
||||
String endpoint = UUID_TO_PROFILE.formatted(uuid) + (signed ? "?unsigned=false" : "");
|
||||
MojangProfileToken token = JsonWebRequest.makeRequest(endpoint, HttpMethod.GET).execute(MojangProfileToken.class);
|
||||
MojangProfileToken.SkinProperties skinProperties = token.getSkinProperties(); // Get the skin and cape
|
||||
ProfileAction[] profileActions = token.getProfileActions();
|
||||
|
||||
// Build our player model, cache it, and then return it
|
||||
CachedPlayer player = new CachedPlayer(uuid, token.getName(),
|
||||
CachedPlayer player = new CachedPlayer(cacheId, uuid, token.getName(),
|
||||
skinProperties.getSkin() == null ? Skin.DEFAULT_STEVE : skinProperties.getSkin(),
|
||||
skinProperties.getCape(), token.getProperties(), profileActions.length == 0 ? null : profileActions,
|
||||
System.currentTimeMillis()
|
||||
|
Loading…
Reference in New Issue
Block a user