diff --git a/Plan/src/main/java/com/djrapitops/plan/Plan.java b/Plan/src/main/java/com/djrapitops/plan/Plan.java index 948db10d7..d0557f136 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Plan.java +++ b/Plan/src/main/java/com/djrapitops/plan/Plan.java @@ -62,6 +62,7 @@ import main.java.com.djrapitops.plan.systems.tasks.TPSCountTimer; import main.java.com.djrapitops.plan.systems.webserver.PageCache; import main.java.com.djrapitops.plan.systems.webserver.WebServer; import main.java.com.djrapitops.plan.utilities.file.FileUtil; +import main.java.com.djrapitops.plan.utilities.file.export.HtmlExport; import main.java.com.djrapitops.plan.utilities.metrics.BStats; import org.bukkit.ChatColor; import org.bukkit.configuration.file.FileConfiguration; @@ -246,6 +247,9 @@ public class Plan extends BukkitPlugin implements IPlan { Log.info(Locale.get(Msg.ENABLED).toString()); StaticHolder.saveInstance(ShutdownHook.class, this.getClass()); new ShutdownHook(this); + if (Settings.ANALYSIS_EXPORT.isTrue()) { + RunnableFactory.createNew(new HtmlExport(this)); + } } catch (Exception e) { Log.error("Plugin Failed to Initialize Correctly."); Log.toLog(this.getClass().getName(), e); diff --git a/Plan/src/main/java/com/djrapitops/plan/PlanBungee.java b/Plan/src/main/java/com/djrapitops/plan/PlanBungee.java index 7f779f8cd..1f5e80426 100644 --- a/Plan/src/main/java/com/djrapitops/plan/PlanBungee.java +++ b/Plan/src/main/java/com/djrapitops/plan/PlanBungee.java @@ -34,6 +34,7 @@ import main.java.com.djrapitops.plan.systems.queue.ProcessingQueue; import main.java.com.djrapitops.plan.systems.tasks.TPSCountTimer; import main.java.com.djrapitops.plan.systems.webserver.WebServer; import main.java.com.djrapitops.plan.utilities.file.FileUtil; +import main.java.com.djrapitops.plan.utilities.file.export.HtmlExport; import net.md_5.bungee.api.ChatColor; import java.io.File; @@ -141,6 +142,9 @@ public class PlanBungee extends BungeePlugin implements IPlan { Log.logDebug("Enable", "WebServer Initialization"); Log.info(Locale.get(Msg.ENABLED).toString()); + if (Settings.ANALYSIS_EXPORT.isTrue()) { + RunnableFactory.createNew(new HtmlExport(this)); + } } catch (Exception e) { Log.error("Plugin Failed to Initialize Correctly."); Log.toLog(this.getClass().getName(), e); diff --git a/Plan/src/main/java/com/djrapitops/plan/systems/info/BukkitInformationManager.java b/Plan/src/main/java/com/djrapitops/plan/systems/info/BukkitInformationManager.java index 828465668..ec8803513 100644 --- a/Plan/src/main/java/com/djrapitops/plan/systems/info/BukkitInformationManager.java +++ b/Plan/src/main/java/com/djrapitops/plan/systems/info/BukkitInformationManager.java @@ -1,4 +1,4 @@ -/* +/* * 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 */ @@ -30,6 +30,7 @@ import main.java.com.djrapitops.plan.systems.webserver.webapi.bungee.*; import main.java.com.djrapitops.plan.systems.webserver.webapi.universal.PingWebAPI; import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.analysis.Analysis; +import main.java.com.djrapitops.plan.utilities.file.export.HtmlExport; import main.java.com.djrapitops.plan.utilities.html.HtmlStructure; import main.java.com.djrapitops.plan.utilities.html.structure.InspectPluginsTabContentCreator; @@ -110,6 +111,9 @@ public class BukkitInformationManager extends InformationManager { } } else { PageCache.cachePage("inspectPage: " + uuid, () -> new InspectPageResponse(this, uuid)); + if (Settings.ANALYSIS_EXPORT.isTrue()) { + HtmlExport.exportPlayer(plugin, uuid); + } } plugin.addToProcessQueue(new Processor(uuid) { @Override @@ -289,7 +293,11 @@ public class BukkitInformationManager extends InformationManager { cacheAnalysisHtml(html); } } else { - PageCache.cachePage("analysisPage:" + Plan.getServerUUID(), () -> new AnalysisPageResponse(html)); + UUID serverUUID = Plan.getServerUUID(); + PageCache.cachePage("analysisPage:" + serverUUID, () -> new AnalysisPageResponse(html)); + if (Settings.ANALYSIS_EXPORT.isTrue()) { + HtmlExport.exportServer(plugin, serverUUID); + } } } diff --git a/Plan/src/main/java/com/djrapitops/plan/systems/webserver/webapi/bungee/PostHtmlWebAPI.java b/Plan/src/main/java/com/djrapitops/plan/systems/webserver/webapi/bungee/PostHtmlWebAPI.java index c828d3001..b09389234 100644 --- a/Plan/src/main/java/com/djrapitops/plan/systems/webserver/webapi/bungee/PostHtmlWebAPI.java +++ b/Plan/src/main/java/com/djrapitops/plan/systems/webserver/webapi/bungee/PostHtmlWebAPI.java @@ -1,4 +1,4 @@ -/* +/* * 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 */ @@ -14,6 +14,7 @@ import main.java.com.djrapitops.plan.systems.webserver.response.AnalysisPageResp import main.java.com.djrapitops.plan.systems.webserver.response.InspectPageResponse; import main.java.com.djrapitops.plan.systems.webserver.response.Response; import main.java.com.djrapitops.plan.systems.webserver.webapi.WebAPI; +import main.java.com.djrapitops.plan.utilities.file.export.HtmlExport; import org.apache.commons.lang3.text.StrSubstitutor; import java.util.HashMap; @@ -54,9 +55,16 @@ public class PostHtmlWebAPI extends WebAPI { map.put("networkName", Settings.BUNGEE_NETWORK_NAME.toString()); PageCache.cachePage("inspectPage:" + uuid, () -> new InspectPageResponse(infoManager, UUID.fromString(uuid), StrSubstitutor.replace(html, map))); + if (Settings.ANALYSIS_EXPORT.isTrue()) { + HtmlExport.exportPlayer(plugin, UUID.fromString(uuid)); + } break; case "analysisPage": - PageCache.cachePage("analysisPage:" + variables.get("sender"), () -> new AnalysisPageResponse(html)); + String sender = variables.get("sender"); + PageCache.cachePage("analysisPage:" + sender, () -> new AnalysisPageResponse(html)); + if (Settings.ANALYSIS_EXPORT.isTrue()) { + HtmlExport.exportServer(plugin, UUID.fromString(sender)); + } break; default: return badRequest("Faulty Target"); diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java index d6c0b4931..f8c9316f0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java @@ -21,7 +21,6 @@ import main.java.com.djrapitops.plan.systems.info.BukkitInformationManager; import main.java.com.djrapitops.plan.systems.info.InformationManager; import main.java.com.djrapitops.plan.systems.webserver.response.ErrorResponse; import main.java.com.djrapitops.plan.systems.webserver.response.InternalErrorResponse; -import main.java.com.djrapitops.plan.utilities.file.export.HtmlExport; import java.util.*; @@ -137,10 +136,6 @@ public class Analysis { Log.logDebug("Analysis", "Analyzing additional data sources (3rd party)"); analysisData.parsePluginsSection(analyzeAdditionalPluginData(profile.getUuids())); ((BukkitInformationManager) infoManager).cacheAnalysisData(analysisData); - - if (Settings.ANALYSIS_EXPORT.isTrue()) { - RunnableFactory.createNew(new HtmlExport(plugin)).runTaskAsynchronously(); - } } catch (Exception e) { Log.toLog(this.getClass().getName(), e); ((BukkitInformationManager) plugin.getInfoManager()).cacheAnalysisHtml(new InternalErrorResponse(e, "Analysis").getContent()); diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/AnalysisExport.java b/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/AnalysisExport.java new file mode 100644 index 000000000..bea12100c --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/AnalysisExport.java @@ -0,0 +1,38 @@ +/* + * 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.utilities.file.export; + +import com.djrapitops.plugin.api.utility.log.Log; + +import java.io.IOException; +import java.util.UUID; + +/** + * Task that exports a single Analysis page if it is in PageCache. + * + * @author Rsl1122 + */ +public class AnalysisExport extends SpecificExport { + + private final UUID serverUUID; + private final String serverName; + + public AnalysisExport(UUID serverUUID, String serverName) { + super("ServerPageExport:" + serverName); + this.serverUUID = serverUUID; + this.serverName = serverName; + } + + @Override + public void run() { + try { + exportAvailableServerPage(serverUUID, serverName); + } catch (IOException e) { + Log.toLog(this.getClass().getName(), e); + } finally { + this.cancel(); + } + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/HtmlExport.java b/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/HtmlExport.java index 01768026e..370496427 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/HtmlExport.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/HtmlExport.java @@ -4,60 +4,53 @@ */ package main.java.com.djrapitops.plan.utilities.file.export; -import com.djrapitops.plugin.api.Check; import com.djrapitops.plugin.api.utility.log.Log; -import com.djrapitops.plugin.task.AbsRunnable; -import main.java.com.djrapitops.plan.Plan; +import com.djrapitops.plugin.task.RunnableFactory; import main.java.com.djrapitops.plan.api.IPlan; -import main.java.com.djrapitops.plan.settings.Settings; -import main.java.com.djrapitops.plan.systems.webserver.PageCache; -import main.java.com.djrapitops.plan.systems.webserver.response.Response; -import main.java.com.djrapitops.plan.utilities.MiscUtils; +import main.java.com.djrapitops.plan.data.container.UserInfo; +import main.java.com.djrapitops.plan.settings.theme.Theme; +import main.java.com.djrapitops.plan.settings.theme.ThemeVal; +import main.java.com.djrapitops.plan.systems.webserver.response.PlayersPageResponse; +import main.java.com.djrapitops.plan.systems.webserver.webapi.bungee.PostHtmlWebAPI; import main.java.com.djrapitops.plan.utilities.file.FileUtil; import java.io.File; import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Paths; import java.sql.SQLException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; /** * Class responsible for Html Export task. * * @author Rsl1122 */ -public class HtmlExport extends AbsRunnable { +public class HtmlExport extends SpecificExport { private final IPlan plugin; - private final boolean usingBungee; - private final boolean exportSpecificPage; - - private String specificPage; - - private final File outputFolder; public HtmlExport(IPlan plugin) { super("HtmlExportTask"); - usingBungee = Check.isBungeeAvailable(); this.plugin = plugin; - - outputFolder = getFolder(); - exportSpecificPage = false; } - public HtmlExport(IPlan plugin, String specificPage) { - super("HtmlExportTask"); - usingBungee = Check.isBungeeAvailable(); - this.plugin = plugin; + public static void exportServer(IPlan plugin, UUID serverUUID) { + try { + Optional serverName = plugin.getDB().getServerTable().getServerName(serverUUID); + serverName.ifPresent(s -> RunnableFactory.createNew(new AnalysisExport(serverUUID, s)).runTaskAsynchronously()); + } catch (SQLException e) { + Log.toLog(PostHtmlWebAPI.class.getClass().getName(), e); + } + } - outputFolder = getFolder(); - exportSpecificPage = true; - this.specificPage = specificPage; + public static void exportPlayer(IPlan plugin, UUID playerUUID) { + try { + String playerName = plugin.getDB().getUsersTable().getPlayerName(playerUUID); + if (playerName != null) { + RunnableFactory.createNew(new PlayerExport(playerUUID, playerName)).runTaskAsynchronously(); + } + } catch (SQLException e) { + Log.toLog(PostHtmlWebAPI.class.getClass().getName(), e); + } } @Override @@ -73,6 +66,8 @@ public class HtmlExport extends AbsRunnable { exportPlugins(); exportAvailableServerPages(); + exportAvailablePlayers(); + exportPlayersPage(); } catch (IOException | SQLException e) { Log.toLog(this.getClass().getName(), e); } finally { @@ -80,38 +75,33 @@ public class HtmlExport extends AbsRunnable { } } + private void exportPlayersPage() throws IOException { + PlayersPageResponse playersPageResponse = new PlayersPageResponse(); + + String html = playersPageResponse.getContent() + .replace("href=\"plugins/", "href=\"../plugins/") + .replace("href=\"css/", "href=\"../css/") + .replace("src=\"plugins/", "src=\"../plugins/") + .replace("src=\"js/", "src=\"../js/"); + List lines = Arrays.asList(html.split("\n")); + + File htmlLocation = new File(outputFolder, "players"); + htmlLocation.mkdirs(); + File exportFile = new File(htmlLocation, "index.html"); + export(exportFile, lines); + } + + private void exportAvailablePlayers() throws SQLException, IOException { + for (Map.Entry entry : plugin.getDB().getUsersTable().getUsers().entrySet()) { + exportAvailablePlayerPage(entry.getKey(), entry.getValue().getName()); + } + } + private void exportAvailableServerPages() throws SQLException, IOException { Map serverNames = plugin.getDB().getServerTable().getServerNames(); for (Map.Entry entry : serverNames.entrySet()) { - UUID serverUUID = entry.getKey(); - - Response response = PageCache.loadPage("analysisPage:" + serverUUID); - if (response == null) { - continue; - } - - String html = response.getContent() - .replace("href=\"plugins/", "href=\"../plugins/") - .replace("href=\"css/", "href=\"../css/") - .replace("src=\"plugins/", "src=\"../plugins/") - .replace("src=\"js/", "src=\"../js/"); - - File htmlLocation = null; - if (usingBungee && serverUUID.equals(MiscUtils.getIPlan().getServerUuid())) { - htmlLocation = new File(outputFolder, "network"); - } else { - String serverName = entry.getValue(); - File serverFolder = getServerFolder(); - htmlLocation = new File(serverFolder, serverName.replace(" ", "%20")); - html = html.replace("../", "../../"); - } - htmlLocation.mkdirs(); - File exportFile = new File(htmlLocation, "index.html"); - - List lines = Arrays.asList(html.split("\n")); - - export(exportFile, lines); + exportAvailableServerPage(entry.getKey(), entry.getValue()); } } @@ -122,13 +112,12 @@ public class HtmlExport extends AbsRunnable { "web/css/style.css", "web/css/themes/all-themes.css" }; - copyFromJar(resources); + copyFromJar(resources, true); } private void exportJs() { String[] resources = new String[]{ "web/js/admin.js", - "web/js/demo.js", "web/js/helpers.js", "web/js/script.js", "web/js/charts/activityPie.js", @@ -145,7 +134,18 @@ public class HtmlExport extends AbsRunnable { "web/js/charts/worldPie.js", "web/js/charts/healthGauge.js" }; - copyFromJar(resources); + copyFromJar(resources, false); + + try { + String demo = FileUtil.getStringFromResource("web/js/demo.js") + .replace("${defaultTheme}", Theme.getValue(ThemeVal.THEME_DEFAULT)); + List lines = Arrays.asList(demo.split("\n")); + File outputFolder = new File(this.outputFolder, "js"); + outputFolder.mkdirs(); + export(new File(outputFolder, "demo.js"), lines); + } catch (IOException e) { + Log.toLog(this.getClass().getName(), e); + } } private void exportPlugins() { @@ -160,58 +160,34 @@ public class HtmlExport extends AbsRunnable { "web/plugins/jquery-datatable/skin/bootstrap/js/dataTables.bootstrap.js", "web/plugins/jquery-datatable/jquery.dataTables.js" }; - copyFromJar(resources); + copyFromJar(resources, true); } - public File getFolder() { - String path = Settings.ANALYSIS_EXPORT_PATH.toString(); - Log.logDebug("Export", "Path: " + path); - boolean isAbsolute = Paths.get(path).isAbsolute(); - Log.logDebug("Export", "Absolute: " + (isAbsolute ? "Yes" : "No")); - if (isAbsolute) { - File folder = new File(path); - if (!folder.exists() || !folder.isDirectory()) { - folder.mkdirs(); - } - return folder; - } - File dataFolder = Plan.getInstance().getDataFolder(); - File folder = new File(dataFolder, path); - folder.mkdirs(); - return folder; - } - - private void copyFromJar(String[] resources) { + private void copyFromJar(String[] resources, boolean overwrite) { for (String resource : resources) { try { - copyFromJar(resource); + copyFromJar(resource, overwrite); } catch (IOException e) { Log.toLog(this.getClass().getName(), e); } } } - private void copyFromJar(String resource) throws IOException { + private void copyFromJar(String resource, boolean overwrite) throws IOException { String possibleFile = resource.replace("web/", "").replace("/", File.separator); List lines = FileUtil.lines(plugin, new File(plugin.getDataFolder(), possibleFile), resource); String outputFile = possibleFile.replace("web/", ""); File to = new File(outputFolder, outputFile); to.mkdirs(); if (to.exists()) { - to.delete(); - to.createNewFile(); + if (overwrite) { + to.delete(); + to.createNewFile(); + } else { + return; + } } export(to, lines); } - - private void export(File to, List lines) throws IOException { - Files.write(to.toPath(), lines, Charset.forName("UTF-8")); - } - - public File getServerFolder() { - File server = new File(outputFolder, "server"); - server.mkdirs(); - return server; - } } \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/PlayerExport.java b/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/PlayerExport.java new file mode 100644 index 000000000..276112e9b --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/PlayerExport.java @@ -0,0 +1,38 @@ +/* + * 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.utilities.file.export; + +import com.djrapitops.plugin.api.utility.log.Log; + +import java.io.IOException; +import java.util.UUID; + +/** + * Task for exporting a single player page. + * + * @author Rsl1122 + */ +public class PlayerExport extends SpecificExport { + + private final UUID uuid; + private final String name; + + public PlayerExport(UUID uuid, String name) { + super("PlayerPageExport:" + name); + this.uuid = uuid; + this.name = name; + } + + @Override + public void run() { + try { + exportAvailablePlayerPage(uuid, name); + } catch (IOException e) { + Log.toLog(this.getClass().getName(), e); + } finally { + this.cancel(); + } + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/SpecificExport.java b/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/SpecificExport.java new file mode 100644 index 000000000..b12f6c46d --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/file/export/SpecificExport.java @@ -0,0 +1,127 @@ +/* + * 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.utilities.file.export; + +import com.djrapitops.plugin.api.Check; +import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.task.AbsRunnable; +import main.java.com.djrapitops.plan.Plan; +import main.java.com.djrapitops.plan.settings.Settings; +import main.java.com.djrapitops.plan.systems.webserver.PageCache; +import main.java.com.djrapitops.plan.systems.webserver.response.Response; +import main.java.com.djrapitops.plan.utilities.MiscUtils; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +/** + * //TODO Class Javadoc Comment + * + * @author Rsl1122 + */ +public abstract class SpecificExport extends AbsRunnable { + + protected final File outputFolder; + protected final boolean usingBungee; + + protected SpecificExport(String taskName) { + super(taskName); + outputFolder = getFolder(); + usingBungee = Check.isBungeeAvailable(); + } + + protected File getFolder() { + String path = Settings.ANALYSIS_EXPORT_PATH.toString(); + + Log.logDebug("Export", "Path: " + path); + boolean isAbsolute = Paths.get(path).isAbsolute(); + Log.logDebug("Export", "Absolute: " + (isAbsolute ? "Yes" : "No")); + if (isAbsolute) { + File folder = new File(path); + if (!folder.exists() || !folder.isDirectory()) { + folder.mkdirs(); + } + return folder; + } + File dataFolder = Plan.getInstance().getDataFolder(); + File folder = new File(dataFolder, path); + folder.mkdirs(); + return folder; + } + + protected void export(File to, List lines) throws IOException { + Files.write(to.toPath(), lines, Charset.forName("UTF-8")); + } + + protected File getServerFolder() { + File server = new File(outputFolder, "server"); + server.mkdirs(); + return server; + } + + protected File getPlayerFolder() { + File player = new File(outputFolder, "player"); + player.mkdirs(); + return player; + } + + protected void exportAvailablePlayerPage(UUID uuid, String name) throws IOException { + Response response = PageCache.loadPage("inspectPage: " + uuid); + if (response == null) { + return; + } + + String html = response.getContent() + .replace("href=\"plugins/", "href=\"../plugins/") + .replace("href=\"css/", "href=\"../css/") + .replace("src=\"plugins/", "src=\"../plugins/") + .replace("src=\"js/", "src=\"../js/"); + List lines = Arrays.asList(html.split("\n")); + + File htmlLocation = new File(getPlayerFolder(), name.replace(" ", "%20").replace(".", "%2E")); + htmlLocation.mkdirs(); + File exportFile = new File(htmlLocation, "index.html"); + + export(exportFile, lines); + } + + protected void exportAvailableServerPage(UUID serverUUID, String serverName) throws IOException { + + Response response = PageCache.loadPage("analysisPage:" + serverUUID); + if (response == null) { + return; + } + + String html = response.getContent() + .replace("href=\"plugins/", "href=\"../plugins/") + .replace("href=\"css/", "href=\"../css/") + .replace("src=\"plugins/", "src=\"../plugins/") + .replace("src=\"js/", "src=\"../js/"); + + File htmlLocation = null; + if (usingBungee) { + if (serverUUID.equals(MiscUtils.getIPlan().getServerUuid())) { + htmlLocation = new File(outputFolder, "network"); + } else { + htmlLocation = new File(getServerFolder(), serverName.replace(" ", "%20").replace(".", "%2E")); + html = html.replace("../", "../../"); + } + } else { + htmlLocation = getServerFolder(); + } + htmlLocation.mkdirs(); + File exportFile = new File(htmlLocation, "index.html"); + + List lines = Arrays.asList(html.split("\n")); + + export(exportFile, lines); + } +} \ No newline at end of file