Skip to content

Commit 4e0f1b3

Browse files
committed
Update command #539
1 parent 23a3fc4 commit 4e0f1b3

File tree

17 files changed

+592
-14
lines changed

17 files changed

+592
-14
lines changed

Plan/src/main/java/com/djrapitops/plan/command/PlanBungeeCommand.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.djrapitops.plan.command.commands.*;
55
import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
66
import com.djrapitops.plan.system.settings.Permissions;
7+
import com.djrapitops.plan.system.settings.Settings;
78
import com.djrapitops.plan.system.settings.locale.Locale;
89
import com.djrapitops.plan.system.settings.locale.Msg;
910
import com.djrapitops.plugin.command.CommandNode;
@@ -49,6 +50,7 @@ public PlanBungeeCommand(PlanBungee plugin) {
4950
new BungeeSetupToggleCommand(),
5051
new ReloadCommand(plugin),
5152
new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()),
53+
(Settings.ALLOW_UPDATE.isTrue() ? new UpdateCommand() : null)
5254
}
5355
);
5456
}

Plan/src/main/java/com/djrapitops/plan/command/PlanCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ public PlanCommand(PlanPlugin plugin) {
4646
new ReloadCommand(plugin),
4747
new ManageCommand(plugin, this),
4848
new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()),
49-
(Settings.DEV_MODE.isTrue() ? new DevCommand() : null)
49+
(Settings.DEV_MODE.isTrue() ? new DevCommand() : null),
50+
(Settings.ALLOW_UPDATE.isTrue() ? new UpdateCommand() : null)
5051
}
5152
);
5253
}
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
package com.djrapitops.plan.command.commands;
2+
3+
import com.djrapitops.plan.api.exceptions.connection.*;
4+
import com.djrapitops.plan.api.exceptions.database.DBException;
5+
import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
6+
import com.djrapitops.plan.system.database.databases.Database;
7+
import com.djrapitops.plan.system.database.databases.operation.FetchOperations;
8+
import com.djrapitops.plan.system.info.InfoSystem;
9+
import com.djrapitops.plan.system.info.request.CheckConnectionRequest;
10+
import com.djrapitops.plan.system.info.request.UpdateCancelRequest;
11+
import com.djrapitops.plan.system.info.server.Server;
12+
import com.djrapitops.plan.system.settings.Permissions;
13+
import com.djrapitops.plan.system.update.VersionCheckSystem;
14+
import com.djrapitops.plan.system.update.VersionInfo;
15+
import com.djrapitops.plan.system.webserver.WebServerSystem;
16+
import com.djrapitops.plugin.api.utility.log.Log;
17+
import com.djrapitops.plugin.command.CommandNode;
18+
import com.djrapitops.plugin.command.CommandType;
19+
import com.djrapitops.plugin.command.ISender;
20+
21+
import java.util.List;
22+
import java.util.Map;
23+
import java.util.Optional;
24+
import java.util.UUID;
25+
26+
/**
27+
* Command that updates all servers in the network
28+
*
29+
* @author Rsl1122
30+
*/
31+
public class UpdateCommand extends CommandNode {
32+
33+
public UpdateCommand() {
34+
super("update", Permissions.MANAGE.getPermission(), CommandType.ALL);
35+
setArguments("[-update]/[cancel]");
36+
setShortHelp("Get change log link or update plugin.");
37+
setInDepthHelp(
38+
"/plan update",
39+
" Used to update the plugin on the next shutdown\n",
40+
" /plan update - get change log link",
41+
" /plan update -update - Schedule update to happen on all network servers that are online next time they reboot.",
42+
" /plan update cancel - Cancel scheduled update on servers that haven't rebooted yet."
43+
);
44+
}
45+
46+
@Override
47+
public void onCommand(ISender sender, String commandLabel, String[] args) {
48+
if (!VersionCheckSystem.isNewVersionAvailable()) {
49+
sender.sendMessage("§aYou're running the latest version of Plan.");
50+
return;
51+
}
52+
53+
VersionInfo available = VersionCheckSystem.getInstance().getNewVersionAvailable();
54+
String downloadUrl = available.getDownloadUrl();
55+
56+
if (!available.isTrusted()) {
57+
sender.sendMessage("§cVersion download url did not start with " +
58+
"https://github.com/Rsl1122/Plan-PlayerAnalytics/releases/ " +
59+
"and might not be trusted. You can download this version manually here (Direct download):");
60+
sender.sendLink(downloadUrl, downloadUrl);
61+
return;
62+
}
63+
64+
if (args.length == 0) {
65+
sender.sendLink("Change Log v" + available.getVersion().toString() + ": ", "Click me", available.getChangeLogUrl());
66+
return;
67+
}
68+
69+
String firstArgument = args[0];
70+
if ("-update".equals(firstArgument)) {
71+
handleUpdate(sender, args);
72+
} else if ("cancel".equals(firstArgument)) {
73+
cancel(sender);
74+
} else {
75+
throw new IllegalArgumentException("Unknown argument, use '-update' or 'cancel'");
76+
}
77+
}
78+
79+
private void cancel(ISender sender) {
80+
try {
81+
cancel(sender, Database.getActive().fetch().getServers());
82+
sender.sendMessage("§aUpdate has been cancelled.");
83+
} catch (DBException e) {
84+
sender.sendMessage("§cDatabase error occurred, cancel could not be performed.");
85+
Log.toLog(this.getClass().getName(), e);
86+
}
87+
}
88+
89+
private void handleUpdate(ISender sender, String[] args) {
90+
sender.sendMessage("§aYou can cancel the update on servers that haven't rebooted yet with /plan update cancel.");
91+
sender.sendMessage("Checking that all servers are online..");
92+
if (!checkNetworkStatus(sender)) {
93+
sender.sendMessage("§cNot all servers were online or accessible, you can still update available servers using -force as a 2nd argument.");
94+
if (args.length <= 1 || !"-force".equals(args[1])) {
95+
return;
96+
}
97+
}
98+
try {
99+
List<Server> servers = Database.getActive().fetch().getServers();
100+
update(sender, servers);
101+
} catch (DBException e) {
102+
Log.toLog(this.getClass().getName(), e);
103+
}
104+
}
105+
106+
private void update(ISender sender, List<Server> servers) {
107+
for (Server server : servers) {
108+
if (update(sender, server)) {
109+
sender.sendMessage("§a" + server.getName() + " scheduled for update.");
110+
} else {
111+
sender.sendMessage("§cUpdate failed on a server, cancelling update on all servers..");
112+
cancel(sender, servers);
113+
sender.sendMessage("§cUpdate cancelled.");
114+
break;
115+
}
116+
}
117+
}
118+
119+
private void cancel(ISender sender, List<Server> servers) {
120+
for (Server server : servers) {
121+
cancel(sender, server);
122+
}
123+
124+
}
125+
126+
private void cancel(ISender sender, Server server) {
127+
try {
128+
InfoSystem.getInstance().getConnectionSystem().sendInfoRequest(new UpdateCancelRequest(), server);
129+
} catch (ForbiddenException | GatewayException | InternalErrorException e) {
130+
sender.sendMessage("§cCancel failed on " + server.getName() + ": Odd Exception: " + e.getClass().getSimpleName());
131+
} catch (UnauthorizedServerException e) {
132+
sender.sendMessage("§cCancel failed on " + server.getName() + ": Unauthorized. " + server.getName() + " might be using different database.");
133+
} catch (ConnectionFailException e) {
134+
sender.sendMessage("§cCancel failed on " + server.getName() + ": " + e.getCause().getClass().getSimpleName() + " " + e.getCause().getMessage());
135+
String address = server.getWebAddress();
136+
boolean local = address.contains("localhost")
137+
|| address.startsWith("https://:") // IP empty = Localhost
138+
|| address.startsWith("http://:") // IP empty = Localhost
139+
|| address.contains("127.0.0.1");
140+
if (!local) {
141+
sender.sendMessage("§cNon-local address, check that port is open");
142+
}
143+
} catch (NotFoundException e) {
144+
/* Ignored, older version */
145+
} catch (WebException e) {
146+
sender.sendMessage("§cCancel failed on " + server.getName() + ": Odd Exception:" + e.getClass().getSimpleName());
147+
}
148+
}
149+
150+
private boolean update(ISender sender, Server server) {
151+
try {
152+
InfoSystem.getInstance().getConnectionSystem().sendInfoRequest(new CheckConnectionRequest(), server);
153+
return true;
154+
} catch (BadRequestException e) {
155+
sender.sendMessage("§c" + server.getName() + " has Allow-Update set to false, aborting update.");
156+
return false;
157+
} catch (ForbiddenException | GatewayException | InternalErrorException e) {
158+
sender.sendMessage("§c" + server.getName() + ": Odd Exception: " + e.getClass().getSimpleName());
159+
return false;
160+
} catch (UnauthorizedServerException e) {
161+
sender.sendMessage("§cFail reason: Unauthorized. " + server.getName() + " might be using different database.");
162+
return false;
163+
} catch (ConnectionFailException e) {
164+
sender.sendMessage("§cFail reason: " + e.getCause().getClass().getSimpleName() + " " + e.getCause().getMessage());
165+
String address = server.getWebAddress();
166+
boolean local = address.contains("localhost")
167+
|| address.startsWith("https://:") // IP empty = Localhost
168+
|| address.startsWith("http://:") // IP empty = Localhost
169+
|| address.contains("127.0.0.1");
170+
if (!local) {
171+
sender.sendMessage("§cNon-local address, check that port is open");
172+
}
173+
return false;
174+
} catch (NotFoundException e) {
175+
sender.sendMessage("§e" + server.getName() + " is using older version and can not be scheduled for update. " +
176+
"You can update it manually, update will proceed.");
177+
return true;
178+
} catch (WebException e) {
179+
sender.sendMessage("§eOdd Exception: " + e.getClass().getSimpleName());
180+
return false;
181+
}
182+
}
183+
184+
private boolean checkNetworkStatus(ISender sender) {
185+
try {
186+
FetchOperations fetch = Database.getActive().fetch();
187+
Optional<Server> bungeeInformation = fetch.getBungeeInformation();
188+
if (!bungeeInformation.isPresent()) {
189+
return true;
190+
}
191+
Map<UUID, Server> bukkitServers = fetch.getBukkitServers();
192+
String accessAddress = WebServerSystem.getInstance().getWebServer().getAccessAddress();
193+
boolean success = true;
194+
for (Server server : bukkitServers.values()) {
195+
if (!ManageConDebugCommand.testServer(sender, accessAddress, server)) {
196+
success = false;
197+
}
198+
}
199+
Server bungee = bungeeInformation.get();
200+
if (!ManageConDebugCommand.testServer(sender, accessAddress, bungee)) {
201+
success = false;
202+
}
203+
return success;
204+
} catch (DBException e) {
205+
sender.sendMessage("§cDatabase error occurred, update has been cancelled.");
206+
Log.toLog(this.getClass().getName(), e);
207+
return false;
208+
}
209+
}
210+
}

Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageConDebugCommand.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,9 @@
2828
*/
2929
public class ManageConDebugCommand extends CommandNode {
3030

31-
private final ColorScheme cs;
32-
3331
public ManageConDebugCommand() {
3432
super("con", Permissions.MANAGE.getPermission(), CommandType.ALL);
3533
setShortHelp("Debug Bukkit-Bungee Connections");
36-
cs = PlanPlugin.getInstance().getColorScheme();
3734
}
3835

3936
@Override
@@ -68,18 +65,19 @@ private void testServers(ISender sender) {
6865
}
6966
}
7067

