@karinjs/plugin-basic 1.2.1 → 1.3.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/dist/apps/logger.d.ts +6 -0
- package/dist/apps/logger.js +229 -0
- package/dist/apps/login.js +5 -4
- package/dist/apps/master.d.ts +3 -1
- package/dist/apps/master.js +21 -3
- package/dist/apps/restart.js +4 -3
- package/dist/apps/status.js +5 -6
- package/dist/apps/update.d.ts +4 -5
- package/dist/apps/update.js +165 -81
- package/dist/chunk-7LNXK3JJ.js +127 -0
- package/dist/chunk-W3Q26Z2E.js +131 -0
- package/dist/index.js +17 -0
- package/dist/web.config.d.ts +4 -0
- package/dist/web.config.js +29 -16
- package/package.json +3 -3
- package/resources/img/logger.png +0 -0
- package/resources/img/plugin.png +0 -0
- package/resources/logger/index.css +215 -0
- package/resources/logger/index.html +37 -0
- package/resources/plugins/index.css +210 -0
- package/resources/plugins/index.html +71 -0
- package/config/config.json +0 -7
- package/dist/chunk-MNDJRJH2.js +0 -129
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import {
|
|
2
|
+
render
|
|
3
|
+
} from "../chunk-W3Q26Z2E.js";
|
|
4
|
+
|
|
5
|
+
// src/apps/logger.ts
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { karin, logger } from "node-karin";
|
|
9
|
+
var ansiToHtml = (text) => {
|
|
10
|
+
if (!text) return "";
|
|
11
|
+
const ESC = "\x1B";
|
|
12
|
+
const ansiRegex = new RegExp(`${ESC}\\[([0-9;]+)m`, "g");
|
|
13
|
+
const escapeHtml = (str) => str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
14
|
+
let result = "";
|
|
15
|
+
let lastIndex = 0;
|
|
16
|
+
let openSpan = "";
|
|
17
|
+
const colorMap = {
|
|
18
|
+
30: "#020617",
|
|
19
|
+
31: "#ef4444",
|
|
20
|
+
32: "#22c55e",
|
|
21
|
+
33: "#eab308",
|
|
22
|
+
34: "#3b82f6",
|
|
23
|
+
35: "#ec4899",
|
|
24
|
+
36: "#06b6d4",
|
|
25
|
+
37: "#e5e7eb",
|
|
26
|
+
90: "#6b7280",
|
|
27
|
+
91: "#f97373",
|
|
28
|
+
92: "#4ade80",
|
|
29
|
+
93: "#fde047",
|
|
30
|
+
94: "#60a5fa",
|
|
31
|
+
95: "#a855f7",
|
|
32
|
+
96: "#38bdf8",
|
|
33
|
+
97: "#f9fafb"
|
|
34
|
+
};
|
|
35
|
+
text.replace(ansiRegex, (match, codesStr, offset) => {
|
|
36
|
+
const chunk = text.slice(lastIndex, offset);
|
|
37
|
+
if (chunk) {
|
|
38
|
+
result += escapeHtml(chunk);
|
|
39
|
+
}
|
|
40
|
+
lastIndex = offset + match.length;
|
|
41
|
+
const codes = codesStr.split(";").map((n) => Number(n) || 0);
|
|
42
|
+
if (openSpan) {
|
|
43
|
+
result += "</span>";
|
|
44
|
+
openSpan = "";
|
|
45
|
+
}
|
|
46
|
+
if (codes.includes(0) || codes.includes(39)) {
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
if (codes[0] === 38 && codes[1] === 2 && codes.length >= 5) {
|
|
50
|
+
const r = codes[2];
|
|
51
|
+
const g = codes[3];
|
|
52
|
+
const b = codes[4];
|
|
53
|
+
openSpan = `color: rgb(${r}, ${g}, ${b})`;
|
|
54
|
+
result += `<span style="${openSpan}">`;
|
|
55
|
+
return "";
|
|
56
|
+
}
|
|
57
|
+
const colorCode = codes.find((c) => colorMap[c]);
|
|
58
|
+
if (colorCode !== void 0) {
|
|
59
|
+
const color = colorMap[colorCode];
|
|
60
|
+
openSpan = `color: ${color}`;
|
|
61
|
+
result += `<span style="${openSpan}">`;
|
|
62
|
+
return "";
|
|
63
|
+
}
|
|
64
|
+
return "";
|
|
65
|
+
});
|
|
66
|
+
const tail = text.slice(lastIndex);
|
|
67
|
+
if (tail) {
|
|
68
|
+
result += escapeHtml(tail);
|
|
69
|
+
}
|
|
70
|
+
if (openSpan) {
|
|
71
|
+
result += "</span>";
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
};
|
|
75
|
+
var trimEmptyLines = (text) => {
|
|
76
|
+
const lines = text.split("\n");
|
|
77
|
+
while (lines.length && !lines[0].trim()) lines.shift();
|
|
78
|
+
while (lines.length && !lines[lines.length - 1].trim()) lines.pop();
|
|
79
|
+
return lines.join("\n");
|
|
80
|
+
};
|
|
81
|
+
var groupLogLines = (lines) => {
|
|
82
|
+
const groups = [];
|
|
83
|
+
let current = [];
|
|
84
|
+
const isNewEntry = (line) => {
|
|
85
|
+
const trimmed = line.trim();
|
|
86
|
+
if (!trimmed) return false;
|
|
87
|
+
return /^\[\d{2}:\d{2}:\d{2}\.\d{3}\]\[[A-Z]+]/.test(trimmed);
|
|
88
|
+
};
|
|
89
|
+
for (const line of lines) {
|
|
90
|
+
if (isNewEntry(line)) {
|
|
91
|
+
if (current.length) groups.push(current);
|
|
92
|
+
current = [line];
|
|
93
|
+
} else {
|
|
94
|
+
if (current.length) {
|
|
95
|
+
current.push(line);
|
|
96
|
+
} else {
|
|
97
|
+
current = [line];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (current.length) groups.push(current);
|
|
102
|
+
return groups.map((item) => item.join("\n"));
|
|
103
|
+
};
|
|
104
|
+
var getTodayLogs = async (limit = 50) => {
|
|
105
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
106
|
+
const logDir = path.join(process.cwd(), "@karinjs", "logs");
|
|
107
|
+
const logFile = path.join(logDir, `logger.${today}.log`);
|
|
108
|
+
try {
|
|
109
|
+
if (!fs.existsSync(logFile)) {
|
|
110
|
+
const files = fs.readdirSync(logDir).filter((f) => f.startsWith("logger.") && f.endsWith(".log") && !f.includes("error")).sort().reverse();
|
|
111
|
+
if (files.length === 0) {
|
|
112
|
+
return ["\u6682\u65E0\u65E5\u5FD7\u8BB0\u5F55"];
|
|
113
|
+
}
|
|
114
|
+
const latestLog = path.join(logDir, files[0]);
|
|
115
|
+
const content2 = fs.readFileSync(latestLog, "utf-8");
|
|
116
|
+
const lines2 = content2.split("\n").filter((line) => line.trim());
|
|
117
|
+
const groups2 = groupLogLines(lines2);
|
|
118
|
+
return groups2.slice(-limit).reverse();
|
|
119
|
+
}
|
|
120
|
+
const content = fs.readFileSync(logFile, "utf-8");
|
|
121
|
+
const lines = content.split("\n").filter((line) => line.trim());
|
|
122
|
+
const groups = groupLogLines(lines);
|
|
123
|
+
return groups.slice(-limit).reverse();
|
|
124
|
+
} catch (error) {
|
|
125
|
+
logger.error("\u8BFB\u53D6\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:", error);
|
|
126
|
+
return ["\u8BFB\u53D6\u65E5\u5FD7\u5931\u8D25"];
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
var getErrorLogs = async (limit = 50) => {
|
|
130
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
131
|
+
const errorDir = path.join(process.cwd(), "@karinjs", "logs", "error");
|
|
132
|
+
if (!fs.existsSync(errorDir)) {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
let logFile = null;
|
|
136
|
+
try {
|
|
137
|
+
const todayLoggerError = path.join(errorDir, `logger.error.${today}.log`);
|
|
138
|
+
const todayError = path.join(errorDir, `error.${today}.log`);
|
|
139
|
+
if (fs.existsSync(todayLoggerError)) {
|
|
140
|
+
logFile = todayLoggerError;
|
|
141
|
+
} else if (fs.existsSync(todayError)) {
|
|
142
|
+
logFile = todayError;
|
|
143
|
+
} else {
|
|
144
|
+
const files = fs.readdirSync(errorDir).filter((f) => f.endsWith(".log")).sort().reverse();
|
|
145
|
+
if (files.length) {
|
|
146
|
+
logFile = path.join(errorDir, files[0]);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (!logFile) return [];
|
|
150
|
+
const content = fs.readFileSync(logFile, "utf-8");
|
|
151
|
+
const lines = content.split("\n").filter((line) => line.trim());
|
|
152
|
+
const groups = groupLogLines(lines);
|
|
153
|
+
return groups.slice(-limit).reverse();
|
|
154
|
+
} catch (error) {
|
|
155
|
+
logger.error("\u8BFB\u53D6\u9519\u8BEF\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:", error);
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
var parseLogLine = (line) => {
|
|
160
|
+
const [firstLine, ...rest] = line.split("\n");
|
|
161
|
+
let time = "";
|
|
162
|
+
let levelRaw = "INFO";
|
|
163
|
+
const timeMatch = firstLine.match(/^\[(\d{2}:\d{2}:\d{2}\.\d{3})]/);
|
|
164
|
+
const levelMatch = firstLine.match(/\[([A-Z]+)]/);
|
|
165
|
+
if (timeMatch) time = timeMatch[1];
|
|
166
|
+
if (levelMatch) levelRaw = levelMatch[1];
|
|
167
|
+
const levelKey = levelRaw.toLowerCase();
|
|
168
|
+
const level = levelKey === "erro" ? "error" : levelKey;
|
|
169
|
+
const messageHead = firstLine.replace(/^\[\d{2}:\d{2}:\d{2}\.\d{3}]\[[A-Z]+]\s*/, "");
|
|
170
|
+
const messageTail = rest.length ? "\n" + rest.join("\n") : "";
|
|
171
|
+
const fullMessage = trimEmptyLines(`${messageHead}${messageTail}`);
|
|
172
|
+
const plainMessage = fullMessage.replace(/\u001b\[[0-9;]+m/g, "");
|
|
173
|
+
return {
|
|
174
|
+
time,
|
|
175
|
+
level,
|
|
176
|
+
message: plainMessage,
|
|
177
|
+
messageHtml: ansiToHtml(fullMessage)
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
var logViewer = karin.command(/^#日志\s*(\d+)?$/, async (e) => {
|
|
181
|
+
const match = e.msg.match(/^#日志\s*(\d+)?$/);
|
|
182
|
+
let limit = match && match[1] ? Number(match[1]) : 50;
|
|
183
|
+
if (!Number.isFinite(limit) || limit <= 0) limit = 50;
|
|
184
|
+
if (limit > 200) limit = 200;
|
|
185
|
+
const logs = await getTodayLogs(limit);
|
|
186
|
+
const parsedLogs = logs.map(parseLogLine);
|
|
187
|
+
try {
|
|
188
|
+
const img = await render("logger/index", {
|
|
189
|
+
logs: parsedLogs,
|
|
190
|
+
total: parsedLogs.length,
|
|
191
|
+
date: (/* @__PURE__ */ new Date()).toLocaleString("zh-CN")
|
|
192
|
+
});
|
|
193
|
+
await e.reply(img);
|
|
194
|
+
return true;
|
|
195
|
+
} catch (error) {
|
|
196
|
+
logger.error("\u6E32\u67D3\u65E5\u5FD7\u5931\u8D25:", error);
|
|
197
|
+
await e.reply("\u65E5\u5FD7\u6E32\u67D3\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u63A7\u5236\u53F0\u9519\u8BEF\u4FE1\u606F");
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
}, { name: "\u65E5\u5FD7\u67E5\u770B\u5668", perm: "admin" });
|
|
201
|
+
var errorLogViewer = karin.command(/^#错误日志\s*(\d+)?$/, async (e) => {
|
|
202
|
+
const match = e.msg.match(/^#错误日志\s*(\d+)?$/);
|
|
203
|
+
let limit = match && match[1] ? Number(match[1]) : 50;
|
|
204
|
+
if (!Number.isFinite(limit) || limit <= 0) limit = 50;
|
|
205
|
+
if (limit > 200) limit = 200;
|
|
206
|
+
const logs = await getErrorLogs(limit);
|
|
207
|
+
if (!logs.length) {
|
|
208
|
+
await e.reply("\u6682\u65E0\u9519\u8BEF\u65E5\u5FD7");
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
const parsedLogs = logs.map(parseLogLine);
|
|
212
|
+
try {
|
|
213
|
+
const img = await render("logger/index", {
|
|
214
|
+
logs: parsedLogs,
|
|
215
|
+
total: parsedLogs.length,
|
|
216
|
+
date: (/* @__PURE__ */ new Date()).toLocaleString("zh-CN")
|
|
217
|
+
});
|
|
218
|
+
await e.reply(img);
|
|
219
|
+
return true;
|
|
220
|
+
} catch (error) {
|
|
221
|
+
logger.error("\u6E32\u67D3\u9519\u8BEF\u65E5\u5FD7\u5931\u8D25:", error);
|
|
222
|
+
await e.reply("\u9519\u8BEF\u65E5\u5FD7\u6E32\u67D3\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u63A7\u5236\u53F0\u9519\u8BEF\u4FE1\u606F");
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}, { name: "\u9519\u8BEF\u65E5\u5FD7\u67E5\u770B\u5668", perm: "admin" });
|
|
226
|
+
export {
|
|
227
|
+
errorLogViewer,
|
|
228
|
+
logViewer
|
|
229
|
+
};
|
package/dist/apps/login.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "../chunk-
|
|
2
|
+
cfg
|
|
3
|
+
} from "../chunk-7LNXK3JJ.js";
|
|
4
|
+
import "../chunk-W3Q26Z2E.js";
|
|
4
5
|
|
|
5
6
|
// src/apps/login.ts
|
|
6
7
|
import karin, { common, contactFriend, logger, segment } from "node-karin";
|
|
@@ -9,7 +10,7 @@ import os from "os";
|
|
|
9
10
|
var url = { IPv4: ["https://4.ipw.cn"], IPv6: ["https://6.ipw.cn"] };
|
|
10
11
|
var login = karin.command(/#?(面板|web)登录$/i, async (e) => {
|
|
11
12
|
const net = os.networkInterfaces();
|
|
12
|
-
const
|
|
13
|
+
const config = cfg.get();
|
|
13
14
|
const IP = { lan: { ipv4: null, ipv6: null }, net: { ipv4: null, ipv6: null } };
|
|
14
15
|
for (const i in net) {
|
|
15
16
|
for (const iface of net[i]) {
|
|
@@ -32,7 +33,7 @@ var login = karin.command(/#?(面板|web)登录$/i, async (e) => {
|
|
|
32
33
|
const port = process.env.HTTP_PORT;
|
|
33
34
|
const token = process.env.HTTP_AUTH_KEY;
|
|
34
35
|
const msg = [segment.text("\u9762\u677F\u767B\u5F55\u5730\u5740\uFF1A")];
|
|
35
|
-
if (
|
|
36
|
+
if (config.domain) msg.push(segment.text(`- \u81EA\u5B9A\u4E49\u57DF\u540D: ${config.domain}/web/login?token=${token}`));
|
|
36
37
|
msg.push(segment.text(`- \u5185\u7F51\u5730\u5740: ${IP.lan.ipv4 ? `http://${IP.lan.ipv4}:${port}/web/login?token=${token}` : `http://${IP.lan.ipv4}:${port}/web/login?token=${token}`}`));
|
|
37
38
|
if (IP.net.ipv4) msg.push(segment.text(`- \u5916\u7F51IPv4\u5730\u5740: http://${IP.net.ipv4}:${port}/web/login?token=${token}`));
|
|
38
39
|
if (IP.net.ipv6) msg.push(segment.text(`- \u5916\u7F51IPv6\u5730\u5740: http://${IP.net.ipv6}:${port}/web/login?token=${token}`));
|
package/dist/apps/master.d.ts
CHANGED
|
@@ -3,5 +3,7 @@ import * as node_karin from 'node-karin';
|
|
|
3
3
|
declare const Master: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
4
4
|
declare const addMaster: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
5
5
|
declare const delMaster: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
6
|
+
declare const listMaster: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
7
|
+
declare const setMasterCaptcha: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
6
8
|
|
|
7
|
-
export { Master, addMaster, delMaster };
|
|
9
|
+
export { Master, addMaster, delMaster, listMaster, setMasterCaptcha };
|
package/dist/apps/master.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/apps/master.ts
|
|
2
2
|
import crypto from "crypto";
|
|
3
|
-
import { karin, logger, config } from "node-karin";
|
|
4
|
-
var
|
|
3
|
+
import { karin, logger, config, segment } from "node-karin";
|
|
4
|
+
var CAPTCHA = /* @__PURE__ */ new Map();
|
|
5
|
+
var Master = karin.command(/^#设置主人$/, async (e) => {
|
|
5
6
|
if (e.isMaster) {
|
|
6
7
|
await e.reply(`
|
|
7
8
|
[${e.userId}] \u5DF2\u7ECF\u662F\u4E3B\u4EBA`, { at: true });
|
|
@@ -9,6 +10,7 @@ var Master = karin.command(/^#设置主人/, async (e) => {
|
|
|
9
10
|
}
|
|
10
11
|
const sign = crypto.randomUUID();
|
|
11
12
|
logger.mark(`\u8BBE\u7F6E\u4E3B\u4EBA\u9A8C\u8BC1\u7801\uFF1A${logger.green(sign)}`);
|
|
13
|
+
CAPTCHA.set(e.userId, sign);
|
|
12
14
|
await e.reply("\n\u8BF7\u8F93\u5165\u63A7\u5236\u53F0\u9A8C\u8BC1\u7801", { at: true });
|
|
13
15
|
const event = await karin.ctx(e);
|
|
14
16
|
if (sign !== event.msg.trim()) {
|
|
@@ -62,8 +64,24 @@ var delMaster = karin.command(/^#删除主人/, async (e) => {
|
|
|
62
64
|
\u5220\u9664\u4E3B\u4EBA: ${userId}`, { at: true });
|
|
63
65
|
return true;
|
|
64
66
|
}, { name: "\u5220\u9664\u4E3B\u4EBA", priority: -1, permission: "master" });
|
|
67
|
+
var listMaster = karin.command(/^#主人列表$/, async (e) => {
|
|
68
|
+
const masters = config.master();
|
|
69
|
+
await e.reply(`\u4E3B\u4EBA\u5217\u8868:
|
|
70
|
+
${masters.map((v) => `- ${v}`).join("\n")}`, { reply: true });
|
|
71
|
+
return true;
|
|
72
|
+
}, { name: "\u4E3B\u4EBA\u5217\u8868", priority: -1, permission: "master" });
|
|
73
|
+
var setMasterCaptcha = karin.command(/^#设置主人验证码$/, async (e) => {
|
|
74
|
+
const msg = [];
|
|
75
|
+
CAPTCHA.forEach((v, k) => {
|
|
76
|
+
msg.push(segment.text(`- \u7528\u6237: ${k} \u9A8C\u8BC1\u7801: ${v}`));
|
|
77
|
+
});
|
|
78
|
+
if (msg.length === 0) return e.reply("\u6682\u65E0\u9A8C\u8BC1\u7801", { reply: true });
|
|
79
|
+
await e.reply(["\u4E3B\u4EBA\u9A8C\u8BC1\u7801\u5217\u8868:\n", ...msg], { reply: true });
|
|
80
|
+
}, { name: "\u8BBE\u7F6E\u4E3B\u4EBA\u9A8C\u8BC1\u7801", priority: -1, permission: "master" });
|
|
65
81
|
export {
|
|
66
82
|
Master,
|
|
67
83
|
addMaster,
|
|
68
|
-
delMaster
|
|
84
|
+
delMaster,
|
|
85
|
+
listMaster,
|
|
86
|
+
setMasterCaptcha
|
|
69
87
|
};
|
package/dist/apps/restart.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "../chunk-
|
|
2
|
+
cfg
|
|
3
|
+
} from "../chunk-7LNXK3JJ.js";
|
|
4
|
+
import "../chunk-W3Q26Z2E.js";
|
|
4
5
|
|
|
5
6
|
// src/apps/restart.ts
|
|
6
7
|
import { common, karin, logger, restart } from "node-karin";
|
|
7
8
|
var restarts = karin.command(/^#重启$/, async (e) => {
|
|
8
9
|
try {
|
|
9
10
|
await e.reply(`\u5F00\u59CB\u91CD\u542F \u672C\u6B21\u8FD0\u884C\u65F6\u95F4: ${common.uptime()}`, { at: true });
|
|
10
|
-
const { status, data } = await restart(e.selfId, e.contact, e.messageId,
|
|
11
|
+
const { status, data } = await restart(e.selfId, e.contact, e.messageId, cfg.get().restartMode);
|
|
11
12
|
if (status === "failed") throw data;
|
|
12
13
|
return true;
|
|
13
14
|
} catch (error) {
|
package/dist/apps/status.js
CHANGED
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
uptime
|
|
7
7
|
} from "../chunk-ODFXVVIE.js";
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
cfg
|
|
10
|
+
} from "../chunk-7LNXK3JJ.js";
|
|
11
|
+
import "../chunk-W3Q26Z2E.js";
|
|
12
12
|
|
|
13
13
|
// src/apps/status.ts
|
|
14
|
-
import { karin
|
|
14
|
+
import { karin } from "node-karin";
|
|
15
15
|
var status = karin.command(/^#状态$/, async (e) => {
|
|
16
16
|
const { send, recv, event } = await getTodayStat();
|
|
17
17
|
const { send: sendMonth, recv: recvMonth, event: eventMonth } = await getMonthStat();
|
|
@@ -31,8 +31,7 @@ var status = karin.command(/^#状态$/, async (e) => {
|
|
|
31
31
|
].join("\n"));
|
|
32
32
|
return true;
|
|
33
33
|
}, { name: "\u72B6\u6001\u7EDF\u8BA1" });
|
|
34
|
-
if (
|
|
35
|
-
logger.info(`${logger.violet(`[\u63D2\u4EF6:${info.version}]`)} ${logger.green(info.pkg.name)} \u521D\u59CB\u5316\u5B8C\u6210~`);
|
|
34
|
+
if (cfg.get().status) initStat();
|
|
36
35
|
export {
|
|
37
36
|
status
|
|
38
37
|
};
|
package/dist/apps/update.d.ts
CHANGED
|
@@ -2,13 +2,12 @@ import * as node_karin from 'node-karin';
|
|
|
2
2
|
|
|
3
3
|
/** 插件列表 */
|
|
4
4
|
declare const plugins: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
5
|
+
/** 更新插件 */
|
|
6
|
+
declare const updatePlugin: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
5
7
|
/** 检查更新 */
|
|
6
8
|
declare const check: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
7
|
-
/** 更新插件 */
|
|
8
|
-
declare const update: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
9
9
|
/** 更新日志 */
|
|
10
10
|
declare const log: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
11
|
-
|
|
12
|
-
declare const updateAll: node_karin.Command<keyof node_karin.MessageEventMap>;
|
|
11
|
+
declare const TaskUpdate: node_karin.Task;
|
|
13
12
|
|
|
14
|
-
export { check, log, plugins,
|
|
13
|
+
export { TaskUpdate, check, log, plugins, updatePlugin };
|
package/dist/apps/update.js
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cfg,
|
|
3
|
+
sendToFirstAdmin
|
|
4
|
+
} from "../chunk-7LNXK3JJ.js";
|
|
5
|
+
import {
|
|
6
|
+
render
|
|
7
|
+
} from "../chunk-W3Q26Z2E.js";
|
|
8
|
+
|
|
1
9
|
// src/apps/update.ts
|
|
2
10
|
import fs from "fs";
|
|
3
11
|
import path from "path";
|
|
4
|
-
import { changelog, checkGitPluginUpdate, checkPkgUpdate, getCommit, getPlugins, getPkgVersion, karin, updateAllGitPlugin, updateAllPkg, updateGitPlugin, updatePkg } from "node-karin";
|
|
12
|
+
import { changelog, checkGitPluginUpdate, checkPkgUpdate, getCommit, getPlugins, getPkgVersion, karin, updateAllGitPlugin, updateAllPkg, updateGitPlugin, updatePkg, segment, restartDirect, db, logger, getPluginInfo } from "node-karin";
|
|
13
|
+
var NODE_KARIN_UPDATE_KEY = "basic:update:node-karin";
|
|
5
14
|
var cache = [];
|
|
6
15
|
var getAll = async () => {
|
|
7
16
|
if (cache.length) return cache;
|
|
@@ -19,19 +28,119 @@ var getAll = async () => {
|
|
|
19
28
|
return list;
|
|
20
29
|
};
|
|
21
30
|
var plugins = karin.command(/^#插件列表$/, async (e) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
try {
|
|
32
|
+
const allPlugins = await getPlugins("all", true);
|
|
33
|
+
const pluginsData = [];
|
|
34
|
+
let index = 1;
|
|
35
|
+
for (const plugin of allPlugins) {
|
|
36
|
+
if (plugin.type === "app") {
|
|
37
|
+
const apps = plugin.apps || [];
|
|
38
|
+
for (const appPath of apps) {
|
|
39
|
+
const fileName = path.basename(appPath, path.extname(appPath));
|
|
40
|
+
pluginsData.push({
|
|
41
|
+
index: index++,
|
|
42
|
+
name: fileName,
|
|
43
|
+
type: "app",
|
|
44
|
+
typeIcon: "\u{1F50C}",
|
|
45
|
+
version: "",
|
|
46
|
+
description: "",
|
|
47
|
+
author: "\u672A\u77E5",
|
|
48
|
+
dir: appPath
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
const pkgData = plugin.pkgData || {};
|
|
53
|
+
let author = "\u672A\u77E5";
|
|
54
|
+
if (typeof pkgData.author === "string") {
|
|
55
|
+
author = pkgData.author;
|
|
56
|
+
} else if (pkgData.author && typeof pkgData.author === "object" && "name" in pkgData.author) {
|
|
57
|
+
author = pkgData.author.name || "\u672A\u77E5";
|
|
58
|
+
}
|
|
59
|
+
const description = pkgData.description || "";
|
|
60
|
+
const version = pkgData.version || "";
|
|
61
|
+
const typeIcon = plugin.type === "npm" ? "\u{1F4E6}" : "\u{1F527}";
|
|
62
|
+
pluginsData.push({
|
|
63
|
+
index: index++,
|
|
64
|
+
name: plugin.name,
|
|
65
|
+
type: plugin.type,
|
|
66
|
+
typeIcon,
|
|
67
|
+
version,
|
|
68
|
+
description,
|
|
69
|
+
author,
|
|
70
|
+
dir: plugin.dir
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (pluginsData.length === 0) {
|
|
75
|
+
await e.reply("\n\u6682\u65E0\u63D2\u4EF6", { at: true });
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
const img = await render("plugins/index", {
|
|
79
|
+
plugins: pluginsData,
|
|
80
|
+
total: pluginsData.length,
|
|
81
|
+
date: (/* @__PURE__ */ new Date()).toLocaleString("zh-CN")
|
|
82
|
+
});
|
|
83
|
+
await e.reply(img);
|
|
84
|
+
return true;
|
|
85
|
+
} catch (error) {
|
|
86
|
+
logger.error("\u6E32\u67D3\u63D2\u4EF6\u5217\u8868\u5931\u8D25:", error);
|
|
87
|
+
try {
|
|
88
|
+
const list = await getAll();
|
|
89
|
+
const textList = list.map((item, index) => `${index + 1}. ${item}`);
|
|
90
|
+
await e.reply([
|
|
91
|
+
"\n\u63D2\u4EF6\u5217\u8868\uFF1A",
|
|
92
|
+
"\u66F4\u65B0\uFF1A#\u66F4\u65B0\u63D2\u4EF6 \u540D\u79F0",
|
|
93
|
+
"\u68C0\u67E5\u66F4\u65B0\uFF1A#\u68C0\u67E5\u66F4\u65B0 \u5E8F\u53F7\u6216\u540D\u79F0",
|
|
94
|
+
"\u65E5\u5FD7\uFF1A#\u66F4\u65B0\u65E5\u5FD7 \u6761\u6570 \u5E8F\u53F7\u6216\u540D\u79F0",
|
|
95
|
+
...textList
|
|
96
|
+
].join("\n"), { at: true });
|
|
97
|
+
} catch (fallbackError) {
|
|
98
|
+
logger.error("\u53D1\u9001\u6587\u672C\u63D2\u4EF6\u5217\u8868\u5931\u8D25:", fallbackError);
|
|
99
|
+
await e.reply("\n\u83B7\u53D6\u63D2\u4EF6\u5217\u8868\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u65E5\u5FD7", { at: true });
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
34
103
|
}, { name: "\u63D2\u4EF6\u5217\u8868", perm: "admin" });
|
|
104
|
+
var updatePlugin = karin.command(/^#(全部)?(强制)?更新(.*)?$/, async (e) => {
|
|
105
|
+
const [, all, force, name = "node-karin"] = e.msg.match(/^#(全部)?(强制)?更新(.*)?$/);
|
|
106
|
+
const cmd = force ? "git reset --hard && git pull --allow-unrelated-histories" : "git pull";
|
|
107
|
+
if (all) {
|
|
108
|
+
try {
|
|
109
|
+
const git = await updateAllGitPlugin(cmd);
|
|
110
|
+
const npm = await updateAllPkg();
|
|
111
|
+
await e.reply([
|
|
112
|
+
"\n\u5168\u90E8\u66F4\u65B0\u5B8C\u6210",
|
|
113
|
+
"-----",
|
|
114
|
+
git,
|
|
115
|
+
"-----",
|
|
116
|
+
npm
|
|
117
|
+
].join("\n"), { at: true });
|
|
118
|
+
} catch (error) {
|
|
119
|
+
await e.reply(`
|
|
120
|
+
\u66F4\u65B0\u5168\u90E8\u63D2\u4EF6\u5931\u8D25: ${error.message || "\u672A\u77E5\u9519\u8BEF"}`, { at: true });
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
let res;
|
|
124
|
+
if (name !== "node-karin") {
|
|
125
|
+
const info = getPluginInfo(name.trim());
|
|
126
|
+
if (!info) return await e.reply("\u63D2\u4EF6\u672A\u5B89\u88C5~", { reply: true });
|
|
127
|
+
if (info.type === "app") return await e.reply("\u5E94\u7528\u63D2\u4EF6\u4E0D\u652F\u6301\u66F4\u65B0~", { reply: true });
|
|
128
|
+
res = info.type === "git" ? await updateGitPlugin(info.dir, cmd, 120) : await updatePkg(info.name);
|
|
129
|
+
} else {
|
|
130
|
+
res = await updatePkg("node-karin");
|
|
131
|
+
}
|
|
132
|
+
if (res.status === "failed") {
|
|
133
|
+
const { data } = res;
|
|
134
|
+
const msg = typeof data === "string" ? data : `\u83B7\u53D6\u66F4\u65B0\u4FE1\u606F\u5931\u8D25: ${data.message || "\u672A\u77E5\u9519\u8BEF"}`;
|
|
135
|
+
await e.reply(`
|
|
136
|
+
${msg}`, { at: true });
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
return await e.reply(`
|
|
140
|
+
\u66F4\u65B0\u6210\u529F
|
|
141
|
+
${res.data}`, { at: true });
|
|
142
|
+
}
|
|
143
|
+
});
|
|
35
144
|
var check = karin.command(/^#检查更新/, async (e) => {
|
|
36
145
|
let name = e.msg.replace(/^#检查更新/, "").trim();
|
|
37
146
|
const index = Number(name);
|
|
@@ -94,54 +203,6 @@ ${tips}`, { at: true });
|
|
|
94
203
|
await e.reply("\n\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u63D2\u4EF6\u540D\u79F0\u6216\u5E8F\u53F7~", { at: true });
|
|
95
204
|
return true;
|
|
96
205
|
}, { name: "\u68C0\u67E5\u66F4\u65B0", perm: "admin" });
|
|
97
|
-
var update = karin.command(/^#(强制)?更新(插件)?(?!列表|日志)/, async (e) => {
|
|
98
|
-
let name = e.msg.replace(/^#(强制)?更新(插件)?(?!列表|日志)/, "").trim();
|
|
99
|
-
const index = Number(name);
|
|
100
|
-
if (index && typeof index === "number") {
|
|
101
|
-
const list = await getAll();
|
|
102
|
-
name = list[index - 1];
|
|
103
|
-
}
|
|
104
|
-
if (!name) {
|
|
105
|
-
await e.reply("\n\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u63D2\u4EF6\u540D\u79F0\u6216\u5E8F\u53F7~", { at: true });
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
if (name.includes("git:")) {
|
|
109
|
-
name = name.replace("git:", "");
|
|
110
|
-
const file = path.join(process.cwd(), "plugins", name.replace("git:", ""));
|
|
111
|
-
let cmd = "git pull";
|
|
112
|
-
if (e.msg.includes("\u5F3A\u5236")) cmd = "git reset --hard && git pull --allow-unrelated-histories";
|
|
113
|
-
const result = await updateGitPlugin(file, cmd, 120);
|
|
114
|
-
if (result.status === "failed") {
|
|
115
|
-
const { data } = result;
|
|
116
|
-
const msg = typeof data === "string" ? data : `\u83B7\u53D6\u66F4\u65B0\u4FE1\u606F\u5931\u8D25: ${data.message || "\u672A\u77E5\u9519\u8BEF"}`;
|
|
117
|
-
await e.reply(msg, { at: true });
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
await e.reply(`
|
|
121
|
-
${result.data}`, { at: true });
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
if (name.includes("npm:")) {
|
|
125
|
-
name = name.replace("npm:", "");
|
|
126
|
-
const result = await updatePkg(name);
|
|
127
|
-
if (result.status === "failed") {
|
|
128
|
-
const { data } = result;
|
|
129
|
-
const msg = typeof data === "string" ? data : `\u83B7\u53D6\u66F4\u65B0\u4FE1\u606F\u5931\u8D25: ${data.message || "\u672A\u77E5\u9519\u8BEF"}`;
|
|
130
|
-
await e.reply(`
|
|
131
|
-
${msg}`, { at: true });
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
const log2 = parseLog(name, result.local, result.remote);
|
|
135
|
-
await e.reply(`
|
|
136
|
-
\u66F4\u65B0\u6210\u529F
|
|
137
|
-
\u5F53\u524D\u7248\u672C: ${result.remote}
|
|
138
|
-
\u66F4\u65B0\u65E5\u5FD7:
|
|
139
|
-
${log2}`, { at: true });
|
|
140
|
-
return true;
|
|
141
|
-
}
|
|
142
|
-
await e.reply("\n\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u63D2\u4EF6\u540D\u79F0\u6216\u5E8F\u53F7~", { at: true });
|
|
143
|
-
return true;
|
|
144
|
-
}, { name: "\u66F4\u65B0\u63D2\u4EF6", perm: "admin" });
|
|
145
206
|
var log = karin.command(/^#更新日志/, async (e) => {
|
|
146
207
|
const [index, num] = e.msg.replace(/^#更新日志/, "").trim().split(" ");
|
|
147
208
|
if (!index || !num) {
|
|
@@ -181,24 +242,6 @@ ${result}`, { at: true });
|
|
|
181
242
|
await e.reply("\n\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u63D2\u4EF6\u540D\u79F0\u6216\u5E8F\u53F7~", { at: true });
|
|
182
243
|
return true;
|
|
183
244
|
}, { name: "\u66F4\u65B0\u65E5\u5FD7", perm: "admin" });
|
|
184
|
-
var updateAll = karin.command(/^#全部(强制)?更新$/, async (e) => {
|
|
185
|
-
const cmd = e.msg.includes("\u5F3A\u5236") ? "git reset --hard && git pull --allow-unrelated-histories" : "git pull";
|
|
186
|
-
try {
|
|
187
|
-
const git = await updateAllGitPlugin(cmd);
|
|
188
|
-
const npm = await updateAllPkg();
|
|
189
|
-
await e.reply([
|
|
190
|
-
"\n\u5168\u90E8\u66F4\u65B0\u5B8C\u6210",
|
|
191
|
-
"-----",
|
|
192
|
-
git,
|
|
193
|
-
"-----",
|
|
194
|
-
npm
|
|
195
|
-
].join("\n"), { at: true });
|
|
196
|
-
} catch (error) {
|
|
197
|
-
await e.reply(`
|
|
198
|
-
\u5168\u90E8\u66F4\u65B0\u5931\u8D25: ${error.message || "\u672A\u77E5\u9519\u8BEF"}`, { at: true });
|
|
199
|
-
}
|
|
200
|
-
return true;
|
|
201
|
-
}, { name: "\u5168\u90E8\u66F4\u65B0", perm: "admin" });
|
|
202
245
|
var parseLog = (pkg, local, count) => {
|
|
203
246
|
const file = path.join(process.cwd(), "node_modules", pkg, "CHANGELOG.md");
|
|
204
247
|
if (!fs.existsSync(file)) return "\u63D2\u4EF6\u672A\u63D0\u4F9B`CHANGELOG.md`\u6587\u4EF6";
|
|
@@ -208,10 +251,51 @@ var parseLog = (pkg, local, count) => {
|
|
|
208
251
|
}
|
|
209
252
|
return changelog.range(data, local, count) || "\u672A\u627E\u5230\u5BF9\u5E94\u7684\u66F4\u65B0\u65E5\u5FD7";
|
|
210
253
|
};
|
|
254
|
+
var TaskUpdate = karin.task("Karin-\u5B9A\u65F6\u66F4\u65B0\u68C0\u67E5", "*/10 * * * *", async () => {
|
|
255
|
+
if (process.env.NODE_ENV === "development") return true;
|
|
256
|
+
const res = await checkPkgUpdate("node-karin");
|
|
257
|
+
if (res.status !== "yes") return true;
|
|
258
|
+
const botIds = karin.getAllBotID();
|
|
259
|
+
const selfId = botIds.find((id) => id.toString() !== "console");
|
|
260
|
+
if (!selfId) return true;
|
|
261
|
+
const config = cfg.get();
|
|
262
|
+
if (config.autoupdate) {
|
|
263
|
+
const up = await updatePkg("node-karin");
|
|
264
|
+
if (up.status === "failed") {
|
|
265
|
+
await sendToFirstAdmin(selfId, [segment.text(`\u81EA\u52A8\u66F4\u65B0 node-karin \u5931\u8D25: ${String(up.data)}`)]);
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
await sendToFirstAdmin(selfId, [
|
|
269
|
+
segment.text(
|
|
270
|
+
`\u68C0\u6D4B\u5230\u63D2\u4EF6 [node-karin] \u6709\u65B0\u7248\u672C~
|
|
271
|
+
\u5DF2\u81EA\u52A8\u66F4\u65B0 (v${up.local} \u2192 v${up.remote})\uFF0C\u5373\u5C06\u91CD\u542F\u4EE5\u5E94\u7528\u66F4\u65B0`
|
|
272
|
+
)
|
|
273
|
+
]);
|
|
274
|
+
await restartDirect({ isPm2: false, reloadDeps: true });
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
const last = await db.get(NODE_KARIN_UPDATE_KEY);
|
|
278
|
+
if (last && last.lastRemote === res.remote) return true;
|
|
279
|
+
const msg = [
|
|
280
|
+
segment.text(
|
|
281
|
+
`\u68C0\u6D4B\u5230\u63D2\u4EF6 [node-karin] \u6709\u65B0\u7248\u672C~
|
|
282
|
+
\u5F53\u524D\u7248\u672C: v${res.local}
|
|
283
|
+
\u6700\u65B0\u7248\u672C: v${res.remote}
|
|
284
|
+
\u8BF7\u53D1\u9001 #\u66F4\u65B0 \u8FDB\u884C\u66F4\u65B0\u3002`
|
|
285
|
+
)
|
|
286
|
+
];
|
|
287
|
+
const messageId = await sendToFirstAdmin(selfId, msg);
|
|
288
|
+
if (!messageId) return false;
|
|
289
|
+
await db.set(NODE_KARIN_UPDATE_KEY, {
|
|
290
|
+
lastRemote: res.remote,
|
|
291
|
+
lastLocal: res.local
|
|
292
|
+
});
|
|
293
|
+
return true;
|
|
294
|
+
}, { name: "Karin-\u5B9A\u65F6\u66F4\u65B0\u68C0\u67E5", log: false });
|
|
211
295
|
export {
|
|
296
|
+
TaskUpdate,
|
|
212
297
|
check,
|
|
213
298
|
log,
|
|
214
299
|
plugins,
|
|
215
|
-
|
|
216
|
-
updateAll
|
|
300
|
+
updatePlugin
|
|
217
301
|
};
|