Skip to content

Commit

Permalink
Update version to v1.4.0
Browse files Browse the repository at this point in the history
Updated to be compatible with new http server
Add all code headers
  • Loading branch information
jie65535 committed Sep 2, 2022
1 parent b3bc0f0 commit 623856c
Show file tree
Hide file tree
Showing 23 changed files with 418 additions and 105 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

group 'com.github.jie65535.opencommand'
version 'dev-1.3.0'
version 'dev-1.4.0'

sourceCompatibility = 17
targetCompatibility = 17
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.github.jie65535.opencommand;

import com.github.jie65535.opencommand.socket.SocketClient;
import com.github.jie65535.opencommand.socket.SocketUtils;
import com.github.jie65535.opencommand.socket.packet.player.PlayerList;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.player.Player;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,43 @@
package com.github.jie65535.opencommand;

public class OpenCommandConfig {
/**
* 控制台 Token
*/
public String consoleToken = "";

/**
* 验证码过期时间(单位秒)
*/
public int codeExpirationTime_S = 60;

/**
* 临时Token过期时间(单位秒)
*/
public int tempTokenExpirationTime_S = 300;

/**
* Token 最后使用过期时间(单位小时)
*/
public int tokenLastUseExpirationTime_H = 48;

/**
* Socket 端口
*/
public int socketPort = 5746;

/**
* Socket Token
*/
public String socketToken = "";

/**
* Socket 主机地址
*/
public String socketHost = "127.0.0.1";

/**
* Socket 显示名称
*/
public String socketDisplayName = "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@
import emu.grasscutter.utils.Crypto;
import emu.grasscutter.utils.MessageHandler;
import emu.grasscutter.utils.Utils;
import express.Express;
import express.http.Request;
import express.http.Response;
import io.javalin.Javalin;
import io.javalin.http.Context;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;

Expand All @@ -40,34 +38,33 @@
public final class OpenCommandHandler implements Router {

@Override
public void applyRoutes(Express express, Javalin javalin) {
express.post("/opencommand/api", OpenCommandHandler::handle);
public void applyRoutes(Javalin javalin) {
javalin.post("/opencommand/api", OpenCommandHandler::handle);
}

private static final Map<String, Integer> clients = new HashMap<>();
private static final Map<String, Date> tokenExpireTime = new HashMap<>();
private static final Map<String, Integer> codes = new HashMap<>();
private static final Int2ObjectMap<Date> codeExpireTime = new Int2ObjectOpenHashMap<>();

public static void handle(Request request, Response response) {
public static void handle(Context context) {
// 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");
var req = context.bodyAsClass(JsonRequest.class);
if (req.action.equals("sendCode")) {
int playerId = (int) req.data;
var player = plugin.getServer().getPlayerByUid(playerId);
if (player == null) {
response.json(new JsonResponse(404, "Player Not Found."));
context.json(new JsonResponse(404, "Player Not Found."));
} else {
if (codeExpireTime.containsKey(playerId)) {
var expireTime = codeExpireTime.get(playerId);
if (now.before(expireTime)) {
response.json(new JsonResponse(403, "Requests are too frequent"));
context.json(new JsonResponse(403, "Requests are too frequent"));
return;
}
}
Expand All @@ -81,52 +78,52 @@ public static void handle(Request request, Response response) {
codes.put(token, code);
clients.put(token, playerId);
player.dropMessage("[Open Command] Verification code: " + code);
response.json(new JsonResponse(token));
context.json(new JsonResponse(token));
}
return;
} else if (req.action.equals("ping")) {
response.json(new JsonResponse());
context.json(new JsonResponse());
return;
} else if (req.action.equals("online")) {
var p = new ArrayList<String>();
plugin.getServer().getPlayers().forEach((uid, player) -> p.add(player.getNickname()));
response.json(new JsonResponse(200, "Success", new SocketData.OnlinePlayer(p)));
context.json(new JsonResponse(200, "Success", new SocketData.OnlinePlayer(p)));
return;
}

// token is required
if (req.token == null || req.token.isEmpty()) {
response.json(new JsonResponse(401, "Unauthorized"));
context.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"));
context.json(new JsonResponse(401, "Unauthorized"));
return;
}

if (isConsole) {
if (req.action.equals("verify")) {
response.json(new JsonResponse());
context.json(new JsonResponse());
return;
} else if (req.action.equals("command")) {
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (plugin) {
try {
plugin.getLogger().info(String.format("IP: %s run command in console > %s", request.ip(), req.data));
plugin.getLogger().info(String.format("IP: %s run command in console > %s", context.ip(), req.data));
var resultCollector = new MessageHandler();
EventListeners.setConsoleMessageHandler(resultCollector);
CommandMap.getInstance().invoke(null, null, req.data.toString());
response.json(new JsonResponse(resultCollector.getMessage()));
context.json(new JsonResponse(resultCollector.getMessage()));
} catch (Exception e) {
plugin.getLogger().warn("Run command failed.", e);
EventListeners.setConsoleMessageHandler(null);
response.json(new JsonResponse(500, "error", e.getLocalizedMessage()));
context.json(new JsonResponse(500, "error", e.getLocalizedMessage()));
}
}
return;
} else if (req.action.equals("runmode")) {
response.json(new JsonResponse(200, "Success", 0));
context.json(new JsonResponse(200, "Success", 0));
return;
}
} else if (codes.containsKey(req.token)) {
Expand All @@ -135,10 +132,10 @@ public static void handle(Request request, Response response) {
codes.remove(req.token);
// update token expire time
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()));
context.json(new JsonResponse());
plugin.getLogger().info(String.format("Player %d has passed the verification, ip: %s", clients.get(req.token), context.ip()));
} else {
response.json(new JsonResponse(400, "Verification failed"));
context.json(new JsonResponse(400, "Verification failed"));
}
return;
}
Expand All @@ -150,7 +147,7 @@ public static void handle(Request request, Response response) {
var player = plugin.getServer().getPlayerByUid(playerId);
var command = req.data.toString();
if (player == null) {
response.json(new JsonResponse(404, "Player not found"));
context.json(new JsonResponse(404, "Player not found"));
return;
}
// Player MessageHandler do not support concurrency
Expand All @@ -160,18 +157,18 @@ public static void handle(Request request, Response response) {
var resultCollector = new MessageHandler();
player.setMessageHandler(resultCollector);
CommandMap.getInstance().invoke(player, player, command);
response.json(new JsonResponse(resultCollector.getMessage()));
context.json(new JsonResponse(resultCollector.getMessage()));
} catch (Exception e) {
plugin.getLogger().warn("Run command failed.", e);
response.json(new JsonResponse(500, "error", e.getLocalizedMessage()));
context.json(new JsonResponse(500, "error", e.getLocalizedMessage()));
} finally {
player.setMessageHandler(null);
}
}
return;
}
}
response.json(new JsonResponse(403, "forbidden"));
context.json(new JsonResponse(403, "forbidden"));
}

private static void cleanupExpiredData() {
Expand Down
Loading

0 comments on commit 623856c

Please sign in to comment.