mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-08 01:17:45 +01:00
Export of /network page
This commit is contained in:
parent
c1c2da8517
commit
d1123525ac
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan;
|
package com.djrapitops.plan;
|
||||||
|
|
||||||
import com.djrapitops.plan.delivery.upkeep.PeriodicServerExportTask;
|
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
|
import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
|
||||||
import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask;
|
import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask;
|
||||||
import com.djrapitops.plan.gathering.ShutdownHook;
|
import com.djrapitops.plan.gathering.ShutdownHook;
|
||||||
@ -25,7 +24,6 @@ import com.djrapitops.plan.gathering.timed.BukkitTPSCounter;
|
|||||||
import com.djrapitops.plan.gathering.timed.PaperTPSCounter;
|
import com.djrapitops.plan.gathering.timed.PaperTPSCounter;
|
||||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||||
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
||||||
import com.djrapitops.plan.settings.config.paths.ExportSettings;
|
|
||||||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||||
import com.djrapitops.plan.settings.upkeep.ConfigStoreTask;
|
import com.djrapitops.plan.settings.upkeep.ConfigStoreTask;
|
||||||
import com.djrapitops.plan.storage.upkeep.DBCleanTask;
|
import com.djrapitops.plan.storage.upkeep.DBCleanTask;
|
||||||
@ -52,7 +50,6 @@ public class BukkitTaskSystem extends TaskSystem {
|
|||||||
private final PlanConfig config;
|
private final PlanConfig config;
|
||||||
private final ShutdownHook shutdownHook;
|
private final ShutdownHook shutdownHook;
|
||||||
private final JSONCache.CleanTask jsonCacheCleanTask;
|
private final JSONCache.CleanTask jsonCacheCleanTask;
|
||||||
private final PeriodicServerExportTask periodicServerExportTask;
|
|
||||||
private final LogsFolderCleanTask logsFolderCleanTask;
|
private final LogsFolderCleanTask logsFolderCleanTask;
|
||||||
private final BukkitPingCounter pingCounter;
|
private final BukkitPingCounter pingCounter;
|
||||||
private final ConfigStoreTask configStoreTask;
|
private final ConfigStoreTask configStoreTask;
|
||||||
@ -75,9 +72,7 @@ public class BukkitTaskSystem extends TaskSystem {
|
|||||||
LogsFolderCleanTask logsFolderCleanTask,
|
LogsFolderCleanTask logsFolderCleanTask,
|
||||||
ConfigStoreTask configStoreTask,
|
ConfigStoreTask configStoreTask,
|
||||||
DBCleanTask dbCleanTask,
|
DBCleanTask dbCleanTask,
|
||||||
JSONCache.CleanTask jsonCacheCleanTask,
|
JSONCache.CleanTask jsonCacheCleanTask
|
||||||
|
|
||||||
PeriodicServerExportTask periodicServerExportTask
|
|
||||||
) {
|
) {
|
||||||
super(runnableFactory);
|
super(runnableFactory);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@ -92,8 +87,6 @@ public class BukkitTaskSystem extends TaskSystem {
|
|||||||
this.logsFolderCleanTask = logsFolderCleanTask;
|
this.logsFolderCleanTask = logsFolderCleanTask;
|
||||||
this.configStoreTask = configStoreTask;
|
this.configStoreTask = configStoreTask;
|
||||||
this.dbCleanTask = dbCleanTask;
|
this.dbCleanTask = dbCleanTask;
|
||||||
|
|
||||||
this.periodicServerExportTask = periodicServerExportTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -117,10 +110,6 @@ public class BukkitTaskSystem extends TaskSystem {
|
|||||||
);
|
);
|
||||||
long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES);
|
long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES);
|
||||||
registerTask(jsonCacheCleanTask).runTaskTimerAsynchronously(minute, minute);
|
registerTask(jsonCacheCleanTask).runTaskTimerAsynchronously(minute, minute);
|
||||||
|
|
||||||
if (config.get(ExportSettings.SERVER_PAGE)) {
|
|
||||||
registerTask(periodicServerExportTask).runTaskTimerAsynchronously(TimeAmount.toTicks(30L, TimeUnit.SECONDS), TimeAmount.toTicks(20L, TimeUnit.MINUTES));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerTPSCounter() {
|
private void registerTPSCounter() {
|
||||||
|
@ -16,20 +16,22 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan.delivery.export;
|
package com.djrapitops.plan.delivery.export;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.exceptions.ExportException;
|
||||||
import com.djrapitops.plan.exceptions.ParseException;
|
import com.djrapitops.plan.exceptions.ParseException;
|
||||||
import com.djrapitops.plan.exceptions.connection.NotFoundException;
|
import com.djrapitops.plan.exceptions.connection.NotFoundException;
|
||||||
import com.djrapitops.plan.identification.Server;
|
import com.djrapitops.plan.identification.Server;
|
||||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||||
import com.djrapitops.plan.settings.config.paths.ExportSettings;
|
import com.djrapitops.plan.settings.config.paths.ExportSettings;
|
||||||
import com.djrapitops.plan.storage.file.PlanFiles;
|
import com.djrapitops.plan.storage.file.PlanFiles;
|
||||||
import com.djrapitops.plugin.logging.L;
|
|
||||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles export for different pages.
|
* Handles export for different pages.
|
||||||
@ -42,33 +44,54 @@ public class Exporter {
|
|||||||
private final PlanFiles files;
|
private final PlanFiles files;
|
||||||
private final PlanConfig config;
|
private final PlanConfig config;
|
||||||
private final ServerPageExporter serverPageExporter;
|
private final ServerPageExporter serverPageExporter;
|
||||||
private final ErrorHandler errorHandler;
|
private final NetworkPageExporter networkPageExporter;
|
||||||
|
|
||||||
|
private final Set<UUID> failedServers;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Exporter(
|
public Exporter(
|
||||||
PlanFiles files,
|
PlanFiles files,
|
||||||
PlanConfig config,
|
PlanConfig config,
|
||||||
ServerPageExporter serverPageExporter,
|
ServerPageExporter serverPageExporter,
|
||||||
ErrorHandler errorHandler
|
NetworkPageExporter networkPageExporter
|
||||||
) {
|
) {
|
||||||
this.files = files;
|
this.files = files;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.serverPageExporter = serverPageExporter;
|
this.serverPageExporter = serverPageExporter;
|
||||||
this.errorHandler = errorHandler;
|
this.networkPageExporter = networkPageExporter;
|
||||||
|
|
||||||
|
failedServers = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Path getPageExportDirectory() {
|
private Path getPageExportDirectory() {
|
||||||
Path exportDirectory = Paths.get(config.get(ExportSettings.HTML_EXPORT_PATH));
|
Path exportDirectory = Paths.get(config.get(ExportSettings.HTML_EXPORT_PATH));
|
||||||
return exportDirectory.isAbsolute()
|
return exportDirectory.isAbsolute()
|
||||||
? exportDirectory
|
? exportDirectory
|
||||||
: files.getDataDirectory().resolve(exportDirectory);
|
: files.getDataDirectory().resolve(exportDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exportServerPage(Server server) {
|
/**
|
||||||
|
* Export a page of a server.
|
||||||
|
*
|
||||||
|
* @param server Server which page is going to be exported
|
||||||
|
* @return false if the page was not exported due to previous failure.
|
||||||
|
* @throws ExportException If the export failed
|
||||||
|
*/
|
||||||
|
public boolean exportServerPage(Server server) throws ExportException {
|
||||||
|
UUID serverUUID = server.getUuid();
|
||||||
|
if (failedServers.contains(serverUUID)) return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serverPageExporter.export(getPageExportDirectory(), server);
|
Path toDirectory = getPageExportDirectory();
|
||||||
|
if (server.isProxy()) {
|
||||||
|
networkPageExporter.export(toDirectory, server);
|
||||||
|
} else {
|
||||||
|
serverPageExporter.export(toDirectory, server);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
} catch (IOException | NotFoundException | ParseException e) {
|
} catch (IOException | NotFoundException | ParseException e) {
|
||||||
errorHandler.log(L.WARN, this.getClass(), e);
|
failedServers.add(serverUUID);
|
||||||
|
throw new ExportException("Failed to export server: " + server.getIdentifiableName() + " (Attempts disabled until next reload), " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ import com.djrapitops.plan.delivery.rendering.json.JSONFactory;
|
|||||||
import com.djrapitops.plan.delivery.rendering.pages.NetworkPage;
|
import com.djrapitops.plan.delivery.rendering.pages.NetworkPage;
|
||||||
import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
|
import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
|
||||||
import com.djrapitops.plan.delivery.rendering.pages.PlayerPage;
|
import com.djrapitops.plan.delivery.rendering.pages.PlayerPage;
|
||||||
|
import com.djrapitops.plan.exceptions.ExportException;
|
||||||
import com.djrapitops.plan.exceptions.ParseException;
|
import com.djrapitops.plan.exceptions.ParseException;
|
||||||
import com.djrapitops.plan.exceptions.database.DBOpException;
|
import com.djrapitops.plan.exceptions.database.DBOpException;
|
||||||
import com.djrapitops.plan.gathering.domain.BaseUser;
|
import com.djrapitops.plan.gathering.domain.BaseUser;
|
||||||
@ -97,7 +98,11 @@ public class HtmlExport extends SpecificExport {
|
|||||||
// if (serverInfo.getServer().isNotProxy() && hasProxy) {
|
// if (serverInfo.getServer().isNotProxy() && hasProxy) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
exporter.exportServerPage(server);
|
try {
|
||||||
|
exporter.exportServerPage(server);
|
||||||
|
} catch (ExportException e) {
|
||||||
|
errorHandler.log(L.WARN, this.getClass(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exportPlayerPage(UUID playerUUID) {
|
public void exportPlayerPage(UUID playerUUID) {
|
||||||
|
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Player Analytics (Plan).
|
||||||
|
*
|
||||||
|
* Plan is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Plan is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.djrapitops.plan.delivery.export;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.delivery.rendering.pages.Page;
|
||||||
|
import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.RequestTarget;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONHandler;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.response.Response;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.response.errors.ErrorResponse;
|
||||||
|
import com.djrapitops.plan.exceptions.ParseException;
|
||||||
|
import com.djrapitops.plan.exceptions.connection.NotFoundException;
|
||||||
|
import com.djrapitops.plan.exceptions.connection.WebException;
|
||||||
|
import com.djrapitops.plan.identification.Server;
|
||||||
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
|
import com.djrapitops.plan.settings.theme.Theme;
|
||||||
|
import com.djrapitops.plan.storage.file.PlanFiles;
|
||||||
|
import com.djrapitops.plan.storage.file.Resource;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles exporting of /network page html, data and resources.
|
||||||
|
*
|
||||||
|
* @author Rsl1122
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class NetworkPageExporter extends FileExporter {
|
||||||
|
|
||||||
|
private final PlanFiles files;
|
||||||
|
private final PageFactory pageFactory;
|
||||||
|
private final RootJSONHandler jsonHandler;
|
||||||
|
private final Locale locale;
|
||||||
|
private final Theme theme;
|
||||||
|
|
||||||
|
private final ExportPaths exportPaths;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NetworkPageExporter(
|
||||||
|
PlanFiles files,
|
||||||
|
PageFactory pageFactory,
|
||||||
|
RootJSONHandler jsonHandler,
|
||||||
|
Locale locale,
|
||||||
|
Theme theme
|
||||||
|
) {
|
||||||
|
this.files = files;
|
||||||
|
this.pageFactory = pageFactory;
|
||||||
|
this.jsonHandler = jsonHandler;
|
||||||
|
this.locale = locale;
|
||||||
|
this.theme = theme;
|
||||||
|
|
||||||
|
exportPaths = new ExportPaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void export(Path toDirectory, Server server) throws IOException, NotFoundException, ParseException {
|
||||||
|
exportRequiredResources(toDirectory);
|
||||||
|
exportJSON(toDirectory, server);
|
||||||
|
exportHtml(toDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportHtml(Path toDirectory) throws IOException, ParseException {
|
||||||
|
Path to = toDirectory
|
||||||
|
.resolve("network")
|
||||||
|
.resolve("index.html");
|
||||||
|
|
||||||
|
Page page = pageFactory.networkPage();
|
||||||
|
export(to, exportPaths.resolveExportPaths(locale.replaceMatchingLanguage(page.toHtml())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportJSON(Path toDirectory, Server server) throws IOException, NotFoundException {
|
||||||
|
String serverUUID = server.getUuid().toString();
|
||||||
|
|
||||||
|
exportJSON(toDirectory,
|
||||||
|
"network/overview",
|
||||||
|
"network/servers",
|
||||||
|
"network/sessionsOverview",
|
||||||
|
"network/playerbaseOverview",
|
||||||
|
"graph?type=playersOnline&server=" + serverUUID,
|
||||||
|
"graph?type=uniqueAndNew",
|
||||||
|
"graph?type=serverPie",
|
||||||
|
"graph?type=activity",
|
||||||
|
"graph?type=geolocation",
|
||||||
|
"graph?type=uniqueAndNew",
|
||||||
|
"network/pingTable",
|
||||||
|
"sessions"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportJSON(Path toDirectory, String... resources) throws NotFoundException, IOException {
|
||||||
|
for (String resource : resources) {
|
||||||
|
exportJSON(toDirectory, resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportJSON(Path toDirectory, String resource) throws NotFoundException, IOException {
|
||||||
|
Response found = getJSONResponse(resource);
|
||||||
|
if (found instanceof ErrorResponse) {
|
||||||
|
throw new NotFoundException(resource + " was not properly exported: " + found.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
String jsonResourceName = toFileName(toJSONResourceName(resource)) + ".json";
|
||||||
|
|
||||||
|
export(toDirectory.resolve("data").resolve(jsonResourceName), found.getContent());
|
||||||
|
exportPaths.put("../v1/" + resource, toRelativePathFromRoot("data/" + jsonResourceName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toJSONResourceName(String resource) {
|
||||||
|
return StringUtils.replaceEach(resource, new String[]{"?", "&", "type=", "server="}, new String[]{"-", "_", "", ""});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response getJSONResponse(String resource) {
|
||||||
|
try {
|
||||||
|
return jsonHandler.getResponse(null, new RequestTarget(URI.create(resource)));
|
||||||
|
} catch (WebException e) {
|
||||||
|
// The rest of the exceptions should not be thrown
|
||||||
|
throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportRequiredResources(Path toDirectory) throws IOException {
|
||||||
|
exportImage(toDirectory, "img/Flaticon_circle.png");
|
||||||
|
|
||||||
|
exportResources(toDirectory,
|
||||||
|
"css/sb-admin-2.css",
|
||||||
|
"css/style.css",
|
||||||
|
"vendor/jquery/jquery.min.js",
|
||||||
|
"vendor/bootstrap/js/bootstrap.bundle.min.js",
|
||||||
|
"vendor/jquery-easing/jquery.easing.min.js",
|
||||||
|
"vendor/datatables/jquery.dataTables.min.js",
|
||||||
|
"vendor/datatables/dataTables.bootstrap4.min.js",
|
||||||
|
"vendor/highcharts/highstock.js",
|
||||||
|
"vendor/highcharts/map.js",
|
||||||
|
"vendor/highcharts/world.js",
|
||||||
|
"vendor/highcharts/drilldown.js",
|
||||||
|
"vendor/highcharts/highcharts-more.js",
|
||||||
|
"vendor/highcharts/no-data-to-display.js",
|
||||||
|
"js/sb-admin-2.js",
|
||||||
|
"js/xmlhttprequests.js",
|
||||||
|
"js/color-selector.js",
|
||||||
|
"js/sessionAccordion.js",
|
||||||
|
"js/pingTable.js",
|
||||||
|
"js/graphs.js",
|
||||||
|
"js/network-values.js"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportResources(Path toDirectory, String... resourceNames) throws IOException {
|
||||||
|
for (String resourceName : resourceNames) {
|
||||||
|
exportResource(toDirectory, resourceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportResource(Path toDirectory, String resourceName) throws IOException {
|
||||||
|
Resource resource = files.getCustomizableResourceOrDefault("web/" + resourceName);
|
||||||
|
Path to = toDirectory.resolve(resourceName);
|
||||||
|
if (resourceName.endsWith(".css")) {
|
||||||
|
export(to, theme.replaceThemeColors(resource.asString()));
|
||||||
|
} else {
|
||||||
|
export(to, resource.asLines());
|
||||||
|
}
|
||||||
|
|
||||||
|
exportPaths.put(resourceName, toRelativePathFromRoot(resourceName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportImage(Path toDirectory, String resourceName) throws IOException {
|
||||||
|
Resource resource = files.getCustomizableResourceOrDefault("web/" + resourceName);
|
||||||
|
Path to = toDirectory.resolve(resourceName);
|
||||||
|
export(to, resource);
|
||||||
|
|
||||||
|
exportPaths.put(resourceName, toRelativePathFromRoot(resourceName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toRelativePathFromRoot(String resourceName) {
|
||||||
|
// Network html is exported at /network//index.html or /server/index.html
|
||||||
|
return "../" + toNonRelativePath(resourceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toNonRelativePath(String resourceName) {
|
||||||
|
return StringUtils.remove(resourceName, "../");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,8 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan.delivery.export;
|
package com.djrapitops.plan.delivery.export;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.delivery.rendering.pages.Page;
|
||||||
import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
|
import com.djrapitops.plan.delivery.rendering.pages.PageFactory;
|
||||||
import com.djrapitops.plan.delivery.rendering.pages.ServerPage;
|
|
||||||
import com.djrapitops.plan.delivery.webserver.RequestTarget;
|
import com.djrapitops.plan.delivery.webserver.RequestTarget;
|
||||||
import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONHandler;
|
import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONHandler;
|
||||||
import com.djrapitops.plan.delivery.webserver.response.Response;
|
import com.djrapitops.plan.delivery.webserver.response.Response;
|
||||||
@ -27,6 +27,8 @@ import com.djrapitops.plan.exceptions.connection.NotFoundException;
|
|||||||
import com.djrapitops.plan.exceptions.connection.WebException;
|
import com.djrapitops.plan.exceptions.connection.WebException;
|
||||||
import com.djrapitops.plan.identification.Server;
|
import com.djrapitops.plan.identification.Server;
|
||||||
import com.djrapitops.plan.identification.ServerInfo;
|
import com.djrapitops.plan.identification.ServerInfo;
|
||||||
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
|
import com.djrapitops.plan.settings.theme.Theme;
|
||||||
import com.djrapitops.plan.storage.file.PlanFiles;
|
import com.djrapitops.plan.storage.file.PlanFiles;
|
||||||
import com.djrapitops.plan.storage.file.Resource;
|
import com.djrapitops.plan.storage.file.Resource;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@ -49,6 +51,8 @@ public class ServerPageExporter extends FileExporter {
|
|||||||
private final PlanFiles files;
|
private final PlanFiles files;
|
||||||
private final PageFactory pageFactory;
|
private final PageFactory pageFactory;
|
||||||
private final RootJSONHandler jsonHandler;
|
private final RootJSONHandler jsonHandler;
|
||||||
|
private final Locale locale;
|
||||||
|
private final Theme theme;
|
||||||
private final ServerInfo serverInfo;
|
private final ServerInfo serverInfo;
|
||||||
|
|
||||||
private final ExportPaths exportPaths;
|
private final ExportPaths exportPaths;
|
||||||
@ -58,11 +62,15 @@ public class ServerPageExporter extends FileExporter {
|
|||||||
PlanFiles files,
|
PlanFiles files,
|
||||||
PageFactory pageFactory,
|
PageFactory pageFactory,
|
||||||
RootJSONHandler jsonHandler,
|
RootJSONHandler jsonHandler,
|
||||||
|
Locale locale,
|
||||||
|
Theme theme,
|
||||||
ServerInfo serverInfo // To know if current server is a Proxy
|
ServerInfo serverInfo // To know if current server is a Proxy
|
||||||
) {
|
) {
|
||||||
this.files = files;
|
this.files = files;
|
||||||
this.pageFactory = pageFactory;
|
this.pageFactory = pageFactory;
|
||||||
this.jsonHandler = jsonHandler;
|
this.jsonHandler = jsonHandler;
|
||||||
|
this.locale = locale;
|
||||||
|
this.theme = theme;
|
||||||
this.serverInfo = serverInfo;
|
this.serverInfo = serverInfo;
|
||||||
|
|
||||||
exportPaths = new ExportPaths();
|
exportPaths = new ExportPaths();
|
||||||
@ -80,31 +88,39 @@ public class ServerPageExporter extends FileExporter {
|
|||||||
.resolve(serverInfo.getServer().isProxy() ? "server/" + server.getName() : "server")
|
.resolve(serverInfo.getServer().isProxy() ? "server/" + server.getName() : "server")
|
||||||
.resolve("index.html");
|
.resolve("index.html");
|
||||||
|
|
||||||
ServerPage serverPage = pageFactory.serverPage(serverUUID);
|
Page page = pageFactory.serverPage(serverUUID);
|
||||||
export(to, exportPaths.resolveExportPaths(serverPage.toHtml()));
|
export(to, exportPaths.resolveExportPaths(locale.replaceMatchingLanguage(page.toHtml())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void exportJSON(Path toDirectory, Server server) throws IOException, NotFoundException {
|
private void exportJSON(Path toDirectory, Server server) throws IOException, NotFoundException {
|
||||||
String serverName = server.getName();
|
String serverName = server.getName();
|
||||||
|
|
||||||
exportJSON(toDirectory, "serverOverview?server=" + serverName);
|
exportJSON(toDirectory,
|
||||||
exportJSON(toDirectory, "onlineOverview?server=" + serverName);
|
"serverOverview?server=" + serverName,
|
||||||
exportJSON(toDirectory, "sessionsOverview?server=" + serverName);
|
"onlineOverview?server=" + serverName,
|
||||||
exportJSON(toDirectory, "playerVersus?server=" + serverName);
|
"sessionsOverview?server=" + serverName,
|
||||||
exportJSON(toDirectory, "playerbaseOverview?server=" + serverName);
|
"playerVersus?server=" + serverName,
|
||||||
exportJSON(toDirectory, "performanceOverview?server=" + serverName);
|
"playerbaseOverview?server=" + serverName,
|
||||||
exportJSON(toDirectory, "graph?type=performance&server=" + serverName);
|
"performanceOverview?server=" + serverName,
|
||||||
exportJSON(toDirectory, "graph?type=aggregatedPing&server=" + serverName);
|
"graph?type=performance&server=" + serverName,
|
||||||
exportJSON(toDirectory, "graph?type=worldPie&server=" + serverName);
|
"graph?type=aggregatedPing&server=" + serverName,
|
||||||
exportJSON(toDirectory, "graph?type=activity&server=" + serverName);
|
"graph?type=worldPie&server=" + serverName,
|
||||||
exportJSON(toDirectory, "graph?type=geolocation&server=" + serverName);
|
"graph?type=activity&server=" + serverName,
|
||||||
exportJSON(toDirectory, "graph?type=uniqueAndNew&server=" + serverName);
|
"graph?type=geolocation&server=" + serverName,
|
||||||
exportJSON(toDirectory, "graph?type=serverCalendar&server=" + serverName);
|
"graph?type=uniqueAndNew&server=" + serverName,
|
||||||
exportJSON(toDirectory, "graph?type=punchCard&server=" + serverName);
|
"graph?type=serverCalendar&server=" + serverName,
|
||||||
exportJSON(toDirectory, "players?server=" + serverName);
|
"graph?type=punchCard&server=" + serverName,
|
||||||
exportJSON(toDirectory, "kills?server=" + serverName);
|
"players?server=" + serverName,
|
||||||
exportJSON(toDirectory, "pingTable?server=" + serverName);
|
"kills?server=" + serverName,
|
||||||
exportJSON(toDirectory, "sessions?server=" + serverName);
|
"pingTable?server=" + serverName,
|
||||||
|
"sessions?server=" + serverName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportJSON(Path toDirectory, String... resources) throws NotFoundException, IOException {
|
||||||
|
for (String resource : resources) {
|
||||||
|
exportJSON(toDirectory, resource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void exportJSON(Path toDirectory, String resource) throws NotFoundException, IOException {
|
private void exportJSON(Path toDirectory, String resource) throws NotFoundException, IOException {
|
||||||
@ -133,43 +149,51 @@ public class ServerPageExporter extends FileExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void exportRequiredResources(Path toDirectory) throws IOException {
|
private void exportRequiredResources(Path toDirectory) throws IOException {
|
||||||
// Style
|
|
||||||
exportResource(toDirectory, "css/sb-admin-2.css");
|
|
||||||
exportResource(toDirectory, "css/style.css");
|
|
||||||
exportImage(toDirectory, "img/Flaticon_circle.png");
|
exportImage(toDirectory, "img/Flaticon_circle.png");
|
||||||
|
|
||||||
// Plugins
|
// Style
|
||||||
exportResource(toDirectory, "vendor/jquery/jquery.min.js");
|
exportResources(toDirectory,
|
||||||
exportResource(toDirectory, "vendor/bootstrap/js/bootstrap.bundle.min.js");
|
"css/sb-admin-2.css",
|
||||||
exportResource(toDirectory, "vendor/jquery-easing/jquery.easing.min.js");
|
"css/style.css",
|
||||||
exportResource(toDirectory, "vendor/datatables/jquery.dataTables.min.js");
|
"vendor/jquery/jquery.min.js",
|
||||||
exportResource(toDirectory, "vendor/datatables/dataTables.bootstrap4.min.js");
|
"vendor/bootstrap/js/bootstrap.bundle.min.js",
|
||||||
exportResource(toDirectory, "vendor/highcharts/highstock.js");
|
"vendor/jquery-easing/jquery.easing.min.js",
|
||||||
exportResource(toDirectory, "vendor/highcharts/map.js");
|
"vendor/datatables/jquery.dataTables.min.js",
|
||||||
exportResource(toDirectory, "vendor/highcharts/world.js");
|
"vendor/datatables/dataTables.bootstrap4.min.js",
|
||||||
exportResource(toDirectory, "vendor/highcharts/drilldown.js");
|
"vendor/highcharts/highstock.js",
|
||||||
exportResource(toDirectory, "vendor/highcharts/highcharts-more.js");
|
"vendor/highcharts/map.js",
|
||||||
exportResource(toDirectory, "vendor/highcharts/no-data-to-display.js");
|
"vendor/highcharts/world.js",
|
||||||
exportResource(toDirectory, "vendor/fullcalendar/fullcalendar.min.css");
|
"vendor/highcharts/drilldown.js",
|
||||||
exportResource(toDirectory, "vendor/momentjs/moment.js");
|
"vendor/highcharts/highcharts-more.js",
|
||||||
exportResource(toDirectory, "vendor/fullcalendar/fullcalendar.min.js");
|
"vendor/highcharts/no-data-to-display.js",
|
||||||
|
"vendor/fullcalendar/fullcalendar.min.css",
|
||||||
|
"vendor/momentjs/moment.js",
|
||||||
|
"vendor/fullcalendar/fullcalendar.min.js",
|
||||||
|
"js/sb-admin-2.js",
|
||||||
|
"js/xmlhttprequests.js",
|
||||||
|
"js/color-selector.js",
|
||||||
|
"js/sessionAccordion.js",
|
||||||
|
"js/pingTable.js",
|
||||||
|
"js/graphs.js",
|
||||||
|
"js/server-values.js"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Page level plugins
|
private void exportResources(Path toDirectory, String... resourceNames) throws IOException {
|
||||||
exportResource(toDirectory, "js/sb-admin-2.js");
|
for (String resourceName : resourceNames) {
|
||||||
exportResource(toDirectory, "js/xmlhttprequests.js");
|
exportResource(toDirectory, resourceName);
|
||||||
exportResource(toDirectory, "js/color-selector.js");
|
}
|
||||||
|
|
||||||
// Page level scripts
|
|
||||||
exportResource(toDirectory, "js/sessionAccordion.js");
|
|
||||||
exportResource(toDirectory, "js/pingTable.js");
|
|
||||||
exportResource(toDirectory, "js/graphs.js");
|
|
||||||
exportResource(toDirectory, "js/server-values.js");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void exportResource(Path toDirectory, String resourceName) throws IOException {
|
private void exportResource(Path toDirectory, String resourceName) throws IOException {
|
||||||
Resource resource = files.getCustomizableResourceOrDefault("web/" + resourceName);
|
Resource resource = files.getCustomizableResourceOrDefault("web/" + resourceName);
|
||||||
Path to = toDirectory.resolve(resourceName);
|
Path to = toDirectory.resolve(resourceName);
|
||||||
export(to, resource.asLines());
|
|
||||||
|
if (resourceName.endsWith(".css")) {
|
||||||
|
export(to, theme.replaceThemeColors(resource.asString()));
|
||||||
|
} else {
|
||||||
|
export(to, resource.asLines());
|
||||||
|
}
|
||||||
|
|
||||||
exportPaths.put(resourceName, toRelativePathFromRoot(resourceName));
|
exportPaths.put(resourceName, toRelativePathFromRoot(resourceName));
|
||||||
}
|
}
|
||||||
|
@ -16,29 +16,29 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan.delivery.upkeep;
|
package com.djrapitops.plan.delivery.upkeep;
|
||||||
|
|
||||||
import com.djrapitops.plan.delivery.export.HtmlExport;
|
import com.djrapitops.plan.delivery.export.Exporter;
|
||||||
|
import com.djrapitops.plan.exceptions.ExportException;
|
||||||
|
import com.djrapitops.plan.utilities.java.ThrowingConsumer;
|
||||||
import com.djrapitops.plugin.logging.L;
|
import com.djrapitops.plugin.logging.L;
|
||||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||||
import com.djrapitops.plugin.task.AbsRunnable;
|
import com.djrapitops.plugin.task.AbsRunnable;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
public class ExportTask extends AbsRunnable {
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
@Singleton
|
private final Exporter exporter;
|
||||||
public class PeriodicServerExportTask extends AbsRunnable {
|
private final ThrowingConsumer<Exporter, ExportException> exportAction;
|
||||||
|
|
||||||
private final HtmlExport htmlExport;
|
|
||||||
private final PluginLogger logger;
|
private final PluginLogger logger;
|
||||||
private final ErrorHandler errorHandler;
|
private final ErrorHandler errorHandler;
|
||||||
|
|
||||||
@Inject
|
public ExportTask(
|
||||||
public PeriodicServerExportTask(
|
Exporter exporter,
|
||||||
HtmlExport htmlExport,
|
ThrowingConsumer<Exporter, ExportException> exportAction,
|
||||||
PluginLogger logger,
|
PluginLogger logger,
|
||||||
ErrorHandler errorHandler
|
ErrorHandler errorHandler
|
||||||
) {
|
) {
|
||||||
this.htmlExport = htmlExport;
|
this.exporter = exporter;
|
||||||
|
this.exportAction = exportAction;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.errorHandler = errorHandler;
|
this.errorHandler = errorHandler;
|
||||||
}
|
}
|
||||||
@ -46,11 +46,11 @@ public class PeriodicServerExportTask extends AbsRunnable {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
htmlExport.exportAvailableServerPages();
|
exportAction.accept(exporter);
|
||||||
} catch (IllegalStateException ignore) {
|
} catch (ExportException e) {
|
||||||
/* Plugin was reloading */
|
errorHandler.log(L.WARN, this.getClass(), e);
|
||||||
} catch (Exception | NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) {
|
} catch (Exception | NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) {
|
||||||
logger.error("Periodic Analysis Task Disabled due to error, reload Plan to re-enable.");
|
logger.error("Export Task Disabled due to error, reload Plan to re-enable.");
|
||||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||||
cancel();
|
cancel();
|
||||||
}
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Player Analytics (Plan).
|
||||||
|
*
|
||||||
|
* Plan is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Plan is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.djrapitops.plan.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown by {@link com.djrapitops.plan.delivery.export.Exporter} if something goes wrong with export.
|
||||||
|
*
|
||||||
|
* @author Rsl1122
|
||||||
|
*/
|
||||||
|
public class ExportException extends Exception {
|
||||||
|
|
||||||
|
public ExportException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExportException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Player Analytics (Plan).
|
||||||
|
*
|
||||||
|
* Plan is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Plan is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.djrapitops.plan.utilities.java;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional interface that performs an operation that might throw an exception.
|
||||||
|
* <p>
|
||||||
|
* Follows naming scheme of Java 8 functional interfaces.
|
||||||
|
*
|
||||||
|
* @author Rsl1122
|
||||||
|
*/
|
||||||
|
public interface ThrowingConsumer<T, K extends Throwable> {
|
||||||
|
|
||||||
|
void accept(T consume) throws K;
|
||||||
|
|
||||||
|
}
|
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan;
|
package com.djrapitops.plan;
|
||||||
|
|
||||||
import com.djrapitops.plan.delivery.upkeep.PeriodicServerExportTask;
|
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
|
import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
|
||||||
import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask;
|
import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask;
|
||||||
import com.djrapitops.plan.gathering.ShutdownHook;
|
import com.djrapitops.plan.gathering.ShutdownHook;
|
||||||
@ -24,7 +23,6 @@ import com.djrapitops.plan.gathering.timed.SpongePingCounter;
|
|||||||
import com.djrapitops.plan.gathering.timed.SpongeTPSCounter;
|
import com.djrapitops.plan.gathering.timed.SpongeTPSCounter;
|
||||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||||
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
||||||
import com.djrapitops.plan.settings.config.paths.ExportSettings;
|
|
||||||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||||
import com.djrapitops.plan.settings.upkeep.ConfigStoreTask;
|
import com.djrapitops.plan.settings.upkeep.ConfigStoreTask;
|
||||||
import com.djrapitops.plan.storage.upkeep.DBCleanTask;
|
import com.djrapitops.plan.storage.upkeep.DBCleanTask;
|
||||||
@ -46,7 +44,6 @@ public class SpongeTaskSystem extends TaskSystem {
|
|||||||
private final ShutdownHook shutdownHook;
|
private final ShutdownHook shutdownHook;
|
||||||
private final SpongeTPSCounter tpsCounter;
|
private final SpongeTPSCounter tpsCounter;
|
||||||
private final JSONCache.CleanTask jsonCacheCleanTask;
|
private final JSONCache.CleanTask jsonCacheCleanTask;
|
||||||
private final PeriodicServerExportTask periodicServerExportTask;
|
|
||||||
private final SpongePingCounter pingCounter;
|
private final SpongePingCounter pingCounter;
|
||||||
private final LogsFolderCleanTask logsFolderCleanTask;
|
private final LogsFolderCleanTask logsFolderCleanTask;
|
||||||
private final ConfigStoreTask configStoreTask;
|
private final ConfigStoreTask configStoreTask;
|
||||||
@ -67,9 +64,7 @@ public class SpongeTaskSystem extends TaskSystem {
|
|||||||
LogsFolderCleanTask logsFolderCleanTask,
|
LogsFolderCleanTask logsFolderCleanTask,
|
||||||
ConfigStoreTask configStoreTask,
|
ConfigStoreTask configStoreTask,
|
||||||
DBCleanTask dbCleanTask,
|
DBCleanTask dbCleanTask,
|
||||||
JSONCache.CleanTask jsonCacheCleanTask,
|
JSONCache.CleanTask jsonCacheCleanTask
|
||||||
|
|
||||||
PeriodicServerExportTask periodicServerExportTask
|
|
||||||
) {
|
) {
|
||||||
super(runnableFactory);
|
super(runnableFactory);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@ -85,7 +80,6 @@ public class SpongeTaskSystem extends TaskSystem {
|
|||||||
this.dbCleanTask = dbCleanTask;
|
this.dbCleanTask = dbCleanTask;
|
||||||
this.jsonCacheCleanTask = jsonCacheCleanTask;
|
this.jsonCacheCleanTask = jsonCacheCleanTask;
|
||||||
|
|
||||||
this.periodicServerExportTask = periodicServerExportTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -109,10 +103,6 @@ public class SpongeTaskSystem extends TaskSystem {
|
|||||||
);
|
);
|
||||||
long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES);
|
long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES);
|
||||||
registerTask(jsonCacheCleanTask).runTaskTimerAsynchronously(minute, minute);
|
registerTask(jsonCacheCleanTask).runTaskTimerAsynchronously(minute, minute);
|
||||||
|
|
||||||
if (config.get(ExportSettings.SERVER_PAGE)) {
|
|
||||||
registerTask(periodicServerExportTask).runTaskTimerAsynchronously(TimeAmount.toTicks(30L, TimeUnit.SECONDS), TimeAmount.toTicks(20L, TimeUnit.MINUTES));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerTPSCounter() {
|
private void registerTPSCounter() {
|
||||||
|
Loading…
Reference in New Issue
Block a user