koishi-plugin-terminal 1.0.1 → 1.0.2
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 -0
- package/lib/index.js +39 -4
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -75,10 +75,42 @@ function getKey(session) {
|
|
|
75
75
|
return `${session.platform}:${session.userId}`;
|
|
76
76
|
}
|
|
77
77
|
__name(getKey, "getKey");
|
|
78
|
+
function isInteractiveCommand(command) {
|
|
79
|
+
const trimmed = command.trim();
|
|
80
|
+
if (!trimmed) return false;
|
|
81
|
+
const [name2, ...args] = trimmed.split(/\s+/);
|
|
82
|
+
if (/^(vi|vim|nvim|nano|emacs)$/.test(name2)) return true;
|
|
83
|
+
if (/^(less|more|man)$/.test(name2)) return true;
|
|
84
|
+
if (/^(top|htop|btop|watch)$/.test(name2)) return true;
|
|
85
|
+
if (/^(tmux|screen)$/.test(name2)) return true;
|
|
86
|
+
if (/^(ssh|sftp|ftp|telnet)$/.test(name2)) return true;
|
|
87
|
+
if (/^(mysql|psql|sqlite3|redis-cli|mongosh)$/.test(name2)) return true;
|
|
88
|
+
if (/^(node|python|python3|ipython|ruby|irb|php|lua|R)$/.test(name2) && !args.length) return true;
|
|
89
|
+
if (name2 === "tail" && args.includes("-f")) return true;
|
|
90
|
+
if (name2 === "docker" && args.includes("exec") && args.some((arg) => arg.includes("it"))) return true;
|
|
91
|
+
if (name2 === "kubectl" && args.includes("exec") && args.some((arg) => arg.includes("it"))) return true;
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
__name(isInteractiveCommand, "isInteractiveCommand");
|
|
78
95
|
var map = /* @__PURE__ */ new Map();
|
|
79
96
|
function apply(ctx, config) {
|
|
80
97
|
const allowedUsers = config.admin;
|
|
81
|
-
function
|
|
98
|
+
function refreshTimeout(shellSession, key, session) {
|
|
99
|
+
if (!config.timeout) return;
|
|
100
|
+
if (shellSession.timeoutTimer) (0, import_node_timers.clearTimeout)(shellSession.timeoutTimer);
|
|
101
|
+
shellSession.timeoutTimer = setTimeout(async () => {
|
|
102
|
+
if (map.get(key) !== shellSession) return;
|
|
103
|
+
cleanupSession(shellSession, key, true);
|
|
104
|
+
await session.send("Shell session timed out.");
|
|
105
|
+
}, config.timeout);
|
|
106
|
+
}
|
|
107
|
+
__name(refreshTimeout, "refreshTimeout");
|
|
108
|
+
function sendCommand(shellSession, key, session, command) {
|
|
109
|
+
refreshTimeout(shellSession, key, session);
|
|
110
|
+
if (isInteractiveCommand(command)) {
|
|
111
|
+
shellSession.terminal.write(`echo "Interactive command is not supported in chat terminal. Use a non-interactive form, or run shell -t to restart."\r`);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
82
114
|
shellSession.terminal.write(command + "\r");
|
|
83
115
|
}
|
|
84
116
|
__name(sendCommand, "sendCommand");
|
|
@@ -115,12 +147,14 @@ function apply(ctx, config) {
|
|
|
115
147
|
});
|
|
116
148
|
shellSession.disposables.push(dataDisposable, exitDisposable);
|
|
117
149
|
map.set(key, shellSession);
|
|
150
|
+
refreshTimeout(shellSession, key, session);
|
|
118
151
|
return shellSession;
|
|
119
152
|
}
|
|
120
153
|
__name(initSession, "initSession");
|
|
121
154
|
function cleanupSession(shellSession, key, kill = true) {
|
|
122
155
|
map.delete(key);
|
|
123
156
|
if (shellSession.timer) (0, import_node_timers.clearTimeout)(shellSession.timer);
|
|
157
|
+
if (shellSession.timeoutTimer) (0, import_node_timers.clearTimeout)(shellSession.timeoutTimer);
|
|
124
158
|
shellSession.disposables.forEach((d) => d.dispose());
|
|
125
159
|
shellSession.disposables.length = 0;
|
|
126
160
|
if (kill) {
|
|
@@ -131,7 +165,7 @@ function apply(ctx, config) {
|
|
|
131
165
|
}
|
|
132
166
|
}
|
|
133
167
|
__name(cleanupSession, "cleanupSession");
|
|
134
|
-
ctx.command("shell [command:text]", "Start a persistent shell session", { authority:
|
|
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, regular user messages will be sent to shell process.").example("shell echo Operating System: Three Easy Pieces > qljj.txt").action(async ({ session, options }, command) => {
|
|
135
169
|
if (!allowedUsers.includes(session.userId)) {
|
|
136
170
|
return "Unauthorized user.";
|
|
137
171
|
}
|
|
@@ -148,7 +182,7 @@ function apply(ctx, config) {
|
|
|
148
182
|
if (!command) return "Shell session started. Send regular messages as commands. Send shell -t to terminate.";
|
|
149
183
|
}
|
|
150
184
|
if (!command) return "Shell session is running.";
|
|
151
|
-
sendCommand(current, command);
|
|
185
|
+
sendCommand(current, key, session, command);
|
|
152
186
|
});
|
|
153
187
|
ctx.middleware(async (session, next) => {
|
|
154
188
|
const key = getKey(session);
|
|
@@ -159,12 +193,13 @@ function apply(ctx, config) {
|
|
|
159
193
|
return next();
|
|
160
194
|
}
|
|
161
195
|
if (!content) return;
|
|
162
|
-
sendCommand(current, content);
|
|
196
|
+
sendCommand(current, key, session, content);
|
|
163
197
|
}, true);
|
|
164
198
|
ctx.on("dispose", () => {
|
|
165
199
|
for (const current of map.values()) {
|
|
166
200
|
current.disposables.forEach((d) => d.dispose());
|
|
167
201
|
if (current.timer) (0, import_node_timers.clearTimeout)(current.timer);
|
|
202
|
+
if (current.timeoutTimer) (0, import_node_timers.clearTimeout)(current.timeoutTimer);
|
|
168
203
|
current.terminal.kill();
|
|
169
204
|
}
|
|
170
205
|
map.clear();
|