T2C-OPSecurity/src/main/java/de/jatitv/opsecurity/system/NameHistory.java

150 lines
6.4 KiB
Java

package de.jatitv.opsecurity.system;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.UUID;
public class NameHistory {
/**
* The URL from Mojang API that provides the JSON String in response.
*/
private static final String LOOKUP_URL = "https://api.mojang.com/user/profiles/%s/names";
/**
* The URL from Mojang API to resolve the UUID of a player from their name.
*/
private static final String GET_UUID_URL = "https://api.mojang.com/users/profiles/minecraft/%s?t=0";
private static final Gson JSON_PARSER = new Gson();
/**
* <h1>NOTE: Avoid running this method <i>Synchronously</i> with the main thread!It blocks while attempting to get a response from Mojang servers!</h1>
*
* @param player The UUID of the player to be looked up.
* @return Returns an array of {@link PreviousPlayerNameEntry} objects, or null if the response couldn't be interpreted.
* @throws IOException {@link #getPlayerPreviousNames(String)}
*/
public static PreviousPlayerNameEntry[] getPlayerPreviousNames(UUID player) throws IOException {
return getPlayerPreviousNames(player.toString());
}
/**
* <h1>NOTE: Avoid running this method <i>Synchronously</i> with the main thread! It blocks while attempting to get a response from Mojang servers!</h1>
* Alternative method accepting an 'OfflinePlayer' (and therefore 'Player') objects as parameter.
*
* @param player The OfflinePlayer object to obtain the UUID from.
* @return Returns an array of {@link PreviousPlayerNameEntry} objects, or null if the response couldn't be interpreted.
* @throws IOException {@link #getPlayerPreviousNames(UUID)}
*/
public static PreviousPlayerNameEntry[] getPlayerPreviousNames(OfflinePlayer player) throws IOException {
return getPlayerPreviousNames(player.getUniqueId());
}
/**
* <h1>NOTE: Avoid running this method <i>Synchronously</i> with the main thread! It blocks while attempting to get a response from Mojang servers!</h1>
* Alternative method accepting an {@link OfflinePlayer} (and therefore {@link Player}) objects as parameter.
*
* @param uuid The UUID String to lookup
* @return Returns an array of {@link PreviousPlayerNameEntry} objects, or null if the response couldn't be interpreted.
* @throws IOException
*/
public static PreviousPlayerNameEntry[] getPlayerPreviousNames(String uuid) throws IOException {
if (uuid == null || uuid.isEmpty())
return null;
String response = getRawJsonResponse(new URL(String.format(LOOKUP_URL, uuid)));
PreviousPlayerNameEntry[] names = JSON_PARSER.fromJson(response, PreviousPlayerNameEntry[].class);
return names;
}
/**
* If you don't have the UUID of a player, this method will resolve it for you.<br>
* The output of this method may be used directly with {@link #getPlayerPreviousNames(String)}.<br>
* <b>NOTE: as with the rest, this method opens a connection with a remote server, so running it synchronously will block the main thread which will lead to server lag.</b>
*
* @param name The name of the player to lookup.
* @return A String which represents the player's UUID. <b>Note: the uuid cannot be parsed to a UUID object directly, as it doesnt contain dashes. This feature will be implemented later</b>
* @throws IOException Inherited by {@link BufferedReader#readLine()}, {@link BufferedReader#close()}, {@link URL}, {@link HttpURLConnection#getInputStream()}
*/
public static String getPlayerUUID(String name) throws IOException {
String response = getRawJsonResponse(new URL(String.format(GET_UUID_URL, name)));
JsonObject o = JSON_PARSER.fromJson(response, JsonObject.class);
if (o == null)
return null;
return o.get("id") == null ? null : o.get("id").getAsString();
}
/**
* This is a helper method used to read the response of Mojang's API webservers.
*
* @param u the URL to connect to
* @return a String with the data read.
* @throws IOException Inherited by {@link BufferedReader#readLine()}, {@link BufferedReader#close()}, {@link URL}, {@link HttpURLConnection#getInputStream()}
*/
private static String getRawJsonResponse(URL u) throws IOException {
HttpURLConnection con = (HttpURLConnection) u.openConnection();
con.setDoInput(true);
con.setConnectTimeout(2000);
con.setReadTimeout(2000);
con.connect();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String response = in.readLine();
in.close();
return response;
}
/**
* This class represents the typical response expected by Mojang servers when requesting the name history of a player.
*/
public class PreviousPlayerNameEntry {
private String name;
@SerializedName("changedToAt")
private long changeTime;
/**
* Gets the player name of this entry.
*
* @return The name of the player.
*/
public String getPlayerName() {
return name;
}
/**
* Get the time of change of the name.
* <br><b>Note: This will return 0 if the name is the original (initial) name of the player! Make sure you check if it is 0 before handling!
* <br>Parsing 0 to a Date will result in the date "01/01/1970".</b>
*
* @return a timestamp in miliseconds that you can turn into a date or handle however you want :)
*/
public long getChangeTime() {
return changeTime;
}
/**
* Check if this name is the name used to register the account (the initial/original name)
*
* @return a boolean, true if it is the the very first name of the player, otherwise false.
*/
public boolean isPlayersInitialName() {
return getChangeTime() == 0;
}
@Override
public String toString() {
return "Name: " + name + " Date of change: " + new Date(changeTime).toString();
}
}
}