package dev.bailey.etplaceholders; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.bukkit.Bukkit; public class DataManager { private final ETPlaceholdersPlugin plugin; private final Gson gson = new Gson(); private final Map> leaderboardCache = new ConcurrentHashMap<>(); private final Map> leaderboardTierCache = new ConcurrentHashMap<>(); private final Map> playerTierCache = new ConcurrentHashMap<>(); private final Map playerRankCache = new ConcurrentHashMap<>(); private final String[] trackedModes = {"overall", "vanilla", "mace", "axe", "sword", "smp", "diamondsmp", "uhc", "pot", "nethop", "cart"}; public DataManager(ETPlaceholdersPlugin plugin) { this.plugin = plugin; } public void startTasks() { int minutes = plugin.getConfig().getInt("cache-refresh-minutes", 15); long ticks = minutes * 60 * 20L; Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, this::refreshLeaderboards, 0L, ticks); } private String getApiUrl() { String url = plugin.getConfig().getString("api-url", "https://api.eaglertiers.com/api"); if (url.endsWith("/")) { url = url.substring(0, url.length() - 1); } return url; } private HttpURLConnection createConnection(String endpoint) throws Exception { String urlStr = getApiUrl() + endpoint; String key = plugin.getConfig().getString("api-key", ""); if (key != null && !key.trim().isEmpty()) { if (urlStr.contains("?")) { urlStr += "&key=" + key; } else { urlStr += "?key=" + key; } } URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setRequestProperty("Accept", "application/json"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); if (key != null && !key.trim().isEmpty()) { conn.setRequestProperty("X-API-Key", key); } return conn; } public void refreshLeaderboards() { for (String mode : trackedModes) { try { String endpoint = mode.equalsIgnoreCase("overall") ? "/players" : "/rankings/" + mode; HttpURLConnection conn = createConnection(endpoint); if (conn.getResponseCode() == 200) { try (InputStreamReader reader = new InputStreamReader(conn.getInputStream())) { JsonObject json = gson.fromJson(reader, JsonObject.class); if (json != null && json.has("data")) { JsonArray data = json.getAsJsonArray("data"); Map modeTopNames = new ConcurrentHashMap<>(); Map modeTopTiers = new ConcurrentHashMap<>(); for (int i = 0; i < data.size(); i++) { JsonObject pObj = data.get(i).getAsJsonObject(); String name = pObj.has("username") && !pObj.get("username").isJsonNull() ? pObj.get("username").getAsString() : "Unknown"; int pos = pObj.has("position") && !pObj.get("position").isJsonNull() ? pObj.get("position").getAsInt() : (i + 1); modeTopNames.put(pos, name); String tier = plugin.getConfig().getString("not-found-text", "Unranked"); if (pObj.has("tiers") && !pObj.get("tiers").isJsonNull()) { JsonObject tiersObj = pObj.getAsJsonObject("tiers"); if (tiersObj.has(mode) && !tiersObj.get(mode).isJsonNull()) { tier = tiersObj.get(mode).getAsString(); } } modeTopTiers.put(pos, tier); } leaderboardCache.put(mode.toLowerCase(), modeTopNames); leaderboardTierCache.put(mode.toLowerCase(), modeTopTiers); } } } } catch (Exception e) { plugin.getLogger().warning("Failed to fetch leaderboard for " + mode + ": " + e.getMessage()); } } } public void fetchPlayerAsync(String playerName) { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { try { HttpURLConnection conn = createConnection("/players/" + playerName); if (conn.getResponseCode() == 200) { try (InputStreamReader reader = new InputStreamReader(conn.getInputStream())) { JsonObject json = gson.fromJson(reader, JsonObject.class); if (json != null) { Map pTiers = new ConcurrentHashMap<>(); if (json.has("tiers") && !json.get("tiers").isJsonNull()) { JsonObject tiersObj = json.getAsJsonObject("tiers"); for (Map.Entry entry : tiersObj.entrySet()) { if (!entry.getValue().isJsonNull()) { pTiers.put(entry.getKey().toLowerCase(), entry.getValue().getAsString()); } } } playerTierCache.put(playerName.toLowerCase(), pTiers); if (json.has("position") && !json.get("position").isJsonNull()) { playerRankCache.put(playerName.toLowerCase(), json.get("position").getAsInt()); } } } } } catch (Exception e) { } }); } public String getPlayerTier(String playerName, String mode) { String pLow = playerName.toLowerCase(); if (!playerTierCache.containsKey(pLow)) { fetchPlayerAsync(playerName); return plugin.getConfig().getString("not-found-text", "Unranked"); } Map tiers = playerTierCache.get(pLow); return tiers.getOrDefault(mode.toLowerCase(), plugin.getConfig().getString("not-found-text", "Unranked")); } public String getPlayerRank(String playerName) { String pLow = playerName.toLowerCase(); if (!playerRankCache.containsKey(pLow)) { fetchPlayerAsync(playerName); return plugin.getConfig().getString("not-found-text", "Unranked"); } return String.valueOf(playerRankCache.get(pLow)); } public String getTopPlayerName(String mode, int position) { Map modeCache = leaderboardCache.get(mode.toLowerCase()); if (modeCache == null || !modeCache.containsKey(position)) { return plugin.getConfig().getString("not-found-text", "None"); } return modeCache.get(position); } public String getTopPlayerTier(String mode, int position) { Map modeCache = leaderboardTierCache.get(mode.toLowerCase()); if (modeCache == null || !modeCache.containsKey(position)) { return plugin.getConfig().getString("not-found-text", "Unranked"); } return modeCache.get(position); } }