mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-10-16 07:16:03 +02:00
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:
parent
d7f5e18de3
commit
22a5348e33
@ -17,23 +17,21 @@
|
||||
package com.djrapitops.plan;
|
||||
|
||||
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 java.io.Serializable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class BStatsBungee {
|
||||
|
||||
private final PlanBungee plugin;
|
||||
private final Database database;
|
||||
private final ConnectionSystem connectionSystem;
|
||||
|
||||
private Metrics metrics;
|
||||
|
||||
public BStatsBungee(PlanBungee plugin, Database database, ConnectionSystem connectionSystem) {
|
||||
public BStatsBungee(PlanBungee plugin, Database database) {
|
||||
this.plugin = plugin;
|
||||
this.database = database;
|
||||
this.connectionSystem = connectionSystem;
|
||||
}
|
||||
|
||||
public void registerMetrics() {
|
||||
@ -44,15 +42,12 @@ public class BStatsBungee {
|
||||
}
|
||||
|
||||
private void registerConfigSettingGraphs() {
|
||||
String serverType = plugin.getProxy().getName();
|
||||
String databaseType = database.getType().getName();
|
||||
|
||||
addStringSettingPie("server_type", serverType);
|
||||
addStringSettingPie("database_type", databaseType);
|
||||
addStringSettingPie("network_servers", connectionSystem.getDataServers().size());
|
||||
addStringSettingPie("server_type", () -> plugin.getProxy().getName());
|
||||
addStringSettingPie("database_type", () -> database.getType().getName());
|
||||
addStringSettingPie("network_servers", () -> String.valueOf(database.query(ServerQueries.fetchPlanServerInformationCollection()).size()));
|
||||
}
|
||||
|
||||
protected void addStringSettingPie(String id, Serializable setting) {
|
||||
metrics.addCustomChart(new Metrics.SimplePie(id, setting::toString));
|
||||
protected void addStringSettingPie(String id, Supplier<String> setting) {
|
||||
metrics.addCustomChart(new Metrics.SimplePie(id, setting::get));
|
||||
}
|
||||
}
|
||||
|
@ -48,8 +48,7 @@ public class PlanBungee extends BungeePlugin implements PlanPlugin {
|
||||
|
||||
new BStatsBungee(
|
||||
this,
|
||||
system.getDatabaseSystem().getDatabase(),
|
||||
system.getInfoSystem().getConnectionSystem()
|
||||
system.getDatabaseSystem().getDatabase()
|
||||
).registerMetrics();
|
||||
|
||||
logger.info(locale.getString(PluginLang.ENABLED));
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@
|
||||
package com.djrapitops.plan.command;
|
||||
|
||||
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.ManageUninstalledCommand;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
@ -48,9 +47,7 @@ public class PlanProxyCommand extends TreeCmdNode {
|
||||
private final ListPlayersCommand listPlayersCommand;
|
||||
private final RegisterCommand registerCommand;
|
||||
private final Lazy<WebUserCommand> webUserCommand;
|
||||
private final ManageConDebugCommand conDebugCommand;
|
||||
private final ManageRawDataCommand rawDataCommand;
|
||||
private final BungeeSetupToggleCommand setupToggleCommand;
|
||||
private final ReloadCommand reloadCommand;
|
||||
private final DisableCommand disableCommand;
|
||||
private final ManageUninstalledCommand uninstalledCommand;
|
||||
@ -70,9 +67,7 @@ public class PlanProxyCommand extends TreeCmdNode {
|
||||
RegisterCommand registerCommand,
|
||||
Lazy<WebUserCommand> webUserCommand,
|
||||
// Group 3
|
||||
ManageConDebugCommand conDebugCommand,
|
||||
ManageRawDataCommand rawDataCommand,
|
||||
BungeeSetupToggleCommand setupToggleCommand,
|
||||
ManageUninstalledCommand uninstalledCommand,
|
||||
ReloadCommand reloadCommand,
|
||||
DisableCommand disableCommand
|
||||
@ -87,9 +82,7 @@ public class PlanProxyCommand extends TreeCmdNode {
|
||||
this.listPlayersCommand = listPlayersCommand;
|
||||
this.registerCommand = registerCommand;
|
||||
this.webUserCommand = webUserCommand;
|
||||
this.conDebugCommand = conDebugCommand;
|
||||
this.rawDataCommand = rawDataCommand;
|
||||
this.setupToggleCommand = setupToggleCommand;
|
||||
this.reloadCommand = reloadCommand;
|
||||
this.disableCommand = disableCommand;
|
||||
|
||||
@ -113,9 +106,7 @@ public class PlanProxyCommand extends TreeCmdNode {
|
||||
webUserCommand.get()
|
||||
};
|
||||
CommandNode[] manageGroup = {
|
||||
conDebugCommand,
|
||||
rawDataCommand,
|
||||
setupToggleCommand,
|
||||
uninstalledCommand,
|
||||
reloadCommand,
|
||||
disableCommand
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -117,7 +117,7 @@ public class InspectCommand extends CommandNode {
|
||||
}
|
||||
|
||||
checkWebUserAndNotify(sender);
|
||||
processing.submit(processorFactory.inspectCacheRequestProcessor(playerUUID, sender, playerName, this::sendInspectMsg));
|
||||
this.sendInspectMsg(sender, playerName);
|
||||
} catch (DBOpException e) {
|
||||
sender.sendMessage("§eDatabase exception occurred: " + e.getMessage());
|
||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||
|
@ -48,8 +48,6 @@ public class ManageCommand extends TreeCmdNode {
|
||||
ManageHotSwapCommand hotSwapCommand,
|
||||
ManageClearCommand clearCommand,
|
||||
// Group 2
|
||||
ManageSetupCommand setupCommand,
|
||||
ManageConDebugCommand conDebugCommand,
|
||||
ManageImportCommand importCommand,
|
||||
ManageExportCommand exportCommand,
|
||||
ManageDisableCommand disableCommand,
|
||||
@ -70,8 +68,6 @@ public class ManageCommand extends TreeCmdNode {
|
||||
clearCommand,
|
||||
};
|
||||
CommandNode[] pluginGroup = {
|
||||
setupCommand,
|
||||
conDebugCommand,
|
||||
importCommand,
|
||||
exportCommand,
|
||||
disableCommand,
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
@ -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()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -20,6 +20,10 @@ import com.djrapitops.plan.data.store.objects.DateHolder;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link PlayerKill} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class PlayerDeath implements DateHolder {
|
||||
|
||||
private final UUID killer;
|
||||
|
@ -46,7 +46,7 @@ public abstract class PluginData {
|
||||
|
||||
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) {
|
||||
this.size = size;
|
||||
|
@ -16,545 +16,16 @@
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @see com.djrapitops.plan.data.store.keys.AnalysisKeys for Key objects
|
||||
* @see com.djrapitops.plan.data.store.PlaceholderKey for placeholder information
|
||||
* @deprecated AnalysisContainer is no longer used.
|
||||
*/
|
||||
@Deprecated
|
||||
public class AnalysisContainer extends DynamicDataContainer {
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
public AnalysisContainer() {
|
||||
}
|
||||
}
|
@ -37,6 +37,7 @@ import java.util.UUID;
|
||||
* @author Rsl1122
|
||||
* @see com.djrapitops.plan.data.store.containers.AnalysisContainer for Suppliers for each Key.
|
||||
*/
|
||||
@Deprecated
|
||||
public class AnalysisKeys {
|
||||
|
||||
// Constants (Affected only by config settings)
|
||||
|
@ -51,6 +51,7 @@ public class CommonKeys {
|
||||
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");
|
||||
|
||||
@Deprecated
|
||||
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<Integer> PLAYER_KILL_COUNT = new Key<>(Integer.class, "player_kill_count");
|
||||
|
@ -96,6 +96,10 @@ public class SessionsMutator {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Incorrect results.
|
||||
*/
|
||||
@Deprecated
|
||||
public List<PlayerDeath> toPlayerDeathList() {
|
||||
return sessions.stream()
|
||||
.map(session -> session.getValue(SessionKeys.PLAYER_DEATHS).orElse(new ArrayList<>()))
|
||||
@ -232,6 +236,10 @@ public class SessionsMutator {
|
||||
return sorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Incorrect value, use PlayerVersusMutator instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public int toPlayerDeathCount() {
|
||||
return toPlayerDeathList().size();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -22,8 +22,6 @@ import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.ProxyDBSystem;
|
||||
import com.djrapitops.plan.system.importing.EmptyImportSystem;
|
||||
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.ProxyConnectionSystem;
|
||||
import com.djrapitops.plan.system.settings.ConfigSystem;
|
||||
@ -48,13 +46,10 @@ public interface ProxySuperClassBindingModule {
|
||||
@Binds
|
||||
ConfigSystem bindProxyConfigSystem(ProxyConfigSystem proxyConfigSystem);
|
||||
|
||||
@Binds
|
||||
InfoSystem bindProxyInfoSystem(ProxyInfoSystem proxyInfoSystem);
|
||||
|
||||
@Binds
|
||||
ConnectionSystem bindProxyConnectionSystem(ProxyConnectionSystem proxyConnectionSystem);
|
||||
|
||||
@Binds
|
||||
ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem);
|
||||
|
||||
@Binds
|
||||
ConnectionSystem bindServerConnectionSystem(ProxyConnectionSystem connectionSystem);
|
||||
|
||||
}
|
@ -18,8 +18,6 @@ package com.djrapitops.plan.modules;
|
||||
|
||||
import com.djrapitops.plan.api.CommonAPI;
|
||||
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.ServerConnectionSystem;
|
||||
import dagger.Binds;
|
||||
@ -37,8 +35,6 @@ public interface ServerSuperClassBindingModule {
|
||||
PlanAPI bindServerPlanAPI(CommonAPI serverAPI);
|
||||
|
||||
@Binds
|
||||
InfoSystem bindServerInfoSystem(ServerInfoSystem serverInfoSystem);
|
||||
ConnectionSystem bindServerConnectionSystem(ServerConnectionSystem connectionSystem);
|
||||
|
||||
@Binds
|
||||
ConnectionSystem bindServerConnectionSystem(ServerConnectionSystem serverConnectionSystem);
|
||||
}
|
@ -29,8 +29,11 @@ public class DebugChannels {
|
||||
}
|
||||
|
||||
public static final String ANALYSIS = "Analysis";
|
||||
@Deprecated
|
||||
public static final String INFO_REQUESTS = "InfoRequests";
|
||||
@Deprecated
|
||||
public static final String CONNECTIONS = "Connections";
|
||||
@Deprecated
|
||||
public static final String WEB_REQUESTS = "Web Requests";
|
||||
public static final String IMPORTING = "Importing";
|
||||
public static final String SQL = "SQL";
|
||||
|
@ -28,7 +28,6 @@ import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.export.ExportSystem;
|
||||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
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.listeners.ListenerSystem;
|
||||
import com.djrapitops.plan.system.locale.LocaleSystem;
|
||||
@ -63,7 +62,6 @@ public class PlanSystem implements SubSystem {
|
||||
private final CacheSystem cacheSystem;
|
||||
private final ListenerSystem listenerSystem;
|
||||
private final TaskSystem taskSystem;
|
||||
private final InfoSystem infoSystem;
|
||||
private final ServerInfo serverInfo;
|
||||
private final WebServerSystem webServerSystem;
|
||||
|
||||
@ -88,7 +86,6 @@ public class PlanSystem implements SubSystem {
|
||||
CacheSystem cacheSystem,
|
||||
ListenerSystem listenerSystem,
|
||||
TaskSystem taskSystem,
|
||||
InfoSystem infoSystem,
|
||||
ServerInfo serverInfo,
|
||||
WebServerSystem webServerSystem,
|
||||
Processing processing,
|
||||
@ -109,7 +106,6 @@ public class PlanSystem implements SubSystem {
|
||||
this.cacheSystem = cacheSystem;
|
||||
this.listenerSystem = listenerSystem;
|
||||
this.taskSystem = taskSystem;
|
||||
this.infoSystem = infoSystem;
|
||||
this.serverInfo = serverInfo;
|
||||
this.webServerSystem = webServerSystem;
|
||||
this.processing = processing;
|
||||
@ -138,7 +134,6 @@ public class PlanSystem implements SubSystem {
|
||||
serverInfo,
|
||||
importSystem,
|
||||
exportSystem,
|
||||
infoSystem,
|
||||
cacheSystem,
|
||||
listenerSystem,
|
||||
taskSystem,
|
||||
@ -168,7 +163,6 @@ public class PlanSystem implements SubSystem {
|
||||
processing,
|
||||
databaseSystem,
|
||||
webServerSystem,
|
||||
infoSystem,
|
||||
serverInfo,
|
||||
localeSystem,
|
||||
configSystem,
|
||||
@ -235,10 +229,6 @@ public class PlanSystem implements SubSystem {
|
||||
return cacheSystem;
|
||||
}
|
||||
|
||||
public InfoSystem getInfoSystem() {
|
||||
return infoSystem;
|
||||
}
|
||||
|
||||
public HookHandler getHookHandler() {
|
||||
return hookHandler;
|
||||
}
|
||||
|
@ -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.ResponseCache;
|
||||
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.PageFactory;
|
||||
import com.djrapitops.plan.utilities.html.pages.PlayerPage;
|
||||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
@ -114,7 +114,7 @@ public class HtmlExport extends SpecificExport {
|
||||
}
|
||||
|
||||
public void exportPlayerPage(UUID playerUUID, String playerName) {
|
||||
InspectPage playerPage = pageFactory.inspectPage(playerUUID);
|
||||
PlayerPage playerPage = pageFactory.playerPage(playerUUID);
|
||||
try {
|
||||
exportPlayerPage(playerName, playerPage.toHtml());
|
||||
} catch (ParseException | IOException e) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -16,101 +16,29 @@
|
||||
*/
|
||||
package com.djrapitops.plan.system.info.connection;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
|
||||
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.db.access.queries.objects.ServerQueries;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import dagger.Lazy;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* ConnectionSystem manages out- and inbound InfoRequest connections.
|
||||
* <p>
|
||||
* It decides what server to use for each request.
|
||||
* ConnectionSystem manages proxy server status.
|
||||
*
|
||||
* @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 Map<UUID, Server> dataServers;
|
||||
private boolean setupAllowed;
|
||||
|
||||
public ConnectionSystem(
|
||||
ConnectionLog connectionLog,
|
||||
InfoRequests infoRequests,
|
||||
Lazy<InfoSystem> infoSystem,
|
||||
ServerInfo serverInfo
|
||||
) {
|
||||
this.connectionLog = connectionLog;
|
||||
this.infoSystem = infoSystem;
|
||||
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();
|
||||
|
||||
@Deprecated
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -16,24 +16,12 @@
|
||||
*/
|
||||
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.webserver.WebServer;
|
||||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import dagger.Lazy;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* ConnectionSystem for proxy servers.
|
||||
@ -43,70 +31,15 @@ import java.util.stream.Collectors;
|
||||
@Singleton
|
||||
public class ProxyConnectionSystem extends ConnectionSystem {
|
||||
|
||||
private final DBSystem dbSystem;
|
||||
private final Lazy<WebServer> webServer;
|
||||
private final ErrorHandler errorHandler;
|
||||
private final WebExceptionLogger webExceptionLogger;
|
||||
|
||||
private long latestServerMapRefresh;
|
||||
|
||||
@Inject
|
||||
public ProxyConnectionSystem(
|
||||
DBSystem dbSystem,
|
||||
Lazy<WebServer> webServer,
|
||||
ConnectionLog connectionLog,
|
||||
InfoRequests infoRequests,
|
||||
Lazy<InfoSystem> infoSystem,
|
||||
ServerInfo serverInfo,
|
||||
ErrorHandler errorHandler,
|
||||
WebExceptionLogger webExceptionLogger
|
||||
ServerInfo serverInfo
|
||||
) {
|
||||
super(connectionLog, infoRequests, infoSystem, serverInfo);
|
||||
this.dbSystem = dbSystem;
|
||||
super(serverInfo);
|
||||
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
|
||||
@ -119,10 +52,4 @@ public class ProxyConnectionSystem extends ConnectionSystem {
|
||||
return webServer.get().getAccessAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
super.enable();
|
||||
refreshServerMap();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,24 +16,12 @@
|
||||
*/
|
||||
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.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.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||
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.Singleton;
|
||||
@ -50,13 +38,8 @@ import java.util.concurrent.TimeUnit;
|
||||
@Singleton
|
||||
public class ServerConnectionSystem extends ConnectionSystem {
|
||||
|
||||
private final Locale locale;
|
||||
private final PlanConfig config;
|
||||
private final Processing processing;
|
||||
private final DBSystem dbSystem;
|
||||
private final Lazy<WebServer> webServer;
|
||||
private final PluginLogger pluginLogger;
|
||||
private final WebExceptionLogger webExceptionLogger;
|
||||
|
||||
private long latestServerMapRefresh;
|
||||
|
||||
@ -64,32 +47,20 @@ public class ServerConnectionSystem extends ConnectionSystem {
|
||||
|
||||
@Inject
|
||||
public ServerConnectionSystem(
|
||||
Locale locale,
|
||||
PlanConfig config,
|
||||
Processing processing,
|
||||
DBSystem dbSystem,
|
||||
Lazy<WebServer> webServer,
|
||||
ConnectionLog connectionLog,
|
||||
InfoRequests infoRequests,
|
||||
Lazy<InfoSystem> infoSystem,
|
||||
ServerInfo serverInfo,
|
||||
PluginLogger pluginLogger,
|
||||
WebExceptionLogger webExceptionLogger
|
||||
ServerInfo serverInfo
|
||||
) {
|
||||
super(connectionLog, infoRequests, infoSystem, serverInfo);
|
||||
this.locale = locale;
|
||||
this.config = config;
|
||||
super(serverInfo);
|
||||
this.processing = processing;
|
||||
this.dbSystem = dbSystem;
|
||||
this.webServer = webServer;
|
||||
this.pluginLogger = pluginLogger;
|
||||
this.webExceptionLogger = webExceptionLogger;
|
||||
latestServerMapRefresh = 0;
|
||||
}
|
||||
|
||||
private void refreshServerMap() {
|
||||
processing.submitNonCritical(() -> {
|
||||
if (latestServerMapRefresh < System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(15L)) {
|
||||
|
||||
Database database = dbSystem.getDatabase();
|
||||
Map<UUID, Server> servers = database.query(ServerQueries.fetchPlanServerInformation());
|
||||
Optional<Server> proxy = servers.values().stream()
|
||||
@ -98,73 +69,21 @@ public class ServerConnectionSystem extends ConnectionSystem {
|
||||
mainServer = proxy.orElse(null);
|
||||
|
||||
proxy.ifPresent(proxyServer -> servers.remove(proxyServer.getUuid()));
|
||||
|
||||
dataServers = servers;
|
||||
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
|
||||
public boolean isServerAvailable() {
|
||||
refreshServerMap();
|
||||
return mainServer != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMainAddress() {
|
||||
refreshServerMap();
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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 {
|
||||
}
|
@ -36,7 +36,9 @@ public enum CmdHelpLang implements Lang {
|
||||
WEB_REGISTER("Command Help - /plan register", "Register a Web User"),
|
||||
WEB("Command Help - /plan webuser", "Manage Web Users"),
|
||||
DEV("Command Help - /plan dev", "Development mode command"),
|
||||
@Deprecated
|
||||
SETUP("Command Help - /planbungee setup", "Toggle set-up mode"),
|
||||
@Deprecated
|
||||
CON("Command Help - /planbungee con", "Debug Proxy-Server connections"),
|
||||
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_HOTSWAP("Command Help - /plan manage hotswap", "Change Database quickly"),
|
||||
MANAGE_CLEAR("Command Help - /plan manage clear", "Clear a Database"),
|
||||
@Deprecated
|
||||
MANAGE_CON("Command Help - /plan manage con", "Debug Server-Proxy connections"),
|
||||
MANAGE_IMPORT("Command Help - /plan manage import", "Import data from elsewhere"),
|
||||
MANAGE_EXPORT("Command Help - /plan manage export", "Trigger export manually"),
|
||||
MANAGE_DISABLE("Command Help - /plan manage disable", "Disable a feature temporarily"),
|
||||
@Deprecated
|
||||
MANAGE_SETUP("Command Help - /plan manage setup", "Set-up Server-Proxy connection"),
|
||||
|
||||
WEB_LEVEL("Command Help - /plan web level", "Information about permission levels"),
|
||||
|
@ -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>"),
|
||||
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.."),
|
||||
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."),
|
||||
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}"),
|
||||
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."),
|
||||
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_SUCCESS("Cmd Setup - Success", "§aConnection successful, Plan may restart in a few seconds.."),
|
||||
@Deprecated 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_BAD_REQUEST("Cmd Setup - Bad Request", "§eConnection succeeded, but Receiving server was a Bukkit or Sponge server. Use another address instead."),
|
||||
@Deprecated CONNECT_UNAUTHORIZED("Cmd Setup - Unauthorized", "§eConnection succeeded, but Receiving server didn't authorize this server. Contact Discord for support"),
|
||||
@Deprecated CONNECT_FAIL("Cmd Setup - Generic Fail", "§eConnection failed: ${0}"),
|
||||
@Deprecated CONNECT_INTERNAL_ERROR("Cmd Setup - Internal Error", "§eConnection succeeded. ${0}, check possible ErrorLog on receiving server's debug page."),
|
||||
@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."),
|
||||
@Deprecated CONNECT_WEBSERVER_NOT_ENABLED("Cmd Setup - WebServer not Enabled", "§cWebServer is not enabled on this server! Make sure it enables on boot!"),
|
||||
@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"),
|
||||
SETUP_FORBIDDEN("Cmd Setup - Disallowed", "§cSet-up is now Forbidden"),
|
||||
@Deprecated SETUP_ALLOWED("Cmd Setup - Allowed", "§aSet-up is now Allowed"),
|
||||
@Deprecated SETUP_FORBIDDEN("Cmd Setup - Disallowed", "§cSet-up is now Forbidden"),
|
||||
|
||||
LINK_CLICK_ME("Cmd - Click Me", "Click me"),
|
||||
LINK_PREFIX("Cmd - Link", " §2Link: §f"),
|
||||
|
@ -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_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_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_WRONG_DB("Enable FAIL - Wrong Database Type", "${0} is not a supported Database"),
|
||||
|
@ -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.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.plugin.command.Sender;
|
||||
import dagger.Lazy;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
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
|
||||
*/
|
||||
@ -40,35 +36,19 @@ public class InfoProcessors {
|
||||
private final Lazy<PlanConfig> config;
|
||||
private final Lazy<HtmlExport> htmlExport;
|
||||
private final Lazy<JSONExport> jsonExport;
|
||||
private final Lazy<InfoSystem> infoSystem;
|
||||
private final Lazy<WebExceptionLogger> webExceptionLogger;
|
||||
|
||||
@Inject
|
||||
public InfoProcessors(
|
||||
Lazy<PlanConfig> config,
|
||||
Lazy<HtmlExport> htmlExport,
|
||||
Lazy<JSONExport> jsonExport,
|
||||
Lazy<InfoSystem> infoSystem,
|
||||
Lazy<WebExceptionLogger> webExceptionLogger
|
||||
Lazy<JSONExport> jsonExport
|
||||
) {
|
||||
this.config = config;
|
||||
this.htmlExport = htmlExport;
|
||||
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) {
|
||||
return new PlayerPageUpdateProcessor(uuid, config.get(), htmlExport.get(), jsonExport.get());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -126,7 +126,11 @@ public class ConfigUpdater {
|
||||
new ConfigChange.Removed("Analysis"),
|
||||
new ConfigChange.Removed("Data"),
|
||||
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")
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,10 @@ import com.djrapitops.plan.system.settings.paths.key.StringSetting;
|
||||
public class DisplaySettings {
|
||||
|
||||
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<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> 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");
|
||||
|
@ -18,7 +18,6 @@ package com.djrapitops.plan.system.webserver;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.WebUserAuthException;
|
||||
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.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
@ -47,7 +46,6 @@ public class ResponseHandler extends TreePageHandler {
|
||||
private final PlayersPageHandler playersPageHandler;
|
||||
private final PlayerPageHandler playerPageHandler;
|
||||
private final ServerPageHandler serverPageHandler;
|
||||
private final InfoRequestPageHandler infoRequestPageHandler;
|
||||
private final RootJSONHandler rootJSONHandler;
|
||||
private final ErrorHandler errorHandler;
|
||||
|
||||
@ -62,7 +60,6 @@ public class ResponseHandler extends TreePageHandler {
|
||||
PlayersPageHandler playersPageHandler,
|
||||
PlayerPageHandler playerPageHandler,
|
||||
ServerPageHandler serverPageHandler,
|
||||
InfoRequestPageHandler infoRequestPageHandler,
|
||||
RootJSONHandler rootJSONHandler,
|
||||
|
||||
ErrorHandler errorHandler
|
||||
@ -73,7 +70,6 @@ public class ResponseHandler extends TreePageHandler {
|
||||
this.playersPageHandler = playersPageHandler;
|
||||
this.playerPageHandler = playerPageHandler;
|
||||
this.serverPageHandler = serverPageHandler;
|
||||
this.infoRequestPageHandler = infoRequestPageHandler;
|
||||
this.rootJSONHandler = rootJSONHandler;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
@ -92,7 +88,6 @@ public class ResponseHandler extends TreePageHandler {
|
||||
registerPage("", responseFactory.redirectResponse("/server"), 5);
|
||||
}
|
||||
|
||||
registerPage("info", infoRequestPageHandler);
|
||||
registerPage("v1", rootJSONHandler);
|
||||
}
|
||||
|
||||
@ -107,10 +102,6 @@ public class ResponseHandler extends TreePageHandler {
|
||||
return responseFactory.forbidden403(e.getMessage());
|
||||
} catch (BadRequestException e) {
|
||||
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) {
|
||||
if (e.getCause() != null) {
|
||||
return responseFactory.internalErrorResponse(e.getCause(), request.getTargetString());
|
||||
@ -141,8 +132,7 @@ public class ResponseHandler extends TreePageHandler {
|
||||
return ResponseCache.loadResponse(PageId.FAVICON.id(), responseFactory::faviconResponse);
|
||||
}
|
||||
|
||||
boolean isNotInfoRequest = target.isEmpty() || !target.get(0).equals("info");
|
||||
boolean isAuthRequired = webServer.get().isAuthRequired() && isNotInfoRequest;
|
||||
boolean isAuthRequired = webServer.get().isAuthRequired();
|
||||
if (isAuthRequired && !authentication.isPresent()) {
|
||||
if (webServer.get().isUsingHTTPS()) {
|
||||
return responseFactory.basicAuth();
|
||||
|
@ -151,6 +151,10 @@ public class WebServer implements SubSystem {
|
||||
enabled = true;
|
||||
|
||||
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) {
|
||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||
enabled = false;
|
||||
|
@ -24,7 +24,6 @@ import com.djrapitops.plan.data.WebUser;
|
||||
import com.djrapitops.plan.db.Database;
|
||||
import com.djrapitops.plan.db.access.queries.PlayerFetchQueries;
|
||||
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.RequestTarget;
|
||||
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.response.Response;
|
||||
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 javax.inject.Inject;
|
||||
@ -49,19 +47,16 @@ public class PlayerPageHandler implements PageHandler {
|
||||
|
||||
private final ResponseFactory responseFactory;
|
||||
private final DBSystem dbSystem;
|
||||
private final InfoSystem infoSystem;
|
||||
private final UUIDUtility uuidUtility;
|
||||
|
||||
@Inject
|
||||
public PlayerPageHandler(
|
||||
ResponseFactory responseFactory,
|
||||
DBSystem dbSystem,
|
||||
InfoSystem infoSystem,
|
||||
UUIDUtility uuidUtility
|
||||
) {
|
||||
this.responseFactory = responseFactory;
|
||||
this.dbSystem = dbSystem;
|
||||
this.infoSystem = infoSystem;
|
||||
this.uuidUtility = uuidUtility;
|
||||
}
|
||||
|
||||
@ -99,12 +94,9 @@ public class PlayerPageHandler implements PageHandler {
|
||||
return responseFactory.serverNotFound404();
|
||||
}
|
||||
|
||||
private Response playerResponseOrNotFound(UUID uuid) throws WebException {
|
||||
Response response = ResponseCache.loadResponse(PageId.PLAYER.of(uuid));
|
||||
if (!(response instanceof InspectPageResponse)) {
|
||||
infoSystem.generateAndCachePlayerPage(uuid);
|
||||
response = ResponseCache.loadResponse(PageId.PLAYER.of(uuid));
|
||||
}
|
||||
private Response playerResponseOrNotFound(UUID playerUUID) throws WebException {
|
||||
Response response = ResponseCache.loadResponse(PageId.PLAYER.of(playerUUID),
|
||||
() -> responseFactory.playerPageResponse(playerUUID));
|
||||
return response != null ? response : responseFactory.playerNotFound404();
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,10 @@ import com.djrapitops.plan.system.file.PlanFiles;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.ErrorPageLang;
|
||||
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.utilities.html.pages.PageFactory;
|
||||
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() {
|
||||
try {
|
||||
return PromptAuthorizationResponse.getBasicAuthResponse(versionCheckSystem, files);
|
||||
@ -217,4 +204,14 @@ public class ResponseFactory {
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -16,45 +16,28 @@
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.response.pages;
|
||||
|
||||
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 org.apache.commons.text.StringSubstitutor;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class InspectPageResponse extends PageResponse {
|
||||
public class PlayerPageResponse extends PageResponse {
|
||||
|
||||
private final UUID uuid;
|
||||
|
||||
public InspectPageResponse(UUID uuid, String html) {
|
||||
public PlayerPageResponse(UUID uuid, String html) {
|
||||
super.setHeader("HTTP/1.1 200 OK");
|
||||
super.setContent(html);
|
||||
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
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof InspectPageResponse)) return false;
|
||||
if (!(o instanceof PlayerPageResponse)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
InspectPageResponse that = (InspectPageResponse) o;
|
||||
PlayerPageResponse that = (PlayerPageResponse) o;
|
||||
return Objects.equals(uuid, that.uuid);
|
||||
}
|
||||
|
@ -22,9 +22,7 @@ import com.djrapitops.plan.data.store.objects.DateHolder;
|
||||
import com.djrapitops.plan.db.Database;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
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.server.Server;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.info.server.properties.ServerProperties;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
@ -167,54 +165,11 @@ public class DebugPage implements Page {
|
||||
StringBuilder content = new StringBuilder();
|
||||
|
||||
appendServerInformation(content);
|
||||
appendConnectionLog(content);
|
||||
appendBenchmarks(content);
|
||||
|
||||
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) {
|
||||
ServerProperties serverProperties = serverInfo.getServerProperties();
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
@ -136,16 +136,14 @@ public class PageFactory {
|
||||
)).orElseThrow(() -> new NotFoundException("Server not found in the database"));
|
||||
}
|
||||
|
||||
public InspectPage inspectPage(UUID playerUUID) {
|
||||
public PlayerPage playerPage(UUID playerUUID) {
|
||||
Database db = dbSystem.get().getDatabase();
|
||||
PlayerContainer player = db.query(ContainerFetchQueries.fetchPlayerContainer(playerUUID));
|
||||
Map<UUID, String> serverNames = db.query(ServerQueries.fetchServerNames());
|
||||
return new InspectPage(
|
||||
player, serverNames,
|
||||
return new PlayerPage(
|
||||
player,
|
||||
versionCheckSystem.get(),
|
||||
fileSystem.get(), config.get(), this, theme.get(),
|
||||
graphs.get(), tables.get(), accordions.get(), formatters.get(),
|
||||
serverInfo.get(), timings.get()
|
||||
formatters.get(), serverInfo.get()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@
|
||||
package com.djrapitops.plan.utilities.html.structure;
|
||||
|
||||
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.paths.DisplaySettings;
|
||||
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.Singleton;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@ -62,28 +60,6 @@ public class Accordions {
|
||||
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.
|
||||
*
|
||||
@ -107,19 +83,4 @@ public class Accordions {
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -16,13 +16,14 @@
|
||||
*/
|
||||
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.TableContainer;
|
||||
import com.djrapitops.plan.data.plugin.PluginData;
|
||||
import com.djrapitops.plan.data.store.containers.DataContainer;
|
||||
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.paths.DisplaySettings;
|
||||
import com.djrapitops.plan.system.settings.paths.TimeSettings;
|
||||
@ -65,26 +66,6 @@ public class HtmlTables {
|
||||
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.
|
||||
*
|
||||
@ -96,17 +77,6 @@ public class HtmlTables {
|
||||
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.
|
||||
*
|
||||
@ -117,20 +87,6 @@ public class HtmlTables {
|
||||
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.
|
||||
*
|
||||
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
@ -106,8 +106,6 @@ Display_options:
|
||||
# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Themes
|
||||
Theme: default
|
||||
Sessions:
|
||||
Replace_accordion_with_table: false
|
||||
Show_most_played_world_in_title: true
|
||||
Show_on_page: 50
|
||||
# By Default World playtime pie is ordered alphabetically.
|
||||
# Colors will be determined alphabetically in any case.
|
||||
|
@ -113,8 +113,6 @@ Display_options:
|
||||
# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Themes
|
||||
Theme: default
|
||||
Sessions:
|
||||
Replace_accordion_with_table: false
|
||||
Show_most_played_world_in_title: true
|
||||
Show_on_page: 50
|
||||
# By Default World playtime pie is ordered alphabetically.
|
||||
# Colors will be determined alphabetically in any case.
|
||||
|
@ -20,11 +20,13 @@ import com.djrapitops.plan.data.WebUser;
|
||||
import com.djrapitops.plan.data.container.*;
|
||||
import com.djrapitops.plan.data.element.TableContainer;
|
||||
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.PlayerContainer;
|
||||
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.objects.DateObj;
|
||||
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());
|
||||
}
|
||||
|
||||
@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
|
||||
default void networkContainerSupportsAllNetworkKeys() throws IllegalAccessException, NoSuchAlgorithmException {
|
||||
serverContainerSupportsAllServerKeys();
|
||||
@ -1107,29 +1076,6 @@ public interface DatabaseTest {
|
||||
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
|
||||
default void extensionPlayerValuesAreStored() {
|
||||
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system().getExtensionService();
|
||||
|
@ -65,8 +65,6 @@ interface HttpsServerTest {
|
||||
throw new ForbiddenException(url.toString() + " returned 403");
|
||||
case 404:
|
||||
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:
|
||||
throw new InternalErrorException();
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user