mioku-plugin-admin 2.3.4 → 3.0.0

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.
@@ -1,18 +1,30 @@
1
- import type { AISkill } from "mioku";
1
+ import type { AISkill, Bot, MessageEvent } from "mioku";
2
+
2
3
  import { getImageUrlByMessageId } from "./message-image";
3
4
 
5
+ import type { MessageSegment } from "mioku";
6
+
7
+ interface SkillRuntimeContext {
8
+ ctx?: {
9
+ segment: { text(text: string): MessageSegment };
10
+ logger?: { error?: (...args: unknown[]) => void };
11
+ };
12
+ event?: MessageEvent;
13
+ rawEvent?: MessageEvent;
14
+ }
15
+
4
16
  function parseProfileSex(value: string): 0 | 1 | 2 {
5
- const normalized = String(value || "")
6
- .trim()
7
- .toLowerCase();
8
- if (normalized === "男" || normalized === "male" || normalized === "1")
9
- return 1;
10
- if (normalized === "女" || normalized === "female" || normalized === "2")
11
- return 2;
17
+ const normalized = String(value || "").trim().toLowerCase();
18
+ if (normalized === "男" || normalized === "male" || normalized === "1") return 1;
19
+ if (normalized === "女" || normalized === "female" || normalized === "2") return 2;
12
20
  return 0;
13
21
  }
14
22
 
