Skip to content

Instantly share code, notes, and snippets.

@Techcable
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Techcable/2dce0a6f87bc2e2bba19 to your computer and use it in GitHub Desktop.
Save Techcable/2dce0a6f87bc2e2bba19 to your computer and use it in GitHub Desktop.
A UUIDFetcher for techcable's uuid service with caching
import java.lang.ref.SoftReference;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Utilities to lookup player names and uuids from techcable's uuid service
* This caches results so you won't have issues with the rate limit
*
* <p>
* <b>DONT Rely on Bukkit.getOfflinePlayer()</b>
* It doesn't cache and is a workaround solution
*
* evilmidgets fetchers are a fair solution, but they don't cache so you can run into ratelimits
*
* @author Techcable
*/
public class UUIDFetcher {
private UUIDFetcher() {}
private static Cache<String, PlayerProfile> nameCache = new Cache<String, PlayerProfile>();
private static Cache<UUID, PlayerProfile> idCache = new Cache<UUID, PlayerProfile>();
/**
* Lookup a profile with the given name
*
* Returns null in the event of failure
*
* @param name look for a profile with this name
* @return a profile with the given name, or null if failed
*/
public static PlayerProfile lookup(String name) {
if (name == null) return null;
if (nameCache.contains(name)) return nameCache.get(name);
String rawUuid = get("http://uuid.techcable.net/api/uuid/" + name);
if (name == null) return null;
if (rawUuid == "unknown" || rawUuid == "error") return null;
UUID id = UUID.fromString(rawUuid);
PlayerProfile player = new PlayerProfile(id, name);
nameCache.put(name, player);
return player;
}
/**
* Lookup a profile with the given uuid
*
* Returns null in the event of failure
*
* @param id look for a profile with this uuid
* @return a profile with the given id, or null if failed
*/
public static PlayerProfile lookup(UUID id) {
if (id == null) return null;
if (idCache.contains(id)) return idCache.get(id);
String name = get("http://uuid.techcable.net/api/name/" + id.toString());
if (name == null) return null;
if (name == "\"error\"") return null;
PlayerProfile player = new PlayerProfile(id, name);
idCache.put(id, player);
return player;
}
/**
* Represnents a player
* Contains their uuid and username
*
* @author Techcable
*/
public static class PlayerProfile {
public PlayerProfile(UUID id, String name) {
this.id = id;
this.name = name;
}
private final UUID id;
private final String name;
/**
* Get this player's uuid
*
* @return this players uuid
*/
public UUID getId() {
return id;
}
/**
* Get this player's name
*
* @return this player's name
*/
public String getName() {
return name;
}
}
//Utilities
public static String get(String rawUrl) {
BufferedReader reader = null;
try {
URL url = new URL(rawUrl);
reader = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuffer result = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) result.append(line);
return result.toString();
} catch (IOException ex) {
ex.printStackTrace();
return null;
} finally {
try {
if (reader != null) reader.close();
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
}
}
private static class Cache<K, V> {
private long expireTime = 1000 * 60 * 5; //default 5 min
private Map<K, CachedEntry<V>> map = new HashMap<>();
public boolean contains(K key) {
return map.containsKey(key) && get(key) != null;
}
public V get(K key) {
CachedEntry<V> entry = map.get(key);
if (entry == null) return null;
if (entry.isExpired()) {
map.remove(key);
return null;
} else {
return entry.getValue();
}
}
public void put(K key, V value) {
map.put(key, new CachedEntry<V>(value, expireTime));
}
private static class CachedEntry<V> {
public CachedEntry(V value, long expireTime) {
this.value = new SoftReference<V>(value);
this.expires = expireTime + System.currentTimeMillis();
}
private final SoftReference<V> value; //Caching is low memory priortiy
private final long expires;
public V getValue() {
if (isExpired()) {
return null;
}
return value.get();
}
public boolean isExpired() {
if (value.get() == null) return true;
return expires != -1 && expires > System.currentTimeMillis();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment