UNPKG

@sphekes/koishi-plugin-palctrl

Version:

A simple extension to manage PalWorld Server

259 lines (255 loc) 11.1 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name2 in all) __defProp(target, name2, { get: all[name2], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Config: () => Config, apply: () => apply, inject: () => inject, name: () => name }); module.exports = __toCommonJS(src_exports); var import_ping = __toESM(require("ping")); var import_nodejs_winrm = __toESM(require("nodejs-winrm")); // src/config.ts var import_koishi = require("koishi"); var Config = import_koishi.Schema.intersect([ import_koishi.Schema.object({ host: import_koishi.Schema.string().description("幻兽帕鲁服务器名").required(), timeout: import_koishi.Schema.number().description("请求超时时间[ms]").default(1e3) }).description("基本设置"), import_koishi.Schema.object({ // restUrl: Schema.string().description("幻兽帕鲁服务器 REST API 地址(例: http://localhost:8212/v1/api/)<br>建议公网帕鲁服务器使用 HTTPS 反代 API 确保账号密码安全").required(), restPort: import_koishi.Schema.number().description("REST API 端口号").default(8212), restUsername: import_koishi.Schema.string().description("管理员名称").default("admin"), restPassword: import_koishi.Schema.string().description("管理员密码").default("123456"), useHttps: import_koishi.Schema.boolean().description("是否使用https").default(false) }).description("REST api连接设置"), import_koishi.Schema.object({ winrmPort: import_koishi.Schema.number().description("winRM 端口号").default(5985), winrmUsername: import_koishi.Schema.string().description("openssh 用户名").default(""), winrmPassword: import_koishi.Schema.string().description("openssh 密码,需要开启密码登录").default(""), winrmServiceName: import_koishi.Schema.string().description("PalWorld服务名").default("PalServer") }).description("WinRM连接设置") ]); // src/index.ts var name = "azimiao-palworld-server-tool"; var inject = ["http"]; function apply(ctx, config) { function wr_ping(host) { return setTimeoutPromise(import_ping.default.promise.probe(host)); } __name(wr_ping, "wr_ping"); function wr_get(url, config2) { return setTimeoutPromise(ctx.http.get(url, config2)); } __name(wr_get, "wr_get"); function wr_post(url, data, config2) { return setTimeoutPromise(ctx.http.post(url, data, config2)); } __name(wr_post, "wr_post"); function wr_runCommand(command, host, name2, pass, port) { return setTimeoutPromise(import_nodejs_winrm.default.runCommand(command, host, name2, pass, port)); } __name(wr_runCommand, "wr_runCommand"); function setTimeoutPromise(promise) { const timeoutPromise = new Promise( (_, reject) => setTimeout(() => reject(new Error("Operation timed out")), config.timeout) ); return Promise.race([promise, timeoutPromise]); } __name(setTimeoutPromise, "setTimeoutPromise"); function getFullUrl(method) { let url = `http://${config.host}:${config.restPort}/v1/api/${method}`; return url; } __name(getFullUrl, "getFullUrl"); ctx.command("pal", "控制帕鲁服务器").action((_) => { return `控制帕鲁服务器`; }); ctx.command("pal").subcommand("info [arg]", "获取幻兽帕鲁服务器信息").action(async (argv, arg) => { let msg = ""; if (arg == "ping") { await wr_ping(config.host).then((res) => { msg = res.alive ? `主机${config.host}在线,ping延迟 ${res.time} ms。` : `主机${config.host}不在线。`; }).catch((err) => { console.error("Error pinging the server:", err); }); } else { await wr_get(getFullUrl("info"), { headers: { "Authorization": "Basic " + Buffer.from(`${config.restUsername}:${config.restPassword}`).toString("base64") }, responseType: "json" }).then(async (res) => { if (res.servername && res.version && res.description) { msg = `帕鲁服务器运行中 - 名称: ${res.servername} - 版本: ${res.version} - 描述: ${res.description}`; await wr_get(getFullUrl("metrics"), { headers: { "Authorization": "Basic " + Buffer.from(`${config.restUsername}:${config.restPassword}`).toString("base64") }, responseType: "json" }).then((res2) => { res2 ? msg += ` - 当前玩家数: ${res2.currentplayernum} - 服务器帧率: ${res2.serverfps}fps - 游玩天数: ${res2.days} - 服务器运行时间: ${res2.uptime}s ` : msg = "获取信息失败: 返回信息错误"; }).catch((error) => { msg = error.response ? `请求错误: ${error.response.data}` : `请求失败: ${error.code ? `错误码 ${error.code})}` : "连接服务器失败,请检查服务器状态或后台配置信息"}`; }); } else { msg = "获取信息失败: 返回信息错误"; } }).catch((error) => { msg = error.response ? `请求错误: ${error.response.data}` : `请求失败: ${error.code ? `错误码 ${error.code})}` : "连接服务器失败,请检查服务器状态或后台配置信息"}`; }); } return msg; }); ctx.command("pal").subcommand("players", "获取幻兽帕鲁服务器在线玩家").action(async (argv) => { let msg = ""; await wr_get(getFullUrl("players"), { headers: { "Authorization": "Basic " + Buffer.from(`${config.restUsername}:${config.restPassword}`).toString("base64") }, responseType: "json" }).then((res) => { if (res.players) { if (res.players.length > 0) { msg = `当前共有 ${res.players.length} 位玩家在线: `; res.players.forEach((player, index) => { msg += `- [Lv.${player.level}] ${player.name} ${player.userId}\r `; }); } else { msg = "当前没有玩家在线"; } } else { msg = "获取信息失败: 返回信息错误"; } }).catch((error) => { msg = error.response ? `请求错误: ${error.response.data}` : `请求失败: ${error.code ? `错误码 ${error.code})}` : "连接服务器失败,请检查服务器状态或后台配置信息"}`; }); return msg; }); ctx.command("pal").subcommand("announce <message:text>", "向帕鲁服务器发送公屏消息").action(async (_, message) => { let msg = ""; if (!message) { return "请输入发送的消息"; } await wr_post( getFullUrl("announce"), JSON.stringify({ "message": message }), { headers: { "Authorization": "Basic " + Buffer.from(`${config.restUsername}:${config.restPassword}`).toString("base64"), "Content-Type": "application/json" } } ).then((res) => { msg = `发送成功,${res}`; }).catch((error) => { msg = error.response ? `请求错误: ${error.response.data}` : `请求失败: ${error.code ? `错误码 ${error.code})}` : "连接服务器失败,请检查服务器状态或后台配置信息"}`; }); return msg; }); ctx.command("pal").subcommand("save", "向幻兽帕鲁服务器发送保存命令").action(async (argv, message) => { let msg = ""; await wr_post( getFullUrl("save"), "", { headers: { "Authorization": "Basic " + Buffer.from(`${config.restUsername}:${config.restPassword}`).toString("base64") } } ).then((res) => { msg = `保存成功,${res}`; }).catch((error) => { msg = error.response ? `请求错误: ${error.response.data}` : `请求失败: ${error.code ? `错误码 ${error.code})}` : "连接服务器失败,请检查服务器状态或后台配置信息"}`; }); return msg; }); ctx.command("pal").subcommand("start", "启动帕鲁服务器").action(async (_) => { let msg = ""; try { var result = await wr_runCommand(`sc start ${config.winrmServiceName}`, config.host, config.winrmUsername, config.winrmPassword, config.winrmPort); msg = result; } catch (error) { msg = `请求失败: ${error}`; } return msg; }); ctx.command("pal").subcommand("stop", "立刻关闭帕鲁服务器").action(async (_) => { let msg = ""; try { var result = await wr_runCommand(`sc stop ${config.winrmServiceName}`, config.host, config.winrmUsername, config.winrmPassword, config.winrmPort); msg = result; } catch (error) { msg = `请求失败: ${error}`; } return msg; }); ctx.command("pal").subcommand("shutdown", "关闭帕鲁服务器并发送消息").option("now", "-n").option("waittime", "-t <waittime>").option("message", "-m <message>").action(async ({ options }) => { let msg = ""; await wr_post( getFullUrl("shutdown"), JSON.stringify({ "waittime": !options || options.now ? 1 : options.waittime ? options.waittime : 30, "message": options && options.message ? options.message : "服务器将在30s后关闭" }), { headers: { "Authorization": "Basic " + Buffer.from(`${config.restUsername}:${config.restPassword}`).toString("base64"), "Content-Type": "application/json" } } ).then((res) => { msg = `发送成功,${res}`; }).catch((error) => { msg = error.response ? `请求错误: ${error.response.data}` : `请求失败: ${error.code ? `错误码 ${error.code})}` : "连接服务器失败,请检查服务器状态或后台配置信息"}`; }); return msg; }); } __name(apply, "apply"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Config, apply, inject, name });