15
- function logAdminSkillError(runtimeCtx: any, toolName: string, err: unknown) {
23
+ function logAdminSkillError(
24
+ runtimeCtx: SkillRuntimeContext | undefined,
25
+ toolName: string,
26
+ err: unknown,
27
+ ) {
16
28
  runtimeCtx?.ctx?.logger?.error?.(
17
29
  `[admin skills] ${toolName} failed: ${String(err)}`,
18
30
  );
@@ -22,7 +34,7 @@ const personalSkill: AISkill = {
22
34
  name: "admin_personal",
23
35
  description:
24
36
  "Bot个人账号与消息管理统一入口:修改Bot资料、发送消息、获取列表、管理关系",
25
- permission: "owner",
37
+ permission: "master",
26
38
  tools: [
27
39
  {
28
40
  name: "manage_personal",
@@ -51,10 +63,7 @@ const personalSkill: AISkill = {
51
63
  type: "number",
52
64
  description: "包含图片的消息 message_id,仅 set_avatar 需要",
53
65
  },
54
- nickname: {
55
- type: "string",
56
- description: "新昵称,仅 set_nickname 需要",
57
- },
66
+ nickname: { type: "string", description: "新昵称,仅 set_nickname 需要" },
58
67
  personal_note: {
59
68
  type: "string",
60
69
  description: "新个性签名,仅 set_signature 需要",
@@ -79,94 +88,72 @@ const personalSkill: AISkill = {
79
88
  },
80
89
  required: ["action"],
81
90
  },
82
- handler: async (args: any, runtimeCtx?: any) => {
91
+ handler: async (args: unknown, runtimeCtx?: SkillRuntimeContext) => {
83
92
  const ctx = runtimeCtx?.ctx;
84
93
  if (!ctx) return { error: "无法获取上下文" };
85
- const event = runtimeCtx?.event || runtimeCtx?.rawEvent;
86
- const selfId = event?.self_id;
87
- if (!selfId) return { error: "无法获取Bot ID" };
88
- const bot = ctx.pickBot(selfId);
94
+ const event = runtimeCtx?.event ?? runtimeCtx?.rawEvent;
95
+ if (!event) return { error: "无法获取事件" };
96
+ const bot = event.bot;
89
97
  if (!bot) return { error: "Bot不可用" };
90
- const action = String(args?.action || "");
98
+ const a = args as Record<string, unknown>;
99
+ const action = String(a?.action ?? "");
91
100
 
92
101
  try {
93
102
  switch (action) {
94
103
  case "set_avatar": {
95
- const messageId = Number(args?.message_id);
104
+ const messageId = Number(a?.message_id);
96
105
  if (!Number.isFinite(messageId) || messageId <= 0) {
97
106
  return { error: "set_avatar 需要提供有效的 message_id" };
98
107
  }
99
108
  const imageUrl = await getImageUrlByMessageId(bot, messageId);
100
- if (!imageUrl) {
101
- return { error: "指定 message_id 中未找到图片" };
102
- }
103
- await bot.api("set_qq_avatar", { file: imageUrl });
109
+ if (!imageUrl) return { error: "指定 message_id 中未找到图片" };
110
+ await bot.setAvatar(imageUrl);
104
111
  return { success: true, message: "Bot头像已修改" };
105
112
  }
106
113
  case "set_nickname": {
107
- const nickname = String(args?.nickname || "").trim();
108
- if (!nickname) {
109
- return { error: "set_nickname 需要提供 nickname" };
110
- }
111
- await bot.api("set_qq_profile", { nickname });
112
- return {
113
- success: true,
114
- message: `Bot昵称已修改为: ${nickname}`,
115
- };
114
+ const nickname = String(a?.nickname ?? "").trim();
115
+ if (!nickname) return { error: "set_nickname 需要提供 nickname" };
116
+ await bot.setProfile({ nickname });
117
+ return { success: true, message: `Bot昵称已修改为: ${nickname}` };
116
118
  }
117
119
  case "set_signature": {
118
- const personalNote = String(args?.personal_note || "").trim();
119
- if (!personalNote) {
120
- return { error: "set_signature 需要提供 personal_note" };
121
- }
122
- await bot.api("set_qq_profile", { personal_note: personalNote });
120
+ const personalNote = String(a?.personal_note ?? "").trim();
121
+ if (!personalNote) return { error: "set_signature 需要提供 personal_note" };
122
+ await bot.setProfile({ personal_note: personalNote });
123
123
  return { success: true, message: "Bot个性签名已修改" };
124
124
  }
125
125
  case "set_gender": {
126
- const sex = parseProfileSex(args?.gender);
127
- await bot.api("set_qq_profile", { sex });
128
- const genderMap: Record<number, string> = {
129
- 0: "无",
130
- 1: "男",
131
- 2: "女",
132
- };
133
- return {
134
- success: true,
135
- message: `Bot性别已修改为: ${genderMap[sex]}`,
136
- };
126
+ const sex = parseProfileSex(String(a?.gender ?? ""));
127
+ await bot.setProfile({ sex });
128
+ const genderMap: Record<number, string> = { 0: "无", 1: "男", 2: "女" };
129
+ return { success: true, message: `Bot性别已修改为: ${genderMap[sex]}` };
137
130
  }
138
131
  case "send_private": {
139
- const userId = Number(args?.user_id);
140
- const content = String(args?.content || "");
141
- if (!userId || !content) {
142
- return { error: "send_private 需要提供 user_id 和 content" };
143
- }
144
- await bot.sendPrivateMsg(userId, [ctx.segment.text(content)]);
145
- return {
146
- success: true,
147
- message: `已发送私聊消息给 ${userId}`,
148
- };
132
+ const userId = Number(a?.user_id);
133
+ const content = String(a?.content ?? "");
134
+ if (!userId || !content) return { error: "send_private 需要提供 user_id 和 content" };
135
+ await bot.sendMessage(
136
+ { type: "private", user_id: userId},
137
+ [ctx.segment.text(content)],
138
+ );
139
+ return { success: true, message: `已发送私聊消息给 ${userId}` };
149
140
  }
150
141
  case "send_group": {
151
- const groupId = Number(args?.group_id);
152
- const content = String(args?.content || "");
153
- if (!groupId || !content) {
154
- return { error: "send_group 需要提供 group_id 和 content" };
155
- }
156
- await bot.sendGroupMsg(groupId, [ctx.segment.text(content)]);
157
- return {
158
- success: true,
159
- message: `已发送群消息到 ${groupId}`,
160
- };
142
+ const groupId = Number(a?.group_id);
143
+ const content = String(a?.content ?? "");
144
+ if (!groupId || !content) return { error: "send_group 需要提供 group_id 和 content" };
145
+ await bot.sendMessage(
146
+ { type: "group", group_id: groupId},
147
+ [ctx.segment.text(content)],
148
+ );
149
+ return { success: true, message: `已发送群消息到 ${groupId}` };
161
150
  }
162
151
  case "list_friends": {
163
- if (event?.message_type === "group") {
164
- return { error: "在私聊使用试试看吧~" };
165
- }
166
- const friendList: any[] = await bot.api("get_friend_list");
152
+ if (event?.message_type === "group") return { error: "在私聊使用试试看吧~" };
153
+ const friendList = await bot.getFriendList();
167
154
  if (!Array.isArray(friendList)) return { friends: [] };
168
155
  return {
169
- friends: friendList.map((f) => ({
156
+ friends: friendList.map((f: { user_id?: unknown; nickname?: unknown; remark?: unknown }) => ({
170
157
  user_id: f.user_id,
171
158
  nickname: f.nickname,
172
159
  remark: f.remark,
@@ -174,13 +161,11 @@ const personalSkill: AISkill = {
174
161
  };
175
162
  }
176
163
  case "list_groups": {
177
- if (event?.message_type === "group") {
178
- return { error: "在私聊使用试试看吧~" };
179
- }
180
- const groupList: any[] = await bot.api("get_group_list");
164
+ if (event?.message_type === "group") return { error: "在私聊使用试试看吧~" };
165
+ const groupList = await bot.getGroupList();
181
166
  if (!Array.isArray(groupList)) return { groups: [] };
182
167
  return {
183
- groups: groupList.map((g) => ({
168
+ groups: groupList.map((g: { group_id?: unknown; group_name?: unknown; member_count?: unknown }) => ({
184
169
  group_id: g.group_id,
185
170
  group_name: g.group_name,
186
171
  member_count: g.member_count,
@@ -188,33 +173,22 @@ const personalSkill: AISkill = {
188
173
  };
189
174
  }
190
175
  case "delete_friend": {
191
- const userId = Number(args?.user_id);
192
- if (!userId) {
193
- return { error: "delete_friend 需要提供 user_id" };
194
- }
195
- await bot.api("delete_friend", { user_id: userId });
176
+ const userId = Number(a?.user_id);
177
+ if (!userId) return { error: "delete_friend 需要提供 user_id" };
178
+ await bot.deleteFriend(userId);
196
179
  return { success: true, message: `已删除好友 ${userId}` };
197
180
  }
198
181
  case "leave_group": {
199
- const groupId = Number(args?.group_id);
200
- if (!groupId) {
201
- return { error: "leave_group 需要提供 group_id" };
202
- }
203
- await bot.api("set_group_leave", {
204
- group_id: groupId,
205
- is_dismiss: false,
206
- });
182
+ const groupId = Number(a?.group_id);
183
+ if (!groupId) return { error: "leave_group 需要提供 group_id" };
184
+ await bot.leaveGroup(groupId, false);
207
185
  return { success: true, message: `已退出群 ${groupId}` };
208
186
  }
209
187
  default:
210
188
  return { error: `未知的 action: ${action}` };
211
189
  }
212
190
  } catch (err) {
213
- logAdminSkillError(
214
- runtimeCtx,
215
- `admin_personal.manage_personal.${action}`,
216
- err,
217
- );
191
+ logAdminSkillError(runtimeCtx, `admin_personal.manage_personal.${action}`, err);
218
192
  return { error: `执行 ${action} 失败: ${err}` };
219
193
  }
220
194
  },
@@ -222,4 +196,4 @@ const personalSkill: AISkill = {
222
196
  ],
223
197
  };
224
198
 
225
- export default personalSkill;
199
+ export default personalSkill;
package/verify/chiral.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { MiokiContext } from "mioki";
1
+ import type { MiokuContext } from "mioku";
2
2
  import type { VerifyConfig } from "./config";
3
3
  import type { PendingVerify } from "./types";
4
4
 
@@ -41,11 +41,11 @@ async function fetchChiralCaptcha(
41
41
  }
42
42
 
43
43
  export async function prepareChiral(
44
- ctx: MiokiContext,
44
+ ctx: MiokuContext,
45
45
  cfg: VerifyConfig,
46
46
  p: PendingVerify,
47
47
  ): Promise<boolean> {
48
- const bot = ctx.pickBot(p.selfId);
48
+ const bot = p.bot;
49
49
  if (!bot) return false;
50
50
  try {
51
51
  const captcha = await fetchChiralCaptcha(cfg.chiralApiUrl, cfg.chiralDifficulty);
@@ -55,7 +55,7 @@ export async function prepareChiral(
55
55
  "{count}",
56
56
  String(captcha.regions.length),
57
57
  );
58
- await bot.sendGroupMsg(p.groupId, [
58
+ await bot.sendMessage({ type: "group", group_id: p.groupId}, [
59
59
  ctx.segment.at(String(p.userId)),
60
60
  ctx.segment.text(` ${prompt}`),
61
61
  ctx.segment.image(captcha.imageDataUrl),
package/verify/index.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { MiokiContext } from "mioki";
1
+ import type { Bot, MiokuContext, RouteEvent } from "mioku";
2
+
2
3
  import { existsSync } from "fs";
3
4
  import { getMemberRole } from "../config";
4
5
  import { resolveMemberName, triggerSingleWelcome } from "../notify/welcome";
@@ -50,21 +51,17 @@ export function createVerifyController(
50
51
  }
51
52
  }
52
53
 
53
- async function recallMessage(bot: any, messageId: number) {
54
+ async function recallMessage(bot: Bot, messageId: number) {
54
55
  try {
55
- await bot.api("delete_msg", { message_id: messageId });
56
+ await bot.recallMessage(messageId);
56
57
  } catch (err) {
57
58
  ctx.logger.warn(`admin verify 撤回消息失败: ${err}`);
58
59
  }
59
60
  }
60
61
 
61
- async function kickMember(bot: any, groupId: number, userId: number) {
62
+ async function kickMember(bot: Bot, groupId: number, userId: number) {
62
63
  try {
63
- await bot.api("set_group_kick", {
64
- group_id: groupId,
65
- user_id: userId,
66
- reject_add_request: false,
67
- });
64
+ await bot.kickMember(groupId, userId, false);
68
65
  } catch (err) {
69
66
  ctx.logger.warn(`admin verify 踢出成员失败: ${err}`);
70
67
  }
@@ -78,20 +75,32 @@ export function createVerifyController(
78
75
  }
79
76
  }
80
77
 
81
- async function passVerification(p: PendingVerify) {
78
+ async function passVerification(p: PendingVerify, bot?: Bot) {
82
79
  if (p.passed) return;
83
80
  p.passed = true;
84
81
  clearTimers(p);
85
82
  pending.delete(pendingKey(p.selfId, p.groupId, p.userId));
86
83
 
87
- if (p.mode === "reaction" && p.promptMessageId) {
88
- const bot = ctx.pickBot(p.selfId);
89
- if (bot) {
90
- try {
91
- await bot.addReaction(p.promptMessageId, PASS_REACTION_EMOJI_ID);
92
- } catch (err) {
93
- ctx.logger.warn(`admin verify 通过表态失败: ${err}`);
84
+ if (
85
+ p.mode === "reaction" &&
86
+ p.promptMessageId &&
87
+ bot &&
88
+ (bot.adapter === "onebotv11" || bot.adapter === "icqq")
89
+ ) {
90
+ try {
91
+ if (bot.adapter === "onebotv11") {
92
+ // onebot:set_msg_emoji_like 专属 action
93
+ await bot.sendApi("set_msg_emoji_like", {
94
+ message_id: p.promptMessageId,
95
+ emoji_id: PASS_REACTION_EMOJI_ID,
96
+ set: true,
97
+ });
98
+ } else {
99
+ // icqq:Group.setReaction(0x9082)
100
+ await bot.setReaction(p.promptMessageId, PASS_REACTION_EMOJI_ID, true);
94
101
  }
102
+ } catch (err) {
103
+ ctx.logger.warn(`admin verify 通过表态失败: ${err}`);
95
104
  }
96
105
  }
97
106
 
@@ -102,7 +111,7 @@ export function createVerifyController(
102
111
  groupId: p.groupId,
103
112
  userId: p.userId,
104
113
  groupName: p.groupName,
105
- });
114
+ }, bot);
106
115
  if (customSent) return;
107
116
  await triggerSingleWelcome({
108
117
  ctx,
@@ -120,33 +129,33 @@ export function createVerifyController(
120
129
  }
121
130
  }
122
131
 
123
- async function failKick(p: PendingVerify, reason: string) {
132
+ async function failKick(p: PendingVerify, reason: string, bot?: Bot) {
124
133
  clearTimers(p);
125
134
  pending.delete(pendingKey(p.selfId, p.groupId, p.userId));
126
135
  const cfg = getVerifyConfig();
127
136
  if (!cfg.kickOnFail) return;
128
- const bot = ctx.pickBot(p.selfId);
129
- if (!bot) return;
137
+ const target = bot ?? p.bot;
138
+ if (!target) return;
130
139
  ctx.logger.info(
131
140
  `admin verify 踢出群 ${p.groupId} 用户 ${p.userId}(${reason})`,
132
141
  );
133
- await kickMember(bot, p.groupId, p.userId);
142
+ await kickMember(target, p.groupId, p.userId);
134
143
  }
135
144
 
136
- async function timeoutExpire(p: PendingVerify) {
145
+ async function timeoutExpire(p: PendingVerify, bot?: Bot) {
137
146
  p.timeoutTimer = null;
138
147
  const cfg = getVerifyConfig();
139
148
  if (!cfg.kickOnTimeout) {
140
149
  pending.delete(pendingKey(p.selfId, p.groupId, p.userId));
141
150
  return;
142
151
  }
143
- const bot = ctx.pickBot(p.selfId);
144
- if (!bot) {
152
+ const target = bot ?? p.bot;
153
+ if (!target) {
145
154
  pending.delete(pendingKey(p.selfId, p.groupId, p.userId));
146
155
  return;
147
156
  }
148
157
  try {
149
- await bot.sendGroupMsg(p.groupId, [
158
+ await target.sendMessage({ type: "group", group_id: p.groupId}, [
150
159
  ctx.segment.at(String(p.userId)),
151
160
  ctx.segment.text(" 验证超时啦,下次再来哦~"),
152
161
  ]);
@@ -154,25 +163,25 @@ export function createVerifyController(
154
163
  ctx.logger.warn(`admin verify 超时提示发送失败: ${err}`);
155
164
  }
156
165
  ctx.logger.info(`admin verify 超时踢出群 ${p.groupId} 用户 ${p.userId}`);
157
- await kickMember(bot, p.groupId, p.userId);
166
+ await kickMember(target, p.groupId, p.userId);
158
167
  pending.delete(pendingKey(p.selfId, p.groupId, p.userId));
159
168
  }
160
169
 
161
170
  async function startVerification(
162
171
  info: MemberJoinInfo,
172
+ bot?: Bot,
163
173
  skipDelay = false,
164
174
  ): Promise<boolean> {
165
175
  const cfg = getVerifyConfig();
166
176
  const groupCfg = getGroupVerifyConfig(cfg, info.groupId);
167
177
  if (!groupCfg.enabled) return false;
168
178
 
169
- const bot = ctx.pickBot(info.selfId);
170
179
  if (!bot) return false;
171
180
 
172
181
  const botRole = await getMemberRole(bot, info.groupId, info.selfId);
173
182
  if (botRole !== "owner" && botRole !== "admin") {
174
183
  try {
175
- await bot.sendGroupMsg(info.groupId, [
184
+ await bot.sendMessage({ type: "group", group_id: info.groupId}, [
176
185
  ctx.segment.text("我在不是管理员,没法入群验证啦,本群验证已关闭~"),
177
186
  ]);
178
187
  } catch (err) {
@@ -188,9 +197,9 @@ export function createVerifyController(
188
197
  const mode = groupCfg.mode;
189
198
  const memberName = await resolveMemberName(
190
199
  ctx,
200
+ bot,
191
201
  info.groupId,
192
202
  info.userId,
193
- info.selfId,
194
203
  );
195
204
 
196
205
  const entry: PendingVerify = {
@@ -200,6 +209,7 @@ export function createVerifyController(
200
209
  memberName,
201
210
  groupName: info.groupName,
202
211
  mode,
212
+ bot,
203
213
  invalidCount: 0,
204
214
  startedAt: Date.now(),
205
215
  passed: false,
@@ -232,7 +242,7 @@ export function createVerifyController(
232
242
 
233
243
  entry.timeoutTimer = setTimeout(
234
244
  () => {
235
- void timeoutExpire(entry);
245
+ void timeoutExpire(entry, bot);
236
246
  },
237
247
  Math.max(1000, cfg.verifyTimeoutMs),
238
248
  );
@@ -240,7 +250,7 @@ export function createVerifyController(
240
250
  return true;
241
251
  }
242
252
 
243
- async function onGroupMessage(event: any) {
253
+ async function onGroupMessage(event: RouteEvent<"message.group">) {
244
254
  if (event?.message_type !== "group") return;
245
255
  const selfId = Number(event?.self_id || 0);
246
256
  const groupId = Number(event?.group_id || 0);
@@ -255,23 +265,23 @@ export function createVerifyController(
255
265
  const cfg = getVerifyConfig();
256
266
  const text = ctx.text(event) || "";
257
267
  const messageId = Number(event?.message_id || 0);
258
- const bot = ctx.pickBot(selfId);
268
+ const bot = event.bot;
259
269
 
260
270
  if (p.mode === "number" && isNumberAnswerCorrect(p, text)) {
261
- await passVerification(p);
271
+ await passVerification(p, bot);
262
272
  return;
263
273
  }
264
274
 
265
275
  if (p.mode === "chiral") {
266
276
  const result = checkChiralAnswer(p, text);
267
277
  if (result.status === "pass") {
268
- await passVerification(p);
278
+ await passVerification(p, bot);
269
279
  return;
270
280
  }
271
281
  if (result.status === "progress") {
272
282
  if (bot) {
273
283
  try {
274
- await bot.sendGroupMsg(groupId, [
284
+ await bot.sendMessage({ type: "group", group_id: groupId}, [
275
285
  ctx.segment.at(String(userId)),
276
286
  ctx.segment.text(` 答对一部分啦,还差 ${result.remaining} 个哦~`),
277
287
  ]);
@@ -289,30 +299,31 @@ export function createVerifyController(
289
299
 
290
300
  p.invalidCount += 1;
291
301
  if (p.invalidCount >= cfg.maxInvalidMessages) {
292
- await failKick(p, `连续 ${cfg.maxInvalidMessages} 次无关消息`);
302
+ await failKick(p, `连续 ${cfg.maxInvalidMessages} 次无关消息`, bot);
293
303
  }
294
304
  }
295
305
 
296
- async function onGroupReaction(event: any) {
306
+ async function onGroupReaction(event: RouteEvent<"notice.group.reaction">) {
297
307
  const selfId = Number(event?.self_id || 0);
298
308
  const groupId = Number(event?.group_id || 0);
299
309
  const userId = Number(event?.user_id || 0);
300
310
  if (!selfId || !groupId || !userId) return;
301
311
  if (userId === selfId) return;
302
- if (event?.is_add === false) return;
312
+ const raw = event.raw as { is_add?: boolean } | undefined;
313
+ if (raw?.is_add === false) return;
303
314
 
304
315
  const key = pendingKey(selfId, groupId, userId);
305
316
  const p = pending.get(key);
306
317
  if (!p || p.passed || p.mode !== "reaction") return;
307
318
 
308
319
  if (isReactionPass(p, event)) {
309
- await passVerification(p);
320
+ await passVerification(p, event.bot);
310
321
  }
311
322
  }
312
323
 
313
324
  const messageDispose = ctx.handle(
314
- "message.group" as any,
315
- async (event: any) => {
325
+ "message.group",
326
+ async (event) => {
316
327
  try {
317
328
  await onGroupMessage(event);
318
329
  } catch (err) {
@@ -322,8 +333,8 @@ export function createVerifyController(
322
333
  );
323
334
 
324
335
  const reactionDispose = ctx.handle(
325
- "notice.group.reaction" as any,
326
- async (event: any) => {
336
+ "notice.group.reaction",
337
+ async (event) => {
327
338
  try {
328
339
  await onGroupReaction(event);
329
340
  } catch (err) {
@@ -333,8 +344,8 @@ export function createVerifyController(
333
344
  );
334
345
 
335
346
  const decreaseDispose = ctx.handle(
336
- "notice.group.decrease" as any,
337
- async (event: any) => {
347
+ "notice.group.decrease",
348
+ async (event) => {
338
349
  const selfId = Number(event?.self_id || 0);
339
350
  const groupId = Number(event?.group_id || 0);
340
351
  const userId = Number(event?.user_id || 0);
@@ -348,20 +359,23 @@ export function createVerifyController(
348
359
  },
349
360
  );
350
361
 
351
- async function restartVerification(info: MemberJoinInfo): Promise<boolean> {
362
+ async function restartVerification(info: MemberJoinInfo, bot?: Bot): Promise<boolean> {
352
363
  removePending(pendingKey(info.selfId, info.groupId, info.userId));
353
- return startVerification(info, true);
364
+ return startVerification(info, bot, true);
354
365
  }
355
366
 
356
367
  async function bypassVerification(info: MemberJoinInfo): Promise<void> {
357
368
  removePending(pendingKey(info.selfId, info.groupId, info.userId));
358
369
  }
359
370
 
360
- async function trySendCustomWelcome(info: MemberJoinInfo): Promise<boolean> {
371
+ async function trySendCustomWelcome(
372
+ info: MemberJoinInfo,
373
+ bot?: Bot,
374
+ ): Promise<boolean> {
361
375
  const groupCfg = getGroupVerifyConfig(getVerifyConfig(), info.groupId);
362
376
  if (!hasCustomPrompt(groupCfg)) return false;
363
- const bot = ctx.pickBot(info.selfId);
364
377
  if (!bot) return false;
378
+ const target = bot;
365
379
  const segments: any[] = [];
366
380
  const prompt = String(groupCfg.customPrompt || "").trim();
367
381
  if (prompt) {
@@ -380,7 +394,7 @@ export function createVerifyController(
380
394
  }
381
395
  if (!segments.length) return false;
382
396
  try {
383
- await bot.sendGroupMsg(info.groupId, segments);
397
+ await target.sendMessage({ type: "group", group_id: info.groupId}, segments);
384
398
  return true;
385
399
  } catch (err) {
386
400
  ctx.logger.error(`admin verify 发送自定义入群提示失败: ${err}`);
package/verify/number.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { MiokiContext } from "mioki";
1
+ import type { MiokuContext } from "mioku";
2
2
  import type { VerifyConfig } from "./config";
3
3
  import type { PendingVerify } from "./types";
4
4
 
@@ -17,17 +17,17 @@ function extractNumbers(text: string): number[] {
17
17
  }
18
18
 
19
19
  export async function sendNumberPrompt(
20
- ctx: MiokiContext,
20
+ ctx: MiokuContext,
21
21
  cfg: VerifyConfig,
22
22
  p: PendingVerify,
23
23
  ): Promise<void> {
24
- const bot = ctx.pickBot(p.selfId);
24
+ const bot = p.bot;
25
25
  if (!bot) return;
26
26
  const { question, answer } = genNumberQuestion();
27
27
  p.numberAnswer = answer;
28
28
  const prompt = cfg.numberPrompt.replace("{question}", question);
29
29
  try {
30
- await bot.sendGroupMsg(p.groupId, [
30
+ await bot.sendMessage({ type: "group", group_id: p.groupId}, [
31
31
  ctx.segment.at(String(p.userId)),
32
32
  ctx.segment.text(` ${prompt}`),
33
33
  ]);