Removed proxy<->server connections:

Removed InfoSystem
- Removed /plan m setup
- Removed /planbungee setup
- Removed /planbungee con
- Removed /plan m con
- Removed all InfoRequests
- Removed /info web endpoint
- Removed ConnectionLog

Removed two config settings:
- Display of session accordion as table
  (Accordion is table now)
- Display of most played world on sessions
  (Always displayed now)

Removed html generation java code for player page
tables

Deprecated PlayerDeath related things

Removed AnalysisContainer data, and
server HealthInformation

Affects issues:
- Close #840
This commit is contained in:
Rsl1122 2019-07-24 16:29:14 +03:00
parent d7f5e18de3
commit 22a5348e33
77 changed files with 239 additions and 4617 deletions

View File

@ -17,23 +17,21 @@
package com.djrapitops.plan; package com.djrapitops.plan;
import com.djrapitops.plan.db.Database; import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.system.info.connection.ConnectionSystem; import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import org.bstats.bungeecord.Metrics; import org.bstats.bungeecord.Metrics;
import java.io.Serializable; import java.util.function.Supplier;
public class BStatsBungee { public class BStatsBungee {
private final PlanBungee plugin; private final PlanBungee plugin;
private final Database database; private final Database database;
private final ConnectionSystem connectionSystem;
private Metrics metrics; private Metrics metrics;
public BStatsBungee(PlanBungee plugin, Database database, ConnectionSystem connectionSystem) { public BStatsBungee(PlanBungee plugin, Database database) {
this.plugin = plugin; this.plugin = plugin;
this.database = database; this.database = database;
this.connectionSystem = connectionSystem;
} }
public void registerMetrics() { public void registerMetrics() {
@ -44,15 +42,12 @@ public class BStatsBungee {
} }
private void registerConfigSettingGraphs() { private void registerConfigSettingGraphs() {
String serverType = plugin.getProxy().getName(); addStringSettingPie("server_type", () -> plugin.getProxy().getName());
String databaseType = database.getType().getName(); addStringSettingPie("database_type", () -> database.getType().getName());
addStringSettingPie("network_servers", () -> String.valueOf(database.query(ServerQueries.fetchPlanServerInformationCollection()).size()));
addStringSettingPie("server_type", serverType);
addStringSettingPie("database_type", databaseType);
addStringSettingPie("network_servers", connectionSystem.getDataServers().size());
} }
protected void addStringSettingPie(String id, Serializable setting) { protected void addStringSettingPie(String id, Supplier<String> setting) {
metrics.addCustomChart(new Metrics.SimplePie(id, setting::toString)); metrics.addCustomChart(new Metrics.SimplePie(id, setting::get));
} }
} }

View File

@ -48,8 +48,7 @@ public class PlanBungee extends BungeePlugin implements PlanPlugin {
new BStatsBungee( new BStatsBungee(
this, this,
system.getDatabaseSystem().getDatabase(), system.getDatabaseSystem().getDatabase()
system.getInfoSystem().getConnectionSystem()
).registerMetrics(); ).registerMetrics();
logger.info(locale.getString(PluginLang.ENABLED)); logger.info(locale.getString(PluginLang.ENABLED));

View File

@ -1,31 +0,0 @@
/*
* 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.api.exceptions.connection;
import com.djrapitops.plan.system.webserver.response.ResponseCode;
/**
* Thrown when InfoRequest can not connect to the other server.
*
* @author Rsl1122
*/
public class GatewayException extends WebException {
public GatewayException(String message) {
super(message, ResponseCode.GATEWAY_ERROR);
}
}

View File

@ -1,31 +0,0 @@
/*
* 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.api.exceptions.connection;
import com.djrapitops.plan.system.info.request.InfoRequest;
/**
* Thrown when {@link com.djrapitops.plan.api.exceptions.database.DBOpException} occurs during {@link InfoRequest#runLocally()}.
*
* @author Rsl1122
*/
public class TransferDatabaseException extends WebException {
public TransferDatabaseException(Exception cause) {
super(cause);
}
}

View File

@ -1,39 +0,0 @@
/*
* 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.api.exceptions.connection;
import com.djrapitops.plan.system.webserver.response.ResponseCode;
/**
* Thrown when Connection gets a 412 response due to ServerUUID not being in the database.
*
* @author Rsl1122
*/
public class UnauthorizedServerException extends WebFailException {
public UnauthorizedServerException(String message) {
super(message, ResponseCode.PRECONDITION_FAILED);
}
public UnauthorizedServerException(String message, Throwable cause) {
super(message, cause, ResponseCode.PRECONDITION_FAILED);
}
public UnauthorizedServerException(Throwable cause) {
super(cause, ResponseCode.PRECONDITION_FAILED);
}
}

View File

@ -17,7 +17,6 @@
package com.djrapitops.plan.command; package com.djrapitops.plan.command;
import com.djrapitops.plan.command.commands.*; import com.djrapitops.plan.command.commands.*;
import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
import com.djrapitops.plan.command.commands.manage.ManageRawDataCommand; import com.djrapitops.plan.command.commands.manage.ManageRawDataCommand;
import com.djrapitops.plan.command.commands.manage.ManageUninstalledCommand; import com.djrapitops.plan.command.commands.manage.ManageUninstalledCommand;
import com.djrapitops.plan.system.locale.Locale; import com.djrapitops.plan.system.locale.Locale;
@ -48,9 +47,7 @@ public class PlanProxyCommand extends TreeCmdNode {
private final ListPlayersCommand listPlayersCommand; private final ListPlayersCommand listPlayersCommand;
private final RegisterCommand registerCommand; private final RegisterCommand registerCommand;
private final Lazy<WebUserCommand> webUserCommand; private final Lazy<WebUserCommand> webUserCommand;
private final ManageConDebugCommand conDebugCommand;
private final ManageRawDataCommand rawDataCommand; private final ManageRawDataCommand rawDataCommand;
private final BungeeSetupToggleCommand setupToggleCommand;
private final ReloadCommand reloadCommand; private final ReloadCommand reloadCommand;
private final DisableCommand disableCommand; private final DisableCommand disableCommand;
private final ManageUninstalledCommand uninstalledCommand; private final ManageUninstalledCommand uninstalledCommand;
@ -70,9 +67,7 @@ public class PlanProxyCommand extends TreeCmdNode {
RegisterCommand registerCommand, RegisterCommand registerCommand,
Lazy<WebUserCommand> webUserCommand, Lazy<WebUserCommand> webUserCommand,
// Group 3 // Group 3
ManageConDebugCommand conDebugCommand,
ManageRawDataCommand rawDataCommand, ManageRawDataCommand rawDataCommand,
BungeeSetupToggleCommand setupToggleCommand,
ManageUninstalledCommand uninstalledCommand, ManageUninstalledCommand uninstalledCommand,
ReloadCommand reloadCommand, ReloadCommand reloadCommand,
DisableCommand disableCommand DisableCommand disableCommand
@ -87,9 +82,7 @@ public class PlanProxyCommand extends TreeCmdNode {
this.listPlayersCommand = listPlayersCommand; this.listPlayersCommand = listPlayersCommand;
this.registerCommand = registerCommand; this.registerCommand = registerCommand;
this.webUserCommand = webUserCommand; this.webUserCommand = webUserCommand;
this.conDebugCommand = conDebugCommand;
this.rawDataCommand = rawDataCommand; this.rawDataCommand = rawDataCommand;
this.setupToggleCommand = setupToggleCommand;
this.reloadCommand = reloadCommand; this.reloadCommand = reloadCommand;
this.disableCommand = disableCommand; this.disableCommand = disableCommand;
@ -113,9 +106,7 @@ public class PlanProxyCommand extends TreeCmdNode {
webUserCommand.get() webUserCommand.get()
}; };
CommandNode[] manageGroup = { CommandNode[] manageGroup = {
conDebugCommand,
rawDataCommand, rawDataCommand,
setupToggleCommand,
uninstalledCommand, uninstalledCommand,
reloadCommand, reloadCommand,
disableCommand disableCommand

View File

@ -1,65 +0,0 @@
/*
* 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.command.commands;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.locale.Locale;
import com.djrapitops.plan.system.locale.lang.CmdHelpLang;
import com.djrapitops.plan.system.locale.lang.CommandLang;
import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
import com.djrapitops.plan.system.settings.Permissions;
import com.djrapitops.plugin.command.CommandNode;
import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.Sender;
import javax.inject.Inject;
/**
* Command for Toggling whether or not BungeeCord accepts set up requests.
* <p>
* This was added as a security measure against unwanted MySQL snooping.
*
* @author Rsl1122
*/
public class BungeeSetupToggleCommand extends CommandNode {
private final Locale locale;
private final ConnectionSystem connectionSystem;
@Inject
public BungeeSetupToggleCommand(Locale locale, ConnectionSystem connectionSystem) {
super("setup", Permissions.MANAGE.getPermission(), CommandType.ALL);
this.locale = locale;
this.connectionSystem = connectionSystem;
setShortHelp(locale.getString(CmdHelpLang.SETUP));
setInDepthHelp(locale.getArray(DeepHelpLang.SETUP));
}
@Override
public void onCommand(Sender sender, String s, String[] strings) {
if (connectionSystem.isSetupAllowed()) {
connectionSystem.setSetupAllowed(false);
} else {
connectionSystem.setSetupAllowed(true);
}
String msg = locale.getString(connectionSystem.isSetupAllowed() ? CommandLang.SETUP_ALLOWED : CommandLang.SETUP_FORBIDDEN);
sender.sendMessage(msg);
}
}

View File

@ -117,7 +117,7 @@ public class InspectCommand extends CommandNode {
} }
checkWebUserAndNotify(sender); checkWebUserAndNotify(sender);
processing.submit(processorFactory.inspectCacheRequestProcessor(playerUUID, sender, playerName, this::sendInspectMsg)); this.sendInspectMsg(sender, playerName);
} catch (DBOpException e) { } catch (DBOpException e) {
sender.sendMessage("§eDatabase exception occurred: " + e.getMessage()); sender.sendMessage("§eDatabase exception occurred: " + e.getMessage());
errorHandler.log(L.ERROR, this.getClass(), e); errorHandler.log(L.ERROR, this.getClass(), e);

View File

@ -48,8 +48,6 @@ public class ManageCommand extends TreeCmdNode {
ManageHotSwapCommand hotSwapCommand, ManageHotSwapCommand hotSwapCommand,
ManageClearCommand clearCommand, ManageClearCommand clearCommand,
// Group 2 // Group 2
ManageSetupCommand setupCommand,
ManageConDebugCommand conDebugCommand,
ManageImportCommand importCommand, ManageImportCommand importCommand,
ManageExportCommand exportCommand, ManageExportCommand exportCommand,
ManageDisableCommand disableCommand, ManageDisableCommand disableCommand,
@ -70,8 +68,6 @@ public class ManageCommand extends TreeCmdNode {
clearCommand, clearCommand,
}; };
CommandNode[] pluginGroup = { CommandNode[] pluginGroup = {
setupCommand,
conDebugCommand,
importCommand, importCommand,
exportCommand, exportCommand,
disableCommand, disableCommand,

View File

@ -1,161 +0,0 @@
/*
* 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.command.commands.manage;
import com.djrapitops.plan.api.exceptions.connection.*;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.request.InfoRequestFactory;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.locale.Locale;
import com.djrapitops.plan.system.locale.lang.CmdHelpLang;
import com.djrapitops.plan.system.locale.lang.CommandLang;
import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
import com.djrapitops.plan.system.locale.lang.ManageLang;
import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.settings.Permissions;
import com.djrapitops.plan.system.webserver.WebServer;
import com.djrapitops.plugin.command.ColorScheme;
import com.djrapitops.plugin.command.CommandNode;
import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.Sender;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Map;
import java.util.UUID;
/**
* This manage SubCommand is used to request settings from Bungee so that connection can be established.
*
* @author Rsl1122
*/
@Singleton
public class ManageConDebugCommand extends CommandNode {
private final ColorScheme colorScheme;
private final Locale locale;
private final Processing processing;
private final ServerInfo serverInfo;
private final ConnectionSystem connectionSystem;
private final InfoRequestFactory infoRequestFactory;
private final WebServer webServer;
private final DBSystem dbSystem;
@Inject
public ManageConDebugCommand(
ColorScheme colorScheme,
Locale locale,
Processing processing,
ServerInfo serverInfo,
ConnectionSystem connectionSystem,
InfoRequestFactory infoRequestFactory,
WebServer webServer,
DBSystem dbSystem
) {
super("con", Permissions.MANAGE.getPermission(), CommandType.ALL);
this.colorScheme = colorScheme;
this.locale = locale;
this.processing = processing;
this.serverInfo = serverInfo;
this.connectionSystem = connectionSystem;
this.infoRequestFactory = infoRequestFactory;
this.webServer = webServer;
this.dbSystem = dbSystem;
boolean isProxy = serverInfo.getServer() != null && serverInfo.getServer().isProxy();
setShortHelp(locale.getString(isProxy ? CmdHelpLang.CON : CmdHelpLang.MANAGE_CON));
setInDepthHelp(locale.getArray(DeepHelpLang.MANAGE_CON));
}
private void testServer(Sender sender, Server server, Locale locale) {
String address = server.getWebAddress().toLowerCase();
boolean usingHttps = address.startsWith("https");
boolean local = address.contains("localhost")
|| address.startsWith("https://:") // IP empty = Localhost
|| address.startsWith("http://:") // IP empty = Localhost
|| address.contains("127.0.0.1");
try {
connectionSystem.sendInfoRequest(infoRequestFactory.checkConnectionRequest(address), server);
sender.sendMessage(getMsgFor(address, usingHttps, local, true, true));
} catch (UnauthorizedServerException e) {
sender.sendMessage(getMsgFor(address, usingHttps, local, true, false));
sender.sendMessage(locale.getString(ManageLang.CON_UNAUTHORIZED));
} catch (ConnectionFailException e) {
sender.sendMessage(getMsgFor(address, usingHttps, local, false, false));
sender.sendMessage(locale.getString(ManageLang.CON_GENERIC_FAIL) + e.getCause().getClass().getSimpleName() + " " + e.getCause().getMessage());
if (!local) {
sender.sendMessage(locale.getString(ManageLang.CON_EXTERNAL_URL));
}
} catch (GatewayException e) {
sender.sendMessage(getMsgFor(address, usingHttps, local, true, false));
} catch (NotFoundException e) {
sender.sendMessage(getMsgFor(address, usingHttps, local, false, false));
sender.sendMessage(locale.getString(ManageLang.CON_OLD_VERSION));
} catch (WebException e) {
sender.sendMessage(getMsgFor(address, usingHttps, local, false, false));
sender.sendMessage(locale.getString(ManageLang.CON_EXCEPTION, e.getClass().getSimpleName()));
}
}
@Override
public void onCommand(Sender sender, String commandLabel, String[] args) {
if (!webServer.isEnabled()) {
sender.sendMessage(locale.getString(CommandLang.CONNECT_WEBSERVER_NOT_ENABLED));
return;
}
Database.State dbState = dbSystem.getDatabase().getState();
if (dbState != Database.State.OPEN) {
sender.sendMessage(locale.getString(CommandLang.FAIL_DATABASE_NOT_OPEN, dbState.name()));
return;
}
processing.submitNonCritical(() -> testServers(sender));
}
private void testServers(Sender sender) {
Map<UUID, Server> servers = dbSystem.getDatabase().query(ServerQueries.fetchPlanServerInformation());
if (servers.isEmpty()) {
sender.sendMessage(locale.getString(ManageLang.CON_NO_SERVERS));
}
UUID thisServer = serverInfo.getServerUUID();
for (Server server : servers.values()) {
if (thisServer.equals(server.getUuid())) {
continue;
}
testServer(sender, server, locale);
}
}
private String getMsgFor(String address, boolean usingHttps, boolean local, boolean successTo, boolean successFrom) {
String tCol = colorScheme.getTertiaryColor();
String sCol = colorScheme.getSecondaryColor();
return tCol + address + sCol + ": "
+ (usingHttps ? "HTTPS" : "HTTP") + " : "
+ (local ? "Local" : "External") + " : "
+ "To:" + (successTo ? "§aOK" : "§cFail") + sCol + " : "
+ "From:" + (successFrom ? "§aOK" : "§cFail");
}
}

View File

@ -1,126 +0,0 @@
/*
* 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.command.commands.manage;
import com.djrapitops.plan.api.exceptions.connection.*;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.locale.Locale;
import com.djrapitops.plan.system.locale.lang.CmdHelpLang;
import com.djrapitops.plan.system.locale.lang.CommandLang;
import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.settings.Permissions;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.PluginSettings;
import com.djrapitops.plan.system.webserver.WebServer;
import com.djrapitops.plugin.command.CommandNode;
import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.Sender;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.error.ErrorHandler;
import com.djrapitops.plugin.utilities.Verify;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Arrays;
/**
* This manage SubCommand is used to request settings from Bungee so that connection can be established.
*
* @author Rsl1122
*/
@Singleton
public class ManageSetupCommand extends CommandNode {
private final Locale locale;
private final PlanConfig config;
private final Processing processing;
private final InfoSystem infoSystem;
private final WebServer webServer;
private final ErrorHandler errorHandler;
@Inject
public ManageSetupCommand(
Locale locale,
PlanConfig config,
Processing processing,
InfoSystem infoSystem,
WebServer webServer,
ErrorHandler errorHandler
) {
super("setup", Permissions.MANAGE.getPermission(), CommandType.PLAYER_OR_ARGS);
this.locale = locale;
this.config = config;
this.processing = processing;
this.infoSystem = infoSystem;
this.webServer = webServer;
this.errorHandler = errorHandler;
setArguments("<BungeeAddress>");
setShortHelp(locale.getString(CmdHelpLang.MANAGE_SETUP));
setInDepthHelp(locale.getArray(DeepHelpLang.MANAGE_SETUP));
}
@Override
public void onCommand(Sender sender, String commandLabel, String[] args) {
Verify.isTrue(args.length >= 1,
() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ONE_ARG, Arrays.toString(this.getArguments()))));
if (!webServer.isEnabled()) {
sender.sendMessage(locale.getString(CommandLang.CONNECT_WEBSERVER_NOT_ENABLED));
return;
}
String address = args[0].toLowerCase();
if (!address.startsWith("http") || address.endsWith("://")) {
sender.sendMessage(locale.getString(CommandLang.CONNECT_URL_MISTAKE));
return;
}
if (address.endsWith("/")) {
address = address.substring(0, address.length() - 1);
}
requestSetup(sender, address);
}
private void requestSetup(Sender sender, String address) {
processing.submitNonCritical(() -> {
try {
config.set(PluginSettings.BUNGEE_COPY_CONFIG, true);
infoSystem.requestSetUp(address);
sender.sendMessage(locale.getString(CommandLang.CONNECT_SUCCESS));
} catch (ForbiddenException e) {
sender.sendMessage(locale.getString(CommandLang.CONNECT_FORBIDDEN));
} catch (BadRequestException e) {
sender.sendMessage(locale.getString(CommandLang.CONNECT_BAD_REQUEST));
} catch (UnauthorizedServerException e) {
sender.sendMessage(locale.getString(CommandLang.CONNECT_UNAUTHORIZED));
} catch (ConnectionFailException e) {
sender.sendMessage(locale.getString(CommandLang.CONNECT_FAIL, e.getMessage()));
} catch (InternalErrorException e) {
sender.sendMessage(locale.getString(CommandLang.CONNECT_INTERNAL_ERROR, e.getMessage()));
} catch (GatewayException e) {
sender.sendMessage(locale.getString(CommandLang.CONNECT_GATEWAY));
} catch (WebException e) {
errorHandler.log(L.WARN, this.getClass(), e);
sender.sendMessage(locale.getString(CommandLang.CONNECT_FAIL, e.toString()));
}
});
}
}

View File

@ -20,6 +20,10 @@ import com.djrapitops.plan.data.store.objects.DateHolder;
import java.util.UUID; import java.util.UUID;
/**
* @deprecated Use {@link PlayerKill} instead.
*/
@Deprecated
public class PlayerDeath implements DateHolder { public class PlayerDeath implements DateHolder {
private final UUID killer; private final UUID killer;

View File

@ -46,7 +46,7 @@ public abstract class PluginData {
private String helpText; private String helpText;
protected com.djrapitops.plan.data.store.containers.AnalysisContainer analysisData; protected com.djrapitops.plan.data.store.containers.AnalysisContainer analysisData = new com.djrapitops.plan.data.store.containers.AnalysisContainer();
public PluginData(ContainerSize size, String sourcePlugin) { public PluginData(ContainerSize size, String sourcePlugin) {
this.size = size; this.size = size;

View File

@ -16,545 +16,16 @@
*/ */
package com.djrapitops.plan.data.store.containers; package com.djrapitops.plan.data.store.containers;
import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.Type;
import com.djrapitops.plan.data.store.keys.AnalysisKeys;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.keys.ServerKeys;
import com.djrapitops.plan.data.store.mutators.*;
import com.djrapitops.plan.data.store.mutators.health.HealthInformation;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.system.info.server.properties.ServerProperties;
import com.djrapitops.plan.system.locale.Locale;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.DisplaySettings;
import com.djrapitops.plan.system.settings.paths.TimeSettings;
import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.utilities.formatting.Formatters;
import com.djrapitops.plan.utilities.html.graphs.Graphs;
import com.djrapitops.plan.utilities.html.graphs.bar.BarGraph;
import com.djrapitops.plan.utilities.html.graphs.line.PingGraph;
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
import com.djrapitops.plan.utilities.html.graphs.stack.StackGraph;
import com.djrapitops.plan.utilities.html.pages.AnalysisPluginTabs;
import com.djrapitops.plan.utilities.html.structure.Accordions;
import com.djrapitops.plan.utilities.html.structure.AnalysisPluginsTabContentCreator;
import com.djrapitops.plan.utilities.html.structure.RecentLoginList;
import com.djrapitops.plan.utilities.html.structure.SessionAccordion;
import com.djrapitops.plan.utilities.html.tables.HtmlTables;
import com.djrapitops.plugin.api.TimeAmount;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/** /**
* Container used for analysis. * Container used for analysis.
* *
* @author Rsl1122 * @author Rsl1122
* @see com.djrapitops.plan.data.store.keys.AnalysisKeys for Key objects * @see com.djrapitops.plan.data.store.keys.AnalysisKeys for Key objects
* @see com.djrapitops.plan.data.store.PlaceholderKey for placeholder information * @see com.djrapitops.plan.data.store.PlaceholderKey for placeholder information
* @deprecated AnalysisContainer is no longer used.
*/ */
@Deprecated
public class AnalysisContainer extends DynamicDataContainer { public class AnalysisContainer extends DynamicDataContainer {
public AnalysisContainer() {
private final ServerContainer serverContainer;
private final String version;
private final Locale locale;
private final PlanConfig config;
private final Theme theme;
private final ServerProperties serverProperties;
private final Formatters formatters;
private final Graphs graphs;
private final HtmlTables tables;
private final Accordions accordions;
private final AnalysisPluginsTabContentCreator pluginsTabContentCreator;
private TimeZone timeZone;
public AnalysisContainer(
ServerContainer serverContainer,
String version,
Locale locale,
PlanConfig config,
Theme theme,
ServerProperties serverProperties,
Formatters formatters,
Graphs graphs,
HtmlTables tables,
Accordions accordions,
AnalysisPluginsTabContentCreator pluginsTabContentCreator
) {
this.serverContainer = serverContainer;
this.version = version;
this.locale = locale;
this.config = config;
this.theme = theme;
this.serverProperties = serverProperties;
this.formatters = formatters;
this.graphs = graphs;
this.tables = tables;
this.accordions = accordions;
this.pluginsTabContentCreator = pluginsTabContentCreator;
timeZone = config.get(TimeSettings.USE_SERVER_TIME) ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT");
addAnalysisSuppliers();
}
public ServerContainer getServerContainer() {
return serverContainer;
}
private void addAnalysisSuppliers() {
putCachingSupplier(AnalysisKeys.SESSIONS_MUTATOR, () -> SessionsMutator.forContainer(serverContainer));
putCachingSupplier(AnalysisKeys.TPS_MUTATOR, () -> TPSMutator.forContainer(serverContainer));
putCachingSupplier(AnalysisKeys.PLAYERS_MUTATOR, () -> PlayersMutator.forContainer(serverContainer));
addConstants();
addPlayerSuppliers();
addSessionSuppliers();
addGraphSuppliers();
addTPSAverageSuppliers();
addCommandSuppliers();
addServerHealth();
addPluginSuppliers();
}
private void addConstants() {
long now = System.currentTimeMillis();
putRawData(AnalysisKeys.ANALYSIS_TIME, now);
putRawData(AnalysisKeys.ANALYSIS_TIME_DAY_AGO, now - TimeUnit.DAYS.toMillis(1L));
putRawData(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO, now - TimeAmount.WEEK.toMillis(1L));
putRawData(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO, now - TimeAmount.MONTH.toMillis(1L));
putSupplier(AnalysisKeys.REFRESH_TIME_F, () -> formatters.clockLong().apply(getUnsafe(AnalysisKeys.ANALYSIS_TIME)));
putSupplier(AnalysisKeys.REFRESH_TIME_FULL_F, () -> formatters.secondLong().apply(getUnsafe(AnalysisKeys.ANALYSIS_TIME)));
putRawData(AnalysisKeys.VERSION, version);
putSupplier(AnalysisKeys.TIME_ZONE, config::getTimeZoneOffsetHours);
putRawData(AnalysisKeys.FIRST_DAY, 1);
putRawData(AnalysisKeys.TPS_MEDIUM, config.get(DisplaySettings.GRAPH_TPS_THRESHOLD_MED));
putRawData(AnalysisKeys.TPS_HIGH, config.get(DisplaySettings.GRAPH_TPS_THRESHOLD_HIGH));
putRawData(AnalysisKeys.DISK_MEDIUM, config.get(DisplaySettings.GRAPH_DISK_THRESHOLD_MED));
putRawData(AnalysisKeys.DISK_HIGH, config.get(DisplaySettings.GRAPH_DISK_THRESHOLD_HIGH));
addServerProperties();
addThemeColors();
}
private void addServerProperties() {
putCachingSupplier(AnalysisKeys.SERVER_NAME, () -> serverContainer.getValue(ServerKeys.NAME).orElse("Plan"));
putRawData(AnalysisKeys.PLAYERS_MAX, serverProperties.getMaxPlayers());
putRawData(AnalysisKeys.PLAYERS_ONLINE, serverProperties.getOnlinePlayers());
}
private void addThemeColors() {
putRawData(AnalysisKeys.ACTIVITY_PIE_COLORS, theme.getValue(ThemeVal.GRAPH_ACTIVITY_PIE));
putRawData(AnalysisKeys.GM_PIE_COLORS, theme.getValue(ThemeVal.GRAPH_GM_PIE));
putRawData(AnalysisKeys.PLAYERS_GRAPH_COLOR, theme.getValue(ThemeVal.GRAPH_PLAYERS_ONLINE));
putRawData(AnalysisKeys.TPS_LOW_COLOR, theme.getValue(ThemeVal.GRAPH_TPS_LOW));
putRawData(AnalysisKeys.TPS_MEDIUM_COLOR, theme.getValue(ThemeVal.GRAPH_TPS_MED));
putRawData(AnalysisKeys.TPS_HIGH_COLOR, theme.getValue(ThemeVal.GRAPH_TPS_HIGH));
putRawData(AnalysisKeys.WORLD_MAP_LOW_COLOR, theme.getValue(ThemeVal.WORLD_MAP_LOW));
putRawData(AnalysisKeys.WORLD_MAP_HIGH_COLOR, theme.getValue(ThemeVal.WORLD_MAP_HIGH));
putRawData(AnalysisKeys.WORLD_PIE_COLORS, theme.getValue(ThemeVal.GRAPH_WORLD_PIE));
putRawData(AnalysisKeys.AVG_PING_COLOR, theme.getValue(ThemeVal.GRAPH_AVG_PING));
putRawData(AnalysisKeys.MAX_PING_COLOR, theme.getValue(ThemeVal.GRAPH_MAX_PING));
putRawData(AnalysisKeys.MIN_PING_COLOR, theme.getValue(ThemeVal.GRAPH_MIN_PING));
}
private void addPlayerSuppliers() {
putCachingSupplier(AnalysisKeys.PLAYER_NAMES, () -> serverContainer.getValue(ServerKeys.PLAYERS).orElse(new ArrayList<>())
.stream().collect(Collectors.toMap(
p -> p.getUnsafe(PlayerKeys.UUID), p -> p.getValue(PlayerKeys.NAME).orElse("?"))
)
);
putSupplier(AnalysisKeys.PLAYERS_TOTAL, () -> serverContainer.getValue(ServerKeys.PLAYER_COUNT).orElse(0));
putSupplier(AnalysisKeys.PLAYERS_LAST_PEAK, () ->
serverContainer.getValue(ServerKeys.RECENT_PEAK_PLAYERS)
.map(dateObj -> Integer.toString(dateObj.getValue())).orElse("-")
);
putSupplier(AnalysisKeys.PLAYERS_ALL_TIME_PEAK, () ->
serverContainer.getValue(ServerKeys.ALL_TIME_PEAK_PLAYERS)
.map(dateObj -> Integer.toString(dateObj.getValue())).orElse("-")
);
putSupplier(AnalysisKeys.LAST_PEAK_TIME_F, () ->
serverContainer.getValue(ServerKeys.RECENT_PEAK_PLAYERS)
.map(dateObj -> formatters.year().apply(dateObj)).orElse("-")
);
putSupplier(AnalysisKeys.ALL_TIME_PEAK_TIME_F, () ->
serverContainer.getValue(ServerKeys.ALL_TIME_PEAK_PLAYERS)
.map(dateObj -> formatters.year().apply(dateObj)).orElse("-")
);
putSupplier(AnalysisKeys.OPERATORS, () -> serverContainer.getValue(ServerKeys.OPERATORS).map(List::size).orElse(0));
putSupplier(AnalysisKeys.PLAYERS_TABLE, () ->
tables.playerTableForServerPage(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).all()).parseHtml()
);
putSupplier(AnalysisKeys.PING_TABLE, () ->
tables.pingTable(
getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.getPingPerCountry(serverContainer.getUnsafe(ServerKeys.SERVER_UUID))
).parseHtml()
);
newAndUniquePlayerCounts();
}
private void newAndUniquePlayerCounts() {
Key<PlayersMutator> newDay = new Key<>(PlayersMutator.class, "NEW_DAY");
Key<PlayersMutator> newWeek = new Key<>(PlayersMutator.class, "NEW_WEEK");
Key<PlayersMutator> newMonth = new Key<>(PlayersMutator.class, "NEW_MONTH");
Key<PlayersMutator> uniqueDay = new Key<>(PlayersMutator.class, "UNIQUE_DAY");
Key<PlayersMutator> uniqueWeek = new Key<>(PlayersMutator.class, "UNIQUE_WEEK");
Key<PlayersMutator> uniqueMonth = new Key<>(PlayersMutator.class, "UNIQUE_MONTH");
putCachingSupplier(newDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(newWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(newMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(uniqueDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(uniqueWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(uniqueMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putSupplier(AnalysisKeys.PLAYERS_NEW_DAY, () -> getUnsafe(newDay).count());
putSupplier(AnalysisKeys.PLAYERS_NEW_WEEK, () -> getUnsafe(newWeek).count());
putSupplier(AnalysisKeys.PLAYERS_NEW_MONTH, () -> getUnsafe(newMonth).count());
putSupplier(AnalysisKeys.PLAYERS_DAY, () -> getUnsafe(uniqueDay).count());
putSupplier(AnalysisKeys.PLAYERS_WEEK, () -> getUnsafe(uniqueWeek).count());
putSupplier(AnalysisKeys.PLAYERS_MONTH, () -> getUnsafe(uniqueMonth).count());
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).averageNewPerDay(timeZone));
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_DAY, () -> getUnsafe(newDay).averageNewPerDay(timeZone));
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_WEEK, () -> getUnsafe(newWeek).averageNewPerDay(timeZone));
putSupplier(AnalysisKeys.AVG_PLAYERS_NEW_MONTH, () -> getUnsafe(newMonth).averageNewPerDay(timeZone));
putSupplier(AnalysisKeys.UNIQUE_PLAYERS_PER_DAY, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).uniqueJoinsPerDay(timeZone));
putSupplier(AnalysisKeys.NEW_PLAYERS_PER_DAY, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).newPerDay(timeZone));
putSupplier(AnalysisKeys.UNIQUE_PLAYERS_SERIES, () -> graphs.line().lineGraph(
MutatorFunctions.toPointsWithRemovedOffset(getUnsafe(AnalysisKeys.UNIQUE_PLAYERS_PER_DAY), timeZone)).toHighChartsSeries()
);
putSupplier(AnalysisKeys.NEW_PLAYERS_SERIES, () -> graphs.line().lineGraph(
MutatorFunctions.toPointsWithRemovedOffset(getUnsafe(AnalysisKeys.NEW_PLAYERS_PER_DAY), timeZone)).toHighChartsSeries()
);
Key<Integer> retentionDay = new Key<>(Integer.class, "RETENTION_DAY");
// compareAndFindThoseLikelyToBeRetained can throw exception.
putCachingSupplier(retentionDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).compareAndFindThoseLikelyToBeRetained(
getUnsafe(newDay).all(), getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO),
getUnsafe(AnalysisKeys.PLAYERS_ONLINE_RESOLVER),
config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD)
).count()
);
putSupplier(AnalysisKeys.PLAYERS_RETAINED_DAY, () -> {
try {
return getUnsafe(retentionDay);
} catch (IllegalStateException noPlayersAfterDateFiltering) {
return 0;
}
});
putCachingSupplier(AnalysisKeys.PLAYERS_RETAINED_WEEK, () ->
getUnsafe(newWeek).filterRetained(
getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO),
getUnsafe(AnalysisKeys.ANALYSIS_TIME)
).count()
);
putCachingSupplier(AnalysisKeys.PLAYERS_RETAINED_MONTH, () ->
getUnsafe(newMonth).filterRetained(
getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO),
getUnsafe(AnalysisKeys.ANALYSIS_TIME)
).count()
);
putSupplier(AnalysisKeys.PLAYERS_RETAINED_DAY_PERC, () -> {
try {
Integer playersNewDay = getUnsafe(AnalysisKeys.PLAYERS_NEW_DAY);
return playersNewDay != 0
? formatters.percentage().apply(1.0 * getUnsafe(retentionDay) / playersNewDay)
: "-";
} catch (IllegalStateException noPlayersAfterDateFiltering) {
return "Not enough data";
}
});
putSupplier(AnalysisKeys.PLAYERS_RETAINED_WEEK_PERC, () -> {
Integer playersNewWeek = getUnsafe(AnalysisKeys.PLAYERS_NEW_WEEK);
return playersNewWeek != 0 ? formatters.percentage().apply(1.0 * getUnsafe(AnalysisKeys.PLAYERS_RETAINED_WEEK) / playersNewWeek) : "-";
}
);
putSupplier(AnalysisKeys.PLAYERS_RETAINED_MONTH_PERC, () -> {
Integer playersNewMonth = getUnsafe(AnalysisKeys.PLAYERS_NEW_MONTH);
return playersNewMonth != 0
? formatters.percentage().apply(1.0 * getUnsafe(AnalysisKeys.PLAYERS_RETAINED_MONTH) / playersNewMonth)
: "-";
}
);
}
private void addSessionSuppliers() {
Key<SessionAccordion> sessionAccordion = new Key<>(SessionAccordion.class, "SESSION_ACCORDION");
putCachingSupplier(sessionAccordion, () -> accordions.serverSessionAccordion(
getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).all(),
() -> Collections.singletonMap(
serverContainer.getUnsafe(ServerKeys.SERVER_UUID),
serverContainer.getValue(ServerKeys.NAME).orElse("This server")
),
() -> getUnsafe(AnalysisKeys.PLAYER_NAMES)
));
putSupplier(AnalysisKeys.SESSION_ACCORDION_HTML, () -> getUnsafe(sessionAccordion).toHtml());
putSupplier(AnalysisKeys.SESSION_ACCORDION_FUNCTIONS, () -> getUnsafe(sessionAccordion).toViewScript());
putSupplier(AnalysisKeys.RECENT_LOGINS, () -> new RecentLoginList(
serverContainer.getValue(ServerKeys.PLAYERS).orElse(new ArrayList<>()),
formatters.secondLong()).toHtml()
);
putSupplier(AnalysisKeys.SESSION_TABLE, () -> tables.serverSessionTable(
getUnsafe(AnalysisKeys.PLAYER_NAMES), getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).all()).parseHtml()
);
putSupplier(AnalysisKeys.AVERAGE_SESSION_LENGTH_F,
() -> formatters.timeAmount().apply(getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).toAverageSessionLength())
);
putSupplier(AnalysisKeys.SESSION_COUNT, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).count());
putSupplier(AnalysisKeys.PLAYTIME_TOTAL, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).toPlaytime());
putSupplier(AnalysisKeys.DEATHS, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).toDeathCount());
putSupplier(AnalysisKeys.MOB_KILL_COUNT, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).toMobKillCount());
putSupplier(AnalysisKeys.PLAYER_KILL_COUNT, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).toPlayerKillCount());
putSupplier(AnalysisKeys.PLAYTIME_F,
() -> formatters.timeAmount().apply(getUnsafe(AnalysisKeys.PLAYTIME_TOTAL))
);
putSupplier(AnalysisKeys.AVERAGE_PLAYTIME_F, () -> {
long players = getUnsafe(AnalysisKeys.PLAYERS_TOTAL);
return players != 0
? formatters.timeAmount().apply(getUnsafe(AnalysisKeys.PLAYTIME_TOTAL) / players)
: "-";
}
);
putSupplier(AnalysisKeys.AVERAGE_SESSION_LENGTH_F,
() -> formatters.timeAmount().apply(getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).toAverageSessionLength())
);
Key<SessionsMutator> sessionsDay = new Key<>(SessionsMutator.class, "SESSIONS_DAY");
Key<SessionsMutator> sessionsWeek = new Key<>(SessionsMutator.class, "SESSIONS_WEEK");
Key<SessionsMutator> sessionsMonth = new Key<>(SessionsMutator.class, "SESSIONS_MONTH");
putCachingSupplier(sessionsDay, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
.filterSessionsBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(sessionsWeek, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
.filterSessionsBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(sessionsMonth, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
.filterSessionsBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putSupplier(AnalysisKeys.PUNCHCARD_SERIES, () -> graphs.special().punchCard(getUnsafe(sessionsMonth).all()).toHighChartsSeries());
putSupplier(AnalysisKeys.AVG_PLAYERS, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).toAverageUniqueJoinsPerDay(timeZone));
putSupplier(AnalysisKeys.AVG_PLAYERS_DAY, () -> getUnsafe(sessionsDay).toAverageUniqueJoinsPerDay(timeZone));
putSupplier(AnalysisKeys.AVG_PLAYERS_WEEK, () -> getUnsafe(sessionsWeek).toAverageUniqueJoinsPerDay(timeZone));
putSupplier(AnalysisKeys.AVG_PLAYERS_MONTH, () -> getUnsafe(sessionsMonth).toAverageUniqueJoinsPerDay(timeZone));
}
private void addGraphSuppliers() {
Key<WorldPie> worldPie = new Key<>(WorldPie.class, "WORLD_PIE");
putCachingSupplier(worldPie, () -> graphs.pie().worldPie(
serverContainer.getValue(ServerKeys.WORLD_TIMES).orElse(new WorldTimes())
));
putSupplier(AnalysisKeys.WORLD_PIE_SERIES, () -> getUnsafe(worldPie).toHighChartsSeries());
putSupplier(AnalysisKeys.GM_PIE_SERIES, () -> getUnsafe(worldPie).toHighChartsDrilldown());
putSupplier(AnalysisKeys.PLAYERS_ONLINE_SERIES, () ->
graphs.line().playersOnlineGraph(getUnsafe(AnalysisKeys.TPS_MUTATOR)).toHighChartsSeries()
);
putSupplier(AnalysisKeys.TPS_SERIES, () -> graphs.line().tpsGraph(getUnsafe(AnalysisKeys.TPS_MUTATOR)).toHighChartsSeries());
putSupplier(AnalysisKeys.CPU_SERIES, () -> graphs.line().cpuGraph(getUnsafe(AnalysisKeys.TPS_MUTATOR)).toHighChartsSeries());
putSupplier(AnalysisKeys.RAM_SERIES, () -> graphs.line().ramGraph(getUnsafe(AnalysisKeys.TPS_MUTATOR)).toHighChartsSeries());
putSupplier(AnalysisKeys.DISK_SERIES, () -> graphs.line().diskGraph(getUnsafe(AnalysisKeys.TPS_MUTATOR)).toHighChartsSeries());
putSupplier(AnalysisKeys.ENTITY_SERIES, () -> graphs.line().entityGraph(getUnsafe(AnalysisKeys.TPS_MUTATOR)).toHighChartsSeries());
putSupplier(AnalysisKeys.CHUNK_SERIES, () -> graphs.line().chunkGraph(getUnsafe(AnalysisKeys.TPS_MUTATOR)).toHighChartsSeries());
putSupplier(AnalysisKeys.WORLD_MAP_SERIES, () ->
graphs.special().worldMap(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)).toHighChartsSeries()
);
Key<BarGraph> geolocationBarChart = new Key<>(BarGraph.class, "GEOLOCATION_BAR_GRAPH");
putCachingSupplier(geolocationBarChart, () -> graphs.bar().geolocationBarGraph(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)));
putSupplier(AnalysisKeys.COUNTRY_CATEGORIES, () -> getUnsafe(geolocationBarChart).toHighChartsCategories());
putSupplier(AnalysisKeys.COUNTRY_SERIES, () -> getUnsafe(geolocationBarChart).toHighChartsSeries());
Key<PingGraph> pingGraph = new Key<>(PingGraph.class, "PING_GRAPH");
putCachingSupplier(pingGraph, () ->
graphs.line().pingGraph(PingMutator.forContainer(serverContainer).mutateToByMinutePings().all())
);
putSupplier(AnalysisKeys.AVG_PING_SERIES, () -> getUnsafe(pingGraph).toAvgSeries());
putSupplier(AnalysisKeys.MAX_PING_SERIES, () -> getUnsafe(pingGraph).toMaxSeries());
putSupplier(AnalysisKeys.MIN_PING_SERIES, () -> getUnsafe(pingGraph).toMinSeries());
putSupplier(AnalysisKeys.CALENDAR_SERIES, () -> graphs.calendar().serverCalendar(
getUnsafe(AnalysisKeys.PLAYERS_MUTATOR),
getUnsafe(AnalysisKeys.UNIQUE_PLAYERS_PER_DAY),
getUnsafe(AnalysisKeys.NEW_PLAYERS_PER_DAY)
).toCalendarSeries());
putCachingSupplier(AnalysisKeys.ACTIVITY_DATA, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).toActivityDataMap(getUnsafe(AnalysisKeys.ANALYSIS_TIME), config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD)));
Key<StackGraph> activityStackGraph = new Key<>(StackGraph.class, "ACTIVITY_STACK_GRAPH");
putCachingSupplier(activityStackGraph, () -> graphs.stack().activityStackGraph(getUnsafe(AnalysisKeys.ACTIVITY_DATA)));
putSupplier(AnalysisKeys.ACTIVITY_STACK_CATEGORIES, () -> getUnsafe(activityStackGraph).toHighChartsLabels());
putSupplier(AnalysisKeys.ACTIVITY_STACK_SERIES, () -> getUnsafe(activityStackGraph).toHighChartsSeries());
putSupplier(AnalysisKeys.ACTIVITY_PIE_SERIES, () -> graphs.pie().activityPie_old(
getUnsafe(AnalysisKeys.ACTIVITY_DATA).get(getUnsafe(AnalysisKeys.ANALYSIS_TIME))).toHighChartsSeries()
);
putSupplier(AnalysisKeys.PLAYERS_REGULAR, () -> {
Map<String, Set<UUID>> activityNow = getUnsafe(AnalysisKeys.ACTIVITY_DATA)
.floorEntry(getUnsafe(AnalysisKeys.ANALYSIS_TIME)).getValue();
Set<UUID> veryActiveNow = activityNow.getOrDefault("Very Active", new HashSet<>());
Set<UUID> activeNow = activityNow.getOrDefault("Active", new HashSet<>());
Set<UUID> regularNow = activityNow.getOrDefault("Regular", new HashSet<>());
return veryActiveNow.size() + activeNow.size() + regularNow.size();
});
}
private void addTPSAverageSuppliers() {
Key<TPSMutator> tpsMonth = new Key<>(TPSMutator.class, "TPS_MONTH");
Key<TPSMutator> tpsWeek = new Key<>(TPSMutator.class, "TPS_WEEK");
Key<TPSMutator> tpsDay = new Key<>(TPSMutator.class, "TPS_DAY");
putCachingSupplier(tpsMonth, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
.filterDataBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(tpsWeek, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
.filterDataBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(tpsDay, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
.filterDataBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
putCachingSupplier(AnalysisKeys.PLAYERS_ONLINE_RESOLVER, () -> new PlayersOnlineResolver(getUnsafe(AnalysisKeys.TPS_MUTATOR)));
int threshold = config.get(DisplaySettings.GRAPH_TPS_THRESHOLD_MED);
putSupplier(AnalysisKeys.TPS_SPIKE_MONTH, () -> getUnsafe(tpsMonth).lowTpsSpikeCount(threshold));
putSupplier(AnalysisKeys.AVG_TPS_MONTH, () -> getUnsafe(tpsMonth).averageTPS());
putSupplier(AnalysisKeys.AVG_CPU_MONTH, () -> getUnsafe(tpsMonth).averageCPU());
putSupplier(AnalysisKeys.AVG_RAM_MONTH, () -> getUnsafe(tpsMonth).averageRAM());
putSupplier(AnalysisKeys.AVG_ENTITY_MONTH, () -> getUnsafe(tpsMonth).averageEntities());
putSupplier(AnalysisKeys.AVG_CHUNK_MONTH, () -> getUnsafe(tpsMonth).averageChunks());
putSupplier(AnalysisKeys.AVG_FREE_DISK_MONTH, () -> getUnsafe(tpsMonth).averageFreeDisk());
putSupplier(AnalysisKeys.MAX_FREE_DISK_MONTH, () -> getUnsafe(tpsMonth).maxFreeDisk());
putSupplier(AnalysisKeys.MIN_FREE_DISK_MONTH, () -> getUnsafe(tpsMonth).minFreeDisk());
putSupplier(AnalysisKeys.TPS_SPIKE_WEEK, () -> getUnsafe(tpsWeek).lowTpsSpikeCount(threshold));
putSupplier(AnalysisKeys.AVG_TPS_WEEK, () -> getUnsafe(tpsWeek).averageTPS());
putSupplier(AnalysisKeys.AVG_CPU_WEEK, () -> getUnsafe(tpsWeek).averageCPU());
putSupplier(AnalysisKeys.AVG_RAM_WEEK, () -> getUnsafe(tpsWeek).averageRAM());
putSupplier(AnalysisKeys.AVG_ENTITY_WEEK, () -> getUnsafe(tpsWeek).averageEntities());
putSupplier(AnalysisKeys.AVG_CHUNK_WEEK, () -> getUnsafe(tpsWeek).averageChunks());
putSupplier(AnalysisKeys.AVG_FREE_DISK_WEEK, () -> getUnsafe(tpsWeek).averageFreeDisk());
putSupplier(AnalysisKeys.MAX_FREE_DISK_WEEK, () -> getUnsafe(tpsWeek).maxFreeDisk());
putSupplier(AnalysisKeys.MIN_FREE_DISK_WEEK, () -> getUnsafe(tpsWeek).minFreeDisk());
putSupplier(AnalysisKeys.TPS_SPIKE_DAY, () -> getUnsafe(tpsDay).lowTpsSpikeCount(threshold));
putSupplier(AnalysisKeys.AVG_TPS_DAY, () -> getUnsafe(tpsDay).averageTPS());
putSupplier(AnalysisKeys.AVG_CPU_DAY, () -> getUnsafe(tpsDay).averageCPU());
putSupplier(AnalysisKeys.AVG_RAM_DAY, () -> getUnsafe(tpsDay).averageRAM());
putSupplier(AnalysisKeys.AVG_ENTITY_DAY, () -> getUnsafe(tpsDay).averageEntities());
putSupplier(AnalysisKeys.AVG_CHUNK_DAY, () -> getUnsafe(tpsDay).averageChunks());
putSupplier(AnalysisKeys.AVG_FREE_DISK_DAY, () -> getUnsafe(tpsDay).averageFreeDisk());
putSupplier(AnalysisKeys.MAX_FREE_DISK_DAY, () -> getUnsafe(tpsDay).maxFreeDisk());
putSupplier(AnalysisKeys.MIN_FREE_DISK_DAY, () -> getUnsafe(tpsDay).minFreeDisk());
}
private void addCommandSuppliers() {
putSupplier(AnalysisKeys.COMMAND_USAGE_TABLE, () -> tables.commandUseTable(serverContainer).parseHtml());
putSupplier(AnalysisKeys.COMMAND_COUNT_UNIQUE, () -> serverContainer.getValue(ServerKeys.COMMAND_USAGE).map(Map::size).orElse(0));
putSupplier(AnalysisKeys.COMMAND_COUNT, () -> CommandUseMutator.forContainer(serverContainer).commandUsageCount());
}
private void addServerHealth() {
Key<HealthInformation> healthInformation = new Key<>(HealthInformation.class, "HEALTH_INFORMATION");
putCachingSupplier(healthInformation, () -> new HealthInformation(
this,
locale,
config.get(DisplaySettings.GRAPH_TPS_THRESHOLD_MED),
config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD),
config.get(TimeSettings.ACTIVE_LOGIN_THRESHOLD),
formatters.timeAmount(), formatters.decimals(), formatters.percentage()
));
putSupplier(AnalysisKeys.HEALTH_INDEX, () -> getUnsafe(healthInformation).getServerHealth());
putSupplier(AnalysisKeys.HEALTH_NOTES, () -> getUnsafe(healthInformation).toHtml());
}
private void addPluginSuppliers() {
// TODO Refactor into a system that supports running the analysis on Bungee
Key<String[]> navAndTabs = new Key<>(new Type<String[]>() {}, "NAV_AND_TABS");
Key<AnalysisPluginTabs> pluginTabs = new Key<>(AnalysisPluginTabs.class, "PLUGIN_TABS");
putCachingSupplier(navAndTabs, () -> pluginsTabContentCreator.createContent(
this, getValue(AnalysisKeys.PLAYERS_MUTATOR).orElse(new PlayersMutator(new ArrayList<>()))
));
putCachingSupplier(pluginTabs, () -> new AnalysisPluginTabs(serverContainer.getValue(ServerKeys.EXTENSION_DATA).orElse(new ArrayList<>()), formatters));
putSupplier(AnalysisKeys.PLUGINS_TAB_NAV, () -> getUnsafe(pluginTabs).getNav() + getUnsafe(navAndTabs)[0]);
putSupplier(AnalysisKeys.PLUGINS_TAB, () -> getUnsafe(pluginTabs).getTabs() + getUnsafe(navAndTabs)[1]);
}
@Singleton
public static class Factory {
private final String version;
private final PlanConfig config;
private final Locale locale;
private final Theme theme;
private final ServerProperties serverProperties;
private final Formatters formatters;
private final Graphs graphs;
private final HtmlTables tables;
private final Accordions accordions;
private final AnalysisPluginsTabContentCreator pluginsTabContentCreator;
@Inject
public Factory(
@Named("currentVersion") String version,
PlanConfig config,
Locale locale,
Theme theme,
ServerProperties serverProperties,
Formatters formatters,
Graphs graphs,
HtmlTables tables,
Accordions accordions,
AnalysisPluginsTabContentCreator pluginsTabContentCreator
) {
this.version = version;
this.config = config;
this.locale = locale;
this.theme = theme;
this.serverProperties = serverProperties;
this.formatters = formatters;
this.graphs = graphs;
this.tables = tables;
this.accordions = accordions;
this.pluginsTabContentCreator = pluginsTabContentCreator;
}
public AnalysisContainer forServerContainer(ServerContainer serverContainer) {
return new AnalysisContainer(
serverContainer,
version,
locale,
config,
theme,
serverProperties,
formatters,
graphs,
tables,
accordions,
pluginsTabContentCreator
);
}
} }
} }

