|
12 | 12 | import org.bukkit.plugin.Plugin; |
13 | 13 | import org.bukkit.scheduler.BukkitRunnable; |
14 | 14 | import org.bukkit.scheduler.BukkitTask; |
15 | | -import org.json.JSONArray; // Add this import |
| 15 | +import org.json.JSONArray; |
16 | 16 | import org.json.JSONObject; |
17 | 17 |
|
18 | 18 | import java.io.File; |
|
25 | 25 | import java.nio.file.FileSystems; |
26 | 26 | import java.nio.file.Files; |
27 | 27 | import java.util.Base64; |
28 | | -import java.util.HashMap; // For session.parseBody() |
| 28 | +import java.util.HashMap; |
29 | 29 | import java.util.Map; |
30 | 30 | import java.util.Properties; |
31 | 31 | import java.util.concurrent.atomic.AtomicBoolean; |
@@ -251,102 +251,88 @@ public NanoHTTPD.Response execCommand(final Map<String, String> params) { |
251 | 251 | return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", jsonResponse.toString()); |
252 | 252 | } |
253 | 253 |
|
254 | | -public NanoHTTPD.Response execMultipleCommands(final NanoHTTPD.IHTTPSession session) { |
255 | | - Map<String, String> files = new HashMap<>(); |
256 | | - try { |
257 | | - session.parseBody(files); |
258 | | - } catch (IOException | NanoHTTPD.ResponseException e) { |
259 | | - Logger.error("Error parsing request body: " + e.getMessage()); |
260 | | - return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR, "application/json", "{\"error\":\"Error parsing request body\"}"); |
261 | | - } |
262 | | - |
263 | | - String postBody = files.get("postData"); |
264 | | - if (postBody == null) { |
265 | | - return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{\"error\":\"Missing request body\"}"); |
266 | | - } |
267 | | - |
268 | | - JSONObject requestJson; |
269 | | - try { |
270 | | - requestJson = new JSONObject(postBody); |
271 | | - } catch (Exception e) { |
272 | | - Logger.error("Error parsing JSON request body: " + e.getMessage()); |
273 | | - return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{\"error\":\"Invalid JSON format\"}"); |
274 | | - } |
275 | | - |
276 | | - if (!requestJson.has("commands")) { |
277 | | - return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{\"error\":\"Missing 'commands' field in JSON payload\"}"); |
278 | | - } |
| 254 | + public NanoHTTPD.Response execMultipleCommands(final Map<String, String> params) { |
| 255 | + String commandsParam = params.get("commands"); |
| 256 | + if (commandsParam == null) { |
| 257 | + return NanoHTTPD.newFixedLengthResponse( |
| 258 | + NanoHTTPD.Response.Status.BAD_REQUEST, |
| 259 | + "application/json", |
| 260 | + "{\"error\":\"Missing 'commands' parameter\"}" |
| 261 | + ); |
| 262 | + } |
279 | 263 |
|
280 | | - JSONArray commandsJsonArray; |
281 | | - try { |
282 | | - commandsJsonArray = requestJson.getJSONArray("commands"); |
283 | | - } catch (Exception e) { |
284 | | - Logger.error("Error parsing 'commands' array: " + e.getMessage()); |
285 | | - return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{\"error\":\"'commands' field must be a JSON array\"}"); |
286 | | - } |
| 264 | + JSONArray commandsJsonArray; |
| 265 | + try { |
| 266 | + commandsJsonArray = new JSONArray(commandsParam); |
| 267 | + } catch (Exception e) { |
| 268 | + Logger.error("Error parsing 'commands' array: " + e.getMessage()); |
| 269 | + return NanoHTTPD.newFixedLengthResponse( |
| 270 | + NanoHTTPD.Response.Status.BAD_REQUEST, |
| 271 | + "application/json", |
| 272 | + "{\"error\":\"'commands' parameter must be a valid JSON array\"}" |
| 273 | + ); |
| 274 | + } |
287 | 275 |
|
288 | | - JSONArray resultsArray = new JSONArray(); |
| 276 | + JSONArray resultsArray = new JSONArray(); |
| 277 | + |
| 278 | + for (int i = 0; i < commandsJsonArray.length(); i++) { |
| 279 | + String command = commandsJsonArray.optString(i); |
| 280 | + if (command == null || command.trim().isEmpty()) { |
| 281 | + JSONObject result = new JSONObject(); |
| 282 | + result.put("command", JSONObject.NULL); |
| 283 | + result.put("success", false); |
| 284 | + result.put("output", "Empty command string provided."); |
| 285 | + resultsArray.put(result); |
| 286 | + continue; |
| 287 | + } |
289 | 288 |
|
290 | | - for (int i = 0; i < commandsJsonArray.length(); i++) { |
291 | | - String command = commandsJsonArray.optString(i); |
292 | | - if (command == null || command.trim().isEmpty()) { |
| 289 | + AtomicBoolean success = new AtomicBoolean(false); |
| 290 | + CommandOutputCapture outputCapture = new CommandOutputCapture(); |
293 | 291 | JSONObject result = new JSONObject(); |
294 | | - result.put("command", JSONObject.NULL); |
295 | | - result.put("success", false); |
296 | | - result.put("output", "Empty command string provided."); |
297 | | - resultsArray.put(result); |
298 | | - continue; |
299 | | - } |
| 292 | + result.put("command", command); |
300 | 293 |
|
301 | | - AtomicBoolean success = new AtomicBoolean(false); |
302 | | - CommandOutputCapture outputCapture = new CommandOutputCapture(); |
303 | | - JSONObject result = new JSONObject(); |
304 | | - result.put("command", command); |
305 | | - |
306 | | - try { |
307 | | - BukkitTask task = Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> { |
308 | | - success.set(Bukkit.getServer().dispatchCommand(outputCapture, command)); |
309 | | - }); |
310 | | - |
311 | | - // Wait for the command to complete |
312 | | - while (!task.isCancelled() && (Bukkit.getScheduler().isCurrentlyRunning(task.getTaskId()) || Bukkit.getScheduler().isQueued(task.getTaskId()))) { |
313 | | - try { |
314 | | - Thread.sleep(50); // Check every 50ms |
315 | | - } catch (InterruptedException e) { |
316 | | - Thread.currentThread().interrupt(); |
| 294 | + try { |
| 295 | + BukkitTask task = Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> { |
| 296 | + success.set(Bukkit.getServer().dispatchCommand(outputCapture, command)); |
| 297 | + }); |
| 298 | + |
| 299 | + while (!task.isCancelled() && (Bukkit.getScheduler().isCurrentlyRunning(task.getTaskId()) || Bukkit.getScheduler().isQueued(task.getTaskId()))) { |
| 300 | + try { |
| 301 | + Thread.sleep(50); |
| 302 | + } catch (InterruptedException e) { |
| 303 | + Thread.currentThread().interrupt(); |
| 304 | + Logger.error("Command execution interrupted: " + command); |
| 305 | + result.put("success", false); |
| 306 | + result.put("output", "Command execution was interrupted."); |
| 307 | + break; |
| 308 | + } |
| 309 | + } |
| 310 | + |
| 311 | + if (Thread.currentThread().isInterrupted()){ |
317 | 312 | Logger.error("Command execution interrupted: " + command); |
318 | 313 | result.put("success", false); |
319 | 314 | result.put("output", "Command execution was interrupted."); |
320 | | - break; |
321 | 315 | } |
322 | | - } |
323 | | - if (Thread.currentThread().isInterrupted()){ |
324 | | - // If the thread was interrupted outside the sleep. |
325 | | - Logger.error("Command execution interrupted: " + command); |
326 | | - result.put("success", false); |
327 | | - result.put("output", "Command execution was interrupted."); |
328 | | - } |
329 | 316 |
|
| 317 | + } catch (Exception e) { |
| 318 | + Logger.error("Error executing command '" + command + "': " + e.getMessage()); |
| 319 | + result.put("success", false); |
| 320 | + result.put("output", "Error executing command: " + e.getMessage()); |
| 321 | + } |
330 | 322 |
|
331 | | - } catch (Exception e) { |
332 | | - Logger.error("Error executing command '" + command + "': " + e.getMessage()); |
333 | | - result.put("success", false); |
334 | | - result.put("output", "Error executing command: " + e.getMessage()); |
| 323 | + if (!result.has("success")) { |
| 324 | + result.put("success", success.get()); |
| 325 | + result.put("output", outputCapture.getOutputMessages()); |
| 326 | + } |
| 327 | + resultsArray.put(result); |
335 | 328 | } |
336 | 329 |
|
337 | | - // Ensure result is populated even if interruption occurred before outputCapture could be populated. |
338 | | - if (!result.has("success")) { // if not already set by interruption logic |
339 | | - result.put("success", success.get()); |
340 | | - result.put("output", outputCapture.getOutputMessages()); |
341 | | - } |
342 | | - resultsArray.put(result); |
343 | | - } |
| 330 | + JSONObject responseJson = new JSONObject(); |
| 331 | + responseJson.put("results", resultsArray); |
344 | 332 |
|
345 | | - JSONObject responseJson = new JSONObject(); |
346 | | - responseJson.put("results", resultsArray); |
| 333 | + return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", responseJson.toString()); |
| 334 | + } |
347 | 335 |
|
348 | | - return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", responseJson.toString()); |
349 | | -} |
350 | 336 |
|
351 | 337 | public NanoHTTPD.Response reload(final Map<String, String> ignoredParams) { |
352 | 338 | NanoHTTPD.Response response = NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", "{}"); |
|
0 commit comments