koishi-plugin-terminal 1.0.2 → 1.0.4
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/config.d.ts +12 -0
- package/lib/helper.d.ts +4 -0
- package/lib/index.d.ts +2 -12
- package/lib/index.js +53 -27
- package/lib/stripper.d.ts +2 -0
- package/package.json +5 -1
package/lib/config.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Schema } from "koishi";
|
|
2
|
+
export interface Config {
|
|
3
|
+
admin?: Array<string>;
|
|
4
|
+
auth?: number;
|
|
5
|
+
root?: string;
|
|
6
|
+
shell?: string;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
cols?: number;
|
|
9
|
+
rows?: number;
|
|
10
|
+
maxOutputLength: number;
|
|
11
|
+
}
|
|
12
|
+
export declare const Config: Schema<Config>;
|
package/lib/helper.d.ts
ADDED
package/lib/index.d.ts
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
import { Context
|
|
1
|
+
import { Context } from 'koishi';
|
|
2
2
|
import * as pty from "node-pty";
|
|
3
|
+
import { Config } from "./config";
|
|
3
4
|
export declare const name = "terminal";
|
|
4
|
-
export interface Config {
|
|
5
|
-
admin?: Array<string>;
|
|
6
|
-
auth?: number;
|
|
7
|
-
root?: string;
|
|
8
|
-
shell?: string;
|
|
9
|
-
timeout?: number;
|
|
10
|
-
cols?: number;
|
|
11
|
-
rows?: number;
|
|
12
|
-
maxOutputLength: number;
|
|
13
|
-
}
|
|
14
5
|
export interface ShellSession {
|
|
15
6
|
terminal: pty.IPty;
|
|
16
7
|
buffer: string;
|
|
@@ -20,5 +11,4 @@ export interface ShellSession {
|
|
|
20
11
|
dispose(): void;
|
|
21
12
|
}>;
|
|
22
13
|
}
|
|
23
|
-
export declare const Config: Schema<Config>;
|
|
24
14
|
export declare function apply(ctx: Context, config: Config): void;
|
package/lib/index.js
CHANGED
|
@@ -30,7 +30,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
|
-
Config: () => Config,
|
|
34
33
|
apply: () => apply,
|
|
35
34
|
name: () => name
|
|
36
35
|
});
|
|
@@ -38,17 +37,33 @@ module.exports = __toCommonJS(src_exports);
|
|
|
38
37
|
var import_koishi = require("koishi");
|
|
39
38
|
var pty = __toESM(require("node-pty"));
|
|
40
39
|
var import_node_timers = require("node:timers");
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
40
|
+
|
|
41
|
+
// src/stripper.ts
|
|
42
|
+
function stripBackspaces(input) {
|
|
43
|
+
const chars = [];
|
|
44
|
+
for (const char of input) {
|
|
45
|
+
if (char === "\b") {
|
|
46
|
+
chars.pop();
|
|
47
|
+
} else {
|
|
48
|
+
chars.push(char);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return chars.join("");
|
|
52
|
+
}
|
|
53
|
+
__name(stripBackspaces, "stripBackspaces");
|
|
54
|
+
function stripAnsi(input) {
|
|
55
|
+
const text = stripBackspaces(input.replace(
|
|
56
|
+
// eslint-disable-next-line no-control-regex
|
|
57
|
+
/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g,
|
|
58
|
+
""
|
|
59
|
+
));
|
|
60
|
+
return text.replace(/\r\n/g, "\n").split("\n").map((line) => line.split("\r").at(-1)).join("\n");
|
|
61
|
+
}
|
|
62
|
+
__name(stripAnsi, "stripAnsi");
|
|
63
|
+
|
|
64
|
+
// src/helper.ts
|
|
65
|
+
var import_node_path = require("node:path");
|
|
66
|
+
var import_node_fs = require("node:fs");
|
|
52
67
|
function resolveShell(shell) {
|
|
53
68
|
if (shell) return shell;
|
|
54
69
|
switch (process.platform) {
|
|
@@ -62,28 +77,30 @@ function resolveShell(shell) {
|
|
|
62
77
|
return "bash";
|
|
63
78
|
}
|
|
64
79
|
__name(resolveShell, "resolveShell");
|
|
65
|
-
function stripAnsi(input) {
|
|
66
|
-
const text = input.replace(
|
|
67
|
-
// eslint-disable-next-line no-control-regex
|
|
68
|
-
/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g,
|
|
69
|
-
""
|
|
70
|
-
);
|
|
71
|
-
return text.replace(/\r\n/g, "\n").split("\n").map((line) => line.split("\r").at(-1)).join("\n");
|
|
72
|
-
}
|
|
73
|
-
__name(stripAnsi, "stripAnsi");
|
|
74
80
|
function getKey(session) {
|
|
75
81
|
return `${session.platform}:${session.userId}`;
|
|
76
82
|
}
|
|
77
83
|
__name(getKey, "getKey");
|
|
84
|
+
function fixNodePtyHelper() {
|
|
85
|
+
if (process.platform !== "darwin") return;
|
|
86
|
+
try {
|
|
87
|
+
const root = (0, import_node_path.dirname)(require.resolve("node-pty/package.json"));
|
|
88
|
+
const helper = (0, import_node_path.join)(root, "prebuilds", `darwin-${process.arch}`, "spawn-helper");
|
|
89
|
+
const mode = (0, import_node_fs.statSync)(helper).mode;
|
|
90
|
+
if (!(mode & 73)) (0, import_node_fs.chmodSync)(helper, mode | 493);
|
|
91
|
+
} catch {
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
__name(fixNodePtyHelper, "fixNodePtyHelper");
|
|
78
95
|
function isInteractiveCommand(command) {
|
|
79
96
|
const trimmed = command.trim();
|
|
80
97
|
if (!trimmed) return false;
|
|
81
98
|
const [name2, ...args] = trimmed.split(/\s+/);
|
|
82
99
|
if (/^(vi|vim|nvim|nano|emacs)$/.test(name2)) return true;
|
|
83
|
-
if (/^(less|more
|
|
100
|
+
if (/^(less|more)$/.test(name2)) return true;
|
|
84
101
|
if (/^(top|htop|btop|watch)$/.test(name2)) return true;
|
|
85
102
|
if (/^(tmux|screen)$/.test(name2)) return true;
|
|
86
|
-
if (/^(
|
|
103
|
+
if (/^(sftp|ftp|telnet)$/.test(name2)) return true;
|
|
87
104
|
if (/^(mysql|psql|sqlite3|redis-cli|mongosh)$/.test(name2)) return true;
|
|
88
105
|
if (/^(node|python|python3|ipython|ruby|irb|php|lua|R)$/.test(name2) && !args.length) return true;
|
|
89
106
|
if (name2 === "tail" && args.includes("-f")) return true;
|
|
@@ -92,8 +109,12 @@ function isInteractiveCommand(command) {
|
|
|
92
109
|
return false;
|
|
93
110
|
}
|
|
94
111
|
__name(isInteractiveCommand, "isInteractiveCommand");
|
|
112
|
+
|
|
113
|
+
// src/index.ts
|
|
114
|
+
var name = "terminal";
|
|
95
115
|
var map = /* @__PURE__ */ new Map();
|
|
96
116
|
function apply(ctx, config) {
|
|
117
|
+
fixNodePtyHelper();
|
|
97
118
|
const allowedUsers = config.admin;
|
|
98
119
|
function refreshTimeout(shellSession, key, session) {
|
|
99
120
|
if (!config.timeout) return;
|
|
@@ -120,7 +141,13 @@ function apply(ctx, config) {
|
|
|
120
141
|
cols: config.cols,
|
|
121
142
|
rows: config.rows,
|
|
122
143
|
cwd: config.root,
|
|
123
|
-
env:
|
|
144
|
+
env: {
|
|
145
|
+
...process.env,
|
|
146
|
+
PAGER: "cat",
|
|
147
|
+
MANPAGER: "cat",
|
|
148
|
+
GIT_PAGER: "cat",
|
|
149
|
+
LESS: "-FRX"
|
|
150
|
+
}
|
|
124
151
|
});
|
|
125
152
|
const shellSession = {
|
|
126
153
|
terminal,
|
|
@@ -133,7 +160,7 @@ function apply(ctx, config) {
|
|
|
133
160
|
shellSession.buffer = "";
|
|
134
161
|
if (!output) return;
|
|
135
162
|
const text = output.length > config.maxOutputLength ? output.slice(0, config.maxOutputLength - 1) + "\n ...Truncated output" : output;
|
|
136
|
-
await session.send(text);
|
|
163
|
+
await session.send(import_koishi.h.text(text));
|
|
137
164
|
}, "flush");
|
|
138
165
|
const dataDisposable = terminal.onData((data) => {
|
|
139
166
|
shellSession.buffer += data;
|
|
@@ -165,7 +192,7 @@ function apply(ctx, config) {
|
|
|
165
192
|
}
|
|
166
193
|
}
|
|
167
194
|
__name(cleanupSession, "cleanupSession");
|
|
168
|
-
ctx.command("shell [command:text]", "Start a persistent shell session", { authority: config.auth }).option("terminate", "-t Terminate current shell session").usage("After start up,
|
|
195
|
+
ctx.command("shell [command:text]", "Start a persistent shell session.", { authority: config.auth }).option("terminate", "-t Terminate current shell session").usage("After start up, user messages will be sent to shell process.").example("shell echo Operating System: Three Easy Pieces > qljj.txt").action(async ({ session, options }, command) => {
|
|
169
196
|
if (!allowedUsers.includes(session.userId)) {
|
|
170
197
|
return "Unauthorized user.";
|
|
171
198
|
}
|
|
@@ -208,7 +235,6 @@ function apply(ctx, config) {
|
|
|
208
235
|
__name(apply, "apply");
|
|
209
236
|
// Annotate the CommonJS export names for ESM import in node:
|
|
210
237
|
0 && (module.exports = {
|
|
211
|
-
Config,
|
|
212
238
|
apply,
|
|
213
239
|
name
|
|
214
240
|
});
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-terminal",
|
|
3
3
|
"description": "通过 QQ 运行持久的 Shell 终端",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.4",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
|
+
"author": {
|
|
7
|
+
"email": "ygong68@wisc.edu",
|
|
8
|
+
"name": "Jingmozhiyu"
|
|
9
|
+
},
|
|
6
10
|
"typings": "lib/index.d.ts",
|
|
7
11
|
"files": [
|
|
8
12
|
"lib",
|