View File

@ -37,6 +37,7 @@ import java.util.UUID;
* @author Rsl1122 * @author Rsl1122
* @see com.djrapitops.plan.data.store.containers.AnalysisContainer for Suppliers for each Key. * @see com.djrapitops.plan.data.store.containers.AnalysisContainer for Suppliers for each Key.
*/ */
@Deprecated
public class AnalysisKeys { public class AnalysisKeys {
// Constants (Affected only by config settings) // Constants (Affected only by config settings)

View File

@ -51,6 +51,7 @@ public class CommonKeys {
public static final Key<WorldTimes> WORLD_TIMES = new Key<>(WorldTimes.class, "world_times"); public static final Key<WorldTimes> WORLD_TIMES = new Key<>(WorldTimes.class, "world_times");
public static final PlaceholderKey<Long> LAST_SEEN = new PlaceholderKey<>(Long.class, "lastSeen"); public static final PlaceholderKey<Long> LAST_SEEN = new PlaceholderKey<>(Long.class, "lastSeen");
@Deprecated
public static final Key<List<PlayerDeath>> PLAYER_DEATHS = new Key<>(new Type<List<PlayerDeath>>() {}, "player_deaths"); public static final Key<List<PlayerDeath>> PLAYER_DEATHS = new Key<>(new Type<List<PlayerDeath>>() {}, "player_deaths");
public static final Key<List<PlayerKill>> PLAYER_KILLS = new Key<>(new Type<List<PlayerKill>>() {}, "player_kills"); public static final Key<List<PlayerKill>> PLAYER_KILLS = new Key<>(new Type<List<PlayerKill>>() {}, "player_kills");
public static final Key<Integer> PLAYER_KILL_COUNT = new Key<>(Integer.class, "player_kill_count"); public static final Key<Integer> PLAYER_KILL_COUNT = new Key<>(Integer.class, "player_kill_count");

View File

@ -96,6 +96,10 @@ public class SessionsMutator {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
/**
* @deprecated Incorrect results.
*/
@Deprecated
public List<PlayerDeath> toPlayerDeathList() { public List<PlayerDeath> toPlayerDeathList() {
return sessions.stream() return sessions.stream()
.map(session -> session.getValue(SessionKeys.PLAYER_DEATHS).orElse(new ArrayList<>())) .map(session -> session.getValue(SessionKeys.PLAYER_DEATHS).orElse(new ArrayList<>()))
@ -232,6 +236,10 @@ public class SessionsMutator {
return sorted; return sorted;
} }
/**
* @deprecated Incorrect value, use PlayerVersusMutator instead.
*/
@Deprecated
public int toPlayerDeathCount() { public int toPlayerDeathCount() {
return toPlayerDeathList().size(); return toPlayerDeathList().size();
} }

View File

@ -1,166 +0,0 @@
/*
* 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.data.store.mutators.health;
import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.containers.AnalysisContainer;
import com.djrapitops.plan.data.store.keys.AnalysisKeys;
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.data.store.mutators.PlayersOnlineResolver;
import com.djrapitops.plan.data.store.mutators.TPSMutator;
import com.djrapitops.plan.system.locale.Locale;
import com.djrapitops.plan.system.locale.lang.HealthInfoLang;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.html.icon.Icons;
import com.djrapitops.plugin.api.TimeAmount;
import java.util.ArrayList;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
* Server Health analysis mutator.
*
* @author Rsl1122
*/
public class HealthInformation extends AbstractHealthInfo {
private final AnalysisContainer analysisContainer;
private final int lowTPSThreshold;
public HealthInformation(
AnalysisContainer analysisContainer,
Locale locale,
int lowTPSThreshold,
long activeMsThreshold,
int activeLoginThreshold,
Formatter<Long> timeAmountFormatter,
Formatter<Double> decimalFormatter,
Formatter<Double> percentageFormatter
) {
super(
analysisContainer.getUnsafe(AnalysisKeys.ANALYSIS_TIME),
analysisContainer.getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO),
locale,
activeMsThreshold, activeLoginThreshold,
timeAmountFormatter, decimalFormatter, percentageFormatter
);
this.analysisContainer = analysisContainer;
this.lowTPSThreshold = lowTPSThreshold;
calculate();
}
@Override
public String toHtml() {
StringBuilder healthNoteBuilder = new StringBuilder();
for (String healthNote : notes) {
healthNoteBuilder.append(healthNote);
}
return healthNoteBuilder.toString();
}
@Override
protected void calculate() {
activityChangeNote(analysisContainer.getUnsafe(AnalysisKeys.ACTIVITY_DATA));
newPlayerNote();
activePlayerPlaytimeChange(analysisContainer.getUnsafe(AnalysisKeys.PLAYERS_MUTATOR));
lowPerformance();
}
private void newPlayerNote() {
Key<PlayersMutator> newMonth = new Key<>(PlayersMutator.class, "NEW_MONTH");
PlayersMutator newPlayersMonth = analysisContainer.getValue(newMonth).orElse(new PlayersMutator(new ArrayList<>()));
PlayersOnlineResolver onlineResolver = analysisContainer.getUnsafe(AnalysisKeys.PLAYERS_ONLINE_RESOLVER);
double avgOnlineOnRegister = newPlayersMonth.registerDates().stream()
.map(onlineResolver::getOnlineOn)
.filter(Optional::isPresent)
.mapToInt(Optional::get)
.average().orElse(0);
if (avgOnlineOnRegister >= 1) {
addNote(Icons.GREEN_THUMB + locale.getString(HealthInfoLang.NEW_PLAYER_JOIN_PLAYERS_GOOD,
decimalFormatter.apply(avgOnlineOnRegister)));
} else {
addNote(Icons.YELLOW_FLAG + locale.getString(HealthInfoLang.NEW_PLAYER_JOIN_PLAYERS_BAD,
decimalFormatter.apply(avgOnlineOnRegister)));
serverHealth -= 5;
}
long playersNewMonth = analysisContainer.getValue(AnalysisKeys.PLAYERS_NEW_MONTH).orElse(0);
long playersRetainedMonth = analysisContainer.getValue(AnalysisKeys.PLAYERS_RETAINED_MONTH).orElse(0);
if (playersNewMonth != 0) {
double retainPercentage = playersRetainedMonth * 1.0 / playersNewMonth;
String stickinessSentence = locale.getString(HealthInfoLang.NEW_PLAYER_STICKINESS,
percentageFormatter.apply(retainPercentage), playersRetainedMonth, playersNewMonth);
if (retainPercentage >= 0.25) {
addNote(Icons.GREEN_THUMB + stickinessSentence);
} else {
addNote(Icons.YELLOW_FLAG + stickinessSentence);
}
}
}
private void lowPerformance() {
Key<TPSMutator> tpsMonth = new Key<>(TPSMutator.class, "TPS_MONTH");
TPSMutator tpsMutator = analysisContainer.getUnsafe(tpsMonth);
long serverDownTime = tpsMutator.serverDownTime();
double aboveThreshold = tpsMutator.percentageTPSAboveThreshold(lowTPSThreshold);
long tpsSpikeMonth = analysisContainer.getValue(AnalysisKeys.TPS_SPIKE_MONTH).orElse(0);
StringBuilder avgLowThresholdString = new StringBuilder(SUB_NOTE);
if (aboveThreshold >= 0.96) {
avgLowThresholdString.append(Icons.GREEN_THUMB);
} else if (aboveThreshold >= 0.9) {
avgLowThresholdString.append(Icons.YELLOW_FLAG);
serverHealth *= 0.9;
} else {
avgLowThresholdString.append(Icons.RED_WARN);
serverHealth *= 0.6;
}
avgLowThresholdString.append(locale.getString(HealthInfoLang.TPS_ABOVE_LOW_THERSHOLD, percentageFormatter.apply(aboveThreshold)));
String tpsDipSentence = locale.getString(HealthInfoLang.TPS_LOW_DIPS, lowTPSThreshold, tpsSpikeMonth);
if (tpsSpikeMonth <= 5) {
addNote(Icons.GREEN_THUMB + tpsDipSentence + avgLowThresholdString);
} else if (tpsSpikeMonth <= 25) {
addNote(Icons.YELLOW_FLAG + tpsDipSentence + avgLowThresholdString);
serverHealth *= 0.95;
} else {
addNote(Icons.RED_WARN + tpsDipSentence + avgLowThresholdString);
serverHealth *= 0.8;
}
String downtimeSentence = locale.getString(HealthInfoLang.DOWNTIME, timeAmountFormatter.apply(serverDownTime));
if (serverDownTime <= TimeUnit.DAYS.toMillis(1L)) {
addNote(Icons.GREEN_THUMB + downtimeSentence);
} else {
long weekMs = TimeAmount.WEEK.toMillis(1L);
if (serverDownTime <= weekMs) {
addNote(Icons.YELLOW_FLAG + downtimeSentence);
serverHealth *= (weekMs - serverDownTime) * 1.0 / weekMs;
} else {
addNote(Icons.RED_WARN + downtimeSentence);
long monthMs = TimeAmount.MONTH.toMillis(1L);
serverHealth *= (monthMs - serverDownTime) * 1.0 / monthMs;
}
}
}
}

View File

@ -22,8 +22,6 @@ import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.database.ProxyDBSystem; import com.djrapitops.plan.system.database.ProxyDBSystem;
import com.djrapitops.plan.system.importing.EmptyImportSystem; import com.djrapitops.plan.system.importing.EmptyImportSystem;
import com.djrapitops.plan.system.importing.ImportSystem; import com.djrapitops.plan.system.importing.ImportSystem;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.ProxyInfoSystem;
import com.djrapitops.plan.system.info.connection.ConnectionSystem; import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.connection.ProxyConnectionSystem; import com.djrapitops.plan.system.info.connection.ProxyConnectionSystem;
import com.djrapitops.plan.system.settings.ConfigSystem; import com.djrapitops.plan.system.settings.ConfigSystem;
@ -48,13 +46,10 @@ public interface ProxySuperClassBindingModule {
@Binds @Binds
ConfigSystem bindProxyConfigSystem(ProxyConfigSystem proxyConfigSystem); ConfigSystem bindProxyConfigSystem(ProxyConfigSystem proxyConfigSystem);
@Binds
InfoSystem bindProxyInfoSystem(ProxyInfoSystem proxyInfoSystem);
@Binds
ConnectionSystem bindProxyConnectionSystem(ProxyConnectionSystem proxyConnectionSystem);
@Binds @Binds
ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem); ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem);
@Binds
ConnectionSystem bindServerConnectionSystem(ProxyConnectionSystem connectionSystem);
} }

View File

@ -18,8 +18,6 @@ package com.djrapitops.plan.modules;
import com.djrapitops.plan.api.CommonAPI; import com.djrapitops.plan.api.CommonAPI;
import com.djrapitops.plan.api.PlanAPI; import com.djrapitops.plan.api.PlanAPI;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.ServerInfoSystem;
import com.djrapitops.plan.system.info.connection.ConnectionSystem; import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.connection.ServerConnectionSystem; import com.djrapitops.plan.system.info.connection.ServerConnectionSystem;
import dagger.Binds; import dagger.Binds;
@ -37,8 +35,6 @@ public interface ServerSuperClassBindingModule {
PlanAPI bindServerPlanAPI(CommonAPI serverAPI); PlanAPI bindServerPlanAPI(CommonAPI serverAPI);
@Binds @Binds
InfoSystem bindServerInfoSystem(ServerInfoSystem serverInfoSystem); ConnectionSystem bindServerConnectionSystem(ServerConnectionSystem connectionSystem);
@Binds
ConnectionSystem bindServerConnectionSystem(ServerConnectionSystem serverConnectionSystem);
} }

