mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-14 04:01:58 +01:00
Add the Web API for Bukkit
This commit is contained in:
parent
82cf6e62fd
commit
751719b357
@ -9,14 +9,11 @@ import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import main.java.com.djrapitops.plan.Log;
|
||||
import main.java.com.djrapitops.plan.Permissions;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.Settings;
|
||||
import main.java.com.djrapitops.plan.command.ConditionUtils;
|
||||
import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler;
|
||||
import main.java.com.djrapitops.plan.locale.Locale;
|
||||
import main.java.com.djrapitops.plan.locale.Msg;
|
||||
import main.java.com.djrapitops.plan.ui.text.TextUI;
|
||||
import main.java.com.djrapitops.plan.utilities.Check;
|
||||
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.MiscUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
@ -95,52 +92,4 @@ public class AnalyzeCommand extends SubCommand {
|
||||
analysisCache.sendAnalysisMessage(sender);
|
||||
}
|
||||
}
|
||||
|
||||
private void runMessageSenderTask(ISender sender) {
|
||||
plugin.getRunnableFactory().createNew("AnalysisMessageSenderTask", new AbsRunnable() {
|
||||
private int timesRun = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
timesRun++;
|
||||
if (analysisCache.isCached() && (!analysisCache.isAnalysisBeingRun() || !analysisCache.isAnalysisEnabled())) {
|
||||
sendAnalysisMessage(sender);
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
if (timesRun > 10) {
|
||||
Log.debug("Command Timeout Message, Analysis.");
|
||||
sender.sendMessage(Locale.get(Msg.CMD_FAIL_TIMEOUT).parse("Analysis"));
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskTimer(TimeAmount.SECOND.ticks(), 5 * TimeAmount.SECOND.ticks());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to send the message after /plan analysis.
|
||||
* <p>
|
||||
* Final because
|
||||
*
|
||||
* @param sender Command sender.
|
||||
*/
|
||||
private void sendAnalysisMessage(ISender sender) {
|
||||
boolean textUI = Settings.USE_ALTERNATIVE_UI.isTrue();
|
||||
sender.sendMessage(Locale.get(Msg.CMD_HEADER_ANALYZE).toString());
|
||||
if (textUI) {
|
||||
sender.sendMessage(TextUI.getAnalysisMessages());
|
||||
} else {
|
||||
// Link
|
||||
String url = HtmlUtils.getServerAnalysisUrlWithProtocol();
|
||||
String message = Locale.get(Msg.CMD_INFO_LINK).toString();
|
||||
boolean console = !CommandUtils.isPlayer(sender);
|
||||
if (console) {
|
||||
sender.sendMessage(message + url);
|
||||
} else {
|
||||
sender.sendMessage(message);
|
||||
sender.sendLink(" ", Locale.get(Msg.CMD_INFO_CLICK_ME).toString(), url);
|
||||
}
|
||||
}
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString());
|
||||
}
|
||||
}
|
||||
|
@ -64,9 +64,7 @@ public class AnalysisCacheHandler {
|
||||
cache = data;
|
||||
for (UUID uuid : notifyWhenCached) {
|
||||
Optional<IPlayer> player = plugin.fetch().getPlayer(uuid);
|
||||
if (player.isPresent()) {
|
||||
sendAnalysisMessage(player.get());
|
||||
}
|
||||
player.ifPresent(this::sendAnalysisMessage);
|
||||
}
|
||||
notifyWhenCached.clear();
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.data.UserData;
|
||||
import main.java.com.djrapitops.plan.database.Database;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.InspectPageResponse;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.api.JsonResponse;
|
||||
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.MiscUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.analysis.ExportUtility;
|
||||
@ -46,9 +47,13 @@ public class InspectCacheHandler {
|
||||
*/
|
||||
public void cache(UUID uuid) {
|
||||
DBCallableProcessor cacher = data -> {
|
||||
cache.put(uuid, new UserData(data));
|
||||
UserData userData = new UserData(data);
|
||||
|
||||
cache.put(uuid, userData);
|
||||
cacheTimes.put(uuid, MiscUtils.getTime());
|
||||
PageCacheHandler.cachePage("inspectPage: " + uuid.toString(), () -> new InspectPageResponse(Plan.getInstance().getUiServer().getDataReqHandler(), uuid));
|
||||
|
||||
PageCacheHandler.cachePage("inspectPage: " + uuid, () -> new InspectPageResponse(Plan.getInstance().getUiServer().getDataReqHandler(), uuid));
|
||||
PageCacheHandler.cachePage("inspectionJson: " + uuid, () -> new JsonResponse(userData));
|
||||
|
||||
try {
|
||||
ExportUtility.writeInspectHtml(data, ExportUtility.getPlayersFolder(ExportUtility.getFolder()), HtmlUtils.getStringFromResource("player.html"));
|
||||
|
@ -44,7 +44,7 @@ public class PageCacheHandler {
|
||||
* @return The Response that was cached or created by the {@link PageLoader loader}
|
||||
*/
|
||||
public static Response loadPage(String identifier, PageLoader loader) {
|
||||
Response response = pageCache.getIfPresent(identifier);
|
||||
Response response = loadPage(identifier);
|
||||
|
||||
if (response != null) {
|
||||
return response;
|
||||
@ -57,6 +57,16 @@ public class PageCacheHandler {
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the page from the page cache.
|
||||
*
|
||||
* @param identifier The identifier of the page
|
||||
* @return The Response that was cached or {@code null} if it wasn't
|
||||
*/
|
||||
public static Response loadPage(String identifier) {
|
||||
return pageCache.getIfPresent(identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the page into the page cache.
|
||||
* <p>
|
||||
|
@ -5,6 +5,7 @@ import com.sun.net.httpserver.*;
|
||||
import main.java.com.djrapitops.plan.Log;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.Settings;
|
||||
import main.java.com.djrapitops.plan.data.UserData;
|
||||
import main.java.com.djrapitops.plan.data.WebUser;
|
||||
import main.java.com.djrapitops.plan.data.cache.PageCacheHandler;
|
||||
import main.java.com.djrapitops.plan.database.tables.SecurityTable;
|
||||
@ -12,11 +13,15 @@ import main.java.com.djrapitops.plan.locale.Locale;
|
||||
import main.java.com.djrapitops.plan.locale.Msg;
|
||||
import main.java.com.djrapitops.plan.ui.html.DataRequestHandler;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.*;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.api.BadRequestResponse;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.api.JsonResponse;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.api.SuccessResponse;
|
||||
import main.java.com.djrapitops.plan.utilities.Benchmark;
|
||||
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.PassEncryptUtil;
|
||||
import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.*;
|
||||
@ -26,9 +31,7 @@ import java.nio.file.Paths;
|
||||
import java.security.*;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -84,11 +87,30 @@ public class WebServer {
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
try {
|
||||
Headers responseHeaders = exchange.getResponseHeaders();
|
||||
URI uri = exchange.getRequestURI();
|
||||
String target = uri.toString();
|
||||
|
||||
Headers responseHeaders = exchange.getResponseHeaders();
|
||||
responseHeaders.set("Content-Type", "text/html;");
|
||||
boolean apiRequest = "POST".equals(exchange.getRequestMethod());
|
||||
Response response = null;
|
||||
|
||||
String type = "text/html;";
|
||||
|
||||
if (apiRequest) {
|
||||
response = getAPIResponse(target, exchange);
|
||||
|
||||
if (response instanceof JsonResponse) {
|
||||
type = "application/json;";
|
||||
}
|
||||
}
|
||||
|
||||
responseHeaders.set("Content-Type", type);
|
||||
|
||||
if (apiRequest) {
|
||||
sendData(responseHeaders, exchange, response);
|
||||
return;
|
||||
}
|
||||
|
||||
WebUser user = null;
|
||||
|
||||
if (usingHttps) {
|
||||
@ -100,21 +122,9 @@ public class WebServer {
|
||||
}
|
||||
}
|
||||
|
||||
responseHeaders.set("Content-Encoding", "gzip");
|
||||
response = getResponse(target, user);
|
||||
|
||||
Response response = getResponse(target, user);
|
||||
|
||||
String content = response.getContent();
|
||||
exchange.sendResponseHeaders(response.getCode(), 0);
|
||||
|
||||
try (GZIPOutputStream out = new GZIPOutputStream(exchange.getResponseBody());
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(content.getBytes())) {
|
||||
byte[] buffer = new byte[2048];
|
||||
int count;
|
||||
while ((count = bis.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, count);
|
||||
}
|
||||
}
|
||||
sendData(responseHeaders, exchange, response);
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass().getName(), e);
|
||||
throw e;
|
||||
@ -136,6 +146,20 @@ public class WebServer {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendData(Headers header, HttpExchange exchange, Response response) throws IOException {
|
||||
header.set("Content-Encoding", "gzip");
|
||||
exchange.sendResponseHeaders(response.getCode(), 0);
|
||||
|
||||
try (GZIPOutputStream out = new GZIPOutputStream(exchange.getResponseBody());
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(response.getContent().getBytes())) {
|
||||
byte[] buffer = new byte[2048];
|
||||
int count;
|
||||
while ((count = bis.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private WebUser getUser(Headers requestHeaders) {
|
||||
Benchmark.start("getUser");
|
||||
try {
|
||||
@ -243,6 +267,137 @@ public class WebServer {
|
||||
return startSuccessful;
|
||||
}
|
||||
|
||||
private String readPOSTRequest(HttpExchange exchange) throws IOException {
|
||||
try (InputStream in = exchange.getRequestBody()) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte buf[] = new byte[4096];
|
||||
for (int n = in.read(buf); n > 0; n = in.read(buf)) {
|
||||
out.write(buf, 0, n);
|
||||
}
|
||||
return new String(out.toByteArray(), "ISO-8859-1");
|
||||
}
|
||||
}
|
||||
|
||||
private Response getAPIResponse(String target, HttpExchange exchange) throws IOException {
|
||||
String[] args = target.split("/");
|
||||
|
||||
if (args.length < 3) {
|
||||
String error = "API Method not specified";
|
||||
return PageCacheHandler.loadPage(error, () -> new NotFoundResponse(error));
|
||||
}
|
||||
|
||||
String method = args[2];
|
||||
String response = readPOSTRequest(exchange);
|
||||
Map<String, String> variables = readVariables(response);
|
||||
|
||||
//TODO ADD CHECK IF SERVER KEY VALID
|
||||
|
||||
Plan plan = Plan.getInstance();
|
||||
|
||||
String playerString;
|
||||
UUID uuid;
|
||||
String identifier;
|
||||
|
||||
switch (method) {
|
||||
//TODO Add Bungee APIs
|
||||
case "analyze":
|
||||
plan.getAnalysisCache().updateCache();
|
||||
return PageCacheHandler.loadPage("success", SuccessResponse::new);
|
||||
case "inspect":
|
||||
playerString = variables.get("player");
|
||||
|
||||
if (playerString == null) {
|
||||
String error = "Player String not included";
|
||||
return PageCacheHandler.loadPage(error, () -> new BadRequestResponse(error));
|
||||
}
|
||||
|
||||
uuid = UUIDUtility.getUUIDOf(playerString);
|
||||
|
||||
if (uuid == null) {
|
||||
String error = "UUID not found";
|
||||
return PageCacheHandler.loadPage(error, () -> new BadRequestResponse(error));
|
||||
}
|
||||
|
||||
Plan.getInstance().getInspectCache().cache(uuid);
|
||||
|
||||
return PageCacheHandler.loadPage("success", SuccessResponse::new);
|
||||
case "analysis":
|
||||
case "analytics":
|
||||
identifier = "analysisJson";
|
||||
if (!PageCacheHandler.isCached(identifier)) {
|
||||
return PageCacheHandler.loadPage("No Analysis Data", () -> new BadRequestResponse("No analysis data available"));
|
||||
}
|
||||
|
||||
return PageCacheHandler.loadPage(identifier);
|
||||
case "inspection":
|
||||
playerString = variables.get("player");
|
||||
|
||||
if (playerString == null) {
|
||||
String error = "Player String not included";
|
||||
return PageCacheHandler.loadPage(error, () -> new BadRequestResponse(error));
|
||||
}
|
||||
|
||||
uuid = UUIDUtility.getUUIDOf(playerString);
|
||||
|
||||
if (uuid == null) {
|
||||
String error = "UUID not found";
|
||||
return PageCacheHandler.loadPage(error, () -> new BadRequestResponse(error));
|
||||
}
|
||||
|
||||
UserData userData = plan.getInspectCache().getFromCache(uuid);
|
||||
|
||||
if (userData == null) {
|
||||
String error = "User not cached";
|
||||
return PageCacheHandler.loadPage(error, () -> new BadRequestResponse(error));
|
||||
}
|
||||
|
||||
return PageCacheHandler.loadPage("inspectionJson: " + uuid, () -> new JsonResponse(plan.getInspectCache().getFromCache(uuid)));
|
||||
case "configure":
|
||||
String key = variables.get("configKey");
|
||||
|
||||
if (key == null) {
|
||||
String error = "Config Key null";
|
||||
return PageCacheHandler.loadPage(error, () -> new BadRequestResponse(error));
|
||||
}
|
||||
|
||||
String value = variables.get("configValue");
|
||||
|
||||
if (value == null) {
|
||||
String error = "Config Value null";
|
||||
return PageCacheHandler.loadPage(error, () -> new BadRequestResponse(error));
|
||||
}
|
||||
|
||||
if (value.equals("null")) {
|
||||
value = null;
|
||||
}
|
||||
|
||||
FileConfiguration config = plan.getConfig();
|
||||
config.set(key, value);
|
||||
plan.saveConfig();
|
||||
|
||||
return PageCacheHandler.loadPage("success", SuccessResponse::new);
|
||||
default:
|
||||
String error = "API Method not found";
|
||||
return PageCacheHandler.loadPage(error, () -> new BadRequestResponse(error));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> readVariables(String response) {
|
||||
Map<String, String> variableMap = new HashMap<>();
|
||||
String[] variables = response.split("&");
|
||||
|
||||
for (String variable : variables) {
|
||||
String[] splittedVariables = variable.split("=", 2);
|
||||
if (splittedVariables.length != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
variableMap.put(splittedVariables[0], splittedVariables[1]);
|
||||
}
|
||||
|
||||
return variableMap;
|
||||
}
|
||||
|
||||
private Response getResponse(String target, WebUser user) {
|
||||
if ("/favicon.ico".equals(target)) {
|
||||
return PageCacheHandler.loadPage("Redirect: favicon", () -> new RedirectResponse("https://puu.sh/tK0KL/6aa2ba141b.ico"));
|
||||
@ -259,6 +414,7 @@ public class WebServer {
|
||||
return forbiddenResponse(permLevel, required);
|
||||
}
|
||||
}
|
||||
|
||||
String[] args = target.split("/");
|
||||
if (args.length < 2) {
|
||||
return rootPageResponse(user);
|
||||
@ -294,6 +450,7 @@ public class WebServer {
|
||||
if (user == null) {
|
||||
return notFoundResponse();
|
||||
}
|
||||
|
||||
switch (user.getPermLevel()) {
|
||||
case 0:
|
||||
return serverResponse();
|
||||
@ -333,7 +490,7 @@ public class WebServer {
|
||||
return PageCacheHandler.loadPage("notFound: " + error, () -> new NotFoundResponse(error));
|
||||
}
|
||||
|
||||
return PageCacheHandler.loadPage("inspectPage: " + uuid.toString(), () -> new InspectPageResponse(dataReqHandler, uuid));
|
||||
return PageCacheHandler.loadPage("inspectPage: " + uuid, () -> new InspectPageResponse(dataReqHandler, uuid));
|
||||
}
|
||||
|
||||
private Response notFoundResponse() {
|
||||
|
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Licence is provided in the jar as license.yml also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
|
||||
*/
|
||||
package main.java.com.djrapitops.plan.ui.webserver.response.api;
|
||||
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.Response;
|
||||
|
||||
/**
|
||||
* @author Fuzzlemann
|
||||
*/
|
||||
public class BadRequestResponse extends Response {
|
||||
|
||||
public BadRequestResponse(String error) {
|
||||
super.setHeader("HTTP/1.1 400 Bad Request");
|
||||
super.setContent(error);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Licence is provided in the jar as license.yml also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
|
||||
*/
|
||||
package main.java.com.djrapitops.plan.ui.webserver.response.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.Response;
|
||||
|
||||
/**
|
||||
* @author Fuzzlemann
|
||||
*/
|
||||
public class JsonResponse extends Response {
|
||||
|
||||
public <T> JsonResponse(T object) {
|
||||
Gson gson = new Gson();
|
||||
|
||||
super.setHeader("HTTP/1.1 200 OK");
|
||||
super.setContent(gson.toJson(object));
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Licence is provided in the jar as license.yml also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
|
||||
*/
|
||||
package main.java.com.djrapitops.plan.ui.webserver.response.api;
|
||||
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.Response;
|
||||
|
||||
/**
|
||||
* @author Fuzzlemann
|
||||
*/
|
||||
public class SuccessResponse extends Response {
|
||||
|
||||
public SuccessResponse() {
|
||||
super.setHeader("HTTP/1.1 200 OK");
|
||||
super.setContent("Success");
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ import main.java.com.djrapitops.plan.locale.Msg;
|
||||
import main.java.com.djrapitops.plan.ui.html.tables.PlayersTableCreator;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.AnalysisPageResponse;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.PlayersPageResponse;
|
||||
import main.java.com.djrapitops.plan.ui.webserver.response.api.JsonResponse;
|
||||
import main.java.com.djrapitops.plan.utilities.Benchmark;
|
||||
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.MiscUtils;
|
||||
@ -165,8 +166,9 @@ public class Analysis {
|
||||
Log.info(Locale.get(Msg.ANALYSIS_FINISHED).parse(String.valueOf(time), HtmlUtils.getServerAnalysisUrlWithProtocol()));
|
||||
}
|
||||
|
||||
PageCacheHandler.removeIf(identifier -> identifier.startsWith("inspectPage: "));
|
||||
PageCacheHandler.removeIf(identifier -> identifier.startsWith("inspectPage: ") || identifier.startsWith("inspectionJson: "));
|
||||
PageCacheHandler.cachePage("analysisPage", () -> new AnalysisPageResponse(plugin.getUiServer().getDataReqHandler()));
|
||||
PageCacheHandler.cachePage("analysisJson", () -> new JsonResponse(analysisData));
|
||||
PageCacheHandler.cachePage("players", () -> new PlayersPageResponse(plugin));
|
||||
|
||||
ExportUtility.export(analysisData, rawData);
|
||||
|
@ -37,7 +37,7 @@ public class Hastebin {
|
||||
*/
|
||||
public static String safeUpload(String content) {
|
||||
List<String> parts = ImmutableList.copyOf(split(content)).reverse();
|
||||
|
||||
|
||||
String lastLink = null;
|
||||
try {
|
||||
for (String part : parts) {
|
||||
|
Loading…
Reference in New Issue
Block a user