From d190576c33a4837de528eb03d535b2362faf6c85 Mon Sep 17 00:00:00 2001 From: jie65535 Date: Mon, 16 May 2022 23:01:17 +0800 Subject: [PATCH] Update version to v1.2.0 Add config Add run console command --- build.gradle | 2 +- .../opencommand/OpenCommandConfig.java | 25 ++++++++++ .../opencommand/OpenCommandHandler.java | 47 ++++++++++++++----- .../opencommand/OpenCommandPlugin.java | 47 +++++++++++++++++-- src/main/resources/plugin.json | 2 +- 5 files changed, 103 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/github/jie65535/opencommand/OpenCommandConfig.java diff --git a/build.gradle b/build.gradle index f0d3fbf..e079dd2 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group 'com.github.jie65535.opencommand' -version 'dev-1.1.0' +version 'dev-1.2.0' sourceCompatibility = 17 targetCompatibility = 17 diff --git a/src/main/java/com/github/jie65535/opencommand/OpenCommandConfig.java b/src/main/java/com/github/jie65535/opencommand/OpenCommandConfig.java new file mode 100644 index 0000000..5be40f4 --- /dev/null +++ b/src/main/java/com/github/jie65535/opencommand/OpenCommandConfig.java @@ -0,0 +1,25 @@ +/* + * gc-opencommand + * Copyright (C) 2022 jie65535 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.github.jie65535.opencommand; + +public class OpenCommandConfig { + public String consoleToken = ""; + public int codeExpirationTime_S = 60; + public int tempTokenExpirationTime_S = 300; + public int tokenLastUseExpirationTime_H = 48; +} diff --git a/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java b/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java index f8fdd5c..8da3c05 100644 --- a/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java +++ b/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java @@ -19,7 +19,6 @@ package com.github.jie65535.opencommand; import com.github.jie65535.opencommand.json.JsonRequest; import com.github.jie65535.opencommand.json.JsonResponse; -import emu.grasscutter.Grasscutter; import emu.grasscutter.command.CommandMap; import emu.grasscutter.server.http.Router; import emu.grasscutter.utils.Crypto; @@ -32,7 +31,6 @@ import io.javalin.Javalin; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -52,13 +50,15 @@ public final class OpenCommandHandler implements Router { public static void handle(Request request, Response response) { // Trigger cleanup action cleanupExpiredData(); + var plugin = OpenCommandPlugin.getInstance(); + var config = plugin.getConfig(); var now = new Date(); var req = request.body(JsonRequest.class); response.type("application/json"); if (req.action.equals("sendCode")) { int playerId = (int) req.data; - var player = Grasscutter.getGameServer().getPlayerByUid(playerId); + var player = plugin.getServer().getPlayerByUid(playerId); if (player == null) { response.json(new JsonResponse(404, "Player Not Found.")); } else { @@ -74,33 +74,53 @@ public final class OpenCommandHandler implements Router { if (token == null || token.isEmpty()) token = Utils.bytesToHex(Crypto.createSessionKey(32)); int code = Utils.randomRange(1000, 9999); - codeExpireTime.put(playerId, new Date(now.getTime() + 60 * 1000)); - tokenExpireTime.put(token, new Date(now.getTime() + 5 * 60 * 1000)); + codeExpireTime.put(playerId, new Date(now.getTime() + config.codeExpirationTime_S * 1000L)); + tokenExpireTime.put(token, new Date(now.getTime() + config.tempTokenExpirationTime_S * 1000L)); codes.put(token, code); clients.put(token, playerId); - player.dropMessage("[Open Command] Verification code: {code}".replace("{code}", Integer.toString(code))); - + player.dropMessage("[Open Command] Verification code: " + code); response.json(new JsonResponse(token)); - return; } + return; } else if (req.action.equals("ping")) { response.json(new JsonResponse()); return; } // token is required - if (!clients.containsKey(req.token)) { + if (req.token == null || req.token.isEmpty()) { + response.json(new JsonResponse(401, "Unauthorized")); + return; + } + var isConsole = req.token.equals(config.consoleToken); + if (!isConsole && !clients.containsKey(req.token)) { response.json(new JsonResponse(401, "Unauthorized")); return; } - if (codes.containsKey(req.token)) { + if (isConsole) { + if (req.action.equals("verify")) { + response.json(new JsonResponse()); + return; + } else if (req.action.equals("command")) { + try { + plugin.getLogger().info(String.format("IP: %s run command in console > %s", request.ip(), req.data)); + CommandMap.getInstance().invoke(null, null, req.data.toString()); + response.json(new JsonResponse()); + } catch (Exception e) { + plugin.getLogger().warn("Run command failed.", e); + response.json(new JsonResponse(500, "error", e.getLocalizedMessage())); + } + return; + } + } else if (codes.containsKey(req.token)) { if (req.action.equals("verify")) { if (codes.get(req.token).equals(req.data)) { codes.remove(req.token); // update token expire time - tokenExpireTime.put(req.token, new Date(now.getTime() + 60 * 60 * 1000)); + tokenExpireTime.put(req.token, new Date(now.getTime() + config.tokenLastUseExpirationTime_H * 60L * 60L * 1000L)); response.json(new JsonResponse()); + plugin.getLogger().info(String.format("Player %d has passed the verification, ip: %s", clients.get(req.token), request.ip())); } else { response.json(new JsonResponse(400, "Verification failed")); } @@ -109,9 +129,9 @@ public final class OpenCommandHandler implements Router { } else { if (req.action.equals("command")) { // update token expire time - tokenExpireTime.put(req.token, new Date(now.getTime() + 4 * 60 * 60 * 1000)); + tokenExpireTime.put(req.token, new Date(now.getTime() + config.tokenLastUseExpirationTime_H * 60L * 60L * 1000L)); var playerId = clients.get(req.token); - var player = Grasscutter.getGameServer().getPlayerByUid(playerId); + var player = plugin.getServer().getPlayerByUid(playerId); var command = req.data.toString(); if (player == null) { response.json(new JsonResponse(404, "Player not found")); @@ -126,6 +146,7 @@ public final class OpenCommandHandler implements Router { CommandMap.getInstance().invoke(player, player, command); response.json(new JsonResponse(resultCollector.getMessage())); } catch (Exception e) { + plugin.getLogger().warn("Run command failed.", e); response.json(new JsonResponse(500, "error", e.getLocalizedMessage())); } finally { player.setMessageHandler(null); diff --git a/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java b/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java index 9390d09..21b8aa3 100644 --- a/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java +++ b/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java @@ -20,20 +20,57 @@ package com.github.jie65535.opencommand; import emu.grasscutter.Grasscutter; import emu.grasscutter.plugin.Plugin; -public class OpenCommandPlugin extends Plugin { +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +public final class OpenCommandPlugin extends Plugin { + + private static OpenCommandPlugin instance; + public static OpenCommandPlugin getInstance() { return instance; } + + private OpenCommandConfig config; + @Override public void onLoad() { - + instance = this; + loadConfig(); } @Override public void onEnable() { - Grasscutter.getHttpServer().addRouter(OpenCommandHandler.class); - Grasscutter.getLogger().info("[OpenCommand] Enabled"); + getHandle().addRouter(OpenCommandHandler.class); + getLogger().info("[OpenCommand] Enabled"); } @Override public void onDisable() { - Grasscutter.getLogger().info("[OpenCommand] Disabled"); + getLogger().info("[OpenCommand] Disabled"); + } + + public OpenCommandConfig getConfig() { + return config; + } + + private void loadConfig() { + var configFile = new File(getDataFolder(), "config.json"); + if (!configFile.exists()) { + config = new OpenCommandConfig(); + try (var file = new FileWriter(configFile)){ + file.write(Grasscutter.getGsonFactory().toJson(config)); + } catch (IOException e) { + getLogger().error("Unable to write to config file."); + } catch (Exception e) { + getLogger().error("Unable to save config file."); + } + } else { + try (var file = new FileReader(configFile)) { + config = Grasscutter.getGsonFactory().fromJson(file, OpenCommandConfig.class); + } catch (Exception exception) { + config = new OpenCommandConfig(); + getLogger().error("There was an error while trying to load the configuration from config.json. Please make sure that there are no syntax errors. If you want to start with a default configuration, delete your existing config.json."); + } + } } } diff --git a/src/main/resources/plugin.json b/src/main/resources/plugin.json index a88ae84..1d29cf9 100644 --- a/src/main/resources/plugin.json +++ b/src/main/resources/plugin.json @@ -1,7 +1,7 @@ { "name": "opencommand-plugin", "description": "Open command interface for third-party clients", - "version": "dev-1.1.0", + "version": "dev-1.2.0", "mainClass": "com.github.jie65535.opencommand.OpenCommandPlugin", "authors": ["jie65535"] } \ No newline at end of file