View File

@ -29,8 +29,11 @@ public class DebugChannels {
} }
public static final String ANALYSIS = "Analysis"; public static final String ANALYSIS = "Analysis";
@Deprecated
public static final String INFO_REQUESTS = "InfoRequests"; public static final String INFO_REQUESTS = "InfoRequests";
@Deprecated
public static final String CONNECTIONS = "Connections"; public static final String CONNECTIONS = "Connections";
@Deprecated
public static final String WEB_REQUESTS = "Web Requests"; public static final String WEB_REQUESTS = "Web Requests";
public static final String IMPORTING = "Importing"; public static final String IMPORTING = "Importing";
public static final String SQL = "SQL"; public static final String SQL = "SQL";

View File

@ -28,7 +28,6 @@ import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.export.ExportSystem; import com.djrapitops.plan.system.export.ExportSystem;
import com.djrapitops.plan.system.file.PlanFiles; import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.importing.ImportSystem; import com.djrapitops.plan.system.importing.ImportSystem;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.listeners.ListenerSystem; import com.djrapitops.plan.system.listeners.ListenerSystem;
import com.djrapitops.plan.system.locale.LocaleSystem; import com.djrapitops.plan.system.locale.LocaleSystem;
@ -63,7 +62,6 @@ public class PlanSystem implements SubSystem {
private final CacheSystem cacheSystem; private final CacheSystem cacheSystem;
private final ListenerSystem listenerSystem; private final ListenerSystem listenerSystem;
private final TaskSystem taskSystem; private final TaskSystem taskSystem;
private final InfoSystem infoSystem;
private final ServerInfo serverInfo; private final ServerInfo serverInfo;
private final WebServerSystem webServerSystem; private final WebServerSystem webServerSystem;
@ -88,7 +86,6 @@ public class PlanSystem implements SubSystem {
CacheSystem cacheSystem, CacheSystem cacheSystem,
ListenerSystem listenerSystem, ListenerSystem listenerSystem,
TaskSystem taskSystem, TaskSystem taskSystem,
InfoSystem infoSystem,
ServerInfo serverInfo, ServerInfo serverInfo,
WebServerSystem webServerSystem, WebServerSystem webServerSystem,
Processing processing, Processing processing,
@ -109,7 +106,6 @@ public class PlanSystem implements SubSystem {
this.cacheSystem = cacheSystem; this.cacheSystem = cacheSystem;
this.listenerSystem = listenerSystem; this.listenerSystem = listenerSystem;
this.taskSystem = taskSystem; this.taskSystem = taskSystem;
this.infoSystem = infoSystem;
this.serverInfo = serverInfo; this.serverInfo = serverInfo;
this.webServerSystem = webServerSystem; this.webServerSystem = webServerSystem;
this.processing = processing; this.processing = processing;
@ -138,7 +134,6 @@ public class PlanSystem implements SubSystem {
serverInfo, serverInfo,
importSystem, importSystem,
exportSystem, exportSystem,
infoSystem,
cacheSystem, cacheSystem,
listenerSystem, listenerSystem,
taskSystem, taskSystem,
@ -168,7 +163,6 @@ public class PlanSystem implements SubSystem {
processing, processing,
databaseSystem, databaseSystem,
webServerSystem, webServerSystem,
infoSystem,
serverInfo, serverInfo,
localeSystem, localeSystem,
configSystem, configSystem,
@ -235,10 +229,6 @@ public class PlanSystem implements SubSystem {
return cacheSystem; return cacheSystem;
} }
public InfoSystem getInfoSystem() {
return infoSystem;
}
public HookHandler getHookHandler() { public HookHandler getHookHandler() {
return hookHandler; return hookHandler;
} }

View File

@ -35,9 +35,9 @@ import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.system.webserver.cache.PageId; import com.djrapitops.plan.system.webserver.cache.PageId;
import com.djrapitops.plan.system.webserver.cache.ResponseCache; import com.djrapitops.plan.system.webserver.cache.ResponseCache;
import com.djrapitops.plan.system.webserver.response.pages.NetworkPageResponse; import com.djrapitops.plan.system.webserver.response.pages.NetworkPageResponse;
import com.djrapitops.plan.utilities.html.pages.InspectPage;
import com.djrapitops.plan.utilities.html.pages.NetworkPage; import com.djrapitops.plan.utilities.html.pages.NetworkPage;
import com.djrapitops.plan.utilities.html.pages.PageFactory; import com.djrapitops.plan.utilities.html.pages.PageFactory;
import com.djrapitops.plan.utilities.html.pages.PlayerPage;
import com.djrapitops.plugin.logging.L; import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.error.ErrorHandler; import com.djrapitops.plugin.logging.error.ErrorHandler;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
@ -114,7 +114,7 @@ public class HtmlExport extends SpecificExport {
} }
public void exportPlayerPage(UUID playerUUID, String playerName) { public void exportPlayerPage(UUID playerUUID, String playerName) {
InspectPage playerPage = pageFactory.inspectPage(playerUUID); PlayerPage playerPage = pageFactory.playerPage(playerUUID);
try { try {
exportPlayerPage(playerName, playerPage.toHtml()); exportPlayerPage(playerName, playerPage.toHtml());
} catch (ParseException | IOException e) { } catch (ParseException | IOException e) {

View File

@ -1,153 +0,0 @@
/*
* 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.system.info;
import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
import com.djrapitops.plan.api.exceptions.connection.ConnectionFailException;
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.DebugChannels;
import com.djrapitops.plan.system.SubSystem;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.request.GenerateRequest;
import com.djrapitops.plan.system.info.request.InfoRequest;
import com.djrapitops.plan.system.info.request.InfoRequestFactory;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.webserver.WebServer;
import com.djrapitops.plugin.logging.console.PluginLogger;
import dagger.Lazy;
import java.util.UUID;
/**
* Information management system.
* <p>
* Subclasses should decide how InfoRequests are run locally if necessary.
* <p>
* Everything should be called from an Async thread.
*
* @author Rsl1122
*/
public abstract class InfoSystem implements SubSystem {
protected final InfoRequestFactory infoRequestFactory;
protected final ConnectionSystem connectionSystem;
protected final ServerInfo serverInfo;
protected final Lazy<WebServer> webServer;
protected final PluginLogger logger;
protected InfoSystem(
InfoRequestFactory infoRequestFactory,
ConnectionSystem connectionSystem,
ServerInfo serverInfo,
Lazy<WebServer> webServer,
PluginLogger logger
) {
this.infoRequestFactory = infoRequestFactory;
this.connectionSystem = connectionSystem;
this.serverInfo = serverInfo;
this.webServer = webServer;
this.logger = logger;
}
/**
* Refreshes Player page.
* <p>
* No calls from non-async thread found on 09.02.2018
*
* @param player UUID of the player.
* @throws WebException If fails.
*/
public void generateAndCachePlayerPage(UUID player) throws WebException {
GenerateRequest infoRequest = infoRequestFactory.generateInspectPageRequest(player);
try {
sendRequest(infoRequest);
} catch (ConnectionFailException e) {
runLocally(infoRequest);
}
}
/**
* Send an InfoRequest to another server or run locally if necessary.
* <p>
* No calls from non-async thread found on 09.02.2018
*
* @param infoRequest InfoRequest to send or run.
* @throws WebException If fails.
*/
public void sendRequest(InfoRequest infoRequest) throws WebException {
try {
if (!connectionSystem.isServerAvailable()) {
logger.getDebugLogger().logOn(DebugChannels.INFO_REQUESTS, "Main server unavailable, running locally.");
runLocally(infoRequest);
return;
}
connectionSystem.sendInfoRequest(infoRequest);
} catch (WebException original) {
try {
logger.getDebugLogger().logOn(DebugChannels.INFO_REQUESTS, "Exception during request: " + original.toString() + ", running locally.");
runLocally(infoRequest);
} catch (NoServersException noServers) {
throw original;
}
}
}
/**
* Run the InfoRequest locally.
* <p>
* No calls from non-async thread found on 09.02.2018
*
* @param infoRequest InfoRequest to run.
* @throws WebException If fails.
*/
public abstract void runLocally(InfoRequest infoRequest) throws WebException;
@Override
public void enable() {
connectionSystem.enable();
}
@Override
public void disable() {
connectionSystem.disable();
}
public ConnectionSystem getConnectionSystem() {
return connectionSystem;
}
/**
* Requests Set up from Bungee.
* <p>
* No calls from non-async thread found on 09.02.2018
*
* @param addressToRequestServer Address of Bungee server.
* @throws WebException If fails.
*/
public void requestSetUp(String addressToRequestServer) throws WebException {
if (serverInfo.getServer().isProxy()) {
throw new BadRequestException("Method not available on a Proxy server.");
}
Server bungee = new Server(-1, null, "Bungee", addressToRequestServer, -1);
String addressOfThisServer = webServer.get().getAccessAddress();
connectionSystem.setSetupAllowed(true);
connectionSystem.sendInfoRequest(infoRequestFactory.sendDBSettingsRequest(addressOfThisServer), bungee);
}
}

View File

@ -1,62 +0,0 @@
/*
* 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.system.info;
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.request.*;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.webserver.WebServer;
import com.djrapitops.plugin.logging.console.PluginLogger;
import dagger.Lazy;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* InfoSystem for Bungee.
*
* @author Rsl1122
*/
@Singleton
public class ProxyInfoSystem extends InfoSystem {
@Inject
public ProxyInfoSystem(
InfoRequestFactory infoRequestFactory,
ConnectionSystem connectionSystem,
ServerInfo serverInfo,
Lazy<WebServer> webServer,
PluginLogger logger
) {
super(infoRequestFactory, connectionSystem, serverInfo, webServer, logger);
}
@Override
public void runLocally(InfoRequest infoRequest) throws WebException {
if (infoRequest instanceof CacheRequest
|| infoRequest instanceof GenerateInspectPageRequest
|| infoRequest instanceof GenerateInspectPluginsTabRequest
) {
infoRequest.runLocally();
} else {
// runLocally is called when ConnectionSystem has no servers.
throw new NoServersException("No servers were available to process this request (Local attempt): " + infoRequest.getClass().getSimpleName());
}
}
}

View File

@ -1,61 +0,0 @@
/*
* 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.system.info;
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.DebugChannels;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.request.InfoRequest;
import com.djrapitops.plan.system.info.request.InfoRequestFactory;
import com.djrapitops.plan.system.info.request.SetupRequest;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.webserver.WebServer;
import com.djrapitops.plugin.logging.console.PluginLogger;
import dagger.Lazy;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* InfoSystem for Bukkit servers.
*
* @author Rsl1122
*/
@Singleton
public class ServerInfoSystem extends InfoSystem {
@Inject
public ServerInfoSystem(
ConnectionSystem connectionSystem,
ServerInfo serverInfo,
InfoRequestFactory infoRequestFactory,
Lazy<WebServer> webServer,
PluginLogger logger
) {
super(infoRequestFactory, connectionSystem, serverInfo, webServer, logger);
}
@Override
public void runLocally(InfoRequest infoRequest) throws WebException {
if (infoRequest instanceof SetupRequest) {
throw new NoServersException("Set-up requests can not be run locally.");
}
logger.getDebugLogger().logOn(DebugChannels.INFO_REQUESTS, "Local: " + infoRequest.getClass().getSimpleName());
infoRequest.runLocally();
}
}

View File

@ -1,121 +0,0 @@
/*
* 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.system.info.connection;
import com.djrapitops.plan.api.exceptions.connection.*;
import com.djrapitops.plan.api.exceptions.database.DBOpException;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import com.djrapitops.plan.system.info.request.InfoRequest;
import com.djrapitops.plan.system.info.request.SetupRequest;
import com.djrapitops.plan.system.webserver.Request;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plugin.utilities.Verify;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
public class ConnectionIn {
private final Map<String, String> variables;
private final InfoRequest infoRequest;
private final Database database;
private final ConnectionSystem connectionSystem;
public ConnectionIn(
Request httpRequest, InfoRequest infoRequest,
Database database,
ConnectionSystem connectionSystem
) throws WebException {
this.database = database;
this.connectionSystem = connectionSystem;
Verify.nullCheck(httpRequest, infoRequest);
this.variables = readVariables(httpRequest);
this.infoRequest = infoRequest;
checkAuthentication();
}
private void checkAuthentication() throws WebException {
UUID serverUUID = getServerUUID();
try {
if (database.query(ServerQueries.fetchServerMatchingIdentifier(serverUUID)).isPresent()) {
return;
}
} catch (DBOpException e) {
throw new TransferDatabaseException(e);
}
if (infoRequest instanceof SetupRequest) {
if (!connectionSystem.isSetupAllowed()) {
throw new ForbiddenException("Setup not enabled on this server, use commands to enable.");
}
} else {
throw new UnauthorizedServerException(serverUUID + " (Sender) was not found from database");
}
}
private UUID getServerUUID() throws BadRequestException {
String sender = variables.get("sender");
Verify.nullCheck(sender, () -> new BadRequestException("Sender ('sender') variable not supplied in the request."));
try {
return UUID.fromString(sender);
} catch (IllegalArgumentException e) {
throw new BadRequestException("Sender ('sender') was not a valid UUID: " + e.getMessage());
}
}
private Map<String, String> readVariables(Request request) throws WebException {
String requestBody = readRequestBody(request.getRequestBody());
String[] bodyVariables = requestBody.split(";&variable;");
return Arrays.stream(bodyVariables)
.map(variable -> variable.split("=", 2))
.filter(splitVariables -> splitVariables.length == 2)
.collect(Collectors.toMap(splitVariables -> splitVariables[0], splitVariables -> splitVariables[1], (a, b) -> b));
}
public Response handleRequest() throws WebException {
return infoRequest.handleRequest(variables);
}
private String readRequestBody(InputStream in) throws WebFailException {
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
byte[] bytes;
byte[] buf = new byte[4096];
for (int n = in.read(buf); n > 0; n = in.read(buf)) {
out.write(buf, 0, n);
}
bytes = out.toByteArray();
return new String(bytes, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new WebFailException("Exception while reading Request.", e);
}
}
}

View File

@ -1,116 +0,0 @@
/*
* 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.system.info.connection;
import com.djrapitops.plan.data.store.objects.DateHolder;
import com.djrapitops.plan.system.DebugChannels;
import com.djrapitops.plan.system.info.request.InfoRequest;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plugin.logging.debug.DebugLogger;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* Class responsible for logging what {@link ConnectionOut} and {@link ConnectionIn} objects get as response.
*
* @author Rsl1122
*/
@Singleton
public class ConnectionLog {
private final DebugLogger debugLogger;
private final Map<String, Map<String, Entry>> log;
@Inject
public ConnectionLog(DebugLogger debugLogger) {
this.debugLogger = debugLogger;
log = new HashMap<>();
}
public void logConnectionTo(Server server, InfoRequest request, int responseCode) {
String requestName = request.getClass().getSimpleName();
String address = server.getWebAddress();
logConnection(address, "Out: " + requestName, responseCode);
debugLogger.logOn(DebugChannels.CONNECTIONS, "ConnectionOut: " + requestName + " to " + address);
}
public void logConnectionFrom(String server, String requestTarget, int responseCode) {
logConnection(server, "In: " + requestTarget, responseCode);
debugLogger.logOn(DebugChannels.CONNECTIONS, "ConnectionIn: " + requestTarget + " from " + server);
}
private void logConnection(String address, String infoRequestName, int responseCode) {
Map<String, Entry> requestMap = log.getOrDefault(address, new HashMap<>());
requestMap.put(infoRequestName, new Entry(responseCode, System.currentTimeMillis()));
log.put(address, requestMap);
}
public Map<String, Map<String, Entry>> getLogEntries() {
return log;
}
public static class Entry implements Comparable<Entry>, DateHolder {
private final int responseCode;
private final long date;
public Entry(int responseCode, long date) {
this.responseCode = responseCode;
this.date = date;
}
public int getResponseCode() {
return responseCode;
}
@Override
public long getDate() {
return date;
}
/**
* Most recent first.
*
* @param o object
* @return -1 or 1
*/
@Override
public int compareTo(Entry o) {
return Long.compare(o.date, this.date);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Entry)) return false;
Entry entry = (Entry) o;
return responseCode == entry.responseCode &&
date == entry.date;
}
@Override
public int hashCode() {
return Objects.hash(responseCode, date);
}
}
}

View File

@ -1,201 +0,0 @@
/*
* 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.system.info.connection;
import com.djrapitops.plan.api.exceptions.connection.*;
import com.djrapitops.plan.system.info.request.InfoRequest;
import com.djrapitops.plan.system.info.request.InfoRequestWithVariables;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.utilities.MiscUtils;
import com.djrapitops.plugin.utilities.Verify;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Represents an outbound action request to another Plan server.
*
* @author Rsl1122
*/
public class ConnectionOut {
private final Server toServer;
private final UUID serverUUID;
private final InfoRequest infoRequest;
static {
try {
Properties properties = System.getProperties();
properties.setProperty("sun.net.client.defaultConnectTimeout", Long.toString(TimeUnit.MINUTES.toMillis(1L)));
properties.setProperty("sun.net.client.defaultReadTimeout", Long.toString(TimeUnit.MINUTES.toMillis(1L)));
properties.setProperty("sun.net.http.retryPost", Boolean.toString(false));
} catch (Exception e) {
Logger.getGlobal().log(Level.WARNING, "[Plan] Failed to set sun client timeout system properties.", e);
}
}
private final ConnectionLog connectionLog;
/**
* Constructor.
*
* @param toServer Full address to another Plan webserver. (http://something:port)
* @param serverUUID UUID of server this outbound connection.
* @param infoRequest Type of the action this connection wants to be performed.
* @param connectionLog Where the connection should be logged.
*/
public ConnectionOut(
Server toServer, UUID serverUUID, InfoRequest infoRequest,
ConnectionLog connectionLog
) {
this.connectionLog = connectionLog;
Verify.nullCheck(toServer, serverUUID, infoRequest);
this.toServer = toServer;
this.serverUUID = serverUUID;
this.infoRequest = infoRequest;
}
public void sendRequest() throws WebException {
String address = getAddress();
CloseableHttpClient client = null;
HttpPost post = null;
CloseableHttpResponse response = null;
long start = System.currentTimeMillis();
try {
client = getHttpClient(address);
String url = address + "/info/" + infoRequest.getClass().getSimpleName().toLowerCase();
post = new HttpPost(url);
String parameters = parseVariables();
prepareRequest(post, parameters);
// Send request
response = client.execute(post);
int responseCode = response.getStatusLine().getStatusCode();
handleResult(url, parameters, responseCode);
} catch (SocketTimeoutException e) {
connectionLog.logConnectionTo(toServer, infoRequest, 0);
long seconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - start);
throw new ConnectionFailException("Connection to " + address + " timed out (" + seconds + "s): " + e.getMessage(), e);
} catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException | IOException e) {
connectionLog.logConnectionTo(toServer, infoRequest, -1);
throw new ConnectionFailException("Connection failed to address: " + address + " - Make sure the server is online.", e);
} finally {
if (post != null) {
post.releaseConnection();
}
MiscUtils.close(response);
MiscUtils.close(client);
}
}
private void handleResult(String url, String parameters, int responseCode) throws WebException {
connectionLog.logConnectionTo(toServer, infoRequest, responseCode);
switch (responseCode) {
case 200:
return;
case 400:
throw new BadRequestException("Bad Request: " + url + " | " + parameters);
case 403:
throw new ForbiddenException(url + " returned 403 | " + parameters);
case 404:
throw new NotFoundException(url + " returned a 404, ensure that your server is connected to an up to date Plan server.");
case 412:
throw new UnauthorizedServerException(url + " reported that it does not recognize this server. Make sure '/plan m setup' was successful.");
case 500:
throw new InternalErrorException();
case 504:
throw new GatewayException(url + " reported that it failed to connect to this server.");
default:
throw new WebException(url + "| Wrong response code " + responseCode);
}
}
private void prepareRequest(HttpPost post, String parameters) {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(5000)
.setSocketTimeout(10000)
.setConnectTimeout(9000)
.setRedirectsEnabled(true)
.setRelativeRedirectsAllowed(true)
.setContentCompressionEnabled(true)
.build();
post.setConfig(requestConfig);
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
post.setHeader("charset", "UTF-8");
post.setHeader("Connection", "close");
byte[] toSend = parameters.getBytes();
post.setEntity(new ByteArrayEntity(toSend));
}
private CloseableHttpClient getHttpClient(String address) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
if (address.startsWith("https")) {
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustAllStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
} else {
return HttpClients.createDefault();
}
}
private String getAddress() {
String address = toServer.getWebAddress();
if (address.contains("://:")) {
String[] parts = address.split("://:", 2);
address = parts[0] + "://localhost:" + parts[1];
}
return address;
}
private String parseVariables() {
StringBuilder parameters = new StringBuilder("sender=" + serverUUID + ";&variable;" +
"type=" + infoRequest.getClass().getSimpleName());
if (infoRequest instanceof InfoRequestWithVariables) {
Map<String, String> variables = ((InfoRequestWithVariables) infoRequest).getVariables();
for (Map.Entry<String, String> entry : variables.entrySet()) {
parameters.append(";&variable;").append(entry.getKey()).append("=").append(entry.getValue());
}
}
return parameters.toString();
}
}

View File

@ -16,101 +16,29 @@
*/ */
package com.djrapitops.plan.system.info.connection; package com.djrapitops.plan.system.info.connection;
import com.djrapitops.plan.api.exceptions.connection.NoServersException; import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.SubSystem;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.request.InfoRequest;
import com.djrapitops.plan.system.info.request.InfoRequests;
import com.djrapitops.plan.system.info.request.WideRequest;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.info.server.ServerInfo;
import dagger.Lazy;
import java.util.*;
/** /**
* ConnectionSystem manages out- and inbound InfoRequest connections. * ConnectionSystem manages proxy server status.
* <p>
* It decides what server to use for each request.
* *
* @author Rsl1122 * @author Rsl1122
* @deprecated Usage should be replaced with Database query {@link ServerQueries#fetchProxyServerInformation()}
*/ */
public abstract class ConnectionSystem implements SubSystem { @Deprecated
public abstract class ConnectionSystem {
protected final ConnectionLog connectionLog;
protected final InfoRequests infoRequests;
protected final Lazy<InfoSystem> infoSystem;
protected final ServerInfo serverInfo; protected final ServerInfo serverInfo;
protected Map<UUID, Server> dataServers;
private boolean setupAllowed;
public ConnectionSystem( public ConnectionSystem(
ConnectionLog connectionLog,
InfoRequests infoRequests,
Lazy<InfoSystem> infoSystem,
ServerInfo serverInfo ServerInfo serverInfo
) { ) {
this.connectionLog = connectionLog;
this.infoSystem = infoSystem;
this.serverInfo = serverInfo; this.serverInfo = serverInfo;
setupAllowed = false;
dataServers = new HashMap<>();
this.infoRequests = infoRequests;
}
public InfoRequest getInfoRequest(String name) {
return infoRequests.get(name.toLowerCase());
}
public void setSetupAllowed(boolean setupAllowed) {
this.setupAllowed = setupAllowed;
}
protected abstract Server selectServerForRequest(InfoRequest infoRequest) throws NoServersException;
public boolean isSetupAllowed() {
return setupAllowed;
}
public void sendInfoRequest(InfoRequest infoRequest) throws WebException {
Server server = selectServerForRequest(infoRequest);
sendInfoRequest(infoRequest, server);
}
public void sendInfoRequest(InfoRequest infoRequest, Server toServer) throws WebException {
UUID serverUUID = serverInfo.getServerUUID();
if (serverUUID.equals(toServer.getUuid())) {
infoSystem.get().runLocally(infoRequest);
} else {
new ConnectionOut(toServer, serverUUID, infoRequest, connectionLog).sendRequest();
}
}
public ConnectionLog getConnectionLog() {
return connectionLog;
} }
@Deprecated
public abstract boolean isServerAvailable(); public abstract boolean isServerAvailable();
@Deprecated
public abstract String getMainAddress(); public abstract String getMainAddress();
public abstract void sendWideInfoRequest(WideRequest infoRequest) throws NoServersException;
public List<Server> getDataServers() {
return new ArrayList<>(dataServers.values());
}
@Override
public void enable() {
infoRequests.initializeRequests();
}
@Override
public void disable() {
setupAllowed = false;
dataServers.clear();
infoRequests.clear();
}
} }

View File

@ -1,95 +0,0 @@
/*
* 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.system.info.connection;
import com.djrapitops.plan.api.exceptions.connection.NotFoundException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.request.InfoRequest;
import com.djrapitops.plan.system.webserver.Request;
import com.djrapitops.plan.system.webserver.RequestTarget;
import com.djrapitops.plan.system.webserver.pages.PageHandler;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plan.system.webserver.response.ResponseFactory;
import com.djrapitops.plan.system.webserver.response.errors.BadRequestResponse;
import com.djrapitops.plugin.logging.console.PluginLogger;
import com.djrapitops.plugin.utilities.Verify;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* PageHandler for /info/requestclassname pages.
* <p>
* Used for answering info requests by other servers.
* <p>
* requestclassname should be replaced with lowercase version of {@code Class.getSimpleName()}
*
* @author Rsl1122
*/
@Singleton
public class InfoRequestPageHandler implements PageHandler {
private final DBSystem dbSystem;
private final ConnectionSystem connectionSystem;
private final ResponseFactory responseFactory;
private final PluginLogger logger;
@Inject
public InfoRequestPageHandler(
DBSystem dbSystem,
ConnectionSystem connectionSystem,
ResponseFactory responseFactory, PluginLogger logger
) {
this.dbSystem = dbSystem;
this.connectionSystem = connectionSystem;
this.responseFactory = responseFactory;
this.logger = logger;
}
@Override
public Response getResponse(Request request, RequestTarget target) throws WebException {
int responseCode = 200;
try {
if (target.isEmpty()) {
return responseFactory.pageNotFound404();
}
if (!request.getRequestMethod().equals("POST")) {
return new BadRequestResponse("POST should be used for Info calls.");
}
String requestName = target.get(0);
InfoRequest infoRequest = connectionSystem.getInfoRequest(requestName);
Verify.nullCheck(infoRequest, () -> new NotFoundException("Info Request has not been registered."));
logger.debug("ConnectionIn: " + infoRequest.getClass().getSimpleName());
return new ConnectionIn(request, infoRequest, dbSystem.getDatabase(), connectionSystem).handleRequest();
} catch (WebException e) {
responseCode = getResponseCodeFor(e);
throw e;
} finally {
connectionSystem.getConnectionLog().logConnectionFrom(request.getRemoteAddress(), request.getTargetString(), responseCode);
}
}
private int getResponseCodeFor(WebException e) {
return e.getResponseCode().getCode();
}
}

View File

@ -16,24 +16,12 @@
*/ */
package com.djrapitops.plan.system.info.connection; package com.djrapitops.plan.system.info.connection;
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
import com.djrapitops.plan.api.exceptions.database.DBOpException;
import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.request.*;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.webserver.WebServer; import com.djrapitops.plan.system.webserver.WebServer;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.error.ErrorHandler;
import dagger.Lazy; import dagger.Lazy;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/** /**
* ConnectionSystem for proxy servers. * ConnectionSystem for proxy servers.
@ -43,70 +31,15 @@ import java.util.stream.Collectors;
@Singleton @Singleton
public class ProxyConnectionSystem extends ConnectionSystem { public class ProxyConnectionSystem extends ConnectionSystem {
private final DBSystem dbSystem;
private final Lazy<WebServer> webServer; private final Lazy<WebServer> webServer;
private final ErrorHandler errorHandler;
private final WebExceptionLogger webExceptionLogger;
private long latestServerMapRefresh;
@Inject @Inject
public ProxyConnectionSystem( public ProxyConnectionSystem(
DBSystem dbSystem,
Lazy<WebServer> webServer, Lazy<WebServer> webServer,
ConnectionLog connectionLog, ServerInfo serverInfo
InfoRequests infoRequests,
Lazy<InfoSystem> infoSystem,
ServerInfo serverInfo,
ErrorHandler errorHandler,
WebExceptionLogger webExceptionLogger
) { ) {
super(connectionLog, infoRequests, infoSystem, serverInfo); super(serverInfo);
this.dbSystem = dbSystem;
this.webServer = webServer; this.webServer = webServer;
this.errorHandler = errorHandler;
this.webExceptionLogger = webExceptionLogger;
latestServerMapRefresh = 0;
}
private void refreshServerMap() {
if (latestServerMapRefresh < System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(15L)) {
try {
dataServers = dbSystem.getDatabase().query(ServerQueries.fetchPlanServerInformation()).entrySet().stream()
.filter(entry -> entry.getValue().isNotProxy())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
latestServerMapRefresh = System.currentTimeMillis();
} catch (DBOpException e) {
errorHandler.log(L.ERROR, this.getClass(), e);
}
}
}
@Override
protected Server selectServerForRequest(InfoRequest infoRequest) throws NoServersException {
refreshServerMap();
if (infoRequest instanceof CacheRequest
|| infoRequest instanceof GenerateInspectPageRequest
|| infoRequest instanceof GenerateInspectPluginsTabRequest) {
// Run locally
return serverInfo.getServer();
}
throw new NoServersException("Proper server is not available to process request: " + infoRequest.getClass().getSimpleName());
}
@Override
public void sendWideInfoRequest(WideRequest infoRequest) throws NoServersException {
refreshServerMap();
if (dataServers.isEmpty()) {
throw new NoServersException("No Servers available to make wide-request: " + infoRequest.getClass().getSimpleName());
}
for (Server server : dataServers.values()) {
webExceptionLogger.logIfOccurs(this.getClass(), () -> sendInfoRequest(infoRequest, server));
}
// Quick hack for Bungee Plugins Tab
if (infoRequest instanceof GenerateInspectPluginsTabRequest) {
webExceptionLogger.logIfOccurs(this.getClass(), infoRequest::runLocally);
}
} }
@Override @Override
@ -119,10 +52,4 @@ public class ProxyConnectionSystem extends ConnectionSystem {
return webServer.get().getAccessAddress(); return webServer.get().getAccessAddress();
} }
@Override
public void enable() {
super.enable();
refreshServerMap();
}
} }

View File

@ -16,24 +16,12 @@
*/ */
package com.djrapitops.plan.system.info.connection; package com.djrapitops.plan.system.info.connection;
import com.djrapitops.plan.api.exceptions.connection.ConnectionFailException;
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
import com.djrapitops.plan.db.Database; import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.queries.objects.ServerQueries; import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import com.djrapitops.plan.system.database.DBSystem; import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.request.*;
import com.djrapitops.plan.system.info.server.Server; import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.locale.Locale;
import com.djrapitops.plan.system.locale.lang.PluginLang;
import com.djrapitops.plan.system.processing.Processing; import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.WebserverSettings;
import com.djrapitops.plan.system.webserver.WebServer;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.console.PluginLogger;
import dagger.Lazy;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -50,13 +38,8 @@ import java.util.concurrent.TimeUnit;
@Singleton @Singleton
public class ServerConnectionSystem extends ConnectionSystem { public class ServerConnectionSystem extends ConnectionSystem {
private final Locale locale;
private final PlanConfig config;
private final Processing processing; private final Processing processing;
private final DBSystem dbSystem; private final DBSystem dbSystem;
private final Lazy<WebServer> webServer;
private final PluginLogger pluginLogger;
private final WebExceptionLogger webExceptionLogger;
private long latestServerMapRefresh; private long latestServerMapRefresh;
@ -64,32 +47,20 @@ public class ServerConnectionSystem extends ConnectionSystem {
@Inject @Inject
public ServerConnectionSystem( public ServerConnectionSystem(
Locale locale,
PlanConfig config,
Processing processing, Processing processing,
DBSystem dbSystem, DBSystem dbSystem,
Lazy<WebServer> webServer, ServerInfo serverInfo
ConnectionLog connectionLog,
InfoRequests infoRequests,
Lazy<InfoSystem> infoSystem,
ServerInfo serverInfo,
PluginLogger pluginLogger,
WebExceptionLogger webExceptionLogger
) { ) {
super(connectionLog, infoRequests, infoSystem, serverInfo); super(serverInfo);
this.locale = locale;
this.config = config;
this.processing = processing; this.processing = processing;
this.dbSystem = dbSystem; this.dbSystem = dbSystem;
this.webServer = webServer;
this.pluginLogger = pluginLogger;
this.webExceptionLogger = webExceptionLogger;
latestServerMapRefresh = 0; latestServerMapRefresh = 0;
} }
private void refreshServerMap() { private void refreshServerMap() {
processing.submitNonCritical(() -> { processing.submitNonCritical(() -> {
if (latestServerMapRefresh < System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(15L)) { if (latestServerMapRefresh < System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(15L)) {
Database database = dbSystem.getDatabase(); Database database = dbSystem.getDatabase();
Map<UUID, Server> servers = database.query(ServerQueries.fetchPlanServerInformation()); Map<UUID, Server> servers = database.query(ServerQueries.fetchPlanServerInformation());
Optional<Server> proxy = servers.values().stream() Optional<Server> proxy = servers.values().stream()
@ -98,73 +69,21 @@ public class ServerConnectionSystem extends ConnectionSystem {
mainServer = proxy.orElse(null); mainServer = proxy.orElse(null);
proxy.ifPresent(proxyServer -> servers.remove(proxyServer.getUuid())); proxy.ifPresent(proxyServer -> servers.remove(proxyServer.getUuid()));
dataServers = servers;
latestServerMapRefresh = System.currentTimeMillis(); latestServerMapRefresh = System.currentTimeMillis();
} }
}); });
} }
@Override
protected Server selectServerForRequest(InfoRequest infoRequest) throws NoServersException {
refreshServerMap();
if (mainServer == null && dataServers.isEmpty()) {
throw new NoServersException("Zero servers available to process requests.");
}
Server server = null;
if (infoRequest instanceof CacheRequest ||
infoRequest instanceof GenerateInspectPageRequest) {
server = mainServer;
}
if (server == null) {
throw new NoServersException("Proper server is not available to process request: " + infoRequest.getClass().getSimpleName());
}
return server;
}
@Override
public void sendWideInfoRequest(WideRequest infoRequest) throws NoServersException {
if (dataServers.isEmpty()) {
throw new NoServersException("No Servers available to make wide-request: " + infoRequest.getClass().getSimpleName());
}
for (Server server : dataServers.values()) {
webExceptionLogger.logIfOccurs(this.getClass(), () -> {
try {
sendInfoRequest(infoRequest, server);
} catch (ConnectionFailException ignored) {
/* Wide Requests are used when at least one result is wanted. */
}
});
}
}
@Override @Override
public boolean isServerAvailable() { public boolean isServerAvailable() {
refreshServerMap();
return mainServer != null; return mainServer != null;
} }
@Override @Override
public String getMainAddress() { public String getMainAddress() {
refreshServerMap();
return isServerAvailable() ? mainServer.getWebAddress() : serverInfo.getServer().getWebAddress(); return isServerAvailable() ? mainServer.getWebAddress() : serverInfo.getServer().getWebAddress();
} }
@Override
public void enable() {
super.enable();
refreshServerMap();
boolean usingBungeeWebServer = isServerAvailable();
boolean usingAlternativeIP = config.isTrue(WebserverSettings.SHOW_ALTERNATIVE_IP);
if (!usingAlternativeIP && serverInfo.getServerProperties().getIp().isEmpty()) {
pluginLogger.log(L.INFO_COLOR, "§e" + locale.getString(PluginLang.ENABLE_NOTIFY_EMPTY_IP));
}
if (usingBungeeWebServer && usingAlternativeIP) {
String webServerAddress = webServer.get().getAccessAddress();
pluginLogger.info(locale.getString(PluginLang.ENABLE_NOTIFY_ADDRESS_CONFIRMATION, webServerAddress));
}
}
} }

View File

@ -1,96 +0,0 @@
/*
* 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.system.info.connection;
import com.djrapitops.plan.api.exceptions.connection.*;
import com.djrapitops.plan.utilities.java.ThrowingVoidFunction;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.console.PluginLogger;
import com.djrapitops.plugin.logging.error.ErrorHandler;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Class that decides what to do with WebExceptions.
*
* @author Rsl1122
*/
@Singleton
public class WebExceptionLogger {
private final ConnectionLog connectionLog;
private final PluginLogger logger;
private final ErrorHandler errorHandler;
@Inject
public WebExceptionLogger(
ConnectionLog connectionLog,
PluginLogger logger,
ErrorHandler errorHandler
) {
this.connectionLog = connectionLog;
this.logger = logger;
this.errorHandler = errorHandler;
}
public void logIfOccurs(Class definingClass, ThrowingVoidFunction<WebException> function) {
try {
function.apply();
} catch (ConnectionFailException e) {
if (shouldLog(e)) {
logger.debug(e.getMessage());
}
} catch (UnauthorizedServerException | NotFoundException | NoServersException e) {
logger.debug(e.getMessage());
} catch (WebException e) {
errorHandler.log(L.WARN, definingClass, e);
}
}
private boolean shouldLog(ConnectionFailException e) {
String address = getAddress(e);
if (address == null) {
return true;
}
Map<String, Map<String, ConnectionLog.Entry>> logEntries = connectionLog.getLogEntries();
Map<String, ConnectionLog.Entry> entries = logEntries.get("Out: " + address);
if (entries != null) {
List<ConnectionLog.Entry> connections = new ArrayList<>(entries.values());
Collections.sort(connections);
return connections.isEmpty() || connections.get(0).getResponseCode() != -1;
}
return true;
}
private static String getAddress(ConnectionFailException e) {
if (e.getMessage().contains("to address")) {
String[] split = e.getMessage().split("to address: ");
if (split.length == 2) {
String[] split2 = split[1].split("<br>");
if (split2.length == 2) {
return split2[0];
}
}
}
return null;
}
}

View File

@ -1,122 +0,0 @@
/*
* 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.system.info.request;
import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.export.HtmlExport;
import com.djrapitops.plan.system.export.JSONExport;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.ExportSettings;
import com.djrapitops.plan.system.webserver.cache.PageId;
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plan.system.webserver.response.pages.InspectPageResponse;
import com.djrapitops.plan.utilities.Base64Util;
import com.djrapitops.plugin.utilities.Verify;
import org.apache.commons.text.StringSubstitutor;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
/**
* InfoRequest used to place HTML of a player to ResponseCache.
*
* @author Rsl1122
*/
public class CacheInspectPageRequest extends InfoRequestWithVariables implements CacheRequest {
private final PlanConfig config;
private final Processing processing;
private final ServerInfo serverInfo;
private final HtmlExport htmlExport;
private final JSONExport jsonExport;
private UUID player;
private String html;
CacheInspectPageRequest(
PlanConfig config,
Processing processing,
ServerInfo serverInfo,
HtmlExport htmlExport,
JSONExport jsonExport
) {
this.config = config;
this.processing = processing;
this.serverInfo = serverInfo;
this.htmlExport = htmlExport;
this.jsonExport = jsonExport;
}
CacheInspectPageRequest(
UUID player, String html,
PlanConfig config,
Processing processing,
ServerInfo serverInfo,
HtmlExport htmlExport,
JSONExport jsonExport
) {
this.config = config;
this.processing = processing;
this.serverInfo = serverInfo;
this.htmlExport = htmlExport;
this.jsonExport = jsonExport;
Verify.nullCheck(player, html);
variables.put("player", player.toString());
variables.put("html", Base64Util.encode(html));
this.player = player;
this.html = html;
}
@Override
public Response handleRequest(Map<String, String> variables) throws WebException {
// Available variables: sender, player, html (Base64)
String player = variables.get("player");
Verify.nullCheck(player, () -> new BadRequestException("Player UUID 'player' variable not supplied in the request."));
UUID uuid = UUID.fromString(player);
String html = variables.get("html");
Verify.nullCheck(html, () -> new BadRequestException("HTML 'html' variable not supplied in the request"));
Map<String, String> replace = Collections.singletonMap("networkName", serverInfo.getServer().getName());
cache(uuid, StringSubstitutor.replace(Base64Util.decode(html), replace));
return DefaultResponses.SUCCESS.get();
}
private void cache(UUID playerUUID, String html) {
ResponseCache.cacheResponse(PageId.PLAYER.of(playerUUID), () -> new InspectPageResponse(playerUUID, html));
if (config.get(ExportSettings.PLAYER_PAGES)) {
processing.submitNonCritical(() -> htmlExport.exportCachedPlayerPage(playerUUID));
}
if (config.get(ExportSettings.PLAYER_JSON)) {
processing.submitNonCritical(() -> jsonExport.exportPlayerJSON(playerUUID));
}
}
@Override
public void runLocally() {
cache(player, html);
}
}

View File

@ -1,83 +0,0 @@
/*
* 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.system.info.request;
import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.webserver.cache.PageId;
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plan.system.webserver.response.pages.parts.InspectPagePluginsContent;
import com.djrapitops.plan.utilities.Base64Util;
import com.djrapitops.plugin.utilities.Verify;
import java.util.Map;
import java.util.UUID;
/**
* InfoRequest used to place HTML of player's Plugins Tab to ResponseCache.
*
* @deprecated Marked for removal when the connection system will be removed.
* @author Rsl1122
*/
@Deprecated
public class CacheInspectPluginsTabRequest extends InfoRequestWithVariables implements CacheRequest {
private UUID player;
private String html;
CacheInspectPluginsTabRequest() {
}
CacheInspectPluginsTabRequest(UUID player, String nav, String html) {
Verify.nullCheck(player, nav);
variables.put("player", player.toString());
variables.put("nav", nav);
variables.put("html", Base64Util.encode(html));
this.player = player;
this.html = html;
}
@Override
public Response handleRequest(Map<String, String> variables) throws WebException {
// Available variables: sender, player, nav, html
String player = variables.get("player");
Verify.nullCheck(player, () -> new BadRequestException("Player UUID 'player' variable not supplied in the request."));
UUID uuid = UUID.fromString(player);
String nav = variables.get("nav");
String html = variables.get("html");
Verify.nullCheck(nav, () -> new BadRequestException("Nav HTML 'nav' variable not supplied in the request"));
Verify.nullCheck(html, () -> new BadRequestException("HTML 'html' variable not supplied in the request"));
InspectPagePluginsContent pluginsTab = getPluginsTab(uuid);
pluginsTab.addTab(nav, Base64Util.decode(html));
return DefaultResponses.SUCCESS.get();
}
private InspectPagePluginsContent getPluginsTab(UUID uuid) {
return (InspectPagePluginsContent) ResponseCache.loadResponse(PageId.PLAYER_PLUGINS_TAB.of(uuid), InspectPagePluginsContent::new);
}
@Override
public void runLocally() {
getPluginsTab(player).addTab(variables.get("nav"), html);
}
}

View File

@ -1,25 +0,0 @@
/*
* 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.system.info.request;
/**
* Interface for all InfoRequests that cache something into RequestCache.
*
* @author Rsl1122
*/
public interface CacheRequest extends InfoRequest {
}

View File

@ -1,93 +0,0 @@
/*
* 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.system.info.request;
import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
import com.djrapitops.plan.api.exceptions.connection.ConnectionFailException;
import com.djrapitops.plan.api.exceptions.connection.GatewayException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plugin.utilities.Verify;
import java.util.Map;
import java.util.UUID;
/**
* InfoRequest used for Checking Bukkit-Bungee connections.
*
* @author Rsl1122
*/
public class CheckConnectionRequest extends InfoRequestWithVariables {
private final ServerInfo serverInfo;
private final ConnectionSystem connectionSystem;
CheckConnectionRequest(String webServerAddress, ServerInfo serverInfo, ConnectionSystem connectionSystem) {
this.serverInfo = serverInfo;
this.connectionSystem = connectionSystem;
Verify.nullCheck(webServerAddress, () -> new IllegalArgumentException("webServerAddress can not be null."));
variables.put("address", webServerAddress);
variables.put("continue", "yes");
}
CheckConnectionRequest(ServerInfo serverInfo, ConnectionSystem connectionSystem) {
this.serverInfo = serverInfo;
this.connectionSystem = connectionSystem;
}
@Override
public void runLocally() {
/* Won't be run */
}
@Override
public Response handleRequest(Map<String, String> variables) throws WebException {
// Available variables: sender, address
if (serverInfo.getServer().isProxy()) {
attemptConnection(variables);
}
return DefaultResponses.SUCCESS.get();
}
private void attemptConnection(Map<String, String> variables) throws WebException {
// Continue variable not present in rebound connection, leading to a single round ping.
boolean shouldNotContinue = variables.get("continue") == null;
if (shouldNotContinue) {
return;
}
String address = variables.get("address");
Verify.nullCheck(address, () -> new BadRequestException("WebServer Address ('address') not specified in the request."));
UUID serverUUID = UUID.fromString(variables.get("sender"));
Server bukkit = new Server(-1, serverUUID, "", address, -1);
try {
connectionSystem.sendInfoRequest(new CheckConnectionRequest(serverInfo, connectionSystem), bukkit);
} catch (ConnectionFailException e) {
throw new GatewayException(e.getMessage());
}
}
}

View File

@ -1,119 +0,0 @@
/*
* 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.system.info.request;
import com.djrapitops.plan.api.exceptions.ParseException;
import com.djrapitops.plan.api.exceptions.connection.*;
import com.djrapitops.plan.api.exceptions.database.DBOpException;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plan.system.webserver.response.ResponseFactory;
import com.djrapitops.plan.utilities.html.pages.PageFactory;
import com.djrapitops.plugin.utilities.Verify;
import java.util.Map;
import java.util.UUID;
/**
* InfoRequest for Generating Inspect page on receiving WebServer.
*
* @author Rsl1122
*/
public class GenerateInspectPageRequest extends InfoRequestWithVariables implements GenerateRequest {
private final InfoRequestFactory infoRequestFactory;
private final ResponseFactory responseFactory;
private final PageFactory pageFactory;
private final InfoSystem infoSystem;
private UUID playerUUID;
GenerateInspectPageRequest(
InfoRequestFactory infoRequestFactory,
ResponseFactory responseFactory, PageFactory pageFactory,
InfoSystem infoSystem
) {
this.infoRequestFactory = infoRequestFactory;
this.responseFactory = responseFactory;
this.pageFactory = pageFactory;
this.infoSystem = infoSystem;
}
GenerateInspectPageRequest(
UUID uuid,
InfoRequestFactory infoRequestFactory,
ResponseFactory responseFactory, PageFactory pageFactory,
InfoSystem infoSystem
) {
this.infoRequestFactory = infoRequestFactory;
this.responseFactory = responseFactory;
this.pageFactory = pageFactory;
this.infoSystem = infoSystem;
Verify.nullCheck(uuid);
playerUUID = uuid;
variables.put("player", uuid.toString());
}
@Override
public Response handleRequest(Map<String, String> variables) throws WebException {
// Available variables: sender, player
String player = variables.get("player");
Verify.nullCheck(player, () -> new BadRequestException("Player UUID 'player' variable not supplied in the request."));
UUID uuid = UUID.fromString(player);
generateAndCache(uuid);
return DefaultResponses.SUCCESS.get();
}
private void generateAndCache(UUID uuid) throws WebException {
String html;
try {
html = getHtml(uuid);
infoSystem.getConnectionSystem().sendWideInfoRequest(infoRequestFactory.generateInspectPluginsTabRequest(uuid));
} catch (NotFoundException e) {
html = responseFactory.notFound404(e.getMessage()).getContent();
}
infoSystem.sendRequest(infoRequestFactory.cacheInspectPageRequest(uuid, html));
}
@Override
public void runLocally() throws WebException {
generateAndCache(playerUUID);
}
private String getHtml(UUID uuid) throws WebException {
try {
return pageFactory.inspectPage(uuid).toHtml();
} catch (ParseException e) {
Throwable cause = e.getCause();
if (cause instanceof DBOpException) {
throw new TransferDatabaseException((DBOpException) cause);
} else if (cause instanceof IllegalStateException && "Player profile was null!".equals(cause.getMessage())) {
throw new NotFoundException("Player has not played on this server.");
} else {
throw new WebFailException("Exception during HTML Parsing", cause);
}
}
}
}

View File

@ -1,90 +0,0 @@
/*
* 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.system.info.request;
import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plan.utilities.html.pages.PageFactory;
import com.djrapitops.plugin.utilities.Verify;
import java.util.Map;
import java.util.UUID;
/**
* InfoRequest for Generating Inspect page plugins tab on receiving WebServer.
*
* @deprecated Marked for removal when the connection system will be removed.
* @author Rsl1122
*/
@Deprecated
public class GenerateInspectPluginsTabRequest extends InfoRequestWithVariables implements GenerateRequest, WideRequest {
private final InfoSystem infoSystem;
private final InfoRequestFactory infoRequestFactory;
private final PageFactory pageFactory;
private UUID playerUUID;
GenerateInspectPluginsTabRequest(
InfoSystem infoSystem,
InfoRequestFactory infoRequestFactory,
PageFactory pageFactory
) {
this.infoSystem = infoSystem;
this.infoRequestFactory = infoRequestFactory;
this.pageFactory = pageFactory;
}
GenerateInspectPluginsTabRequest(
UUID uuid,
InfoSystem infoSystem,
InfoRequestFactory infoRequestFactory,
PageFactory pageFactory
) {
this(infoSystem, infoRequestFactory, pageFactory);
Verify.nullCheck(uuid);
playerUUID = uuid;
variables.put("player", uuid.toString());
}
@Override
public Response handleRequest(Map<String, String> variables) throws WebException {
// Available variables: sender, player
String player = variables.get("player");
Verify.nullCheck(player, () -> new BadRequestException("Player UUID 'player' variable not supplied in the request."));
UUID uuid = UUID.fromString(player);
generateAndCache(uuid);
return DefaultResponses.SUCCESS.get();
}
private void generateAndCache(UUID uuid) throws WebException {
String[] navAndHtml = pageFactory.inspectPagePluginsContent(uuid).getContents();
infoSystem.sendRequest(infoRequestFactory.cacheInspectPluginsTabRequest(uuid, navAndHtml[0], navAndHtml[1]));
}
@Override
public void runLocally() throws WebException {
generateAndCache(playerUUID);
}
}

View File

@ -1,25 +0,0 @@
/*
* 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.system.info.request;
/**
* Interface for all InfoRequests that generate something.
*
* @author Rsl1122
*/
public interface GenerateRequest extends InfoRequest {
}

View File

@ -1,35 +0,0 @@
/*
* 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.system.info.request;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.webserver.response.Response;
import java.util.Map;
/**
* Represents a request that Plan servers can send each other.
*
* @author Rsl1122
*/
public interface InfoRequest {
Response handleRequest(Map<String, String> variables) throws WebException;
void runLocally() throws WebException;
}

View File

@ -1,185 +0,0 @@
/*
* 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.system.info.request;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.system.export.HtmlExport;
import com.djrapitops.plan.system.export.JSONExport;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.webserver.response.ResponseFactory;
import com.djrapitops.plan.utilities.html.pages.PageFactory;
import com.djrapitops.plugin.logging.console.PluginLogger;
import com.djrapitops.plugin.task.RunnableFactory;
import dagger.Lazy;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.UUID;
/**
* Factory for {@link InfoRequest} objects used for server-server communications.
*
* @author Rsl1122
*/
@Singleton
public class InfoRequestFactory {
private final Lazy<PlanPlugin> plugin;
private final Lazy<PlanConfig> config;
private final Lazy<Processing> processing;
private final Lazy<InfoSystem> infoSystem;
private final Lazy<ConnectionSystem> connectionSystem;
private final Lazy<ServerInfo> serverInfo;
private final Lazy<ResponseFactory> responseFactory;
private final Lazy<PageFactory> pageFactory;
private final Lazy<HtmlExport> htmlExport;
private final Lazy<JSONExport> jsonExport;
private final Lazy<PluginLogger> logger;
private final Lazy<RunnableFactory> runnableFactory;
@Inject
public InfoRequestFactory(
Lazy<PlanPlugin> plugin,
Lazy<PlanConfig> config,
Lazy<Processing> processing,
Lazy<InfoSystem> infoSystem,
Lazy<ConnectionSystem> connectionSystem,
Lazy<ServerInfo> serverInfo,
Lazy<ResponseFactory> responseFactory,
Lazy<PageFactory> pageFactory,
Lazy<HtmlExport> htmlExport,
Lazy<JSONExport> jsonExport,
Lazy<PluginLogger> logger,
Lazy<RunnableFactory> runnableFactory
) {
this.plugin = plugin;
this.config = config;
this.processing = processing;
this.infoSystem = infoSystem;
this.connectionSystem = connectionSystem;
this.serverInfo = serverInfo;
this.responseFactory = responseFactory;
this.pageFactory = pageFactory;
this.htmlExport = htmlExport;
this.jsonExport = jsonExport;
this.logger = logger;
this.runnableFactory = runnableFactory;
}
public CacheRequest cacheInspectPageRequest(UUID uuid, String html) {
return new CacheInspectPageRequest(
uuid, html,
config.get(), processing.get(),
serverInfo.get(),
htmlExport.get(), jsonExport.get()
);
}
@Deprecated
public CacheRequest cacheInspectPluginsTabRequest(UUID uuid, String nav, String html) {
return new CacheInspectPluginsTabRequest(uuid, nav, html);
}
public GenerateRequest generateInspectPageRequest(UUID uuid) {
return new GenerateInspectPageRequest(uuid, this, responseFactory.get(), pageFactory.get(), infoSystem.get());
}
@Deprecated
public GenerateInspectPluginsTabRequest generateInspectPluginsTabRequest(UUID uuid) {
return new GenerateInspectPluginsTabRequest(uuid, infoSystem.get(), this, pageFactory.get());
}
public SaveDBSettingsRequest saveDBSettingsRequest() {
return new SaveDBSettingsRequest(plugin.get(), config.get(), serverInfo.get(), logger.get(), runnableFactory.get());
}
public SetupRequest sendDBSettingsRequest(String addressOfThisServer) {
return new SendDBSettingsRequest(addressOfThisServer, serverInfo.get(), this, connectionSystem.get());
}
public CheckConnectionRequest checkConnectionRequest(String webAddress) {
return new CheckConnectionRequest(webAddress, serverInfo.get(), connectionSystem.get());
}
@Singleton
public static class Handlers {
private final InfoRequestFactory factory;
@Inject
public Handlers(InfoRequestFactory factory) {
this.factory = factory;
}
CacheRequest cacheInspectPageRequest() {
return new CacheInspectPageRequest(
factory.config.get(),
factory.processing.get(),
factory.serverInfo.get(),
factory.htmlExport.get(),
factory.jsonExport.get()
);
}
CacheRequest cacheInspectPluginsTabRequest() {
return new CacheInspectPluginsTabRequest();
}
CheckConnectionRequest checkConnectionRequest() {
return new CheckConnectionRequest(factory.serverInfo.get(), factory.connectionSystem.get());
}
GenerateRequest generateInspectPageRequest() {
return new GenerateInspectPageRequest(
factory,
factory.responseFactory.get(),
factory.pageFactory.get(),
factory.infoSystem.get()
);
}
GenerateRequest generateInspectPluginsTabRequest() {
return new GenerateInspectPluginsTabRequest(
factory.infoSystem.get(),
factory,
factory.pageFactory.get()
);
}
SetupRequest saveDBSettingsRequest() {
return new SaveDBSettingsRequest(
factory.plugin.get(),
factory.config.get(),
factory.serverInfo.get(),
factory.logger.get(),
factory.runnableFactory.get()
);
}
SetupRequest sendDBSettingsRequest() {
return new SendDBSettingsRequest(
factory.serverInfo.get(),
factory,
factory.connectionSystem.get()
);
}
}
}

View File

@ -1,40 +0,0 @@
/*
* 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.system.info.request;
import java.util.HashMap;
import java.util.Map;
/**
* Abstract InfoRequest that contains variables in request body.
* <p>
* Used to send request differently.
*
* @author Rsl1122
*/
public abstract class InfoRequestWithVariables implements InfoRequest {
protected final Map<String, String> variables;
public InfoRequestWithVariables() {
this.variables = new HashMap<>();
}
public Map<String, String> getVariables() {
return variables;
}
}

View File

@ -1,67 +0,0 @@
/*
* 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.system.info.request;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.HashMap;
import java.util.Map;
/**
* Map object that holds {@link InfoRequest} objects used for handling incoming requests.
* <p>
* Convenience class for Dagger injection.
*
* @author Rsl1122
*/
@Singleton
public class InfoRequests {
private final InfoRequestFactory.Handlers handlerFactory;
private final Map<String, InfoRequest> requestHandlers;
@Inject
public InfoRequests(InfoRequestFactory.Handlers handlerFactory) {
this.handlerFactory = handlerFactory;
this.requestHandlers = new HashMap<>();
}
public void initializeRequests() {
putRequest(handlerFactory.cacheInspectPageRequest());
putRequest(handlerFactory.cacheInspectPluginsTabRequest());
putRequest(handlerFactory.generateInspectPageRequest());
putRequest(handlerFactory.generateInspectPluginsTabRequest());
putRequest(handlerFactory.saveDBSettingsRequest());
putRequest(handlerFactory.sendDBSettingsRequest());
putRequest(handlerFactory.checkConnectionRequest());
}
private void putRequest(InfoRequest request) {
requestHandlers.put(request.getClass().getSimpleName().toLowerCase(), request);
}
public InfoRequest get(String name) {
return requestHandlers.get(name);
}
public void clear() {
requestHandlers.clear();
}
}

View File

@ -1,130 +0,0 @@
/*
* 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.system.info.request;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
import com.djrapitops.plan.api.exceptions.connection.InternalErrorException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.DatabaseSettings;
import com.djrapitops.plan.system.settings.paths.PluginSettings;
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plan.system.webserver.response.errors.BadRequestResponse;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.logging.console.PluginLogger;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.task.RunnableFactory;
import com.djrapitops.plugin.utilities.Verify;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* InfoRequest for sending Database config settings to Bukkit servers.
*
* @author Rsl1122
*/
public class SaveDBSettingsRequest extends InfoRequestWithVariables implements SetupRequest {
private final PlanPlugin plugin;
private final PlanConfig config;
private final ServerInfo serverInfo;
private final PluginLogger logger;
private final RunnableFactory runnableFactory;
SaveDBSettingsRequest(
PlanPlugin plugin,
PlanConfig config,
ServerInfo serverInfo, PluginLogger logger,
RunnableFactory runnableFactory
) {
this.plugin = plugin;
this.config = config;
this.serverInfo = serverInfo;
this.logger = logger;
this.runnableFactory = runnableFactory;
variables.put("DB_TYPE", "mysql"); // DatabaseSettings.TYPE
variables.put("DB_HOST", config.get(DatabaseSettings.MYSQL_HOST));
variables.put("DB_USER", config.get(DatabaseSettings.MYSQL_USER));
variables.put("DB_PASS", config.get(DatabaseSettings.MYSQL_PASS));
variables.put("DB_DATABASE", config.get(DatabaseSettings.MYSQL_DATABASE));
variables.put("DB_PORT", config.get(DatabaseSettings.MYSQL_PORT));
}
@Override
public void runLocally() {
/* Won't be run */
}
@Override
public Response handleRequest(Map<String, String> variables) throws WebException {
if (serverInfo.getServer().isProxy()) {
return new BadRequestResponse("Not supposed to be called on a proxy server");
}
if (config.isFalse(PluginSettings.BUNGEE_COPY_CONFIG)) {
return new BadRequestResponse("Bungee config settings overridden on this server.");
}
try {
setSettings(variables);
logger.info("----------------------------------");
logger.info("The Received Bungee Database Settings, restarting Plan..");
logger.info("----------------------------------");
return DefaultResponses.SUCCESS.get();
} finally {
runnableFactory.create("Bungee Setup Restart Task", new AbsRunnable() {
@Override
public void run() {
plugin.reloadPlugin(true);
}
}).runTaskLater(TimeAmount.toTicks(2L, TimeUnit.SECONDS));
}
}
private void setSettings(Map<String, String> variables) throws BadRequestException, InternalErrorException {
String type = variables.get("DB_TYPE");
String host = variables.get("DB_HOST");
String user = variables.get("DB_USER");
String pass = variables.get("DB_PASS");
String database = variables.get("DB_DATABASE");
String portS = variables.get("DB_PORT");
Verify.nullCheck(type, () -> new BadRequestException("DB_TYPE not specified in the request."));
Verify.nullCheck(host, () -> new BadRequestException("DB_HOST not specified in the request."));
Verify.nullCheck(user, () -> new BadRequestException("DB_USER not specified in the request."));
Verify.nullCheck(pass, () -> new BadRequestException("DB_PASS not specified in the request."));
Verify.nullCheck(database, () -> new BadRequestException("DB_DATABASE not specified in the request."));
Verify.nullCheck(portS, () -> new BadRequestException("DB_PORT not specified in the request."));
config.set(DatabaseSettings.MYSQL_PORT, portS);
config.set(DatabaseSettings.TYPE, type);
config.set(DatabaseSettings.MYSQL_HOST, host);
config.set(DatabaseSettings.MYSQL_USER, user);
config.set(DatabaseSettings.MYSQL_PASS, pass);
config.set(DatabaseSettings.MYSQL_DATABASE, database);
try {
config.save();
} catch (IOException e) {
throw new InternalErrorException("Failed to Save Config", e);
}
}
}

View File

@ -1,96 +0,0 @@
/*
* 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.system.info.request;
import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
import com.djrapitops.plan.api.exceptions.connection.ConnectionFailException;
import com.djrapitops.plan.api.exceptions.connection.GatewayException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plan.system.webserver.response.errors.BadRequestResponse;
import com.djrapitops.plugin.utilities.Verify;
import java.net.SocketException;
import java.util.Map;
import java.util.UUID;
/**
* InfoRequest used for requesting DB settings from Bungee.
*
* @author Rsl1122
*/
public class SendDBSettingsRequest extends InfoRequestWithVariables implements SetupRequest {
private final ServerInfo serverInfo;
private final InfoRequestFactory infoRequestFactory;
private final ConnectionSystem connectionSystem;
SendDBSettingsRequest(
ServerInfo serverInfo, InfoRequestFactory infoRequestFactory, ConnectionSystem connectionSystem
) {
this.serverInfo = serverInfo;
this.infoRequestFactory = infoRequestFactory;
this.connectionSystem = connectionSystem;
}
SendDBSettingsRequest(
String webServerAddress,
ServerInfo serverInfo, InfoRequestFactory infoRequestFactory, ConnectionSystem connectionSystem
) {
this.serverInfo = serverInfo;
this.infoRequestFactory = infoRequestFactory;
this.connectionSystem = connectionSystem;
Verify.nullCheck(webServerAddress, () -> new IllegalArgumentException("webServerAddress can not be null."));
variables.put("address", webServerAddress);
}
@Override
public void runLocally() {
/* Won't be run */
}
@Override
public Response handleRequest(Map<String, String> variables) throws WebException {
// Available variables: sender, address
if (serverInfo.getServer().isNotProxy()) {
return new BadRequestResponse("Not supposed to be called on a non proxy server");
}
String address = variables.get("address");
Verify.nullCheck(address, () -> new BadRequestException("WebServer Address ('address') not specified in the request."));
UUID serverUUID = UUID.fromString(variables.get("sender"));
Server bukkit = new Server(-1, serverUUID, null, address, -1);
try {
connectionSystem.sendInfoRequest(infoRequestFactory.saveDBSettingsRequest(), bukkit);
} catch (ConnectionFailException e) {
Throwable cause = e.getCause();
if (!(cause instanceof SocketException) || !cause.getMessage().contains("Unexpected end of file from server")) {
throw new GatewayException(e.getMessage());
}
}
return DefaultResponses.SUCCESS.get();
}
}

View File

@ -1,26 +0,0 @@
/*
* 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.system.info.request;
/**
* InfoRequest that is related to initial communications.
*
* @author Rsl1122
*/
public interface SetupRequest extends InfoRequest {
}

View File

@ -1,25 +0,0 @@
/*
* 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.system.info.request;
/**
* InfoRequest that should be relayed to all Bukkit servers.
*
* @author Rsl1122
*/
public interface WideRequest extends InfoRequest {
}

View File

@ -36,7 +36,9 @@ public enum CmdHelpLang implements Lang {
WEB_REGISTER("Command Help - /plan register", "Register a Web User"), WEB_REGISTER("Command Help - /plan register", "Register a Web User"),
WEB("Command Help - /plan webuser", "Manage Web Users"), WEB("Command Help - /plan webuser", "Manage Web Users"),
DEV("Command Help - /plan dev", "Development mode command"), DEV("Command Help - /plan dev", "Development mode command"),
@Deprecated
SETUP("Command Help - /planbungee setup", "Toggle set-up mode"), SETUP("Command Help - /planbungee setup", "Toggle set-up mode"),
@Deprecated
CON("Command Help - /planbungee con", "Debug Proxy-Server connections"), CON("Command Help - /planbungee con", "Debug Proxy-Server connections"),
DISABLE("Command Help - /planbungee disable", "Disable the plugin temporarily"), DISABLE("Command Help - /planbungee disable", "Disable the plugin temporarily"),
@ -46,10 +48,12 @@ public enum CmdHelpLang implements Lang {
MANAGE_REMOVE("Command Help - /plan manage remove", "Remove Player's data"), MANAGE_REMOVE("Command Help - /plan manage remove", "Remove Player's data"),
MANAGE_HOTSWAP("Command Help - /plan manage hotswap", "Change Database quickly"), MANAGE_HOTSWAP("Command Help - /plan manage hotswap", "Change Database quickly"),
MANAGE_CLEAR("Command Help - /plan manage clear", "Clear a Database"), MANAGE_CLEAR("Command Help - /plan manage clear", "Clear a Database"),
@Deprecated
MANAGE_CON("Command Help - /plan manage con", "Debug Server-Proxy connections"), MANAGE_CON("Command Help - /plan manage con", "Debug Server-Proxy connections"),
MANAGE_IMPORT("Command Help - /plan manage import", "Import data from elsewhere"), MANAGE_IMPORT("Command Help - /plan manage import", "Import data from elsewhere"),
MANAGE_EXPORT("Command Help - /plan manage export", "Trigger export manually"), MANAGE_EXPORT("Command Help - /plan manage export", "Trigger export manually"),
MANAGE_DISABLE("Command Help - /plan manage disable", "Disable a feature temporarily"), MANAGE_DISABLE("Command Help - /plan manage disable", "Disable a feature temporarily"),
@Deprecated
MANAGE_SETUP("Command Help - /plan manage setup", "Set-up Server-Proxy connection"), MANAGE_SETUP("Command Help - /plan manage setup", "Set-up Server-Proxy connection"),
WEB_LEVEL("Command Help - /plan web level", "Information about permission levels"), WEB_LEVEL("Command Help - /plan web level", "Information about permission levels"),

View File

@ -42,18 +42,18 @@ public enum CommandLang implements Lang {
NO_WEB_USER_NOTIFY("Cmd Notify - No WebUser", "You might not have a web user, use /plan register <password>"), NO_WEB_USER_NOTIFY("Cmd Notify - No WebUser", "You might not have a web user, use /plan register <password>"),
WEB_PERMISSION_LEVELS("Cmd Web - Permission Levels", ">\\§70: Access all pages\\§71: Access '/players' and all player pages\\§72: Access player page with the same username as the webuser\\§73+: No permissions"), WEB_PERMISSION_LEVELS("Cmd Web - Permission Levels", ">\\§70: Access all pages\\§71: Access '/players' and all player pages\\§72: Access player page with the same username as the webuser\\§73+: No permissions"),
CONNECT_SUCCESS("Cmd Setup - Success", "§aConnection successful, Plan may restart in a few seconds.."), @Deprecated CONNECT_SUCCESS("Cmd Setup - Success", "§aConnection successful, Plan may restart in a few seconds.."),
CONNECT_FORBIDDEN("Cmd Setup - Forbidden", "§eConnection succeeded, but Proxy has set-up mode disabled - use 'planbungee setup' on the proxy to enable it."), @Deprecated CONNECT_FORBIDDEN("Cmd Setup - Forbidden", "§eConnection succeeded, but Proxy has set-up mode disabled - use 'planbungee setup' on the proxy to enable it."),
CONNECT_BAD_REQUEST("Cmd Setup - Bad Request", "§eConnection succeeded, but Receiving server was a Bukkit or Sponge server. Use another address instead."), @Deprecated CONNECT_BAD_REQUEST("Cmd Setup - Bad Request", "§eConnection succeeded, but Receiving server was a Bukkit or Sponge server. Use another address instead."),
CONNECT_UNAUTHORIZED("Cmd Setup - Unauthorized", "§eConnection succeeded, but Receiving server didn't authorize this server. Contact Discord for support"), @Deprecated CONNECT_UNAUTHORIZED("Cmd Setup - Unauthorized", "§eConnection succeeded, but Receiving server didn't authorize this server. Contact Discord for support"),
CONNECT_FAIL("Cmd Setup - Generic Fail", "§eConnection failed: ${0}"), @Deprecated CONNECT_FAIL("Cmd Setup - Generic Fail", "§eConnection failed: ${0}"),
CONNECT_INTERNAL_ERROR("Cmd Setup - Internal Error", "§eConnection succeeded. ${0}, check possible ErrorLog on receiving server's debug page."), @Deprecated CONNECT_INTERNAL_ERROR("Cmd Setup - Internal Error", "§eConnection succeeded. ${0}, check possible ErrorLog on receiving server's debug page."),
CONNECT_GATEWAY("Cmd Setup - Gateway Error", "§eConnection succeeded, but Proxy failed to connect to this server (Did current web server restart?). Use /plan m con & /planbungee con to debug."), @Deprecated CONNECT_GATEWAY("Cmd Setup - Gateway Error", "§eConnection succeeded, but Proxy failed to connect to this server (Did current web server restart?). Use /plan m con & /planbungee con to debug."),
CONNECT_WEBSERVER_NOT_ENABLED("Cmd Setup - WebServer not Enabled", "§cWebServer is not enabled on this server! Make sure it enables on boot!"), @Deprecated CONNECT_WEBSERVER_NOT_ENABLED("Cmd Setup - WebServer not Enabled", "§cWebServer is not enabled on this server! Make sure it enables on boot!"),
CONNECT_URL_MISTAKE("Cmd Setup - Url mistake", "§cMake sure you're using the full address (Starts with http:// or https://) - Check Proxy enable log for the full address."), @Deprecated CONNECT_URL_MISTAKE("Cmd Setup - Url mistake", "§cMake sure you're using the full address (Starts with http:// or https://) - Check Proxy enable log for the full address."),
SETUP_ALLOWED("Cmd Setup - Allowed", "§aSet-up is now Allowed"), @Deprecated SETUP_ALLOWED("Cmd Setup - Allowed", "§aSet-up is now Allowed"),
SETUP_FORBIDDEN("Cmd Setup - Disallowed", "§cSet-up is now Forbidden"), @Deprecated SETUP_FORBIDDEN("Cmd Setup - Disallowed", "§cSet-up is now Forbidden"),
LINK_CLICK_ME("Cmd - Click Me", "Click me"), LINK_CLICK_ME("Cmd - Click Me", "Click me"),
LINK_PREFIX("Cmd - Link", " §2Link: §f"), LINK_PREFIX("Cmd - Link", " §2Link: §f"),

View File

@ -30,7 +30,7 @@ public enum PluginLang implements Lang {
ENABLE_NOTIFY_WEB_SERVER_DISABLED("Enable - Notify Webserver disabled", "WebServer was not initialized. (WebServer.DisableWebServer: true)"), ENABLE_NOTIFY_WEB_SERVER_DISABLED("Enable - Notify Webserver disabled", "WebServer was not initialized. (WebServer.DisableWebServer: true)"),
ENABLE_NOTIFY_GEOLOCATIONS_INTERNET_REQUIRED("Enable - Notify Geolocations Internet Required", "Plan Requires internet access on first run to download GeoLite2 Geolocation database."), ENABLE_NOTIFY_GEOLOCATIONS_INTERNET_REQUIRED("Enable - Notify Geolocations Internet Required", "Plan Requires internet access on first run to download GeoLite2 Geolocation database."),
ENABLE_NOTIFY_GEOLOCATIONS_DISABLED("Enable - Notify Geolocations disabled", "Geolocation gathering is not active. (Data.Geolocations: false)"), ENABLE_NOTIFY_GEOLOCATIONS_DISABLED("Enable - Notify Geolocations disabled", "Geolocation gathering is not active. (Data.Geolocations: false)"),
ENABLE_NOTIFY_ADDRESS_CONFIRMATION("Enable - Notify Address Confirmation", "Make sure that this address points to THIS Server: ${0}"), @Deprecated ENABLE_NOTIFY_ADDRESS_CONFIRMATION("Enable - Notify Address Confirmation", "Make sure that this address points to THIS Server: ${0}"),
ENABLE_FAIL_DB("Enable FAIL - Database", "${0}-Database Connection failed: ${1}"), ENABLE_FAIL_DB("Enable FAIL - Database", "${0}-Database Connection failed: ${1}"),
ENABLE_FAIL_WRONG_DB("Enable FAIL - Wrong Database Type", "${0} is not a supported Database"), ENABLE_FAIL_WRONG_DB("Enable FAIL - Wrong Database Type", "${0} is not a supported Database"),

View File

@ -18,19 +18,15 @@ package com.djrapitops.plan.system.processing.processors.info;
import com.djrapitops.plan.system.export.HtmlExport; import com.djrapitops.plan.system.export.HtmlExport;
import com.djrapitops.plan.system.export.JSONExport; import com.djrapitops.plan.system.export.JSONExport;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.connection.WebExceptionLogger;
import com.djrapitops.plan.system.settings.config.PlanConfig; import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plugin.command.Sender;
import dagger.Lazy; import dagger.Lazy;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.UUID; import java.util.UUID;
import java.util.function.BiConsumer;
/** /**
* Factory for creating Runnables related to {@link InfoSystem} to run with {@link com.djrapitops.plan.system.processing.Processing}. * Factory for creating Runnables related to ... to run with {@link com.djrapitops.plan.system.processing.Processing}.
* *
* @author Rsl1122 * @author Rsl1122
*/ */
@ -40,35 +36,19 @@ public class InfoProcessors {
private final Lazy<PlanConfig> config; private final Lazy<PlanConfig> config;
private final Lazy<HtmlExport> htmlExport; private final Lazy<HtmlExport> htmlExport;
private final Lazy<JSONExport> jsonExport; private final Lazy<JSONExport> jsonExport;
private final Lazy<InfoSystem> infoSystem;
private final Lazy<WebExceptionLogger> webExceptionLogger;
@Inject @Inject
public InfoProcessors( public InfoProcessors(
Lazy<PlanConfig> config, Lazy<PlanConfig> config,
Lazy<HtmlExport> htmlExport, Lazy<HtmlExport> htmlExport,
Lazy<JSONExport> jsonExport, Lazy<JSONExport> jsonExport
Lazy<InfoSystem> infoSystem,
Lazy<WebExceptionLogger> webExceptionLogger
) { ) {
this.config = config; this.config = config;
this.htmlExport = htmlExport; this.htmlExport = htmlExport;
this.jsonExport = jsonExport; this.jsonExport = jsonExport;
this.infoSystem = infoSystem;
this.webExceptionLogger = webExceptionLogger;
}
public InspectCacheRequestProcessor inspectCacheRequestProcessor(
UUID uuid,
Sender sender,
String playerName,
BiConsumer<Sender, String> msgSender
) {
return new InspectCacheRequestProcessor(uuid, sender, playerName, msgSender,
infoSystem.get(), webExceptionLogger.get()
);
} }
// TODO Move
public PlayerPageUpdateProcessor playerPageUpdateProcessor(UUID uuid) { public PlayerPageUpdateProcessor playerPageUpdateProcessor(UUID uuid) {
return new PlayerPageUpdateProcessor(uuid, config.get(), htmlExport.get(), jsonExport.get()); return new PlayerPageUpdateProcessor(uuid, config.get(), htmlExport.get(), jsonExport.get());
} }

View File

@ -1,75 +0,0 @@
/*
* 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.system.processing.processors.info;
import com.djrapitops.plan.api.exceptions.connection.ConnectionFailException;
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
import com.djrapitops.plan.api.exceptions.connection.NotFoundException;
import com.djrapitops.plan.api.exceptions.connection.UnauthorizedServerException;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.connection.WebExceptionLogger;
import com.djrapitops.plugin.command.Sender;
import java.util.UUID;
import java.util.function.BiConsumer;
/**
* Sends a request to cache players inspect page to the ResponseCache on the appropriate WebServer.
*
* @author Rsl1122
*/
public class InspectCacheRequestProcessor implements Runnable {
private final UUID uuid;
private final Sender sender;
private final String playerName;
private final BiConsumer<Sender, String> msgSender;
private final InfoSystem infoSystem;
private final WebExceptionLogger webExceptionLogger;
InspectCacheRequestProcessor(
UUID uuid,
Sender sender,
String playerName,
BiConsumer<Sender, String> msgSender,
InfoSystem infoSystem,
WebExceptionLogger webExceptionLogger
) {
this.uuid = uuid;
this.sender = sender;
this.playerName = playerName;
this.msgSender = msgSender;
this.infoSystem = infoSystem;
this.webExceptionLogger = webExceptionLogger;
}
@Override
public void run() {
SessionCache.refreshActiveSessionsState();
webExceptionLogger.logIfOccurs(this.getClass(), () -> {
try {
infoSystem.generateAndCachePlayerPage(uuid);
msgSender.accept(sender, playerName);
} catch (ConnectionFailException | UnauthorizedServerException
| NotFoundException | NoServersException e) {
sender.sendMessage("§c" + e.getMessage());
}
});
}
}

View File

@ -126,7 +126,11 @@ public class ConfigUpdater {
new ConfigChange.Removed("Analysis"), new ConfigChange.Removed("Analysis"),
new ConfigChange.Removed("Data"), new ConfigChange.Removed("Data"),
new ConfigChange.Removed("Customization"), new ConfigChange.Removed("Customization"),
new ConfigChange.Removed("Theme") new ConfigChange.Removed("Theme"),
// 5.0.0
new ConfigChange.Removed("Display_options.Sessions.Replace_accordion_with_table"),
new ConfigChange.Removed("Display_options.Sessions.Show_most_played_world_in_title")
}; };
} }

View File

@ -30,8 +30,10 @@ import com.djrapitops.plan.system.settings.paths.key.StringSetting;
public class DisplaySettings { public class DisplaySettings {
public static final Setting<String> THEME = new StringSetting("Display_options.Theme"); public static final Setting<String> THEME = new StringSetting("Display_options.Theme");
@Deprecated // Removed in 5.0.0
public static final Setting<Boolean> REPLACE_SESSION_ACCORDION_WITH_TABLE = new BooleanSetting("Display_options.Sessions.Replace_accordion_with_table"); public static final Setting<Boolean> REPLACE_SESSION_ACCORDION_WITH_TABLE = new BooleanSetting("Display_options.Sessions.Replace_accordion_with_table");
public static final Setting<Integer> SESSIONS_PER_PAGE = new IntegerSetting("Display_options.Sessions.Show_on_page"); public static final Setting<Integer> SESSIONS_PER_PAGE = new IntegerSetting("Display_options.Sessions.Show_on_page");
@Deprecated // Removed in 5.0.0
public static final Setting<Boolean> SESSION_MOST_PLAYED_WORLD_IN_TITLE = new BooleanSetting("Display_options.Sessions.Show_most_played_world_in_title"); public static final Setting<Boolean> SESSION_MOST_PLAYED_WORLD_IN_TITLE = new BooleanSetting("Display_options.Sessions.Show_most_played_world_in_title");
public static final Setting<Boolean> ORDER_WORLD_PIE_BY_PERC = new BooleanSetting("Display_options.Sessions.Order_world_pies_by_percentage"); public static final Setting<Boolean> ORDER_WORLD_PIE_BY_PERC = new BooleanSetting("Display_options.Sessions.Order_world_pies_by_percentage");
public static final Setting<Integer> PLAYERS_PER_SERVER_PAGE = new IntegerSetting("Display_options.Players_table.Show_on_server_page"); public static final Setting<Integer> PLAYERS_PER_SERVER_PAGE = new IntegerSetting("Display_options.Players_table.Show_on_server_page");

View File

@ -18,7 +18,6 @@ package com.djrapitops.plan.system.webserver;
import com.djrapitops.plan.api.exceptions.WebUserAuthException; import com.djrapitops.plan.api.exceptions.WebUserAuthException;
import com.djrapitops.plan.api.exceptions.connection.*; import com.djrapitops.plan.api.exceptions.connection.*;
import com.djrapitops.plan.system.info.connection.InfoRequestPageHandler;
import com.djrapitops.plan.system.webserver.auth.Authentication; import com.djrapitops.plan.system.webserver.auth.Authentication;
import com.djrapitops.plan.system.webserver.cache.PageId; import com.djrapitops.plan.system.webserver.cache.PageId;
import com.djrapitops.plan.system.webserver.cache.ResponseCache; import com.djrapitops.plan.system.webserver.cache.ResponseCache;
@ -47,7 +46,6 @@ public class ResponseHandler extends TreePageHandler {
private final PlayersPageHandler playersPageHandler; private final PlayersPageHandler playersPageHandler;
private final PlayerPageHandler playerPageHandler; private final PlayerPageHandler playerPageHandler;
private final ServerPageHandler serverPageHandler; private final ServerPageHandler serverPageHandler;
private final InfoRequestPageHandler infoRequestPageHandler;
private final RootJSONHandler rootJSONHandler; private final RootJSONHandler rootJSONHandler;
private final ErrorHandler errorHandler; private final ErrorHandler errorHandler;
@ -62,7 +60,6 @@ public class ResponseHandler extends TreePageHandler {
PlayersPageHandler playersPageHandler, PlayersPageHandler playersPageHandler,
PlayerPageHandler playerPageHandler, PlayerPageHandler playerPageHandler,
ServerPageHandler serverPageHandler, ServerPageHandler serverPageHandler,
InfoRequestPageHandler infoRequestPageHandler,
RootJSONHandler rootJSONHandler, RootJSONHandler rootJSONHandler,
ErrorHandler errorHandler ErrorHandler errorHandler
@ -73,7 +70,6 @@ public class ResponseHandler extends TreePageHandler {
this.playersPageHandler = playersPageHandler; this.playersPageHandler = playersPageHandler;
this.playerPageHandler = playerPageHandler; this.playerPageHandler = playerPageHandler;
this.serverPageHandler = serverPageHandler; this.serverPageHandler = serverPageHandler;
this.infoRequestPageHandler = infoRequestPageHandler;
this.rootJSONHandler = rootJSONHandler; this.rootJSONHandler = rootJSONHandler;
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
} }
@ -92,7 +88,6 @@ public class ResponseHandler extends TreePageHandler {
registerPage("", responseFactory.redirectResponse("/server"), 5); registerPage("", responseFactory.redirectResponse("/server"), 5);
} }
registerPage("info", infoRequestPageHandler);
registerPage("v1", rootJSONHandler); registerPage("v1", rootJSONHandler);
} }
@ -107,10 +102,6 @@ public class ResponseHandler extends TreePageHandler {
return responseFactory.forbidden403(e.getMessage()); return responseFactory.forbidden403(e.getMessage());
} catch (BadRequestException e) { } catch (BadRequestException e) {
return new BadRequestResponse(e.getMessage() + " (when requesting '" + request.getTargetString() + "')"); return new BadRequestResponse(e.getMessage() + " (when requesting '" + request.getTargetString() + "')");
} catch (UnauthorizedServerException e) {
return responseFactory.unauthorizedServer(e.getMessage());
} catch (GatewayException e) {
return responseFactory.gatewayError504(e.getMessage());
} catch (InternalErrorException e) { } catch (InternalErrorException e) {
if (e.getCause() != null) { if (e.getCause() != null) {
return responseFactory.internalErrorResponse(e.getCause(), request.getTargetString()); return responseFactory.internalErrorResponse(e.getCause(), request.getTargetString());
@ -141,8 +132,7 @@ public class ResponseHandler extends TreePageHandler {
return ResponseCache.loadResponse(PageId.FAVICON.id(), responseFactory::faviconResponse); return ResponseCache.loadResponse(PageId.FAVICON.id(), responseFactory::faviconResponse);
} }
boolean isNotInfoRequest = target.isEmpty() || !target.get(0).equals("info"); boolean isAuthRequired = webServer.get().isAuthRequired();
boolean isAuthRequired = webServer.get().isAuthRequired() && isNotInfoRequest;
if (isAuthRequired && !authentication.isPresent()) { if (isAuthRequired && !authentication.isPresent()) {
if (webServer.get().isUsingHTTPS()) { if (webServer.get().isUsingHTTPS()) {
return responseFactory.basicAuth(); return responseFactory.basicAuth();

View File

@ -151,6 +151,10 @@ public class WebServer implements SubSystem {
enabled = true; enabled = true;
logger.info(locale.getString(PluginLang.ENABLED_WEB_SERVER, server.getAddress().getPort(), getAccessAddress())); logger.info(locale.getString(PluginLang.ENABLED_WEB_SERVER, server.getAddress().getPort(), getAccessAddress()));
boolean usingAlternativeIP = config.isTrue(WebserverSettings.SHOW_ALTERNATIVE_IP);
if (!usingAlternativeIP && getIP().isEmpty()) {
logger.log(L.INFO_COLOR, "§e" + locale.getString(PluginLang.ENABLE_NOTIFY_EMPTY_IP));
}
} catch (IllegalArgumentException | IllegalStateException | IOException e) { } catch (IllegalArgumentException | IllegalStateException | IOException e) {
errorHandler.log(L.ERROR, this.getClass(), e); errorHandler.log(L.ERROR, this.getClass(), e);
enabled = false; enabled = false;

View File

@ -24,7 +24,6 @@ import com.djrapitops.plan.data.WebUser;
import com.djrapitops.plan.db.Database; import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.queries.PlayerFetchQueries; import com.djrapitops.plan.db.access.queries.PlayerFetchQueries;
import com.djrapitops.plan.system.database.DBSystem; import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.webserver.Request; import com.djrapitops.plan.system.webserver.Request;
import com.djrapitops.plan.system.webserver.RequestTarget; import com.djrapitops.plan.system.webserver.RequestTarget;
import com.djrapitops.plan.system.webserver.auth.Authentication; import com.djrapitops.plan.system.webserver.auth.Authentication;
@ -32,7 +31,6 @@ import com.djrapitops.plan.system.webserver.cache.PageId;
import com.djrapitops.plan.system.webserver.cache.ResponseCache; import com.djrapitops.plan.system.webserver.cache.ResponseCache;
import com.djrapitops.plan.system.webserver.response.Response; import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plan.system.webserver.response.ResponseFactory; import com.djrapitops.plan.system.webserver.response.ResponseFactory;
import com.djrapitops.plan.system.webserver.response.pages.InspectPageResponse;
import com.djrapitops.plan.utilities.uuid.UUIDUtility; import com.djrapitops.plan.utilities.uuid.UUIDUtility;
import javax.inject.Inject; import javax.inject.Inject;
@ -49,19 +47,16 @@ public class PlayerPageHandler implements PageHandler {
private final ResponseFactory responseFactory; private final ResponseFactory responseFactory;
private final DBSystem dbSystem; private final DBSystem dbSystem;
private final InfoSystem infoSystem;
private final UUIDUtility uuidUtility; private final UUIDUtility uuidUtility;
@Inject @Inject
public PlayerPageHandler( public PlayerPageHandler(
ResponseFactory responseFactory, ResponseFactory responseFactory,
DBSystem dbSystem, DBSystem dbSystem,
InfoSystem infoSystem,
UUIDUtility uuidUtility UUIDUtility uuidUtility
) { ) {
this.responseFactory = responseFactory; this.responseFactory = responseFactory;
this.dbSystem = dbSystem; this.dbSystem = dbSystem;
this.infoSystem = infoSystem;
this.uuidUtility = uuidUtility; this.uuidUtility = uuidUtility;
} }
@ -99,12 +94,9 @@ public class PlayerPageHandler implements PageHandler {
return responseFactory.serverNotFound404(); return responseFactory.serverNotFound404();
} }
private Response playerResponseOrNotFound(UUID uuid) throws WebException { private Response playerResponseOrNotFound(UUID playerUUID) throws WebException {
Response response = ResponseCache.loadResponse(PageId.PLAYER.of(uuid)); Response response = ResponseCache.loadResponse(PageId.PLAYER.of(playerUUID),
if (!(response instanceof InspectPageResponse)) { () -> responseFactory.playerPageResponse(playerUUID));
infoSystem.generateAndCachePlayerPage(uuid);
response = ResponseCache.loadResponse(PageId.PLAYER.of(uuid));
}
return response != null ? response : responseFactory.playerNotFound404(); return response != null ? response : responseFactory.playerNotFound404();
} }

View File

@ -25,7 +25,10 @@ import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.locale.Locale; import com.djrapitops.plan.system.locale.Locale;
import com.djrapitops.plan.system.locale.lang.ErrorPageLang; import com.djrapitops.plan.system.locale.lang.ErrorPageLang;
import com.djrapitops.plan.system.update.VersionCheckSystem; import com.djrapitops.plan.system.update.VersionCheckSystem;
import com.djrapitops.plan.system.webserver.response.errors.*; import com.djrapitops.plan.system.webserver.response.errors.ErrorResponse;
import com.djrapitops.plan.system.webserver.response.errors.ForbiddenResponse;
import com.djrapitops.plan.system.webserver.response.errors.InternalErrorResponse;
import com.djrapitops.plan.system.webserver.response.errors.NotFoundResponse;
import com.djrapitops.plan.system.webserver.response.pages.*; import com.djrapitops.plan.system.webserver.response.pages.*;
import com.djrapitops.plan.utilities.html.pages.PageFactory; import com.djrapitops.plan.utilities.html.pages.PageFactory;
import com.djrapitops.plugin.logging.L; import com.djrapitops.plugin.logging.L;
@ -194,22 +197,6 @@ public class ResponseFactory {
} }
} }
public ErrorResponse unauthorizedServer(String message) {
try {
return new UnauthorizedServerResponse(message, versionCheckSystem, files);
} catch (IOException e) {
return internalErrorResponse(e, "Failed to parse UnauthorizedServerResponse");
}
}
public ErrorResponse gatewayError504(String message) {
try {
return new GatewayErrorResponse(message, versionCheckSystem, files);
} catch (IOException e) {
return internalErrorResponse(e, "Failed to parse GatewayErrorResponse");
}
}
public ErrorResponse basicAuth() { public ErrorResponse basicAuth() {
try { try {
return PromptAuthorizationResponse.getBasicAuthResponse(versionCheckSystem, files); return PromptAuthorizationResponse.getBasicAuthResponse(versionCheckSystem, files);
@ -217,4 +204,14 @@ public class ResponseFactory {
return internalErrorResponse(e, "Failed to parse PromptAuthorizationResponse"); return internalErrorResponse(e, "Failed to parse PromptAuthorizationResponse");
} }
} }
public Response playerPageResponse(UUID playerUUID) {
try {
return new PlayerPageResponse(playerUUID, pageFactory.playerPage(playerUUID).toHtml());
} catch (IllegalStateException e) {
return playerNotFound404();
} catch (ParseException e) {
return internalErrorResponse(e, "Failed to parse player page");
}
}
} }

View File

@ -1,38 +0,0 @@
/*
* 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.system.webserver.response.errors;
import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.update.VersionCheckSystem;
import java.io.IOException;
/**
* ErrorResponse for GatewayException.
*
* @author Rsl1122
*/
public class GatewayErrorResponse extends ErrorResponse {
public GatewayErrorResponse(String message, VersionCheckSystem versionCheckSystem, PlanFiles files) throws IOException {
super(versionCheckSystem, files);
super.setHeader("HTTP/1.1 504 Gateway Error");
super.setTitle("Failed to Connect (Gateway Error)");
super.setParagraph(message);
super.replacePlaceholders();
}
}

View File

@ -1,37 +0,0 @@
/*
* 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.system.webserver.response.errors;
import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.update.VersionCheckSystem;
import java.io.IOException;
/**
* Response when Server is not found in database when attempting to InfoRequest.
*
* @author Rsl1122
*/
public class UnauthorizedServerResponse extends ErrorResponse {
public UnauthorizedServerResponse(String message, VersionCheckSystem versionCheckSystem, PlanFiles files) throws IOException {
super(versionCheckSystem, files);
super.setHeader("HTTP/1.1 412 Unauthorized");
super.setTitle("Unauthorized Server");
super.setParagraph(message);
super.replacePlaceholders();
}
}

View File

@ -16,45 +16,28 @@
*/ */
package com.djrapitops.plan.system.webserver.response.pages; package com.djrapitops.plan.system.webserver.response.pages;
import com.djrapitops.plan.system.webserver.cache.PageId; import java.util.Objects;
import com.djrapitops.plan.system.webserver.cache.ResponseCache; import java.util.UUID;
import com.djrapitops.plan.system.webserver.response.pages.parts.InspectPagePluginsContent;
import org.apache.commons.text.StringSubstitutor;
import java.util.*;
/** /**
* @author Rsl1122 * @author Rsl1122
*/ */
public class InspectPageResponse extends PageResponse { public class PlayerPageResponse extends PageResponse {
private final UUID uuid; private final UUID uuid;
public InspectPageResponse(UUID uuid, String html) { public PlayerPageResponse(UUID uuid, String html) {
super.setHeader("HTTP/1.1 200 OK"); super.setHeader("HTTP/1.1 200 OK");
super.setContent(html); super.setContent(html);
this.uuid = uuid; this.uuid = uuid;
} }
@Override
public String getContent() {
Map<String, String> replaceMap = new HashMap<>();
// PluginData compatibility
Optional<String[]> pluginsTab = Optional.ofNullable((InspectPagePluginsContent) ResponseCache.loadResponse(PageId.PLAYER_PLUGINS_TAB.of(uuid)))
.map(InspectPagePluginsContent::getContents);
replaceMap.put("navPluginsTabs", pluginsTab.map(nav -> nav[0]).orElse(""));
replaceMap.put("pluginsTabs", pluginsTab.map(tab -> tab[1]).orElse(""));
return StringSubstitutor.replace(super.getContent(), replaceMap);
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
if (!(o instanceof InspectPageResponse)) return false; if (!(o instanceof PlayerPageResponse)) return false;
if (!super.equals(o)) return false; if (!super.equals(o)) return false;
InspectPageResponse that = (InspectPageResponse) o; PlayerPageResponse that = (PlayerPageResponse) o;
return Objects.equals(uuid, that.uuid); return Objects.equals(uuid, that.uuid);
} }

View File

@ -22,9 +22,7 @@ import com.djrapitops.plan.data.store.objects.DateHolder;
import com.djrapitops.plan.db.Database; import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.system.cache.SessionCache; import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.file.FileResource; import com.djrapitops.plan.system.file.FileResource;
import com.djrapitops.plan.system.info.connection.ConnectionLog;
import com.djrapitops.plan.system.info.connection.ConnectionSystem; import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.info.server.properties.ServerProperties; import com.djrapitops.plan.system.info.server.properties.ServerProperties;
import com.djrapitops.plan.system.webserver.cache.ResponseCache; import com.djrapitops.plan.system.webserver.cache.ResponseCache;
@ -167,54 +165,11 @@ public class DebugPage implements Page {
StringBuilder content = new StringBuilder(); StringBuilder content = new StringBuilder();
appendServerInformation(content); appendServerInformation(content);
appendConnectionLog(content);
appendBenchmarks(content); appendBenchmarks(content);
return content.toString(); return content.toString();
} }
private void appendConnectionLog(StringBuilder content) {
try {
Map<String, Map<String, ConnectionLog.Entry>> logEntries = connectionSystem.getConnectionLog().getLogEntries();
content.append("<pre>### Connection Log:<br><br>");
content.append("Server Address | Request Type | Response | Sent<br>")
.append("-- | -- | -- | --<br>");
if (logEntries.isEmpty()) {
content.append("**No Connections Logged**<br>");
}
for (Map.Entry<String, Map<String, ConnectionLog.Entry>> entry : logEntries.entrySet()) {
String address = entry.getKey();
Map<String, ConnectionLog.Entry> requests = entry.getValue();
for (Map.Entry<String, ConnectionLog.Entry> requestEntry : requests.entrySet()) {
String infoRequest = requestEntry.getKey();
ConnectionLog.Entry logEntry = requestEntry.getValue();
content.append(address).append(" | ")
.append(infoRequest).append(" | ")
.append(logEntry.getResponseCode()).append(" | ")
.append(secondFormatter.apply(logEntry)).append("<br>");
}
}
content.append("</pre>");
content.append("<pre>### Servers:<br><br>");
List<Server> servers = connectionSystem.getDataServers();
content.append("Server Name | Address <br>")
.append("-- | --<br>");
for (Server server : servers) {
content.append(server.getName()).append(" | ")
.append(server.getWebAddress()).append("<br>");
}
content.append("</pre>");
} catch (Exception e) {
errorHandler.log(L.WARN, this.getClass(), e);
}
}
private void appendServerInformation(StringBuilder content) { private void appendServerInformation(StringBuilder content) {
ServerProperties serverProperties = serverInfo.getServerProperties(); ServerProperties serverProperties = serverInfo.getServerProperties();

View File

@ -1,376 +0,0 @@
/*
* 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.html.pages;
import com.djrapitops.plan.api.exceptions.ParseException;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.containers.PerServerContainer;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.mutators.*;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.DisplaySettings;
import com.djrapitops.plan.system.settings.paths.ProxySettings;
import com.djrapitops.plan.system.settings.paths.TimeSettings;
import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.system.update.VersionCheckSystem;
import com.djrapitops.plan.system.webserver.cache.PageId;
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
import com.djrapitops.plan.system.webserver.response.pages.parts.InspectPagePluginsContent;
import com.djrapitops.plan.utilities.comparators.SessionStartComparator;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.formatting.Formatters;
import com.djrapitops.plan.utilities.formatting.PlaceholderReplacer;
import com.djrapitops.plan.utilities.html.HtmlStructure;
import com.djrapitops.plan.utilities.html.graphs.Graphs;
import com.djrapitops.plan.utilities.html.graphs.calendar.PlayerCalendar;
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
import com.djrapitops.plan.utilities.html.structure.Accordions;
import com.djrapitops.plan.utilities.html.structure.ServerAccordion;
import com.djrapitops.plan.utilities.html.structure.SessionAccordion;
import com.djrapitops.plan.utilities.html.tables.HtmlTables;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.benchmarking.Timings;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* Used for parsing Inspect page out of database data and the html.
*
* @author Rsl1122
*/
public class InspectPage implements Page {
private final PlayerContainer player;
private final Map<UUID, String> serverNames;
private final VersionCheckSystem versionCheckSystem;
private final PlanFiles files;
private final PlanConfig config;
private final PageFactory pageFactory;
private final Theme theme;
private final Graphs graphs;
private final HtmlTables tables;
private final Accordions accordions;
private final ServerInfo serverInfo;
private final Timings timings;
private final Formatter<Long> timeAmountFormatter;
private final Formatter<Long> clockLongFormatter;
private final Formatter<Long> secondLongFormatter;
private final Formatter<Long> yearLongFormatter;
private final Formatter<Double> decimalFormatter;
InspectPage(
PlayerContainer player, Map<UUID, String> serverNames,
VersionCheckSystem versionCheckSystem,
PlanFiles files,
PlanConfig config,
PageFactory pageFactory,
Theme theme,
Graphs graphs,
HtmlTables tables,
Accordions accordions,
Formatters formatters,
ServerInfo serverInfo,
Timings timings
) {
this.player = player;
this.serverNames = serverNames;
this.versionCheckSystem = versionCheckSystem;
this.files = files;
this.config = config;
this.pageFactory = pageFactory;
this.theme = theme;
this.graphs = graphs;
this.tables = tables;
this.accordions = accordions;
this.serverInfo = serverInfo;
this.timings = timings;
timeAmountFormatter = formatters.timeAmount();
clockLongFormatter = formatters.clockLong();
secondLongFormatter = formatters.secondLong();
yearLongFormatter = formatters.yearLong();
decimalFormatter = formatters.decimals();
}
@Override
public String toHtml() throws ParseException {
try {
timings.start("Inspect Parse, Fetch");
if (!player.getValue(PlayerKeys.REGISTERED).isPresent()) {
throw new IllegalStateException("Player is not registered");
}
UUID serverUUID = serverInfo.getServerUUID();
timings.end("Inspect Parse, Fetch");
return parse(player, serverUUID, serverNames);
} catch (Exception e) {
throw new ParseException(e);
}
}
public String parse(PlayerContainer player, UUID serverUUID, Map<UUID, String> serverNames) throws IOException {
long now = System.currentTimeMillis();
UUID playerUUID = player.getUnsafe(PlayerKeys.UUID);
PlaceholderReplacer replacer = new PlaceholderReplacer();
replacer.put("refresh", clockLongFormatter.apply(now));
replacer.put("refreshFull", secondLongFormatter.apply(now));
replacer.put("version", versionCheckSystem.getCurrentVersion());
replacer.put("update", versionCheckSystem.getUpdateHtml().orElse(""));
replacer.put("timeZone", config.getTimeZoneOffsetHours());
boolean online = false;
Optional<Session> activeSession = SessionCache.getCachedSession(playerUUID);
if (activeSession.isPresent()) {
Session session = activeSession.get();
session.setSessionID(Integer.MAX_VALUE);
online = true;
player.putRawData(PlayerKeys.ACTIVE_SESSION, session);
}
String playerName = player.getValue(PlayerKeys.NAME).orElse("Unknown");
int timesKicked = player.getValue(PlayerKeys.KICK_COUNT).orElse(0);
replacer.addPlaceholderFrom(player, yearLongFormatter, PlayerKeys.REGISTERED);
replacer.addPlaceholderFrom(player, yearLongFormatter, PlayerKeys.LAST_SEEN);
replacer.put("playerName", playerName);
replacer.put("kickCount", timesKicked);
PerServerContainer perServerContainer = player.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer());
PerServerMutator perServerMutator = new PerServerMutator(perServerContainer);
Map<UUID, WorldTimes> worldTimesPerServer = perServerMutator.worldTimesPerServer();
replacer.put("serverPieSeries", graphs.pie().serverPreferencePie(serverNames, worldTimesPerServer).toHighChartsSeries());
replacer.put("worldPieColors", theme.getValue(ThemeVal.GRAPH_WORLD_PIE));
replacer.put("gmPieColors", theme.getValue(ThemeVal.GRAPH_GM_PIE));
replacer.put("serverPieColors", theme.getValue(ThemeVal.GRAPH_SERVER_PREF_PIE));
String favoriteServer = serverNames.getOrDefault(perServerMutator.favoriteServer(), "Unknown");
replacer.put("favoriteServer", favoriteServer);
replacer.put("tableBodyNicknames",
tables.nicknameTable(player.getValue(PlayerKeys.NICKNAMES).orElse(new ArrayList<>()), serverNames).parseBody()
);
replacer.put("tableBodyIPs", tables.geoInfoTable(player.getValue(PlayerKeys.GEO_INFO).orElse(new ArrayList<>())).parseBody());
PingMutator pingMutator = PingMutator.forContainer(player);
double averagePing = pingMutator.average();
int minPing = pingMutator.min();
int maxPing = pingMutator.max();
String unavailable = "Unavailable";
replacer.put("avgPing", averagePing != -1 ? decimalFormatter.apply(averagePing) + " ms" : unavailable);
replacer.put("minPing", minPing != -1 ? minPing + " ms" : unavailable);
replacer.put("maxPing", maxPing != -1 ? maxPing + " ms" : unavailable);
List<Session> allSessions = player.getValue(PlayerKeys.SESSIONS).orElse(new ArrayList<>());
SessionsMutator sessionsMutator = SessionsMutator.forContainer(player);
allSessions.sort(new SessionStartComparator());
String sessionAccordionViewScript = "";
if (allSessions.isEmpty()) {
replacer.put("accordionSessions", "<div class=\"body\">" + "<p>No Sessions</p>" + "</div>");
} else {
if (config.isTrue(DisplaySettings.REPLACE_SESSION_ACCORDION_WITH_TABLE)) {
replacer.put("accordionSessions", tables.playerSessionTable(playerName, allSessions).parseHtml());
} else {
SessionAccordion sessionAccordion = accordions.playerSessionAccordion(allSessions, () -> serverNames);
replacer.put("accordionSessions", sessionAccordion.toHtml());
sessionAccordionViewScript = sessionAccordion.toViewScript();
}
}
ServerAccordion serverAccordion = accordions.serverAccordion(player, serverNames);
PlayerCalendar playerCalendar = graphs.calendar().playerCalendar(player);
replacer.put("calendarSeries", playerCalendar.toCalendarSeries());
replacer.put("firstDay", 1);
replacer.put("accordionServers", serverAccordion.toHtml());
replacer.put("sessionTabGraphViewFunctions", sessionAccordionViewScript + serverAccordion.toViewScript());
long dayAgo = now - TimeUnit.DAYS.toMillis(1L);
long weekAgo = now - TimeAmount.WEEK.toMillis(1L);
long monthAgo = now - TimeAmount.MONTH.toMillis(1L);
SessionsMutator daySessionsMutator = sessionsMutator.filterSessionsBetween(dayAgo, now);
SessionsMutator weekSessionsMutator = sessionsMutator.filterSessionsBetween(weekAgo, now);
SessionsMutator monthSessionsMutator = sessionsMutator.filterSessionsBetween(monthAgo, now);
sessionsAndPlaytime(replacer, sessionsMutator, daySessionsMutator, weekSessionsMutator, monthSessionsMutator);
String punchCardData = graphs.special().punchCard(allSessions).toHighChartsSeries();
WorldTimes worldTimes = player.getValue(PlayerKeys.WORLD_TIMES).orElse(new WorldTimes());
WorldPie worldPie = graphs.pie().worldPie(worldTimes);
replacer.put("worldPieSeries", worldPie.toHighChartsSeries());
replacer.put("gmSeries", worldPie.toHighChartsDrilldown());
replacer.put("punchCardSeries", punchCardData);
pvpAndPve(replacer, sessionsMutator, weekSessionsMutator, monthSessionsMutator);
ActivityIndex activityIndex = player.getActivityIndex(now, config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD));
replacer.put("activityIndexNumber", activityIndex.getFormattedValue(decimalFormatter));
replacer.put("activityIndexColor", activityIndex.getColor());
replacer.put("activityIndex", activityIndex.getGroup());
replacer.put("playerStatus", HtmlStructure.playerStatus(online,
player.getValue(PlayerKeys.BANNED).orElse(false),
player.getValue(PlayerKeys.OPERATOR).orElse(false)));
String serverName = serverNames.get(serverUUID);
replacer.put("networkName",
"bungeecord".equalsIgnoreCase(serverName)
? config.get(ProxySettings.NETWORK_NAME)
: serverName
);
if (serverInfo.getServer().isProxy()) {
replacer.put("backButton", "<li><a title=\"to Network page\" href=\"/network\"><i class=\"material-icons\">arrow_back</i><i class=\"material-icons\">cloud</i></a></li>");
} else {
replacer.put("backButton", "<li><a title=\"to Server page\" href=\"/server\"><i class=\"material-icons\">arrow_back</i><i class=\"material-icons\">storage</i></a></li>");
}
InspectPluginTab pluginTabs = pageFactory.inspectPluginTabs(playerUUID);
// Legacy PluginData support until moved to database.
InspectPagePluginsContent pluginsTab = (InspectPagePluginsContent) ResponseCache.loadResponse(PageId.PLAYER_PLUGINS_TAB.of(playerUUID), InspectPagePluginsContent::new);
pluginsTab.addTab(new InspectPagePluginsContent(pluginTabs.getNav(), pluginTabs.getTab()));
return replacer.apply(files.getCustomizableResourceOrDefault("web/player.html").asString());
}
private void sessionsAndPlaytime(PlaceholderReplacer replacer, SessionsMutator sessionsMutator, SessionsMutator daySessionsMutator, SessionsMutator weekSessionsMutator, SessionsMutator monthSessionsMutator) {
long playtime = sessionsMutator.toPlaytime();
long playtimeDay = daySessionsMutator.toPlaytime();
long playtimeWeek = weekSessionsMutator.toPlaytime();
long playtimeMonth = monthSessionsMutator.toPlaytime();
long afk = sessionsMutator.toAfkTime();
long afkDay = daySessionsMutator.toAfkTime();
long afkWeek = weekSessionsMutator.toAfkTime();
long afkMonth = monthSessionsMutator.toAfkTime();
long activeTotal = playtime - afk;
long longestSession = sessionsMutator.toLongestSessionLength();
long longestSessionDay = daySessionsMutator.toLongestSessionLength();
long longestSessionWeek = weekSessionsMutator.toLongestSessionLength();
long longestSessionMonth = monthSessionsMutator.toLongestSessionLength();
long sessionMedian = sessionsMutator.toMedianSessionLength();
long sessionMedianDay = daySessionsMutator.toMedianSessionLength();
long sessionMedianWeek = weekSessionsMutator.toMedianSessionLength();
long sessionMedianMonth = monthSessionsMutator.toMedianSessionLength();
int sessionCount = sessionsMutator.count();
int sessionCountDay = daySessionsMutator.count();
int sessionCountWeek = weekSessionsMutator.count();
int sessionCountMonth = monthSessionsMutator.count();
long sessionAverage = sessionsMutator.toAverageSessionLength();
long sessionAverageDay = daySessionsMutator.toAverageSessionLength();
long sessionAverageWeek = weekSessionsMutator.toAverageSessionLength();
long sessionAverageMonth = monthSessionsMutator.toAverageSessionLength();
Formatter<Long> formatter = timeAmountFormatter;
replacer.put("playtimeTotal", formatter.apply(playtime));
replacer.put("playtimeDay", formatter.apply(playtimeDay));
replacer.put("playtimeWeek", formatter.apply(playtimeWeek));
replacer.put("playtimeMonth", formatter.apply(playtimeMonth));
replacer.put("activeTotal", formatter.apply(activeTotal));
replacer.put("afkTotal", formatter.apply(afk));
replacer.put("afkDay", formatter.apply(afkDay));
replacer.put("afkWeek", formatter.apply(afkWeek));
replacer.put("afkMonth", formatter.apply(afkMonth));
replacer.put("sessionLengthLongest", formatter.apply(longestSession));
replacer.put("sessionLongestDay", formatter.apply(longestSessionDay));
replacer.put("sessionLongestWeek", formatter.apply(longestSessionWeek));
replacer.put("sessionLongestMonth", formatter.apply(longestSessionMonth));
replacer.put("sessionLengthMedian", formatter.apply(sessionMedian));
replacer.put("sessionMedianDay", formatter.apply(sessionMedianDay));
replacer.put("sessionMedianWeek", formatter.apply(sessionMedianWeek));
replacer.put("sessionMedianMonth", formatter.apply(sessionMedianMonth));
replacer.put("sessionAverage", formatter.apply(sessionAverage));
replacer.put("sessionAverageDay", formatter.apply(sessionAverageDay));
replacer.put("sessionAverageWeek", formatter.apply(sessionAverageWeek));
replacer.put("sessionAverageMonth", formatter.apply(sessionAverageMonth));
replacer.put("sessionCount", sessionCount);
replacer.put("sessionCountDay", sessionCountDay);
replacer.put("sessionCountWeek", sessionCountWeek);
replacer.put("sessionCountMonth", sessionCountMonth);
}
private void pvpAndPve(PlaceholderReplacer replacer, SessionsMutator sessionsMutator, SessionsMutator weekSessionsMutator, SessionsMutator monthSessionsMutator) {
String playerKillsTable = tables.killsTable(sessionsMutator.toPlayerKillList(), "red").parseHtml();
String playerDeathTable = tables.deathsTable(sessionsMutator.toPlayerDeathList()).parseHtml();
PvpInfoMutator pvpInfoMutator = PvpInfoMutator.forMutator(sessionsMutator);
PvpInfoMutator pvpInfoMutatorMonth = PvpInfoMutator.forMutator(monthSessionsMutator);
PvpInfoMutator pvpInfoMutatorWeek = PvpInfoMutator.forMutator(weekSessionsMutator);
replacer.put("tablePlayerKills", playerKillsTable);
replacer.put("tablePlayerDeaths", playerDeathTable);
replacer.put("playerKillCount", pvpInfoMutator.playerKills());
replacer.put("mobKillCount", pvpInfoMutator.mobKills());
replacer.put("playerDeathCount", pvpInfoMutator.playerCausedDeaths());
replacer.put("mobDeathCount", pvpInfoMutator.mobCausedDeaths());
replacer.put("deathCount", pvpInfoMutator.deaths());
replacer.put("KDR", decimalFormatter.apply(pvpInfoMutator.killDeathRatio()));
replacer.put("mobKDR", decimalFormatter.apply(pvpInfoMutator.mobKillDeathRatio()));
replacer.put("playerKillCountMonth", pvpInfoMutatorMonth.playerKills());
replacer.put("mobKillCountMonth", pvpInfoMutatorMonth.mobKills());
replacer.put("playerDeathCountMonth", pvpInfoMutatorMonth.playerCausedDeaths());
replacer.put("mobDeathCountMonth", pvpInfoMutatorMonth.mobCausedDeaths());
replacer.put("deathCountMonth", pvpInfoMutatorMonth.deaths());
replacer.put("KDRMonth", decimalFormatter.apply(pvpInfoMutatorMonth.killDeathRatio()));
replacer.put("mobKDRMonth", decimalFormatter.apply(pvpInfoMutatorMonth.mobKillDeathRatio()));
replacer.put("playerKillCountWeek", pvpInfoMutatorWeek.playerKills());
replacer.put("mobKillCountWeek", pvpInfoMutatorWeek.mobKills());
replacer.put("playerDeathCountWeek", pvpInfoMutatorWeek.playerCausedDeaths());
replacer.put("mobDeathCountWeek", pvpInfoMutatorWeek.mobCausedDeaths());
replacer.put("deathCountWeek", pvpInfoMutatorWeek.deaths());
replacer.put("KDRWeek", decimalFormatter.apply(pvpInfoMutatorWeek.killDeathRatio()));
replacer.put("mobKDRWeek", decimalFormatter.apply(pvpInfoMutatorWeek.mobKillDeathRatio()));
}
}

View File

@ -136,16 +136,14 @@ public class PageFactory {
)).orElseThrow(() -> new NotFoundException("Server not found in the database")); )).orElseThrow(() -> new NotFoundException("Server not found in the database"));
} }
public InspectPage inspectPage(UUID playerUUID) { public PlayerPage playerPage(UUID playerUUID) {
Database db = dbSystem.get().getDatabase(); Database db = dbSystem.get().getDatabase();
PlayerContainer player = db.query(ContainerFetchQueries.fetchPlayerContainer(playerUUID)); PlayerContainer player = db.query(ContainerFetchQueries.fetchPlayerContainer(playerUUID));
Map<UUID, String> serverNames = db.query(ServerQueries.fetchServerNames()); return new PlayerPage(
return new InspectPage( player,
player, serverNames,
versionCheckSystem.get(), versionCheckSystem.get(),
fileSystem.get(), config.get(), this, theme.get(), fileSystem.get(), config.get(), this, theme.get(),
graphs.get(), tables.get(), accordions.get(), formatters.get(), formatters.get(), serverInfo.get()
serverInfo.get(), timings.get()
); );
} }

View File

@ -0,0 +1,123 @@
/*
* 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.html.pages;
import com.djrapitops.plan.api.exceptions.ParseException;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.system.update.VersionCheckSystem;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.formatting.Formatters;
import com.djrapitops.plan.utilities.formatting.PlaceholderReplacer;
import java.io.IOException;
import java.util.UUID;
/**
* Used for parsing Inspect page out of database data and the html.
*
* @author Rsl1122
*/
public class PlayerPage implements Page {
private final PlayerContainer player;
private final VersionCheckSystem versionCheckSystem;
private final PlanFiles files;
private final PlanConfig config;
private final PageFactory pageFactory;
private final Theme theme;
private final ServerInfo serverInfo;
private final Formatter<Long> clockLongFormatter;
private final Formatter<Long> secondLongFormatter;
PlayerPage(
PlayerContainer player,
VersionCheckSystem versionCheckSystem,
PlanFiles files,
PlanConfig config,
PageFactory pageFactory,
Theme theme,
Formatters formatters,
ServerInfo serverInfo
) {
this.player = player;
this.versionCheckSystem = versionCheckSystem;
this.files = files;
this.config = config;
this.pageFactory = pageFactory;
this.theme = theme;
this.serverInfo = serverInfo;
clockLongFormatter = formatters.clockLong();
secondLongFormatter = formatters.secondLong();
}
@Override
public String toHtml() throws ParseException {
try {
if (!player.getValue(PlayerKeys.REGISTERED).isPresent()) {
throw new IllegalStateException("Player is not registered");
}
return parse(player);
} catch (Exception e) {
throw new ParseException(e);
}
}
public String parse(PlayerContainer player) throws IOException {
long now = System.currentTimeMillis();
UUID playerUUID = player.getUnsafe(PlayerKeys.UUID);
PlaceholderReplacer replacer = new PlaceholderReplacer();
replacer.put("refresh", clockLongFormatter.apply(now));
replacer.put("refreshFull", secondLongFormatter.apply(now));
replacer.put("version", versionCheckSystem.getCurrentVersion());
replacer.put("update", versionCheckSystem.getUpdateHtml().orElse(""));
replacer.put("timeZone", config.getTimeZoneOffsetHours());
String playerName = player.getValue(PlayerKeys.NAME).orElse(playerUUID.toString());
replacer.put("playerName", playerName);
replacer.put("worldPieColors", theme.getValue(ThemeVal.GRAPH_WORLD_PIE));
replacer.put("gmPieColors", theme.getValue(ThemeVal.GRAPH_GM_PIE));
replacer.put("serverPieColors", theme.getValue(ThemeVal.GRAPH_SERVER_PREF_PIE));
replacer.put("firstDay", 1);
if (serverInfo.getServer().isProxy()) {
replacer.put("backButton", "<li><a title=\"to Network page\" href=\"/network\"><i class=\"material-icons\">arrow_back</i><i class=\"material-icons\">cloud</i></a></li>");
} else {
replacer.put("backButton", "<li><a title=\"to Server page\" href=\"/server\"><i class=\"material-icons\">arrow_back</i><i class=\"material-icons\">storage</i></a></li>");
}
InspectPluginTab pluginTabs = pageFactory.inspectPluginTabs(playerUUID);
replacer.put("navPluginsTabs", pluginTabs.getNav());
replacer.put("pluginsTabs", pluginTabs.getTab());
return replacer.apply(files.getCustomizableResourceOrDefault("web/player.html").asString());
}
}

View File

@ -17,7 +17,6 @@
package com.djrapitops.plan.utilities.html.structure; package com.djrapitops.plan.utilities.html.structure;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.system.settings.config.PlanConfig; import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.DisplaySettings; import com.djrapitops.plan.system.settings.paths.DisplaySettings;
import com.djrapitops.plan.system.settings.theme.Theme; import com.djrapitops.plan.system.settings.theme.Theme;
@ -27,7 +26,6 @@ import com.djrapitops.plan.utilities.html.tables.HtmlTables;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -62,28 +60,6 @@ public class Accordions {
this.formatters = formatters; this.formatters = formatters;
} }
/**
* Create a new Session accordion for a Player.
*
* @param sessions {@link Session}s of the Player.
* @param serverNamesSupplier Supplier that provides server name map.
* @return a new {@link SessionAccordion}.
*/
public SessionAccordion playerSessionAccordion(
List<Session> sessions,
Supplier<Map<UUID, String>> serverNamesSupplier
) {
boolean appendWorldPercentage = config.isTrue(DisplaySettings.SESSION_MOST_PLAYED_WORLD_IN_TITLE);
int maxSessions = config.get(DisplaySettings.SESSIONS_PER_PAGE);
return new SessionAccordion(
true, sessions,
serverNamesSupplier, HashMap::new,
appendWorldPercentage, maxSessions,
config.getWorldAliasSettings(), theme, graphs, tables,
formatters.year(), formatters.timeAmount()
);
}
/** /**
* Create a new Session accordion for a server. * Create a new Session accordion for a server.
* *
@ -107,19 +83,4 @@ public class Accordions {
formatters.year(), formatters.timeAmount() formatters.year(), formatters.timeAmount()
); );
} }
/**
* Create a Server breakdown accordion for a player.
*
* @param player PlayerContainer of the Player.
* @param serverNames Names of the servers.
* @return a new {@link ServerAccordion}
*/
public ServerAccordion serverAccordion(PlayerContainer player, Map<UUID, String> serverNames) {
return new ServerAccordion(
player, serverNames,
theme, graphs,
formatters.yearLong(), formatters.timeAmount()
);
}
} }

View File

@ -1,71 +0,0 @@
/*
* 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.html.tables;
import com.djrapitops.plan.api.PlanAPI;
import com.djrapitops.plan.data.container.PlayerDeath;
import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.store.objects.DateHolder;
import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.html.Html;
import com.djrapitops.plan.utilities.html.icon.Family;
import com.djrapitops.plan.utilities.html.icon.Icon;
import java.util.List;
/**
* Html table that displays Deaths of a single player.
*
* @author Rsl1122
*/
class DeathsTable extends TableContainer {
private final Formatter<DateHolder> yearFormatter;
DeathsTable(List<PlayerDeath> playerPlayerDeaths, Formatter<DateHolder> yearFormatter) {
super(Icon.called("clock").of(Family.REGULAR) + " Time", "Killed by", "With");
this.yearFormatter = yearFormatter;
setColor("red");
if (playerPlayerDeaths.isEmpty()) {
addRow("No Player caused Deaths");
} else {
addValues(playerPlayerDeaths);
}
}
private void addValues(List<PlayerDeath> playerPlayerDeaths) {
playerPlayerDeaths.sort(new DateHolderRecentComparator());
int i = 0;
for (PlayerDeath death : playerPlayerDeaths) {
if (i >= 40) {
break;
}
String killerName = death.getKillerName();
addRow(
yearFormatter.apply(death),
Html.LINK.parse(PlanAPI.getInstance().getPlayerInspectPageLink(killerName), killerName),
death.getWeapon()
);
i++;
}
}
}

View File

@ -1,60 +0,0 @@
/*
* 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.html.tables;
import com.djrapitops.plan.data.container.GeoInfo;
import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.store.objects.DateHolder;
import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator;
import com.djrapitops.plan.utilities.formatting.Formatter;
import java.util.List;
/**
* Utility Class for creating IP Table for inspect page.
*
* @author Rsl1122
*/
class GeoInfoTable extends TableContainer {
private final boolean displayIP;
private final Formatter<DateHolder> yearFormatter;
GeoInfoTable(List<GeoInfo> geoInfo, boolean displayIP, Formatter<DateHolder> yearFormatter) {
super("IP", "Geolocation", "Last Used");
this.displayIP = displayIP;
this.yearFormatter = yearFormatter;
if (geoInfo.isEmpty()) {
addRow("No Connections");
} else {
addValues(geoInfo);
}
}
private void addValues(List<GeoInfo> geoInfo) {
geoInfo.sort(new DateHolderRecentComparator());
for (GeoInfo info : geoInfo) {
addRow(
displayIP ? info.getIp() : "Hidden (Config)",
info.getGeolocation(),
yearFormatter.apply(info)
);
}
}
}

View File

@ -16,13 +16,14 @@
*/ */
package com.djrapitops.plan.utilities.html.tables; package com.djrapitops.plan.utilities.html.tables;
import com.djrapitops.plan.data.container.*; import com.djrapitops.plan.data.container.Ping;
import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.element.AnalysisContainer; import com.djrapitops.plan.data.element.AnalysisContainer;
import com.djrapitops.plan.data.element.TableContainer; import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.plugin.PluginData; import com.djrapitops.plan.data.plugin.PluginData;
import com.djrapitops.plan.data.store.containers.DataContainer; import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.containers.PlayerContainer; import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.objects.Nickname;
import com.djrapitops.plan.system.settings.config.PlanConfig; import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.DisplaySettings; import com.djrapitops.plan.system.settings.paths.DisplaySettings;
import com.djrapitops.plan.system.settings.paths.TimeSettings; import com.djrapitops.plan.system.settings.paths.TimeSettings;
@ -65,26 +66,6 @@ public class HtmlTables {
return new CommandUseTable(container); return new CommandUseTable(container);
} }
/**
* Create a new Deaths table.
*
* @param deaths List of {@link PlayerDeath}s to be added to the table.
* @return a new {@link DeathsTable}.
*/
public TableContainer deathsTable(List<PlayerDeath> deaths) {
return new DeathsTable(deaths, formatters.year());
}
/**
* Create a new GeoInfo table.
*
* @param geoInfo List of {@link GeoInfo} to be added to the table.
* @return a new {@link GeoInfoTable}.
*/
public TableContainer geoInfoTable(List<GeoInfo> geoInfo) {
return new GeoInfoTable(geoInfo, config.isTrue(DisplaySettings.PLAYER_IPS), formatters.year());
}
/** /**
* Create a new Kill table. * Create a new Kill table.
* *
@ -96,17 +77,6 @@ public class HtmlTables {
return new KillsTable(kills, color, formatters.year()); return new KillsTable(kills, color, formatters.year());
} }
/**
* Create a new Nickname table.
*
* @param nicknames List of {@link Nickname}s to be added to the table.
* @param serverNames Names of the servers, for the server column.
* @return a new {@link NicknameTable}.
*/
public TableContainer nicknameTable(List<Nickname> nicknames, Map<UUID, String> serverNames) {
return new NicknameTable(nicknames, serverNames, formatters.year());
}
/** /**
* Create a new Country - Ping table. * Create a new Country - Ping table.
* *
@ -117,20 +87,6 @@ public class HtmlTables {
return new PingTable(pingPerCountry, formatters.decimals()); return new PingTable(pingPerCountry, formatters.decimals());
} }
/**
* Create a new Session table for a player.
*
* @param playerName Name of the player.
* @param sessions List of {@link Session}s the player has.
* @return a new {@link PlayerSessionTable}.
*/
public TableContainer playerSessionTable(String playerName, List<Session> sessions) {
return new PlayerSessionTable(
playerName, sessions,
config.get(DisplaySettings.SESSIONS_PER_PAGE), config.getWorldAliasSettings(), formatters.year(), formatters.timeAmount()
);
}
/** /**
* Create a new Session table for a server. * Create a new Session table for a server.
* *

View File

@ -1,64 +0,0 @@
/*
* 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.html.tables;
import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.store.objects.DateHolder;
import com.djrapitops.plan.data.store.objects.Nickname;
import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.html.Html;
import com.djrapitops.plan.utilities.html.HtmlUtils;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Html table that displays player's nicknames and where they were seen.
*
* @author Rsl1122
*/
class NicknameTable extends TableContainer {
private final Formatter<DateHolder> yearFormatter;
NicknameTable(List<Nickname> nicknames, Map<UUID, String> serverNames, Formatter<DateHolder> yearFormatter) {
super("Nickname", "Server", "Last Seen");
this.yearFormatter = yearFormatter;
if (nicknames.isEmpty()) {
addRow("No Nicknames");
} else {
addValues(nicknames, serverNames);
}
}
private void addValues(List<Nickname> nicknames, Map<UUID, String> serverNames) {
nicknames.sort(new DateHolderRecentComparator());
for (Nickname nickname : nicknames) {
UUID serverUUID = nickname.getServerUUID();
String serverName = serverNames.getOrDefault(serverUUID, "Unknown");
addRow(
Html.swapColorCodesToSpan(HtmlUtils.removeXSS(nickname.getName())),
serverName,
yearFormatter.apply(nickname)
);
}
}
}

