mioku-plugin-help 3.0.2 → 3.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/help/role.ts +2 -2
- package/index.ts +20 -3
- package/package.json +1 -13
- package/status/data-collector.ts +59 -36
- package/status/html-generator.ts +2 -8
- package/status/types.ts +2 -0
package/help/role.ts
CHANGED
|
@@ -33,7 +33,7 @@ export function canInvokeCommand(
|
|
|
33
33
|
* Resolve the requesting user's effective role for help filtering.
|
|
34
34
|
*
|
|
35
35
|
* - `master` is honored everywhere (private or group) — it comes from
|
|
36
|
-
* mioki's `
|
|
36
|
+
* mioki's `isMaster` allowlist (the bot `owners` list).
|
|
37
37
|
* - Private chat skips the `isAdmin` check and defaults to `admin`,
|
|
38
38
|
* so anyone DM-ing the bot can see admin-level commands.
|
|
39
39
|
* - Group chat resolves bot admin (mioki `isAdmin` allowlist), group
|
|
@@ -49,7 +49,7 @@ export async function resolveViewerRole(
|
|
|
49
49
|
ctx: any,
|
|
50
50
|
event: any,
|
|
51
51
|
): Promise<CommandRole> {
|
|
52
|
-
if (ctx?.
|
|
52
|
+
if (ctx?.isMaster?.(event)) {
|
|
53
53
|
return "master";
|
|
54
54
|
}
|
|
55
55
|
|
package/index.ts
CHANGED
|
@@ -21,8 +21,6 @@ import { createHelpSkills } from "./skills";
|
|
|
21
21
|
|
|
22
22
|
const helpPlugin = definePlugin({
|
|
23
23
|
name: "help",
|
|
24
|
-
version: "2.1.0",
|
|
25
|
-
description: "帮助插件,生成帮助图片,并提供 #状态 指令",
|
|
26
24
|
|
|
27
25
|
async setup(ctx: MiokuContext) {
|
|
28
26
|
// 启动后台采样器
|
|
@@ -75,7 +73,7 @@ const helpPlugin = definePlugin({
|
|
|
75
73
|
for (const skill of createHelpSkills()) aiService.registerSkill(skill);
|
|
76
74
|
}
|
|
77
75
|
|
|
78
|
-
|
|
76
|
+
const handleHelpMessage = async (event: import("mioku").MessageEvent) => {
|
|
79
77
|
const text = ctx.text(event);
|
|
80
78
|
if (!text) {
|
|
81
79
|
return;
|
|
@@ -155,6 +153,25 @@ const helpPlugin = definePlugin({
|
|
|
155
153
|
ctx.logger.error(`生成帮助图片失败: ${error}`);
|
|
156
154
|
await event.reply(`生成帮助图片失败: ${error}`);
|
|
157
155
|
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
ctx.command({
|
|
159
|
+
id: "帮助菜单",
|
|
160
|
+
name: "help",
|
|
161
|
+
aliases: ["帮助", "菜单"],
|
|
162
|
+
match: /^(?:help|帮助|菜单)(?:\s|$)/i,
|
|
163
|
+
prefixes: ["#", "/", ""],
|
|
164
|
+
description: "生成帮助图片",
|
|
165
|
+
handler: ({ event }) => handleHelpMessage(event),
|
|
166
|
+
});
|
|
167
|
+
ctx.command({
|
|
168
|
+
id: "status",
|
|
169
|
+
name: "status",
|
|
170
|
+
aliases: ["状态", "zt"],
|
|
171
|
+
match: /^(?:status|状态|zt)(?:\s|$)/i,
|
|
172
|
+
prefixes: ["#", "/", ""],
|
|
173
|
+
description: "生成系统状态图片",
|
|
174
|
+
handler: ({ event }) => handleHelpMessage(event),
|
|
158
175
|
});
|
|
159
176
|
|
|
160
177
|
return () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mioku-plugin-help",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"description": "帮助插件,使用截图服务生成美观的帮助图片,并提供 #状态 指令",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -17,18 +17,6 @@
|
|
|
17
17
|
"screenshot",
|
|
18
18
|
"config",
|
|
19
19
|
"ai"
|
|
20
|
-
],
|
|
21
|
-
"accessHooks": [
|
|
22
|
-
{
|
|
23
|
-
"id": "帮助菜单",
|
|
24
|
-
"match": "/(?:[#/]\\s*(?:帮助|菜单|help)|^(?:帮助|菜单|help)(?:\\s|$))/",
|
|
25
|
-
"description": "匹配 #help / 帮助 / 菜单 等帮助指令"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"id": "状态",
|
|
29
|
-
"match": "/(?:[#/]\\s*(?:状态|zt|status)|^(?:状态|zt|status)(?:\\s|$))/",
|
|
30
|
-
"description": "匹配 #状态 / 状态 / zt / status 等系统状态指令"
|
|
31
|
-
}
|
|
32
20
|
]
|
|
33
21
|
},
|
|
34
22
|
"peerDependencies": {
|
package/status/data-collector.ts
CHANGED
|
@@ -200,8 +200,7 @@ async function collectBots(
|
|
|
200
200
|
}
|
|
201
201
|
// stdin 适配器恒排第一位(终端是本机主人通道,优先展示)
|
|
202
202
|
const sorted = [...bots].sort(
|
|
203
|
-
(a, b) =>
|
|
204
|
-
Number(b.adapter === "stdin") - Number(a.adapter === "stdin"),
|
|
203
|
+
(a, b) => Number(b.adapter === "stdin") - Number(a.adapter === "stdin"),
|
|
205
204
|
);
|
|
206
205
|
return collectBotStatuses(sorted, ctx, stdinAvatar);
|
|
207
206
|
}
|
|
@@ -226,11 +225,14 @@ async function collectBotStatuses(
|
|
|
226
225
|
version: adapter.version,
|
|
227
226
|
impl: adapter.impl,
|
|
228
227
|
}));
|
|
229
|
-
const report = await withTimeout(
|
|
230
|
-
(
|
|
231
|
-
);
|
|
228
|
+
const report = await withTimeout(
|
|
229
|
+
buildAdapterReport({ bots, adapters }),
|
|
230
|
+
).catch(() => null);
|
|
232
231
|
const instances = new Map<string, AdapterInstanceStatus>();
|
|
233
|
-
const implOf = new Map<
|
|
232
|
+
const implOf = new Map<
|
|
233
|
+
string,
|
|
234
|
+
{ name: string; version?: string } | undefined
|
|
235
|
+
>();
|
|
234
236
|
for (const entry of report?.adapters ?? []) {
|
|
235
237
|
implOf.set(entry.name, entry.impl);
|
|
236
238
|
for (const instance of entry.instances) {
|
|
@@ -238,37 +240,58 @@ async function collectBotStatuses(
|
|
|
238
240
|
}
|
|
239
241
|
}
|
|
240
242
|
|
|
241
|
-
return
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
243
|
+
return Promise.all(
|
|
244
|
+
bots.map(async (bot) => {
|
|
245
|
+
const uin = String(bot.bot_id);
|
|
246
|
+
const adapter = String(bot.adapter);
|
|
247
|
+
const isStdin = adapter === "stdin";
|
|
248
|
+
const instance = instances.get(`${adapter}:${uin}`);
|
|
249
|
+
const lib = implOf.get(adapter);
|
|
250
|
+
const framework = instance?.impl || lib?.name || adapter;
|
|
251
|
+
const appVersion = instance?.version || lib?.version || "";
|
|
252
|
+
const avatarFromBot =
|
|
253
|
+
typeof bot.getAvatar === "function"
|
|
254
|
+
? await bot.getAvatar().catch(() => null)
|
|
255
|
+
: null;
|
|
256
|
+
// 协议端版本文案:平台自报的用 impl/version(如 LLOneBot/7.12.4),
|
|
257
|
+
// 平台不自报的退回适配器元数据(如 ICQQ v1.12.3),与 .status 的展示约定一致
|
|
258
|
+
const implLabel = isStdin
|
|
259
|
+
? "stdin"
|
|
260
|
+
: instance?.impl
|
|
261
|
+
? instance.version
|
|
262
|
+
? `${instance.impl}/${instance.version}`
|
|
263
|
+
: String(instance.impl)
|
|
264
|
+
: lib?.name
|
|
265
|
+
? lib.version
|
|
266
|
+
? `${lib.name} v${lib.version}`
|
|
267
|
+
: lib.name
|
|
268
|
+
: "";
|
|
250
269
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
:
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
return {
|
|
271
|
+
uin,
|
|
272
|
+
nickname: String(bot.nickname || "Unknown Bot"),
|
|
273
|
+
avatarUrl: isStdin
|
|
274
|
+
? toImageSrc(stdinAvatar || "")
|
|
275
|
+
: avatarFromBot
|
|
276
|
+
? toImageSrc(avatarFromBot)
|
|
277
|
+
: `https://q1.qlogo.cn/g?b=qq&nk=${uin}&s=160`,
|
|
278
|
+
adapter,
|
|
279
|
+
implLabel,
|
|
280
|
+
framework: isStdin ? adapter : framework,
|
|
281
|
+
appVersion: isStdin
|
|
282
|
+
? String(ctx.getAdapter(adapter)?.version ?? "")
|
|
283
|
+
: appVersion,
|
|
284
|
+
protocolVersion: instance?.protocol ?? "",
|
|
285
|
+
platform: instance?.platform ?? "",
|
|
286
|
+
platformVersion: instance?.platformVersion ?? "",
|
|
287
|
+
online: bot.online,
|
|
288
|
+
groupCount: instance?.stats.groups ?? 0,
|
|
289
|
+
friendCount: instance?.stats.friends ?? 0,
|
|
290
|
+
send: instance?.stats.sent ?? 0,
|
|
291
|
+
receive: instance?.stats.received ?? 0,
|
|
292
|
+
};
|
|
293
|
+
}),
|
|
294
|
+
);
|
|
272
295
|
}
|
|
273
296
|
|
|
274
297
|
async function collectFramework(
|
package/status/html-generator.ts
CHANGED
|
@@ -140,13 +140,7 @@ function renderHero(
|
|
|
140
140
|
.map((bot) => {
|
|
141
141
|
const statusText = bot.online ? "在线" : "离线";
|
|
142
142
|
const statusColor = bot.online ? "#10b981" : "#ef4444";
|
|
143
|
-
const
|
|
144
|
-
const implText =
|
|
145
|
-
bot.adapter === "stdin"
|
|
146
|
-
? `${adapterLabel}@${bot.appVersion}`
|
|
147
|
-
: bot.appVersion
|
|
148
|
-
? `${bot.framework} ${bot.appVersion}${bot.protocolVersion ? ` · 协议 ${bot.protocolVersion}` : ""}`
|
|
149
|
-
: bot.framework;
|
|
143
|
+
const implText = bot.implLabel;
|
|
150
144
|
const platformText = bot.platform
|
|
151
145
|
? `${bot.platform}${bot.platformVersion ? ` v${bot.platformVersion}` : ""}`
|
|
152
146
|
: "";
|
|
@@ -159,7 +153,7 @@ function renderHero(
|
|
|
159
153
|
{ text: `群聊 ${fmtNumber(bot.groupCount)}`, kind: "data" },
|
|
160
154
|
{ text: `收 ${fmtNumber(bot.receive)}`, kind: "data" },
|
|
161
155
|
{ text: `发 ${fmtNumber(bot.send)}`, kind: "data" },
|
|
162
|
-
{ text: implText, kind: "data" },
|
|
156
|
+
...(implText ? [{ text: implText, kind: "data" }] : []),
|
|
163
157
|
...(platformText ? [{ text: platformText, kind: "data" }] : []),
|
|
164
158
|
];
|
|
165
159
|
const tagsHtml = tags
|
package/status/types.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface BotAccountStatus {
|
|
|
13
13
|
avatarUrl: string;
|
|
14
14
|
/** 适配器名,如 "stdin" / "onebotv11" / "icqq"。 */
|
|
15
15
|
adapter: string;
|
|
16
|
+
/** 协议端与版本的可展示文案,如 "ICQQ v1.12.3" / "LLOneBot/7.12.4",取不到时为空串 */
|
|
17
|
+
implLabel: string;
|
|
16
18
|
/** 实现端名称,如 "NapCat" / "LLOneBot" / "ICQQ",取不到时为空串 */
|
|
17
19
|
framework: string;
|
|
18
20
|
/** 实现端版本,如 "5.0.6"*/
|