koishi-plugin-onebot-group-manage 0.0.6 → 0.0.8
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.js +57 -46
- package/lib/tools.d.ts +3 -3
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -31,11 +31,10 @@ var import_koishi = require("koishi");
|
|
|
31
31
|
var import_tools = require("@langchain/core/tools");
|
|
32
32
|
var import_zod = require("zod");
|
|
33
33
|
var GroupMuteTool = class extends import_tools.StructuredTool {
|
|
34
|
-
constructor(ctx, handlers,
|
|
34
|
+
constructor(ctx, handlers, logger, logVerbose) {
|
|
35
35
|
super();
|
|
36
36
|
this.ctx = ctx;
|
|
37
37
|
this.handlers = handlers;
|
|
38
|
-
this.config = config;
|
|
39
38
|
this.logger = logger;
|
|
40
39
|
this.logVerbose = logVerbose;
|
|
41
40
|
}
|
|
@@ -43,11 +42,11 @@ var GroupMuteTool = class extends import_tools.StructuredTool {
|
|
|
43
42
|
__name(this, "GroupMuteTool");
|
|
44
43
|
}
|
|
45
44
|
name = "group_mute";
|
|
46
|
-
description = "
|
|
45
|
+
description = "在群内禁言成员,duration为0表示取消禁言";
|
|
47
46
|
schema = import_zod.z.object({
|
|
48
|
-
groupId: import_zod.z.string().
|
|
49
|
-
userId: import_zod.z.string().
|
|
50
|
-
duration: import_zod.z.number().int().
|
|
47
|
+
groupId: import_zod.z.string().describe("目标群号,不填则使用当前会话群").optional(),
|
|
48
|
+
userId: import_zod.z.string().describe("要禁言的成员 QQ 号"),
|
|
49
|
+
duration: import_zod.z.number().int().min(0).describe("禁言时长(秒)")
|
|
51
50
|
});
|
|
52
51
|
async _call(input, _runManager, runnableConfig) {
|
|
53
52
|
const session = runnableConfig?.configurable?.session;
|
|
@@ -57,7 +56,6 @@ var GroupMuteTool = class extends import_tools.StructuredTool {
|
|
|
57
56
|
this.ctx,
|
|
58
57
|
session,
|
|
59
58
|
{ targetId: input.userId, duration: input.duration, guildId: input.groupId },
|
|
60
|
-
this.config,
|
|
61
59
|
this.logger,
|
|
62
60
|
this.logVerbose
|
|
63
61
|
);
|
|
@@ -69,11 +67,10 @@ var GroupMuteTool = class extends import_tools.StructuredTool {
|
|
|
69
67
|
}
|
|
70
68
|
};
|
|
71
69
|
var GroupTitleTool = class extends import_tools.StructuredTool {
|
|
72
|
-
constructor(ctx, handlers,
|
|
70
|
+
constructor(ctx, handlers, logger, logVerbose) {
|
|
73
71
|
super();
|
|
74
72
|
this.ctx = ctx;
|
|
75
73
|
this.handlers = handlers;
|
|
76
|
-
this.config = config;
|
|
77
74
|
this.logger = logger;
|
|
78
75
|
this.logVerbose = logVerbose;
|
|
79
76
|
}
|
|
@@ -83,9 +80,9 @@ var GroupTitleTool = class extends import_tools.StructuredTool {
|
|
|
83
80
|
name = "group_set_title";
|
|
84
81
|
description = "为成员设置群头衔(需群主权限)";
|
|
85
82
|
schema = import_zod.z.object({
|
|
86
|
-
groupId: import_zod.z.string().
|
|
87
|
-
userId: import_zod.z.string().
|
|
88
|
-
title: import_zod.z.string().
|
|
83
|
+
groupId: import_zod.z.string().describe("目标群号,不填则使用当前会话群").optional(),
|
|
84
|
+
userId: import_zod.z.string().describe("要设置头衔的成员 QQ 号"),
|
|
85
|
+
title: import_zod.z.string().describe("头衔文案")
|
|
89
86
|
});
|
|
90
87
|
async _call(input, _runManager, runnableConfig) {
|
|
91
88
|
const session = runnableConfig?.configurable?.session;
|
|
@@ -95,7 +92,6 @@ var GroupTitleTool = class extends import_tools.StructuredTool {
|
|
|
95
92
|
this.ctx,
|
|
96
93
|
session,
|
|
97
94
|
{ targetId: input.userId, title: input.title, guildId: input.groupId },
|
|
98
|
-
this.config,
|
|
99
95
|
this.logger,
|
|
100
96
|
this.logVerbose
|
|
101
97
|
);
|
|
@@ -106,7 +102,7 @@ var GroupTitleTool = class extends import_tools.StructuredTool {
|
|
|
106
102
|
}
|
|
107
103
|
}
|
|
108
104
|
};
|
|
109
|
-
function registerChatlunaTools(ctx,
|
|
105
|
+
function registerChatlunaTools(ctx, _config, logger, verbose, handlers) {
|
|
110
106
|
const platform = ctx.chatluna?.platform;
|
|
111
107
|
if (!platform) {
|
|
112
108
|
logger.debug("chatluna 未安装,跳过群管工具注册");
|
|
@@ -114,13 +110,13 @@ function registerChatlunaTools(ctx, config, logger, verbose, handlers) {
|
|
|
114
110
|
}
|
|
115
111
|
ctx.effect(
|
|
116
112
|
() => platform.registerTool("group_mute", {
|
|
117
|
-
createTool: /* @__PURE__ */ __name(() => new GroupMuteTool(ctx, handlers,
|
|
113
|
+
createTool: /* @__PURE__ */ __name(() => new GroupMuteTool(ctx, handlers, logger, verbose), "createTool"),
|
|
118
114
|
selector: /* @__PURE__ */ __name(() => true, "selector")
|
|
119
115
|
})
|
|
120
116
|
);
|
|
121
117
|
ctx.effect(
|
|
122
118
|
() => platform.registerTool("group_set_title", {
|
|
123
|
-
createTool: /* @__PURE__ */ __name(() => new GroupTitleTool(ctx, handlers,
|
|
119
|
+
createTool: /* @__PURE__ */ __name(() => new GroupTitleTool(ctx, handlers, logger, verbose), "createTool"),
|
|
124
120
|
selector: /* @__PURE__ */ __name(() => true, "selector")
|
|
125
121
|
})
|
|
126
122
|
);
|
|
@@ -351,24 +347,26 @@ function randomInt(min, max) {
|
|
|
351
347
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
352
348
|
}
|
|
353
349
|
__name(randomInt, "randomInt");
|
|
354
|
-
async function performMute(ctx, session, params,
|
|
350
|
+
async function performMute(ctx, session, params, logger, verbose) {
|
|
355
351
|
const guildId = params.guildId ?? session.guildId;
|
|
356
352
|
if (!guildId) return "仅限群聊使用";
|
|
357
353
|
const targetId = params.targetId ?? parseTargetId(params.targetRaw || "", session);
|
|
358
354
|
if (!targetId) return "请提供要禁言的用户(@ 或 QQ 号)";
|
|
359
355
|
const seconds = Number(params.duration);
|
|
360
|
-
if (!Number.isFinite(seconds) || seconds
|
|
361
|
-
const msg = await verifyCaller(session, config.mute, logger, verbose, guildId);
|
|
362
|
-
if (msg) return msg;
|
|
356
|
+
if (!Number.isFinite(seconds) || seconds < 0) return "禁言时长必须为大于等于 0 的整数(秒)";
|
|
363
357
|
verbose && logger.info(
|
|
364
358
|
`mute: guild=${guildId} caller=${session.userId} bot=${botKey(session.bot)} target=${targetId} seconds=${seconds}`
|
|
365
359
|
);
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
const targetRole = await getMemberRole(picked.probeOnebot, picked.bot, guildId, targetId, logger, verbose);
|
|
360
|
+
const probeOnebot = session.onebot || getBotOnebot(session.bot);
|
|
361
|
+
const targetRole = await getMemberRole(probeOnebot, session.bot, guildId, targetId, logger, verbose);
|
|
369
362
|
if (targetRole === "owner") return "无法对群主执行该操作";
|
|
363
|
+
const requireOwner = targetRole === "admin";
|
|
364
|
+
const picked = await pickManageBot(ctx, guildId, requireOwner, logger, session.bot, verbose, probeOnebot);
|
|
365
|
+
if (!picked) {
|
|
366
|
+
return requireOwner ? "目标是管理员,需要群主权限的 Bot,但没有可用" : "没有可用且有群管权限的 Bot";
|
|
367
|
+
}
|
|
370
368
|
const actionOnebot = getBotOnebot(picked.bot);
|
|
371
|
-
if (!actionOnebot) return "
|
|
369
|
+
if (!actionOnebot) return "失败:选中的 Bot 缺少 onebot 实例,无法执行";
|
|
372
370
|
try {
|
|
373
371
|
verbose && logger.info(`mute: use bot=${botKey(picked.bot)} role=${picked.role} duration=${seconds}`);
|
|
374
372
|
if (typeof actionOnebot.setGroupBan === "function") {
|
|
@@ -381,29 +379,33 @@ async function performMute(ctx, session, params, config, logger, verbose) {
|
|
|
381
379
|
});
|
|
382
380
|
}
|
|
383
381
|
roleCache.clear();
|
|
384
|
-
|
|
382
|
+
const targetRoleStr = targetRole ? `(${targetRole})` : "";
|
|
383
|
+
if (seconds === 0) {
|
|
384
|
+
return `成功:使用 ${picked.bot.selfId}(${picked.role})解除 ${targetId}${targetRoleStr} 的禁言`;
|
|
385
|
+
}
|
|
386
|
+
return `成功:使用 ${picked.bot.selfId}(${picked.role})禁言 ${targetId}${targetRoleStr} ${seconds} 秒`;
|
|
385
387
|
} catch (error) {
|
|
386
388
|
logger.warn(error);
|
|
387
|
-
return
|
|
389
|
+
return `失败:禁言操作出错,Bot=${picked.bot.selfId}(${picked.role}),目标=${targetId}(${targetRole || "unknown"})`;
|
|
388
390
|
}
|
|
389
391
|
}
|
|
390
392
|
__name(performMute, "performMute");
|
|
391
|
-
async function performTitle(ctx, session, params,
|
|
393
|
+
async function performTitle(ctx, session, params, logger, verbose) {
|
|
392
394
|
const guildId = params.guildId ?? session.guildId;
|
|
393
395
|
if (!guildId) return "仅限群聊使用";
|
|
394
396
|
const title = params.title?.trim();
|
|
395
397
|
if (!title) return "请提供要设置的头衔";
|
|
396
398
|
const userId = params.targetId ?? parseTargetId(params.targetRaw || "", session);
|
|
397
399
|
if (!userId) return "请提供要设置头衔的用户(@ 或 QQ 号)";
|
|
398
|
-
const msg = await verifyCaller(session, config.title, logger, verbose, guildId);
|
|
399
|
-
if (msg) return msg;
|
|
400
400
|
verbose && logger.info(
|
|
401
401
|
`title: guild=${guildId} caller=${session.userId} bot=${botKey(session.bot)} target=${userId} title=${title}`
|
|
402
402
|
);
|
|
403
|
-
const
|
|
404
|
-
|
|
403
|
+
const probeOnebot = session.onebot || getBotOnebot(session.bot);
|
|
404
|
+
const targetRole = await getMemberRole(probeOnebot, session.bot, guildId, userId, logger, verbose);
|
|
405
|
+
const picked = await pickManageBot(ctx, guildId, true, logger, session.bot, verbose, probeOnebot);
|
|
406
|
+
if (!picked) return "失败:没有具备群主权限的 Bot 可用";
|
|
405
407
|
const actionOnebot = getBotOnebot(picked.bot);
|
|
406
|
-
if (!actionOnebot) return "
|
|
408
|
+
if (!actionOnebot) return "失败:选中的 Bot 缺少 onebot 实例,无法执行";
|
|
407
409
|
try {
|
|
408
410
|
verbose && logger.info(`title: use bot=${botKey(picked.bot)} role=${picked.role}`);
|
|
409
411
|
if (typeof actionOnebot.setGroupSpecialTitle === "function") {
|
|
@@ -417,10 +419,11 @@ async function performTitle(ctx, session, params, config, logger, verbose) {
|
|
|
417
419
|
});
|
|
418
420
|
}
|
|
419
421
|
roleCache.clear();
|
|
420
|
-
|
|
422
|
+
const targetRoleStr = targetRole ? `(${targetRole})` : "";
|
|
423
|
+
return `成功:使用 ${picked.bot.selfId}(${picked.role})为 ${userId}${targetRoleStr} 设置头衔「${title}」`;
|
|
421
424
|
} catch (error) {
|
|
422
425
|
logger.warn(error);
|
|
423
|
-
return
|
|
426
|
+
return `失败:设置头衔出错,Bot=${picked.bot.selfId}(${picked.role}),目标=${userId}(${targetRole || "unknown"})`;
|
|
424
427
|
}
|
|
425
428
|
}
|
|
426
429
|
__name(performTitle, "performTitle");
|
|
@@ -474,11 +477,12 @@ function apply(ctx, config) {
|
|
|
474
477
|
});
|
|
475
478
|
ctx.command("group.manage/mute <target:string> <duration:number>", "禁言目标(秒,必须指定)").alias("gmute").action(async ({ session }, target, duration) => {
|
|
476
479
|
if (!session) return "缺少 session";
|
|
480
|
+
const msg = await verifyCaller(session, config.mute, logger, verbose);
|
|
481
|
+
if (msg) return msg;
|
|
477
482
|
return performMute(
|
|
478
483
|
ctx,
|
|
479
484
|
session,
|
|
480
485
|
{ targetRaw: target, duration: Number(duration) },
|
|
481
|
-
config,
|
|
482
486
|
logger,
|
|
483
487
|
verbose
|
|
484
488
|
);
|
|
@@ -490,10 +494,14 @@ function apply(ctx, config) {
|
|
|
490
494
|
const userId = parseTargetId(target, session);
|
|
491
495
|
if (!userId) return "请提供要解禁的用户(@ 或 QQ 号)";
|
|
492
496
|
verbose && logger.info(`unmute: guild=${session.guildId} caller=${session.userId} bot=${botKey(session.bot)} target=${userId}`);
|
|
493
|
-
const
|
|
494
|
-
|
|
495
|
-
const targetRole = await getMemberRole(picked.probeOnebot, picked.bot, session.guildId, userId, logger, verbose);
|
|
497
|
+
const probeOnebot = session.onebot || getBotOnebot(session.bot);
|
|
498
|
+
const targetRole = await getMemberRole(probeOnebot, session.bot, session.guildId, userId, logger, verbose);
|
|
496
499
|
if (targetRole === "owner") return "无法对群主执行该操作";
|
|
500
|
+
const requireOwner = targetRole === "admin";
|
|
501
|
+
const picked = await pickManageBot(ctx, session.guildId, requireOwner, logger, session.bot, verbose, probeOnebot);
|
|
502
|
+
if (!picked) {
|
|
503
|
+
return requireOwner ? "目标是管理员,需要群主权限的 Bot,但没有可用" : "没有可用且有群管权限的 Bot";
|
|
504
|
+
}
|
|
497
505
|
const actionOnebot = getBotOnebot(picked.bot);
|
|
498
506
|
if (!actionOnebot) return "选中的 Bot 缺少 onebot 实例,无法执行";
|
|
499
507
|
try {
|
|
@@ -522,10 +530,14 @@ function apply(ctx, config) {
|
|
|
522
530
|
if (!userId) return "请提供要踢出的用户(@ 或 QQ 号)";
|
|
523
531
|
const reject = Boolean(options?.reject ?? rejectFlag);
|
|
524
532
|
verbose && logger.info(`kick: guild=${session.guildId} caller=${session.userId} bot=${botKey(session.bot)} target=${userId} reject=${reject}`);
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
const targetRole = await getMemberRole(picked.probeOnebot, picked.bot, session.guildId, userId, logger, verbose);
|
|
533
|
+
const probeOnebot = session.onebot || getBotOnebot(session.bot);
|
|
534
|
+
const targetRole = await getMemberRole(probeOnebot, session.bot, session.guildId, userId, logger, verbose);
|
|
528
535
|
if (targetRole === "owner") return "无法对群主执行该操作";
|
|
536
|
+
const requireOwner = targetRole === "admin";
|
|
537
|
+
const picked = await pickManageBot(ctx, session.guildId, requireOwner, logger, session.bot, verbose, probeOnebot);
|
|
538
|
+
if (!picked) {
|
|
539
|
+
return requireOwner ? "目标是管理员,需要群主权限的 Bot,但没有可用" : "没有可用且有群管权限的 Bot";
|
|
540
|
+
}
|
|
529
541
|
const actionOnebot = getBotOnebot(picked.bot);
|
|
530
542
|
if (!actionOnebot) return "选中的 Bot 缺少 onebot 实例,无法执行";
|
|
531
543
|
try {
|
|
@@ -548,11 +560,12 @@ function apply(ctx, config) {
|
|
|
548
560
|
});
|
|
549
561
|
ctx.command("group.manage/title <target:string> <title:text>", "设置群头衔(需群主 Bot)").alias("gtitle").action(async ({ session }, target, title) => {
|
|
550
562
|
if (!session) return "缺少 session";
|
|
563
|
+
const msg = await verifyCaller(session, config.title, logger, verbose);
|
|
564
|
+
if (msg) return msg;
|
|
551
565
|
return performTitle(
|
|
552
566
|
ctx,
|
|
553
567
|
session,
|
|
554
568
|
{ targetRaw: target, title: title || "", guildId: session.guildId },
|
|
555
|
-
config,
|
|
556
569
|
logger,
|
|
557
570
|
verbose
|
|
558
571
|
);
|
|
@@ -568,11 +581,10 @@ function apply(ctx, config) {
|
|
|
568
581
|
ctx,
|
|
569
582
|
session,
|
|
570
583
|
{ targetId: session.userId, duration: seconds, guildId: session.guildId },
|
|
571
|
-
config,
|
|
572
584
|
logger,
|
|
573
585
|
verbose
|
|
574
586
|
);
|
|
575
|
-
if (typeof result === "string" && result.startsWith("
|
|
587
|
+
if (typeof result === "string" && result.startsWith("成功")) return `你已被禁言 ${seconds} 秒`;
|
|
576
588
|
return result;
|
|
577
589
|
});
|
|
578
590
|
ctx.command("group.manage/title.apply <title:text>", "申请群头衔(给自己)").alias("gtitle.apply").action(async ({ session }, title) => {
|
|
@@ -581,11 +593,10 @@ function apply(ctx, config) {
|
|
|
581
593
|
ctx,
|
|
582
594
|
session,
|
|
583
595
|
{ targetId: session.userId, title: title || "", guildId: session.guildId },
|
|
584
|
-
config,
|
|
585
596
|
logger,
|
|
586
597
|
verbose
|
|
587
598
|
);
|
|
588
|
-
if (typeof result === "string" && result.startsWith("
|
|
599
|
+
if (typeof result === "string" && result.startsWith("成功")) {
|
|
589
600
|
return `已为你设置头衔:${(title || "").trim()}`;
|
|
590
601
|
}
|
|
591
602
|
return result;
|
package/lib/tools.d.ts
CHANGED
|
@@ -5,12 +5,12 @@ interface Handlers {
|
|
|
5
5
|
targetId: string;
|
|
6
6
|
duration: number;
|
|
7
7
|
guildId?: string;
|
|
8
|
-
},
|
|
8
|
+
}, logger: ReturnType<Context['logger']>, verbose?: boolean) => Promise<string>;
|
|
9
9
|
performTitle: (ctx: Context, session: Session, params: {
|
|
10
10
|
targetId: string;
|
|
11
11
|
title: string;
|
|
12
12
|
guildId?: string;
|
|
13
|
-
},
|
|
13
|
+
}, logger: ReturnType<Context['logger']>, verbose?: boolean) => Promise<string>;
|
|
14
14
|
}
|
|
15
|
-
export declare function registerChatlunaTools(ctx: Context,
|
|
15
|
+
export declare function registerChatlunaTools(ctx: Context, _config: Config, logger: ReturnType<Context['logger']>, verbose: boolean | undefined, handlers: Handlers): void;
|
|
16
16
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-onebot-group-manage",
|
|
3
3
|
"description": "主要针对多bot环境的群管插件,自动使用有权限的bot",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.8",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"plugin"
|
|
16
16
|
],
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"koishi": "^4.18.7",
|
|
19
18
|
"@langchain/core": "^0.3.0",
|
|
19
|
+
"koishi": "^4.18.7",
|
|
20
20
|
"koishi-plugin-chatluna": "^1.3.0",
|
|
21
21
|
"zod": "^3.23.8"
|
|
22
22
|
}
|