View File

@ -1,85 +0,0 @@
/*
* 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.html.tables;
import com.djrapitops.plan.api.PlanAPI;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.data.store.objects.DateHolder;
import com.djrapitops.plan.system.settings.config.WorldAliasSettings;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.html.Html;
import java.util.List;
/**
* Html table that can be used to replace a {@link com.djrapitops.plan.utilities.html.structure.SessionAccordion}.
*
* @author Rsl1122
*/
class PlayerSessionTable extends TableContainer {
private final int maxSessions;
private final WorldAliasSettings worldAliasSettings;
private final Formatter<DateHolder> yearFormatter;
private final Formatter<Long> timeAmountFormatter;
private final String playerName;
private final List<Session> sessions;
PlayerSessionTable(String playerName, List<Session> sessions,
int maxSessions,
WorldAliasSettings worldAliasSettings,
Formatter<DateHolder> yearFormatter,
Formatter<Long> timeAmountFormatter
) {
super("Player", "Start", "Length", "World");
this.playerName = playerName;
this.sessions = sessions;
this.maxSessions = maxSessions;
this.worldAliasSettings = worldAliasSettings;
this.yearFormatter = yearFormatter;
this.timeAmountFormatter = timeAmountFormatter;
addRows();
}
private void addRows() {
String inspectUrl = PlanAPI.getInstance().getPlayerInspectPageLink(playerName);
int i = 0;
for (Session session : sessions) {
if (i >= maxSessions) {
break;
}
String start = yearFormatter.apply(session);
String length = session.supports(SessionKeys.END)
? timeAmountFormatter.apply(session.getValue(SessionKeys.LENGTH).orElse(0L))
: "Online";
String world = worldAliasSettings.getLongestWorldPlayed(session);
String toolTip = "Session ID: " + session.getValue(SessionKeys.DB_ID)
.map(Object::toString)
.orElse("Not Saved.");
addRow(Html.LINK_TOOLTIP.parse(inspectUrl, playerName, toolTip), start, length, world);
i++;
}
}
}

