feat(webui): implement HTTP-server-backed WebUI module
Recreate the shit.zen.network.webui handlers (categories, modules, toggle, get/set setting, static files) from Recaf and wire them into the WebUI module so it serves a control panel from a configurable local port. Ships a Tailwind-based panel under resources/webui/.
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
|
||||
## TODO
|
||||
- 客户端的Shader渲染明显还有很多问题。
|
||||
- Web Click GUI尚未实现。
|
||||
- 部分UI错位。
|
||||
- 直接构建为热注入DLL。
|
||||
- 你来提出Issue,我来解决。
|
||||
|
||||
@@ -1,22 +1,74 @@
|
||||
package shit.zen.modules.impl.world;
|
||||
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import java.awt.Desktop;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import shit.zen.modules.Category;
|
||||
import shit.zen.modules.Module;
|
||||
import shit.zen.network.webui.CategoriesHandler;
|
||||
import shit.zen.network.webui.ModulesHandler;
|
||||
import shit.zen.network.webui.SetSettingHandler;
|
||||
import shit.zen.network.webui.SettingsHandler;
|
||||
import shit.zen.network.webui.StaticFileHandler;
|
||||
import shit.zen.network.webui.ToggleModuleHandler;
|
||||
import shit.zen.settings.impl.BooleanSetting;
|
||||
import shit.zen.settings.impl.NumberSetting;
|
||||
import shit.zen.utils.misc.ChatUtil;
|
||||
|
||||
public class WebUI extends Module {
|
||||
private final NumberSetting port = new NumberSetting("Port", 8089, 1024, 65535, 1);
|
||||
private final BooleanSetting openBrowser = new BooleanSetting("Open Browser", true);
|
||||
|
||||
private HttpServer httpServer;
|
||||
|
||||
public WebUI() {
|
||||
super("WebUI", Category.WORLD);
|
||||
this.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
ChatUtil.print("WebUI is unavailable in this build.");
|
||||
this.setEnabled(false);
|
||||
try {
|
||||
this.httpServer = this.createHttpServer();
|
||||
ChatUtil.print("WebUI started at http://127.0.0.1:" + this.port.getValue().intValue());
|
||||
if (this.openBrowser.getValue() && mc.player != null) {
|
||||
try {
|
||||
System.setProperty("java.awt.headless", "false");
|
||||
if (Desktop.isDesktopSupported()
|
||||
&& Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
|
||||
Desktop.getDesktop().browse(new URI("http://127.0.0.1:" + this.port.getValue().intValue()));
|
||||
}
|
||||
} catch (URISyntaxException | IOException ex) {
|
||||
ChatUtil.print("Failed to open browser: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException ioException) {
|
||||
ChatUtil.print("Failed to start http server because " + ioException.getMessage());
|
||||
ioException.printStackTrace();
|
||||
this.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (this.httpServer != null) {
|
||||
this.httpServer.stop(0);
|
||||
this.httpServer = null;
|
||||
ChatUtil.print("WebUI stopped");
|
||||
}
|
||||
}
|
||||
|
||||
private HttpServer createHttpServer() throws IOException {
|
||||
HttpServer server = HttpServer.create(new InetSocketAddress(this.port.getValue().intValue()), 0);
|
||||
server.createContext("/api/modulesList", new ModulesHandler());
|
||||
server.createContext("/api/categoriesList", new CategoriesHandler());
|
||||
server.createContext("/api/setStatus", new ToggleModuleHandler());
|
||||
server.createContext("/api/setModuleSettingValue", new SetSettingHandler());
|
||||
server.createContext("/api/getModuleSetting", new SettingsHandler());
|
||||
server.createContext("/", new StaticFileHandler("/webui", "/"));
|
||||
server.start();
|
||||
return server;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package shit.zen.network.webui;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public abstract class AbstractHttpHandler implements HttpHandler {
|
||||
|
||||
@Override
|
||||
public final void handle(HttpExchange exchange) throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
try {
|
||||
int status = this.handleRequest(exchange.getRequestBody(), buffer, exchange);
|
||||
if (buffer.size() == 0) {
|
||||
this.sendResponse(status, buffer, exchange);
|
||||
}
|
||||
if (!(this instanceof StaticFileHandler)
|
||||
&& exchange.getResponseHeaders().getFirst("Content-Type") == null) {
|
||||
exchange.getResponseHeaders().add("Content-Type", "application/json; charset=UTF-8");
|
||||
}
|
||||
exchange.sendResponseHeaders(status, buffer.size());
|
||||
if (buffer.size() != 0) {
|
||||
exchange.getResponseBody().write(buffer.toByteArray());
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
int status = 500;
|
||||
buffer = new ByteArrayOutputStream();
|
||||
exchange.getResponseHeaders().add("Content-Type", "text/html; charset=utf-8");
|
||||
OutputStreamWriter writer = new OutputStreamWriter(buffer, StandardCharsets.UTF_8);
|
||||
writer.append("<!DOCTYPE html>\r\n<html>\r\n<head>\r\n\t<title>Sorry!</title>\r\n\t<meta charset=\"utf-8\">\r\n</head>\r\n<body>\r\n\t<h1>Sorry!</h1>\r\n\tThis request could not be completed due to an unexpected exception.<br/>\r\n\tHere is stack trace:\r\n\t<pre>");
|
||||
throwable.printStackTrace(new PrintWriter(writer));
|
||||
writer.append("</pre>\r\n</body>\r\n</html>");
|
||||
writer.flush();
|
||||
exchange.sendResponseHeaders(status, buffer.size());
|
||||
exchange.getResponseBody().write(buffer.toByteArray());
|
||||
}
|
||||
exchange.close();
|
||||
}
|
||||
|
||||
public abstract int handleRequest(InputStream in, OutputStream out, HttpExchange exchange) throws Throwable;
|
||||
|
||||
public void sendResponse(int status, OutputStream out, HttpExchange exchange) throws IOException {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package shit.zen.network.webui;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class ActionEntry {
|
||||
@SerializedName("a")
|
||||
private final String name;
|
||||
@SerializedName("b")
|
||||
private final ActionType type;
|
||||
@SerializedName("c")
|
||||
private final double current;
|
||||
@SerializedName("d")
|
||||
private final double min;
|
||||
@SerializedName("e")
|
||||
private final double max;
|
||||
|
||||
public ActionEntry(String name, ActionType type, double current, double min, double max) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.current = current;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package shit.zen.network.webui;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public enum ActionType {
|
||||
@SerializedName("a")
|
||||
BUTTON,
|
||||
@SerializedName("b")
|
||||
SLIDER,
|
||||
@SerializedName("c")
|
||||
TOGGLE
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package shit.zen.network.webui;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import shit.zen.modules.Category;
|
||||
|
||||
public class CategoriesHandler extends AbstractHttpHandler {
|
||||
|
||||
@Override
|
||||
public int handleRequest(InputStream in, OutputStream out, HttpExchange exchange) throws Throwable {
|
||||
exchange.getResponseHeaders().add("Content-Type", "application/json; charset=UTF-8");
|
||||
OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
List<String> categories = new ArrayList<>();
|
||||
response.put("success", true);
|
||||
response.put("result", categories);
|
||||
for (Category category : Category.values()) {
|
||||
categories.add(category.displayName);
|
||||
}
|
||||
writer.write(new Gson().toJson(response));
|
||||
writer.flush();
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package shit.zen.network.webui;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import shit.zen.ZenClient;
|
||||
import shit.zen.modules.Category;
|
||||
import shit.zen.modules.Module;
|
||||
import shit.zen.utils.render.TextureUtil;
|
||||
|
||||
public class ModulesHandler extends AbstractHttpHandler {
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
@Override
|
||||
public int handleRequest(InputStream in, OutputStream out, HttpExchange exchange) throws Throwable {
|
||||
exchange.getResponseHeaders().add("Content-Type", "application/json; charset=UTF-8");
|
||||
OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
|
||||
Category filter = null;
|
||||
try {
|
||||
Map<String, String> query = TextureUtil.parseQueryString(exchange.getRequestURI().getQuery());
|
||||
String requested = query.get("category");
|
||||
if (requested != null && !"null".equalsIgnoreCase(requested)) {
|
||||
filter = Category.fromString(requested);
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
Map<String, Map<String, Object>> result = new HashMap<>();
|
||||
for (Module module : ZenClient.getInstance().getModuleManager().getModules()) {
|
||||
if (filter != null && module.getCategory() != filter) {
|
||||
continue;
|
||||
}
|
||||
Map<String, Object> entry = new HashMap<>();
|
||||
entry.put("desc", "");
|
||||
entry.put("state", module.isEnabled());
|
||||
entry.put("settings", !module.getSettings().isEmpty());
|
||||
result.put(module.getName(), entry);
|
||||
}
|
||||
response.put("result", result);
|
||||
writer.write(this.gson.toJson(response));
|
||||
writer.flush();
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package shit.zen.network.webui;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import shit.zen.ZenClient;
|
||||
import shit.zen.exception.ModuleNotFoundException;
|
||||
import shit.zen.modules.Module;
|
||||
import shit.zen.modules.impl.world.WebUI;
|
||||
import shit.zen.settings.Setting;
|
||||
import shit.zen.settings.impl.BooleanSetting;
|
||||
import shit.zen.settings.impl.ModeSetting;
|
||||
import shit.zen.settings.impl.NumberSetting;
|
||||
import shit.zen.utils.render.TextureUtil;
|
||||
|
||||
public class SetSettingHandler extends AbstractHttpHandler {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public int handleRequest(InputStream in, OutputStream out, HttpExchange exchange) throws Throwable {
|
||||
Map<String, String> query = TextureUtil.parseQueryString(exchange.getRequestURI().getQuery());
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
boolean success = false;
|
||||
String reason = null;
|
||||
Object result = null;
|
||||
if (query.containsKey("module") && query.containsKey("name") && query.containsKey("value")) {
|
||||
try {
|
||||
Module module = lookupModule(query.get("module"));
|
||||
if (module == null) {
|
||||
reason = "找不到模块";
|
||||
} else if (module instanceof WebUI) {
|
||||
reason = "sb";
|
||||
} else {
|
||||
String settingName = query.get("name");
|
||||
Optional<Setting<?>> match = module.getSettings().stream()
|
||||
.filter(setting -> setting.getName().equals(settingName))
|
||||
.findFirst();
|
||||
if (match.isEmpty()) {
|
||||
reason = "找不到参数";
|
||||
} else {
|
||||
Setting setting = match.get();
|
||||
String raw = query.get("value");
|
||||
if (setting instanceof NumberSetting) {
|
||||
try {
|
||||
setting.setValue(Double.valueOf(raw));
|
||||
success = true;
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (setting instanceof BooleanSetting) {
|
||||
setting.setValue(Boolean.valueOf(raw));
|
||||
success = true;
|
||||
} else if (setting instanceof ModeSetting modeSetting) {
|
||||
String matchedMode = Stream.of(modeSetting.getModes())
|
||||
.filter(mode -> mode.equals(raw))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (matchedMode != null) {
|
||||
modeSetting.setValue(matchedMode);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
result = setting.getValue();
|
||||
} else {
|
||||
reason = "无效的值";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
success = false;
|
||||
reason = throwable.toString();
|
||||
}
|
||||
} else {
|
||||
result = false;
|
||||
reason = "参数不足";
|
||||
}
|
||||
response.put("success", success);
|
||||
response.put("reason", reason);
|
||||
response.put("result", result);
|
||||
out.write(new Gson().toJson(response).getBytes(StandardCharsets.UTF_8));
|
||||
return 200;
|
||||
}
|
||||
|
||||
private static Module lookupModule(String name) {
|
||||
try {
|
||||
return ZenClient.getInstance().getModuleManager().getModule(name);
|
||||
} catch (ModuleNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package shit.zen.network.webui;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import shit.zen.ZenClient;
|
||||
import shit.zen.exception.ModuleNotFoundException;
|
||||
import shit.zen.modules.Module;
|
||||
import shit.zen.settings.Setting;
|
||||
import shit.zen.settings.impl.BooleanSetting;
|
||||
import shit.zen.settings.impl.ModeSetting;
|
||||
import shit.zen.settings.impl.NumberSetting;
|
||||
import shit.zen.utils.render.TextureUtil;
|
||||
|
||||
public class SettingsHandler extends AbstractHttpHandler {
|
||||
|
||||
@Override
|
||||
public int handleRequest(InputStream in, OutputStream out, HttpExchange exchange) throws Throwable {
|
||||
Map<String, String> query = TextureUtil.parseQueryString(exchange.getRequestURI().getQuery());
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
boolean success = false;
|
||||
String reason = null;
|
||||
if (query.containsKey("module")) {
|
||||
try {
|
||||
Module module = lookupModule(query.get("module"));
|
||||
if (module == null) {
|
||||
reason = "找不到模块";
|
||||
} else {
|
||||
List<Setting<?>> settings = module.getSettings();
|
||||
List<Map<String, Object>> entries = new ArrayList<>();
|
||||
for (Setting<?> setting : settings) {
|
||||
Map<String, Object> entry = new HashMap<>();
|
||||
entry.put("name", setting.getName());
|
||||
entry.put("displayName", setting.getName());
|
||||
if (setting instanceof NumberSetting numberSetting) {
|
||||
entry.put("type", "slider");
|
||||
entry.put("max", numberSetting.getMax());
|
||||
entry.put("min", numberSetting.getMin());
|
||||
entry.put("step", numberSetting.getStep());
|
||||
entry.put("value", numberSetting.getValue());
|
||||
} else if (setting instanceof BooleanSetting) {
|
||||
entry.put("type", "checkbox");
|
||||
entry.put("value", setting.getValue());
|
||||
} else if (setting instanceof ModeSetting modeSetting) {
|
||||
entry.put("type", "selection");
|
||||
entry.put("value", modeSetting.getValue());
|
||||
entry.put("values", modeSetting.getModes());
|
||||
}
|
||||
entries.add(entry);
|
||||
}
|
||||
response.put("result", entries);
|
||||
success = true;
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
success = false;
|
||||
reason = throwable.toString();
|
||||
}
|
||||
} else {
|
||||
reason = "参数不足";
|
||||
}
|
||||
response.put("success", success);
|
||||
response.put("reason", reason);
|
||||
out.write(new Gson().toJson(response).getBytes(StandardCharsets.UTF_8));
|
||||
return 200;
|
||||
}
|
||||
|
||||
private static Module lookupModule(String name) {
|
||||
try {
|
||||
return ZenClient.getInstance().getModuleManager().getModule(name);
|
||||
} catch (ModuleNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package shit.zen.network.webui;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Locale;
|
||||
|
||||
public class StaticFileHandler extends AbstractHttpHandler {
|
||||
private final String resourcePath;
|
||||
private final String urlPrefix;
|
||||
|
||||
public StaticFileHandler(String resourcePath, String urlPrefix) {
|
||||
this.resourcePath = resourcePath;
|
||||
this.urlPrefix = urlPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int handleRequest(InputStream in, OutputStream out, HttpExchange exchange) throws Throwable {
|
||||
String requestPath = exchange.getRequestURI().getPath();
|
||||
if (!requestPath.startsWith(this.urlPrefix)) {
|
||||
return 404;
|
||||
}
|
||||
String relative = requestPath.substring(this.urlPrefix.length());
|
||||
relative = URLDecoder.decode(relative, StandardCharsets.UTF_8);
|
||||
if (relative.isEmpty() || relative.endsWith("/")) {
|
||||
relative += "index.html";
|
||||
}
|
||||
String classpath = this.resourcePath + "/" + relative;
|
||||
InputStream resource = StaticFileHandler.class.getResourceAsStream(classpath);
|
||||
if (resource == null) {
|
||||
return 404;
|
||||
}
|
||||
try (resource) {
|
||||
exchange.getResponseHeaders().add("Content-Type", guessContentType(relative));
|
||||
resource.transferTo(out);
|
||||
}
|
||||
return 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendResponse(int status, OutputStream out, HttpExchange exchange) throws IOException {
|
||||
InputStream resource = StaticFileHandler.class.getResourceAsStream(this.resourcePath + "/" + status + ".html");
|
||||
if (resource != null) {
|
||||
try (resource) {
|
||||
exchange.getResponseHeaders().add("Content-Type", "text/html; charset=utf-8");
|
||||
resource.transferTo(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String guessContentType(String path) {
|
||||
String lower = path.toLowerCase(Locale.ROOT);
|
||||
if (lower.endsWith(".html") || lower.endsWith(".htm")) return "text/html; charset=utf-8";
|
||||
if (lower.endsWith(".css")) return "text/css; charset=utf-8";
|
||||
if (lower.endsWith(".js")) return "application/javascript; charset=utf-8";
|
||||
if (lower.endsWith(".json")) return "application/json; charset=utf-8";
|
||||
if (lower.endsWith(".svg")) return "image/svg+xml";
|
||||
if (lower.endsWith(".png")) return "image/png";
|
||||
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
|
||||
if (lower.endsWith(".ico")) return "image/x-icon";
|
||||
if (lower.endsWith(".woff")) return "font/woff";
|
||||
if (lower.endsWith(".woff2")) return "font/woff2";
|
||||
if (lower.endsWith(".ttf")) return "font/ttf";
|
||||
return "application/octet-stream";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package shit.zen.network.webui;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import shit.zen.ZenClient;
|
||||
import shit.zen.exception.ModuleNotFoundException;
|
||||
import shit.zen.modules.Module;
|
||||
import shit.zen.modules.impl.world.WebUI;
|
||||
import shit.zen.utils.render.TextureUtil;
|
||||
|
||||
public class ToggleModuleHandler extends AbstractHttpHandler {
|
||||
|
||||
@Override
|
||||
public int handleRequest(InputStream in, OutputStream out, HttpExchange exchange) throws Throwable {
|
||||
Map<String, String> query = TextureUtil.parseQueryString(exchange.getRequestURI().getQuery());
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
String reason = null;
|
||||
boolean state;
|
||||
boolean success;
|
||||
if (query.containsKey("module") && query.containsKey("state")) {
|
||||
try {
|
||||
Module module = lookupModule(query.get("module"));
|
||||
if (module == null) {
|
||||
state = false;
|
||||
success = false;
|
||||
reason = "找不到模块";
|
||||
} else if (module instanceof WebUI) {
|
||||
state = true;
|
||||
success = true;
|
||||
} else {
|
||||
module.setEnabled(Boolean.parseBoolean(query.get("state")));
|
||||
state = module.isEnabled();
|
||||
success = true;
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
state = false;
|
||||
success = false;
|
||||
reason = throwable.toString();
|
||||
}
|
||||
} else {
|
||||
state = false;
|
||||
success = false;
|
||||
reason = "参数不足";
|
||||
}
|
||||
response.put("success", success);
|
||||
response.put("reason", reason);
|
||||
response.put("result", state);
|
||||
out.write(new Gson().toJson(response).getBytes(StandardCharsets.UTF_8));
|
||||
return 200;
|
||||
}
|
||||
|
||||
private static Module lookupModule(String name) {
|
||||
try {
|
||||
return ZenClient.getInstance().getModuleManager().getModule(name);
|
||||
} catch (ModuleNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable → Regular
Reference in New Issue
Block a user