koishi-plugin-terminal 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +1 -1
- package/lib/index.js +22 -15
- package/package.json +4 -3
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -40,14 +40,14 @@ var pty = __toESM(require("node-pty"));
|
|
|
40
40
|
var import_node_timers = require("node:timers");
|
|
41
41
|
var name = "terminal";
|
|
42
42
|
var Config = import_koishi.Schema.object({
|
|
43
|
-
admin: import_koishi.Schema.array(String).description("
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
timeout: import_koishi.Schema.number().description("
|
|
43
|
+
admin: import_koishi.Schema.array(String).description("超级管理员用户名单").default([]),
|
|
44
|
+
auth: import_koishi.Schema.number().description("使用本插件所需的最低权限,此外,用户也需要在超级管理员名单中。").min(1).max(4).step(1).default(4),
|
|
45
|
+
root: import_koishi.Schema.string().description("初始工作路径").default(process.env.HOME),
|
|
46
|
+
shell: import_koishi.Schema.string().description("Shell路径,留空则自动检测系统默认Shell"),
|
|
47
|
+
timeout: import_koishi.Schema.number().description("超时时长").default(import_koishi.Time.minute),
|
|
48
48
|
cols: import_koishi.Schema.number().description("终端列数").default(80),
|
|
49
49
|
rows: import_koishi.Schema.number().description("终端行数").default(24),
|
|
50
|
-
maxOutputLength: import_koishi.Schema.number().description("
|
|
50
|
+
maxOutputLength: import_koishi.Schema.number().description("单次发送最大输出长度").default(16384)
|
|
51
51
|
});
|
|
52
52
|
function resolveShell(shell) {
|
|
53
53
|
if (shell) return shell;
|
|
@@ -63,11 +63,12 @@ function resolveShell(shell) {
|
|
|
63
63
|
}
|
|
64
64
|
__name(resolveShell, "resolveShell");
|
|
65
65
|
function stripAnsi(input) {
|
|
66
|
-
|
|
66
|
+
const text = input.replace(
|
|
67
67
|
// eslint-disable-next-line no-control-regex
|
|
68
68
|
/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g,
|
|
69
69
|
""
|
|
70
70
|
);
|
|
71
|
+
return text.replace(/\r\n/g, "\n").split("\n").map((line) => line.split("\r").at(-1)).join("\n");
|
|
71
72
|
}
|
|
72
73
|
__name(stripAnsi, "stripAnsi");
|
|
73
74
|
function getKey(session) {
|
|
@@ -79,7 +80,6 @@ function apply(ctx, config) {
|
|
|
79
80
|
const allowedUsers = config.admin;
|
|
80
81
|
function sendCommand(shellSession, command) {
|
|
81
82
|
shellSession.terminal.write(command + "\r");
|
|
82
|
-
shellSession.terminal.write("pwd\r");
|
|
83
83
|
}
|
|
84
84
|
__name(sendCommand, "sendCommand");
|
|
85
85
|
function initSession(session, key) {
|
|
@@ -101,7 +101,7 @@ function apply(ctx, config) {
|
|
|
101
101
|
shellSession.buffer = "";
|
|
102
102
|
if (!output) return;
|
|
103
103
|
const text = output.length > config.maxOutputLength ? output.slice(0, config.maxOutputLength - 1) + "\n ...Truncated output" : output;
|
|
104
|
-
await session.send(text
|
|
104
|
+
await session.send(text);
|
|
105
105
|
}, "flush");
|
|
106
106
|
const dataDisposable = terminal.onData((data) => {
|
|
107
107
|
shellSession.buffer += data;
|
|
@@ -109,7 +109,8 @@ function apply(ctx, config) {
|
|
|
109
109
|
shellSession.timer = setTimeout(flush, 300);
|
|
110
110
|
});
|
|
111
111
|
const exitDisposable = terminal.onExit(async () => {
|
|
112
|
-
|
|
112
|
+
flush();
|
|
113
|
+
cleanupSession(shellSession, key, false);
|
|
113
114
|
await session.send("Shell exited.");
|
|
114
115
|
});
|
|
115
116
|
shellSession.disposables.push(dataDisposable, exitDisposable);
|
|
@@ -117,14 +118,20 @@ function apply(ctx, config) {
|
|
|
117
118
|
return shellSession;
|
|
118
119
|
}
|
|
119
120
|
__name(initSession, "initSession");
|
|
120
|
-
function cleanupSession(shellSession, key) {
|
|
121
|
+
function cleanupSession(shellSession, key, kill = true) {
|
|
121
122
|
map.delete(key);
|
|
122
|
-
shellSession.disposables.forEach((d) => d.dispose());
|
|
123
|
-
shellSession.terminal.kill();
|
|
124
123
|
if (shellSession.timer) (0, import_node_timers.clearTimeout)(shellSession.timer);
|
|
124
|
+
shellSession.disposables.forEach((d) => d.dispose());
|
|
125
|
+
shellSession.disposables.length = 0;
|
|
126
|
+
if (kill) {
|
|
127
|
+
try {
|
|
128
|
+
shellSession.terminal.kill();
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
}
|
|
125
132
|
}
|
|
126
133
|
__name(cleanupSession, "cleanupSession");
|
|
127
|
-
ctx.command("shell [command:text]", "Start a persistent shell session", { authority:
|
|
134
|
+
ctx.command("shell [command:text]", "Start a persistent shell session", { authority: 0 }).option("terminate", "-t Terminate current shell session").usage("After start up, regular user messages will be sent to shell process.").example("shell echo Operating System: Three Easy Pieces > qljj.txt").action(async ({ session, options }, command) => {
|
|
128
135
|
if (!allowedUsers.includes(session.userId)) {
|
|
129
136
|
return "Unauthorized user.";
|
|
130
137
|
}
|
|
@@ -132,7 +139,7 @@ function apply(ctx, config) {
|
|
|
132
139
|
if (options.terminate) {
|
|
133
140
|
const current2 = map.get(key);
|
|
134
141
|
if (!current2) return "There doesn't exist running shell session.";
|
|
135
|
-
cleanupSession(current2, key);
|
|
142
|
+
cleanupSession(current2, key, true);
|
|
136
143
|
return "Shell session terminated.";
|
|
137
144
|
}
|
|
138
145
|
let current = map.get(key);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-terminal",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "1.0.
|
|
3
|
+
"description": "通过 QQ 运行持久的 Shell 终端",
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"terminal",
|
|
19
19
|
"cmd",
|
|
20
20
|
"bash",
|
|
21
|
-
"zsh"
|
|
21
|
+
"zsh",
|
|
22
|
+
"command"
|
|
22
23
|
],
|
|
23
24
|
"repository": {
|
|
24
25
|
"type": "git",
|