View File

@ -106,8 +106,6 @@ Display_options:
# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Themes # https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Themes
Theme: default Theme: default
Sessions: Sessions:
Replace_accordion_with_table: false
Show_most_played_world_in_title: true
Show_on_page: 50 Show_on_page: 50
# By Default World playtime pie is ordered alphabetically. # By Default World playtime pie is ordered alphabetically.
# Colors will be determined alphabetically in any case. # Colors will be determined alphabetically in any case.

View File

@ -113,8 +113,6 @@ Display_options:
# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Themes # https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Themes
Theme: default Theme: default
Sessions: Sessions:
Replace_accordion_with_table: false
Show_most_played_world_in_title: true
Show_on_page: 50 Show_on_page: 50
# By Default World playtime pie is ordered alphabetically. # By Default World playtime pie is ordered alphabetically.
# Colors will be determined alphabetically in any case. # Colors will be determined alphabetically in any case.

View File

@ -20,11 +20,13 @@ import com.djrapitops.plan.data.WebUser;
import com.djrapitops.plan.data.container.*; import com.djrapitops.plan.data.container.*;
import com.djrapitops.plan.data.element.TableContainer; import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.store.Key; import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.containers.AnalysisContainer;
import com.djrapitops.plan.data.store.containers.NetworkContainer; import com.djrapitops.plan.data.store.containers.NetworkContainer;
import com.djrapitops.plan.data.store.containers.PlayerContainer; import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.containers.ServerContainer; import com.djrapitops.plan.data.store.containers.ServerContainer;
import com.djrapitops.plan.data.store.keys.*; import com.djrapitops.plan.data.store.keys.NetworkKeys;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.keys.ServerKeys;
import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.data.store.mutators.SessionsMutator; import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.data.store.objects.DateObj; import com.djrapitops.plan.data.store.objects.DateObj;
import com.djrapitops.plan.data.store.objects.Nickname; import com.djrapitops.plan.data.store.objects.Nickname;
@ -909,39 +911,6 @@ public interface DatabaseTest {
assertTrue(unsupported.isEmpty(), () -> "Some keys are not supported by ServerContainer: ServerKeys." + unsupported.toString()); assertTrue(unsupported.isEmpty(), () -> "Some keys are not supported by ServerContainer: ServerKeys." + unsupported.toString());
} }
@Test
default void analysisContainerSupportsAllAnalysisKeys() throws IllegalAccessException, NoSuchAlgorithmException {
serverContainerSupportsAllServerKeys();
AnalysisContainer.Factory factory = constructAnalysisContainerFactory();
AnalysisContainer analysisContainer = factory.forServerContainer(
db().query(ContainerFetchQueries.fetchServerContainer(serverUUID()))
);
Collection<String> unsupported = new ArrayList<>();
List<Key> keys = FieldFetcher.getPublicStaticFields(AnalysisKeys.class, Key.class);
for (Key key : keys) {
if (!analysisContainer.supports(key)) {
unsupported.add(key.getKeyName());
}
}
assertTrue(unsupported.isEmpty(), () -> "Some keys are not supported by AnalysisContainer: AnalysisKeys." + unsupported.toString());
}
default AnalysisContainer.Factory constructAnalysisContainerFactory() {
return new AnalysisContainer.Factory(
"1.0.0",
system().getConfigSystem().getConfig(),
system().getLocaleSystem().getLocale(),
system().getConfigSystem().getTheme(),
system().getServerInfo().getServerProperties(),
system().getHtmlUtilities().getFormatters(),
system().getHtmlUtilities().getGraphs(),
system().getHtmlUtilities().getHtmlTables(),
system().getHtmlUtilities().getAccordions(),
system().getHtmlUtilities().getAnalysisPluginsTabContentCreator()
);
}
@Test @Test
default void networkContainerSupportsAllNetworkKeys() throws IllegalAccessException, NoSuchAlgorithmException { default void networkContainerSupportsAllNetworkKeys() throws IllegalAccessException, NoSuchAlgorithmException {
serverContainerSupportsAllServerKeys(); serverContainerSupportsAllServerKeys();
@ -1107,29 +1076,6 @@ public interface DatabaseTest {
assertEquals(expected, result); assertEquals(expected, result);
} }
// This test is against issue https://github.com/Rsl1122/Plan-PlayerAnalytics/issues/956
@Test
default void analysisContainerPlayerNamesAreCollectedFromBaseUsersCorrectly() {
db().executeTransaction(TestData.storeServers());
executeTransactions(TestData.storePlayerOneData());
executeTransactions(TestData.storePlayerTwoData());
BaseUser playerBaseUser = TestData.getPlayerBaseUser();
BaseUser player2BaseUser = TestData.getPlayer2BaseUser();
AnalysisContainer.Factory factory = constructAnalysisContainerFactory();
AnalysisContainer analysisContainer = factory.forServerContainer(
db().query(ContainerFetchQueries.fetchServerContainer(TestConstants.SERVER_UUID))
);
Map<UUID, String> expected = new HashMap<>();
expected.put(playerBaseUser.getUuid(), playerBaseUser.getName());
expected.put(player2BaseUser.getUuid(), player2BaseUser.getName());
Map<UUID, String> result = analysisContainer.getValue(AnalysisKeys.PLAYER_NAMES).orElseThrow(AssertionError::new);
assertEquals(expected, result);
}
@Test @Test
default void extensionPlayerValuesAreStored() { default void extensionPlayerValuesAreStored() {
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system().getExtensionService(); ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system().getExtensionService();

View File

@ -65,8 +65,6 @@ interface HttpsServerTest {
throw new ForbiddenException(url.toString() + " returned 403"); throw new ForbiddenException(url.toString() + " returned 403");
case 404: case 404:
throw new NotFoundException(url.toString() + " returned a 404, ensure that your server is connected to an up to date Plan server."); throw new NotFoundException(url.toString() + " returned a 404, ensure that your server is connected to an up to date Plan server.");
case 412:
throw new UnauthorizedServerException(url.toString() + " reported that it does not recognize this server. Make sure '/plan m setup' was successful.");
case 500: case 500:
throw new InternalErrorException(); throw new InternalErrorException();
default: default: