koishi-plugin-chatluna-toolbox 0.0.7 → 0.0.9

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.
Files changed (2) hide show
  1. package/lib/index.js +310 -38
  2. package/package.json +3 -3
package/lib/index.js CHANGED
@@ -35,9 +35,11 @@ __export(index_exports, {
35
35
  createCharacterTempXmlRuntime: () => createCharacterTempXmlRuntime,
36
36
  createDeleteMessageTool: () => createDeleteMessageTool,
37
37
  createGroupInfoProvider: () => createGroupInfoProvider,
38
+ createGroupShutListProvider: () => createGroupShutListProvider,
38
39
  createLogger: () => createLogger,
39
40
  createPokeTool: () => createPokeTool,
40
41
  createRandomProvider: () => createRandomProvider,
42
+ createSetGroupBanTool: () => createSetGroupBanTool,
41
43
  createSetGroupCardTool: () => createSetGroupCardTool,
42
44
  createSetMsgEmojiTool: () => createSetMsgEmojiTool,
43
45
  createSetProfileTool: () => createSetProfileTool,
@@ -53,6 +55,7 @@ __export(index_exports, {
53
55
  registerXmlTools: () => registerXmlTools,
54
56
  resolveOneBotProtocol: () => resolveOneBotProtocol,
55
57
  sendDeleteMessage: () => sendDeleteMessage,
58
+ sendGroupBan: () => sendGroupBan,
56
59
  sendMsgEmoji: () => sendMsgEmoji,
57
60
  sendPoke: () => sendPoke
58
61
  });
@@ -75,6 +78,7 @@ var import_koishi2 = require("koishi");
75
78
  var DEFAULT_POKE_TOOL_DESCRIPTION = "\u5BF9\u6307\u5B9A\u7528\u6237\u6267\u884C\u6233\u4E00\u6233\u3002";
76
79
  var DEFAULT_SET_SELF_PROFILE_TOOL_DESCRIPTION = "\u4FEE\u6539\u81EA\u5DF1\u7684 QQ \u8D44\u6599\uFF0C\u53EF\u8BBE\u7F6E\u6635\u79F0\u3001\u7B7E\u540D\u548C\u6027\u522B\u3002";
77
80
  var DEFAULT_SET_GROUP_CARD_TOOL_DESCRIPTION = "\u4FEE\u6539\u7FA4\u6210\u5458\u7684\u7FA4\u6635\u79F0\u3002";
81
+ var DEFAULT_SET_GROUP_BAN_TOOL_DESCRIPTION = "\u7981\u8A00\u6307\u5B9A\u7FA4\u6210\u5458\uFF0Cduration=0 \u8868\u793A\u89E3\u9664\u7981\u8A00\u3002";
78
82
  var DEFAULT_SET_MSG_EMOJI_TOOL_DESCRIPTION = "\u5BF9\u6307\u5B9A\u6D88\u606F\u6DFB\u52A0\u8868\u60C5\u56DE\u5E94\u3002";
79
83
  var DEFAULT_DELETE_MESSAGE_TOOL_DESCRIPTION = "\u6839\u636E\u6D88\u606F ID \u64A4\u56DE\u6307\u5B9A\u6D88\u606F\u3002";
80
84
 
@@ -86,7 +90,9 @@ var NativeToolsSchema = import_koishi2.Schema.object({
86
90
  description: import_koishi2.Schema.string().default(DEFAULT_POKE_TOOL_DESCRIPTION).description("\u5DE5\u5177\u63CF\u8FF0")
87
91
  }).description("\u6233\u4E00\u6233\u5DE5\u5177").collapse(),
88
92
  setSelfProfile: import_koishi2.Schema.object({
89
- enabled: import_koishi2.Schema.boolean().default(false).description("\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u4FEE\u6539\u81EA\u8EAB\u8D26\u6237\u4FE1\u606F\uFF08\u652F\u6301\u6635\u79F0/\u7B7E\u540D/\u6027\u522B\uFF09"),
93
+ enabled: import_koishi2.Schema.boolean().default(false).description(
94
+ "\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u4FEE\u6539\u81EA\u8EAB\u8D26\u6237\u4FE1\u606F\uFF08\u652F\u6301\u6635\u79F0/\u7B7E\u540D/\u6027\u522B\uFF09"
95
+ ),
90
96
  toolName: import_koishi2.Schema.string().default("set_self_profile").description("\u5DE5\u5177\u540D\u79F0"),
91
97
  description: import_koishi2.Schema.string().default(DEFAULT_SET_SELF_PROFILE_TOOL_DESCRIPTION).description("\u5DE5\u5177\u63CF\u8FF0")
92
98
  }).description("\u4FEE\u6539\u81EA\u8EAB\u8D26\u6237\u4FE1\u606F\u5DE5\u5177").collapse(),
@@ -95,6 +101,11 @@ var NativeToolsSchema = import_koishi2.Schema.object({
95
101
  toolName: import_koishi2.Schema.string().default("set_group_card").description("\u5DE5\u5177\u540D\u79F0"),
96
102
  description: import_koishi2.Schema.string().default(DEFAULT_SET_GROUP_CARD_TOOL_DESCRIPTION).description("\u5DE5\u5177\u63CF\u8FF0")
97
103
  }).description("\u4FEE\u6539\u7FA4\u6210\u5458\u6635\u79F0\u5DE5\u5177").collapse(),
104
+ setGroupBan: import_koishi2.Schema.object({
105
+ enabled: import_koishi2.Schema.boolean().default(false).description("\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u7981\u8A00\u7FA4\u6210\u5458"),
106
+ toolName: import_koishi2.Schema.string().default("set_group_ban").description("\u5DE5\u5177\u540D\u79F0"),
107
+ description: import_koishi2.Schema.string().default(DEFAULT_SET_GROUP_BAN_TOOL_DESCRIPTION).description("\u5DE5\u5177\u63CF\u8FF0")
108
+ }).description("\u7981\u8A00\u5DE5\u5177").collapse(),
98
109
  setMsgEmoji: import_koishi2.Schema.object({
99
110
  enabled: import_koishi2.Schema.boolean().default(false).description(
100
111
  "\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u7ED9\u6D88\u606F\u6DFB\u52A0\u8868\u60C5\uFF08\u9700 chatluna-character \u5F00\u542F enableMessageId\uFF0C\u4E0E XML\u5DE5\u5177 \u4E8C\u9009\u4E00\uFF0C\u8868\u60C5\u5BF9\u7167\u8868\uFF1Ahttps://bot.q.qq.com/wiki/develop/pythonsdk/model/emoji.html \uFF09"
@@ -125,6 +136,11 @@ var NativeToolsSchema = import_koishi2.Schema.object({
125
136
  toolName: "set_group_card",
126
137
  description: DEFAULT_SET_GROUP_CARD_TOOL_DESCRIPTION
127
138
  },
139
+ setGroupBan: {
140
+ enabled: false,
141
+ toolName: "set_group_ban",
142
+ description: DEFAULT_SET_GROUP_BAN_TOOL_DESCRIPTION
143
+ },
128
144
  setMsgEmoji: {
129
145
  enabled: false,
130
146
  toolName: "set_msg_emoji",
@@ -157,7 +173,13 @@ var DEFAULT_XML_REFERENCE_PROMPT = `## \u52A8\u4F5C\u6307\u4EE4
157
173
  - 66: \u7231\u5FC3
158
174
  - \u9002\u7528\u573A\u666F:
159
175
  - \u7528\u4E8E\u5BF9\u4E0A\u4E0B\u6587\u4E2D\u7684\u7279\u5B9A\u6D88\u606F\u8FDB\u884C\u8868\u60C5\u56DE\u5E94\u3002
160
- 3. \u64A4\u56DE\u6D88\u606F: <delete message_id=""/>
176
+ 3. \u7981\u8A00\u7FA4\u6210\u5458: <ban id="" duration=""/>
177
+ - id: user_id
178
+ - duration: \u7981\u8A00\u65F6\u957F\uFF0C\u5355\u4F4D\u79D2\uFF0C\u4F20 0 \u8868\u793A\u89E3\u9664\u7981\u8A00
179
+ - \u9002\u7528\u573A\u666F:
180
+ - \u4F60\u5728\u672C\u7FA4\u4E3A\u7BA1\u7406\u5458
181
+ - \u7528\u4E8E\u7981\u8A00\u6216\u89E3\u9664\u7981\u8A00\u6307\u5B9A\u7FA4\u6210\u5458
182
+ 4. \u64A4\u56DE\u6D88\u606F: <delete message_id=""/>
161
183
  - message_id: \u6D88\u606F ID
162
184
  - \u9002\u7528\u573A\u666F:
163
185
  - \u4F60\u5728\u672C\u7FA4\u4E3A\u7BA1\u7406\u5458
@@ -168,6 +190,7 @@ var DEFAULT_XML_REFERENCE_PROMPT = `## \u52A8\u4F5C\u6307\u4EE4
168
190
  <actions>
169
191
  <poke id="123456"/>
170
192
  <emoji message_id="346234" emoji_id="66"/>
193
+ <ban id="123456" duration="600"/>
171
194
  <delete message_id="435663"/>
172
195
  </actions>
173
196
  \`\`\``;
@@ -176,7 +199,12 @@ var XmlToolsSchema = import_koishi3.Schema.object({
176
199
  enableEmojiXmlTool: import_koishi3.Schema.boolean().default(false).description(
177
200
  "\u542F\u7528 XML \u5F62\u5F0F\u7684\u6D88\u606F\u8868\u60C5\u8C03\u7528\uFF0C\uFF08\u9700 chatluna-character \u5F00\u542F enableMessageId\uFF0C\u4E0E \u539F\u751F\u5DE5\u5177 \u4E8C\u9009\u4E00\uFF0Cemoji_id \u5BF9\u7167\u8868\uFF1Ahttps://bot.q.qq.com/wiki/develop/pythonsdk/model/emoji.html \uFF09"
178
201
  ),
179
- enableDeleteXmlTool: import_koishi3.Schema.boolean().default(false).description("\u542F\u7528 XML \u5F62\u5F0F\u7684\u6D88\u606F\u64A4\u56DE\u8C03\u7528\uFF08\u9700 chatluna-character \u5F00\u542F enableMessageId\uFF0C\u4E0E \u539F\u751F\u5DE5\u5177 \u4E8C\u9009\u4E00\uFF09"),
202
+ enableDeleteXmlTool: import_koishi3.Schema.boolean().default(false).description(
203
+ "\u542F\u7528 XML \u5F62\u5F0F\u7684\u6D88\u606F\u64A4\u56DE\u8C03\u7528\uFF08\u9700 chatluna-character \u5F00\u542F enableMessageId\uFF0C\u4E0E \u539F\u751F\u5DE5\u5177 \u4E8C\u9009\u4E00\uFF09"
204
+ ),
205
+ enableBanXmlTool: import_koishi3.Schema.boolean().default(false).description(
206
+ "\u542F\u7528 XML \u5F62\u5F0F\u7684\u7FA4\u6210\u5458\u7981\u8A00\u8C03\u7528\uFF08\u4E0E \u539F\u751F\u5DE5\u5177 \u4E8C\u9009\u4E00\uFF09"
207
+ ),
180
208
  referencePrompt: import_koishi3.Schema.string().role("textarea").default(DEFAULT_XML_REFERENCE_PROMPT).description("\u6A21\u578B\u56DE\u590D XML \u53C2\u8003\u63D0\u793A\u8BCD\uFF0C\u81EA\u884C\u5199\u5165\u63D0\u793A\u8BCD\u4E2D\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u6CE8\u5165")
181
209
  }).description("XML \u5DE5\u5177");
182
210
 
@@ -254,6 +282,9 @@ var VariablesSchema = import_koishi4.Schema.object({
254
282
  ])
255
283
  ).role("checkbox").default([...DEFAULT_GROUP_INFO_ITEMS]).description("\u663E\u793A\u7684\u7FA4\u4FE1\u606F\u9879")
256
284
  }).description("\u7FA4\u4FE1\u606F\u53D8\u91CF").collapse(),
285
+ groupShutList: import_koishi4.Schema.object({
286
+ variableName: import_koishi4.Schema.string().default("groupShutList").description("\u53D8\u91CF\u540D\u79F0")
287
+ }).description("\u7FA4\u7981\u8A00\u5217\u8868\u53D8\u91CF").collapse(),
257
288
  random: import_koishi4.Schema.object({
258
289
  variableName: import_koishi4.Schema.string().default("random").description("\u53D8\u91CF\u540D\u79F0"),
259
290
  min: import_koishi4.Schema.number().default(0).description("\u9ED8\u8BA4\u968F\u673A\u6570\u4E0B\u9650"),
@@ -269,6 +300,7 @@ var VariablesSchema = import_koishi4.Schema.object({
269
300
  variableName: "groupInfo",
270
301
  items: [...DEFAULT_GROUP_INFO_ITEMS]
271
302
  },
303
+ groupShutList: { variableName: "groupShutList" },
272
304
  random: { variableName: "random", min: 0, max: 100 }
273
305
  }).description("\u5176\u4ED6\u53D8\u91CF");
274
306
 
@@ -457,18 +489,92 @@ function createPokeTool(deps) {
457
489
  }();
458
490
  }
459
491
 
460
- // src/features/native-tools/tools/set-group-card.ts
492
+ // src/features/native-tools/tools/set-group-ban.ts
461
493
  var import_zod3 = require("zod");
462
494
  var import_tools2 = require("@langchain/core/tools");
463
- function createSetGroupCardTool(deps) {
464
- const { toolName, description, log } = deps;
495
+ function resolveGroupId(session, groupId) {
496
+ return groupId?.trim() || (session.guildId || "").trim() || (session.channelId || "").trim() || (session.roomId || "").trim();
497
+ }
498
+ function parseDuration(duration) {
499
+ const raw = String(duration).trim();
500
+ if (!raw) return null;
501
+ if (!/^\d+$/.test(raw)) return null;
502
+ const parsed = Number(raw);
503
+ return Number.isSafeInteger(parsed) ? parsed : null;
504
+ }
505
+ async function sendGroupBan(params) {
506
+ try {
507
+ const { session, userId, groupId, duration, log } = params;
508
+ const {
509
+ error,
510
+ internal,
511
+ session: validatedSession
512
+ } = ensureOneBotSession(session);
513
+ if (error) return error;
514
+ const resolvedGroupId = resolveGroupId(validatedSession, groupId);
515
+ if (!resolvedGroupId) {
516
+ return "Missing groupId. Provide groupId explicitly or run inside a group session.";
517
+ }
518
+ const userIdRaw = userId.trim();
519
+ if (!userIdRaw) return "userId is required.";
520
+ const parsedDuration = parseDuration(duration);
521
+ if (parsedDuration === null) {
522
+ return "duration must be a non-negative integer in seconds.";
523
+ }
524
+ await callOneBotAPI(
525
+ internal,
526
+ "set_group_ban",
527
+ {
528
+ group_id: resolvedGroupId,
529
+ user_id: userIdRaw,
530
+ duration: parsedDuration
531
+ },
532
+ ["setGroupBan"]
533
+ );
534
+ const success = parsedDuration === 0 ? `\u5DF2\u89E3\u9664\u7FA4 ${resolvedGroupId} \u4E2D\u7528\u6237 ${userIdRaw} \u7684\u7981\u8A00\u3002` : `\u5DF2\u5728\u7FA4 ${resolvedGroupId} \u4E2D\u7981\u8A00\u7528\u6237 ${userIdRaw} ${parsedDuration} \u79D2\u3002`;
535
+ log?.("info", success);
536
+ return success;
537
+ } catch (error) {
538
+ params.log?.("warn", "set_group_ban failed", error);
539
+ return `set_group_ban failed: ${error.message}`;
540
+ }
541
+ }
542
+ function createSetGroupBanTool(deps) {
543
+ const { toolName, description, protocol, log } = deps;
465
544
  return new class extends import_tools2.StructuredTool {
466
- name = toolName || "set_group_card";
467
- description = description || DEFAULT_SET_GROUP_CARD_TOOL_DESCRIPTION;
545
+ name = toolName || "set_group_ban";
546
+ description = description || DEFAULT_SET_GROUP_BAN_TOOL_DESCRIPTION;
468
547
  schema = import_zod3.z.object({
469
548
  groupId: import_zod3.z.string().optional().describe("Target group ID. Defaults to current session group."),
470
549
  userId: import_zod3.z.string().min(1, "userId is required").describe("Target member user ID."),
471
- card: import_zod3.z.string().min(1, "card is required").describe("New group card for the member.")
550
+ duration: import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number().int().min(0)]).describe("Mute duration in seconds. Use 0 to unmute.")
551
+ });
552
+ async _call(input, _manager, runnable) {
553
+ const session = getSession(runnable);
554
+ return sendGroupBan({
555
+ session,
556
+ userId: input.userId,
557
+ duration: input.duration,
558
+ groupId: input.groupId,
559
+ protocol,
560
+ log
561
+ });
562
+ }
563
+ }();
564
+ }
565
+
566
+ // src/features/native-tools/tools/set-group-card.ts
567
+ var import_zod4 = require("zod");
568
+ var import_tools3 = require("@langchain/core/tools");
569
+ function createSetGroupCardTool(deps) {
570
+ const { toolName, description, log } = deps;
571
+ return new class extends import_tools3.StructuredTool {
572
+ name = toolName || "set_group_card";
573
+ description = description || DEFAULT_SET_GROUP_CARD_TOOL_DESCRIPTION;
574
+ schema = import_zod4.z.object({
575
+ groupId: import_zod4.z.string().optional().describe("Target group ID. Defaults to current session group."),
576
+ userId: import_zod4.z.string().min(1, "userId is required").describe("Target member user ID."),
577
+ card: import_zod4.z.string().min(1, "card is required").describe("New group card for the member.")
472
578
  });
473
579
  async _call(input, _manager, runnable) {
474
580
  try {
@@ -501,8 +607,8 @@ function createSetGroupCardTool(deps) {
501
607
  }
502
608
 
503
609
  // src/features/native-tools/tools/set-msg-emoji.ts
504
- var import_zod4 = require("zod");
505
- var import_tools3 = require("@langchain/core/tools");
610
+ var import_zod5 = require("zod");
611
+ var import_tools4 = require("@langchain/core/tools");
506
612
  async function sendMsgEmoji(params) {
507
613
  try {
508
614
  const { session, messageId, emojiId, log, protocol } = params;
@@ -535,12 +641,12 @@ async function sendMsgEmoji(params) {
535
641
  }
536
642
  function createSetMsgEmojiTool(deps) {
537
643
  const { toolName, description, log, protocol } = deps;
538
- return new class extends import_tools3.StructuredTool {
644
+ return new class extends import_tools4.StructuredTool {
539
645
  name = toolName || "set_msg_emoji";
540
646
  description = description || DEFAULT_SET_MSG_EMOJI_TOOL_DESCRIPTION;
541
- schema = import_zod4.z.object({
542
- messageId: import_zod4.z.string().min(1, "message_id is required").describe("Target message ID."),
543
- emojiId: import_zod4.z.string().min(1, "emoji_id is required").describe("Emoji ID to send.")
647
+ schema = import_zod5.z.object({
648
+ messageId: import_zod5.z.string().min(1, "message_id is required").describe("Target message ID."),
649
+ emojiId: import_zod5.z.string().min(1, "emoji_id is required").describe("Emoji ID to send.")
544
650
  });
545
651
  async _call(input, _manager, runnable) {
546
652
  const session = getSession(runnable);
@@ -556,8 +662,8 @@ function createSetMsgEmojiTool(deps) {
556
662
  }
557
663
 
558
664
  // src/features/native-tools/tools/profile.ts
559
- var import_zod5 = require("zod");
560
- var import_tools4 = require("@langchain/core/tools");
665
+ var import_zod6 = require("zod");
666
+ var import_tools5 = require("@langchain/core/tools");
561
667
  var genders = {
562
668
  unknown: "0",
563
669
  male: "1",
@@ -565,13 +671,13 @@ var genders = {
565
671
  };
566
672
  function createSetProfileTool(deps) {
567
673
  const { toolName, description, log, protocol } = deps;
568
- return new class extends import_tools4.StructuredTool {
674
+ return new class extends import_tools5.StructuredTool {
569
675
  name = toolName || "set_self_profile";
570
676
  description = description || DEFAULT_SET_SELF_PROFILE_TOOL_DESCRIPTION;
571
- schema = import_zod5.z.object({
572
- nickname: import_zod5.z.string().min(1, "nickname is required").describe("The new nickname for the bot."),
573
- signature: import_zod5.z.string().optional().describe("Optional: the new personal signature."),
574
- gender: import_zod5.z.enum(["unknown", "male", "female"]).optional().describe("Optional: the new gender.")
677
+ schema = import_zod6.z.object({
678
+ nickname: import_zod6.z.string().min(1, "nickname is required").describe("The new nickname for the bot."),
679
+ signature: import_zod6.z.string().optional().describe("Optional: the new personal signature."),
680
+ gender: import_zod6.z.enum(["unknown", "male", "female"]).optional().describe("Optional: the new gender.")
575
681
  });
576
682
  async _call(input, _manager, runnable) {
577
683
  try {
@@ -662,6 +768,22 @@ function registerNativeTools(deps) {
662
768
  });
663
769
  log?.("info", `\u7FA4\u6635\u79F0\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
664
770
  }
771
+ if (config.setGroupBan.enabled) {
772
+ const toolName = resolveToolName(
773
+ config.setGroupBan.toolName,
774
+ "set_group_ban"
775
+ );
776
+ const description = resolveToolDescription(
777
+ config.setGroupBan.description,
778
+ DEFAULT_SET_GROUP_BAN_TOOL_DESCRIPTION
779
+ );
780
+ plugin.registerTool(toolName, {
781
+ selector: () => true,
782
+ authorization: (session) => session?.platform === "onebot",
783
+ createTool: () => createSetGroupBanTool({ toolName, description, log, protocol })
784
+ });
785
+ log?.("info", `\u7FA4\u6210\u5458\u7981\u8A00\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
786
+ }
665
787
  if (config.setMsgEmoji.enabled) {
666
788
  const toolName = resolveToolName(
667
789
  config.setMsgEmoji.toolName,
@@ -720,14 +842,19 @@ function createXmlProcessor(deps) {
720
842
  log,
721
843
  sendPoke: runPoke = sendPoke,
722
844
  sendMsgEmoji: runEmoji = sendMsgEmoji,
723
- sendDeleteMessage: runDelete = sendDeleteMessage
845
+ sendDeleteMessage: runDelete = sendDeleteMessage,
846
+ sendGroupBan: runBan = sendGroupBan
724
847
  } = deps;
725
- return async ({ response, session }) => {
848
+ return async ({
849
+ response,
850
+ session
851
+ }) => {
726
852
  const content = String(response || "").trim();
727
853
  if (!content) return false;
728
854
  const pokeTags = parseSelfClosingXmlTags(content, "poke");
729
855
  const emojiTags = parseSelfClosingXmlTags(content, "emoji");
730
856
  const deleteTags = parseSelfClosingXmlTags(content, "delete");
857
+ const banTags = parseSelfClosingXmlTags(content, "ban");
731
858
  let handled = false;
732
859
  if (config.enablePokeXmlTool && pokeTags.length > 0) {
733
860
  if (!session) {
@@ -783,6 +910,30 @@ function createXmlProcessor(deps) {
783
910
  }
784
911
  }
785
912
  }
913
+ if (config.enableBanXmlTool && banTags.length > 0) {
914
+ if (!session) {
915
+ log?.("warn", "\u68C0\u6D4B\u5230\u7981\u8A00\u6807\u8BB0\u4F46\u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587");
916
+ } else {
917
+ const items = banTags.map((attrs) => ({
918
+ userId: String(attrs.id || "").trim(),
919
+ duration: String(attrs.duration || "").trim()
920
+ })).filter((item) => item.userId && item.duration);
921
+ if (items.length > 0) handled = true;
922
+ for (const item of items) {
923
+ try {
924
+ await runBan({
925
+ session,
926
+ userId: item.userId,
927
+ duration: item.duration,
928
+ protocol,
929
+ log
930
+ });
931
+ } catch (error) {
932
+ log?.("warn", "XML \u89E6\u53D1\u7981\u8A00\u5931\u8D25", error);
933
+ }
934
+ }
935
+ }
936
+ }
786
937
  return handled;
787
938
  };
788
939
  }
@@ -1355,6 +1506,113 @@ function createGroupInfoProvider(deps) {
1355
1506
  };
1356
1507
  }
1357
1508
 
1509
+ // src/features/variables/providers/group-shut-list.ts
1510
+ function normalizeTimestamp2(raw) {
1511
+ if (raw === null || raw === void 0 || raw === "" || Number(raw) === 0)
1512
+ return null;
1513
+ const numeric = Number(raw);
1514
+ if (!Number.isFinite(numeric)) return null;
1515
+ return numeric < 1e11 ? numeric * 1e3 : numeric;
1516
+ }
1517
+ function formatDateTime2(value) {
1518
+ if (!value) return "\u672A\u77E5";
1519
+ const date = new Date(value);
1520
+ if (Number.isNaN(date.valueOf())) return "\u672A\u77E5";
1521
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")} ${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
1522
+ }
1523
+ function pickFirst2(...values) {
1524
+ for (const value of values) {
1525
+ if (value === null || value === void 0) continue;
1526
+ const text = String(value).trim();
1527
+ if (text) return text;
1528
+ }
1529
+ return "";
1530
+ }
1531
+ function extractList(result) {
1532
+ if (Array.isArray(result)) return result;
1533
+ if (result && typeof result === "object" && Array.isArray(result.data)) {
1534
+ return result.data;
1535
+ }
1536
+ return [];
1537
+ }
1538
+ function normalizeShutItem(item) {
1539
+ const userId = pickFirst2(
1540
+ item.uin,
1541
+ item.user_id
1542
+ );
1543
+ if (!userId) return null;
1544
+ const cardName = pickFirst2(
1545
+ item.cardName,
1546
+ item.remark,
1547
+ item.nick,
1548
+ item.nickname,
1549
+ userId
1550
+ );
1551
+ const shutUpTimeText = formatDateTime2(
1552
+ normalizeTimestamp2(
1553
+ pickFirst2(
1554
+ item.shutUpTime,
1555
+ item.shut_up_time
1556
+ )
1557
+ )
1558
+ );
1559
+ return {
1560
+ userId,
1561
+ cardName,
1562
+ shutUpTimeText
1563
+ };
1564
+ }
1565
+ async function fetchGroupShutList(session, config) {
1566
+ const { error, internal } = ensureOneBotSession(session);
1567
+ if (error || !internal)
1568
+ throw new Error(error || "\u7F3A\u5C11 OneBot internal \u63A5\u53E3\u3002");
1569
+ const preferredProtocol = resolveOneBotProtocol(config);
1570
+ const preferredGroupId = preferredProtocol === "llbot" ? String(session.guildId) : Number(session.guildId);
1571
+ const fallbackGroupId = preferredProtocol === "llbot" ? Number(session.guildId) : String(session.guildId);
1572
+ try {
1573
+ const result = await callOneBotAPI(
1574
+ internal,
1575
+ "get_group_shut_list",
1576
+ { group_id: preferredGroupId },
1577
+ ["getGroupShutList"]
1578
+ );
1579
+ return extractList(result);
1580
+ } catch (error2) {
1581
+ if (preferredGroupId === fallbackGroupId) throw error2;
1582
+ const result = await callOneBotAPI(
1583
+ internal,
1584
+ "get_group_shut_list",
1585
+ { group_id: fallbackGroupId },
1586
+ ["getGroupShutList"]
1587
+ );
1588
+ return extractList(result);
1589
+ }
1590
+ }
1591
+ function renderShutList(items) {
1592
+ if (items.length === 0) return "\u5F53\u524D\u7FA4\u6682\u65E0\u7981\u8A00\u6210\u5458\u3002";
1593
+ return items.map(
1594
+ (item) => `id\uFF1A${item.userId}\uFF0Cname\uFF1A${item.cardName}\uFF0C\u7981\u8A00\u622A\u81F3\uFF1A${item.shutUpTimeText}`
1595
+ ).join("\n");
1596
+ }
1597
+ function createGroupShutListProvider(deps) {
1598
+ const { config, log } = deps;
1599
+ return async (_args, _variables, configurable) => {
1600
+ const session = configurable?.session;
1601
+ if (!session) return "\u6682\u65E0\u7FA4\u7981\u8A00\u5217\u8868\u3002";
1602
+ if (!session.guildId) return "";
1603
+ if (session.platform !== "onebot")
1604
+ return "\u5F53\u524D\u5E73\u53F0\u6682\u4E0D\u652F\u6301\u67E5\u8BE2\u7FA4\u7981\u8A00\u5217\u8868\u3002";
1605
+ try {
1606
+ const list = await fetchGroupShutList(session, config);
1607
+ const normalized = list.map(normalizeShutItem).filter(Boolean);
1608
+ return renderShutList(normalized);
1609
+ } catch (error) {
1610
+ log?.("debug", "\u7FA4\u7981\u8A00\u5217\u8868\u53D8\u91CF\u89E3\u6790\u5931\u8D25", error);
1611
+ return "\u83B7\u53D6\u7FA4\u7981\u8A00\u5217\u8868\u5931\u8D25\u3002";
1612
+ }
1613
+ };
1614
+ }
1615
+
1358
1616
  // src/features/variables/providers/random.ts
1359
1617
  function createRandomProvider(deps) {
1360
1618
  const { config } = deps;
@@ -1379,7 +1637,7 @@ function translateGender2(value) {
1379
1637
  if (["\u672A\u77E5", "unknown", "0", "secret"].includes(text)) return "";
1380
1638
  return String(value);
1381
1639
  }
1382
- function normalizeTimestamp2(raw) {
1640
+ function normalizeTimestamp3(raw) {
1383
1641
  if (raw === null || raw === void 0 || raw === "") return null;
1384
1642
  const numeric = Number(raw);
1385
1643
  if (!Number.isFinite(numeric)) return null;
@@ -1391,13 +1649,13 @@ function formatDateOnly3(value) {
1391
1649
  if (Number.isNaN(date.valueOf())) return "";
1392
1650
  return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
1393
1651
  }
1394
- function formatDateTime2(value) {
1652
+ function formatDateTime3(value) {
1395
1653
  if (!value) return "";
1396
1654
  const date = new Date(value);
1397
1655
  if (Number.isNaN(date.valueOf())) return "";
1398
1656
  return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")} ${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
1399
1657
  }
1400
- function pickFirst2(...values) {
1658
+ function pickFirst3(...values) {
1401
1659
  for (const value of values) {
1402
1660
  if (value === null || value === void 0) continue;
1403
1661
  const text = String(value).trim();
@@ -1455,7 +1713,7 @@ function renderUserInfo(session, member, items) {
1455
1713
  switch (item) {
1456
1714
  case "nickname": {
1457
1715
  const name2 = String(
1458
- pickFirst2(
1716
+ pickFirst3(
1459
1717
  member?.card,
1460
1718
  member?.remark,
1461
1719
  member?.displayName,
@@ -1474,7 +1732,7 @@ function renderUserInfo(session, member, items) {
1474
1732
  break;
1475
1733
  case "role": {
1476
1734
  const role = normalizeRole2(
1477
- pickFirst2(
1735
+ pickFirst3(
1478
1736
  member?.role,
1479
1737
  member?.roleName,
1480
1738
  member?.permission,
@@ -1485,7 +1743,7 @@ function renderUserInfo(session, member, items) {
1485
1743
  break;
1486
1744
  }
1487
1745
  case "level": {
1488
- const level = pickFirst2(
1746
+ const level = pickFirst3(
1489
1747
  member?.level,
1490
1748
  member?.levelName,
1491
1749
  member?.level_name,
@@ -1495,7 +1753,7 @@ function renderUserInfo(session, member, items) {
1495
1753
  break;
1496
1754
  }
1497
1755
  case "title": {
1498
- const title = pickFirst2(
1756
+ const title = pickFirst3(
1499
1757
  member?.title,
1500
1758
  member?.specialTitle,
1501
1759
  member?.special_title
@@ -1514,14 +1772,14 @@ function renderUserInfo(session, member, items) {
1514
1772
  break;
1515
1773
  }
1516
1774
  case "area": {
1517
- const area = pickFirst2(member?.area, member?.region, member?.location);
1775
+ const area = pickFirst3(member?.area, member?.region, member?.location);
1518
1776
  if (area !== null) values.push(`\u5730\u533A:${area}`);
1519
1777
  break;
1520
1778
  }
1521
1779
  case "joinTime": {
1522
1780
  const joinTime = formatDateOnly3(
1523
- normalizeTimestamp2(
1524
- pickFirst2(
1781
+ normalizeTimestamp3(
1782
+ pickFirst3(
1525
1783
  member?.join_time,
1526
1784
  member?.joined_at,
1527
1785
  member?.joinTime,
@@ -1533,9 +1791,9 @@ function renderUserInfo(session, member, items) {
1533
1791
  break;
1534
1792
  }
1535
1793
  case "lastSentTime": {
1536
- const lastSentTime = formatDateTime2(
1537
- normalizeTimestamp2(
1538
- pickFirst2(
1794
+ const lastSentTime = formatDateTime3(
1795
+ normalizeTimestamp3(
1796
+ pickFirst3(
1539
1797
  member?.last_sent_time,
1540
1798
  member?.lastSentTime,
1541
1799
  member?.lastSpeakTimestamp
@@ -1591,6 +1849,17 @@ function registerVariables(deps) {
1591
1849
  promptRenderer.registerFunctionProvider(groupInfoName, groupInfoProvider);
1592
1850
  log?.("info", `\u7FA4\u7EC4\u4FE1\u606F\u53D8\u91CF\u5DF2\u6CE8\u518C: ${groupInfoName}`);
1593
1851
  }
1852
+ const groupShutListProvider = createGroupShutListProvider({ config, log });
1853
+ const groupShutListName = String(
1854
+ config.groupShutList?.variableName || "groupShutList"
1855
+ ).trim();
1856
+ if (groupShutListName) {
1857
+ promptRenderer.registerFunctionProvider(
1858
+ groupShutListName,
1859
+ groupShutListProvider
1860
+ );
1861
+ log?.("info", `\u7FA4\u7981\u8A00\u5217\u8868\u53D8\u91CF\u5DF2\u6CE8\u518C: ${groupShutListName}`);
1862
+ }
1594
1863
  const randomProvider = createRandomProvider({ config });
1595
1864
  const randomName = String(config.random?.variableName || "random").trim();
1596
1865
  if (randomName) {
@@ -1626,7 +1895,7 @@ function apply(ctx, config) {
1626
1895
  xmlRuntime?.stop();
1627
1896
  xmlRuntime = null;
1628
1897
  };
1629
- if (config.enablePokeXmlTool || config.enableEmojiXmlTool || config.enableDeleteXmlTool) {
1898
+ if (config.enablePokeXmlTool || config.enableEmojiXmlTool || config.enableDeleteXmlTool || config.enableBanXmlTool) {
1630
1899
  ctx.inject(["chatluna_character"], (innerCtx) => {
1631
1900
  characterCtx = innerCtx;
1632
1901
  if (!xmlRuntime) return;
@@ -1664,9 +1933,11 @@ function apply(ctx, config) {
1664
1933
  createCharacterTempXmlRuntime,
1665
1934
  createDeleteMessageTool,
1666
1935
  createGroupInfoProvider,
1936
+ createGroupShutListProvider,
1667
1937
  createLogger,
1668
1938
  createPokeTool,
1669
1939
  createRandomProvider,
1940
+ createSetGroupBanTool,
1670
1941
  createSetGroupCardTool,
1671
1942
  createSetMsgEmojiTool,
1672
1943
  createSetProfileTool,
@@ -1682,6 +1953,7 @@ function apply(ctx, config) {
1682
1953
  registerXmlTools,
1683
1954
  resolveOneBotProtocol,
1684
1955
  sendDeleteMessage,
1956
+ sendGroupBan,
1685
1957
  sendMsgEmoji,
1686
1958
  sendPoke
1687
1959
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-chatluna-toolbox",
3
- "description": "为 ChatLuna 提供更多原生工具、XML 工具与变量。",
4
- "version": "0.0.7",
3
+ "description": "为 ChatLuna 提供更多原生工具、XML 工具与变量,仅支持 onebot 平台。",
4
+ "version": "0.0.9",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -10,7 +10,7 @@
10
10
  "license": "MIT",
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "git+https://github.com/Sor85/koishi-plugin-chatluna-toolbox.git"
13
+ "url": "https://github.com/Sor85/koishi-plugins.git"
14
14
  },
15
15
  "keywords": [
16
16
  "chatbot",