71-
private void testServer(ISender sender, String accessAddress, Server server) {
68+
public static boolean testServer(ISender sender, String accessAddress, Server server) {
7269
String address = server.getWebAddress().toLowerCase();
7370
boolean usingHttps = address.startsWith("https");
7471
boolean local = address.contains("localhost")
75-
|| address.startsWith("https://:")
76-
|| address.startsWith("http://:")
72+
|| address.startsWith("https://:") // IP empty = Localhost
73+
|| address.startsWith("http://:") // IP empty = Localhost
7774
|| address.contains("127.0.0.1");
7875

7976
try {
8077

8178
InfoSystem.getInstance().getConnectionSystem().sendInfoRequest(new CheckConnectionRequest(accessAddress), server);
8279
sender.sendMessage(getMsgFor(address, usingHttps, local, true, true));
80+
return true;
8381

8482
} catch (ForbiddenException | BadRequestException | InternalErrorException e) {
8583
sender.sendMessage(getMsgFor(address, usingHttps, local, false, false));
@@ -102,9 +100,11 @@ private void testServer(ISender sender, String accessAddress, Server server) {
102100
sender.sendMessage(getMsgFor(address, usingHttps, local, false, false));
103101
sender.sendMessage("§eOdd Exception: " + e.getClass().getSimpleName());
104102
}
103+
return false;
105104
}
106105

107-
private String getMsgFor(String address, boolean usingHttps, boolean local, boolean successTo, boolean successFrom) {
106+
private static String getMsgFor(String address, boolean usingHttps, boolean local, boolean successTo, boolean successFrom) {
107+
ColorScheme cs = PlanPlugin.getInstance().getColorScheme();
108108
String tCol = cs.getTertiaryColor();
109109
String sCol = cs.getSecondaryColor();
110110
return tCol + address + sCol + ": "

Plan/src/main/java/com/djrapitops/plan/system/info/connection/ConnectionSystem.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ private Map<String, InfoRequest> loadDataRequests() {
125125
putRequest(requests, SaveDBSettingsRequest.createHandler());
126126
putRequest(requests, SendDBSettingsRequest.createHandler());
127127
putRequest(requests, CheckConnectionRequest.createHandler());
128+
129+
putRequest(requests, UpdateRequest.createHandler());
130+
putRequest(requests, UpdateCancelRequest.createHandler());
128131
return requests;
129132
}
130133

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Licence is provided in the jar as license.yml also here:
3+
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
4+
*/
5+
package com.djrapitops.plan.system.info.request;
6+
7+
import com.djrapitops.plan.system.update.ShutdownUpdateHook;
8+
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
9+
import com.djrapitops.plan.system.webserver.response.Response;
10+
11+
import java.util.Map;
12+
13+
/**
14+
* InfoRequest used for Updating the plugin on a network.
15+
*
16+
* @author Rsl1122
17+
*/
18+
public class UpdateCancelRequest implements InfoRequest {
19+
20+
public UpdateCancelRequest() {
21+
}
22+
23+
public static UpdateCancelRequest createHandler() {
24+
return new UpdateCancelRequest();
25+
}
26+
27+
@Override
28+
public void runLocally() {
29+
ShutdownUpdateHook.deActivate();
30+
}
31+
32+
@Override
33+
public Response handleRequest(Map<String, String> variables) {
34+
ShutdownUpdateHook.deActivate();
35+
return DefaultResponses.SUCCESS.get();
36+
}
37+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Licence is provided in the jar as license.yml also here:
3+
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
4+
*/
5+
package com.djrapitops.plan.system.info.request;
6+
7+
import com.djrapitops.plan.system.settings.Settings;
8+
import com.djrapitops.plan.system.update.ShutdownUpdateHook;
9+
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
10+
import com.djrapitops.plan.system.webserver.response.Response;
11+
import com.djrapitops.plan.system.webserver.response.api.BadRequestResponse;
12+
13+
import java.util.Map;
14+
15+
/**
16+
* InfoRequest used for Updating the plugin on a network.
17+
*
18+
* @author Rsl1122
19+
*/
20+
public class UpdateRequest implements InfoRequest {
21+
22+
public UpdateRequest() {
23+
}
24+
25+
public static UpdateRequest createHandler() {
26+
return new UpdateRequest();
27+
}
28+
29+
@Override
30+
public void runLocally() {
31+
new ShutdownUpdateHook().register();
32+
}
33+
34+
@Override
35+
public Response handleRequest(Map<String, String> variables) {
36+
if (Settings.ALLOW_UPDATE.isTrue()) {
37+
new ShutdownUpdateHook().register();
38+
return DefaultResponses.SUCCESS.get();
39+
} else {
40+
return new BadRequestResponse("Update not allowed on this server");
41+
}
42+
}
43+
}

Plan/src/main/java/com/djrapitops/plan/system/settings/Settings.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public enum Settings {
3737
DISPLAY_PLAYER_IPS("Customization.Display.PlayerIPs"),
3838
DISPLAY_GAPS_IN_GRAPH_DATA("Customization.Display.GapsInGraphData"),
3939
DATA_GEOLOCATIONS("Data.Geolocations"),
40+
ALLOW_UPDATE("Plugin.Allow-Update-Command"),
41+
NOTIFY_ABOUT_DEV_RELEASES("Plugin.Notify-About-DEV-Releases"),
4042

4143
// Integer
4244
WEBSERVER_PORT("WebServer.Port"),

0 commit comments

Comments
 (0)