mioku-plugin-admin 2.3.5 → 3.0.1

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/config.ts CHANGED
@@ -101,25 +101,34 @@ export function parseDuration(text: string): number {
101
101
  return 0;
102
102
  }
103
103
 
104
+ import type { Bot } from "mioku";
105
+
106
+
107
+ interface SegmentLike {
108
+ type: string;
109
+ data?: Record<string, unknown>;
110
+ }
111
+
104
112
  // 从消息中提取图片URL
105
- export function extractImageUrl(message: RecvElement[]): string | undefined {
113
+ export function extractImageUrl(message: readonly SegmentLike[] | null | undefined): string | undefined {
106
114
  if (!Array.isArray(message)) return undefined;
107
115
  for (const seg of message) {
108
116
  if (seg.type === "image") {
109
- const imageSeg = seg as RecvImageElement;
110
- return imageSeg.url || imageSeg.file;
117
+ const data = seg.data ?? {};
118
+ const url = String(data.url ?? data.file ?? "");
119
+ return url || undefined;
111
120
  }
112
121
  }
113
122
  return undefined;
114
123
  }
115
124
 
116
- export function extractImageUrls(message: RecvElement[]): string[] {
125
+ export function extractImageUrls(message: readonly SegmentLike[] | null | undefined): string[] {
117
126
  if (!Array.isArray(message)) return [];
118
127
  const urls: string[] = [];
119
128
  for (const seg of message) {
120
129
  if (seg.type === "image") {
121
- const imageSeg = seg as RecvImageElement;
122
- const url = String(imageSeg.url || imageSeg.file || "").trim();
130
+ const data = seg.data ?? {};
131
+ const url = String(data.url ?? data.file ?? "").trim();
123
132
  if (url) urls.push(url);
124
133
  }
125
134
  }
@@ -127,34 +136,37 @@ export function extractImageUrls(message: RecvElement[]): string[] {
127
136
  }
128
137
 
129
138
  // 从消息中提取被@的人的QQ号
130
- export function getAtUserId(message: RecvElement[]): number | undefined {
139
+ export function getAtUserId(message: readonly SegmentLike[] | null | undefined): number | undefined {
131
140
  if (!Array.isArray(message)) return undefined;
132
141
  const atSeg = message.find(
133
- (seg): seg is RecvAtElement => seg.type === "at" && seg.qq !== "all",
142
+ (seg) =>
143
+ seg.type === "at" &&
144
+ String(seg.data?.qq ?? seg.data?.target) !== "all",
134
145
  );
135
146
  if (!atSeg) return undefined;
136
- const qq = Number(atSeg.qq);
147
+ const qq = Number(atSeg.data?.qq ?? atSeg.data?.target);
137
148
  return Number.isFinite(qq) ? qq : undefined;
138
149
  }
139
150
 
140
151
  // 获取群成员头像URL
141
- export function getAvatarUrl(userId: number): string {
142
- return `https://q1.qlogo.cn/g?b=qq&nk=${userId}&s=640`;
152
+ export function getAvatarUrl(userId: number | string): string {
153
+ return `https://q1.qlogo.cn/g?b=qq&nk=${String(userId)}&s=640`;
143
154
  }
144
155
 
145
156
  // 获取群头像URL
146
- export function getGroupAvatarUrl(groupId: number): string {
147
- return `https://p.qlogo.cn/gh/${groupId}/${groupId}/640/`;
157
+ export function getGroupAvatarUrl(groupId: number | string): string {
158
+ const g = String(groupId);
159
+ return `https://p.qlogo.cn/gh/${g}/${g}/640/`;
148
160
  }
149
161
 
150
162
  // 获取Bot群成员角色
151
163
  export async function getMemberRole(
152
- bot: any,
153
- groupId: number,
154
- userId: number,
164
+ bot: Bot,
165
+ groupId: string | number,
166
+ userId: string | number,
155
167
  ): Promise<string> {
156
168
  try {
157
- const info = await bot.getGroupMemberInfo(groupId, userId);
169
+ const info = await bot.getMemberInfo(groupId, userId);
158
170
  return info?.role || "member";
159
171
  } catch {
160
172
  return "member";
package/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { definePlugin, type MiokiContext } from "mioki";
1
+ import { definePlugin, type MiokuContext } from "mioku";
2
2
  import {
3
3
  setPluginRuntimeState,
4
4
  resetPluginRuntimeState,
@@ -21,16 +21,14 @@ import { registerWelcomeHandler } from "./notify/welcome";
21
21
  import { createVerifyController } from "./verify";
22
22
 
23
23
  interface RuntimeState {
24
- ctx?: MiokiContext;
24
+ ctx?: MiokuContext;
25
25
  config?: AdminConfig;
26
26
  }
27
27
 
28
28
  export default definePlugin({
29
29
  name: "admin",
30
- version: "1.0.0",
31
- description: "管理插件,提供事件通知与群管/个人管理指令",
32
30
 
33
- async setup(ctx: MiokiContext) {
31
+ async setup(ctx: MiokuContext) {
34
32
  const configService = getService(ctx, Services.Config);
35
33
  const aiService = getService(ctx, Services.AI);
36
34
 
@@ -91,8 +89,8 @@ export default definePlugin({
91
89
  ctx,
92
90
  aiService,
93
91
  getConfig,
94
- (info) => verifyController.handleMemberJoin(info),
95
- (info) => verifyController.trySendCustomWelcome(info),
92
+ (info, bot) => verifyController.handleMemberJoin(info, bot),
93
+ (info, bot) => verifyController.trySendCustomWelcome(info, bot),
96
94
  );
97
95
 
98
96
  // 注册入群验证指令
package/notify/index.ts CHANGED
@@ -1,30 +1,18 @@
1
- import { botConfig, type MiokiContext } from "mioki";
2
1
  import type {
3
- FriendRequestEvent,
4
- GroupBanNoticeEvent,
5
- GroupDecreaseNoticeEvent,
6
- GroupInviteRequestEvent,
7
2
  MessageEvent,
8
- PrivateMessageEvent,
9
- RecvAtElement,
10
- RecvElement,
11
- RecvFaceElement,
12
- RecvFileElement,
13
- RecvForwardElement,
14
- RecvImageElement,
15
- RecvJsonElement,
16
- RecvRecordElement,
17
- RecvReplyElement,
18
- RecvTextElement,
19
- RecvVideoElement,
20
- } from "napcat-sdk";
3
+ MessageSegment,
4
+ MiokuContext,
5
+ NoticeEvent,
6
+ RequestEvent,
7
+ } from "mioku";
8
+ import {botConfig} from "mioku";
21
9
  import type { AdminConfig } from "../config";
22
10
  import { formatDuration, getAvatarUrl, getGroupAvatarUrl } from "../config";
23
11
 
24
12
  interface NotifyPayload {
25
13
  avatarUrl?: string;
26
14
  lines: string[];
27
- rawSegments?: any[];
15
+ rawSegments?: MessageSegment[];
28
16
  }
29
17
 
30
18
  interface PendingFriendRequest {
@@ -32,6 +20,8 @@ interface PendingFriendRequest {
32
20
  userId: number;
33
21
  flag: string;
34
22
  createdAt: number;
23
+ approve: () => Promise<void>;
24
+ reject: (reason?: string) => Promise<void>;
35
25
  }
36
26
 
37
27
  interface PendingGroupInvite {
@@ -41,6 +31,8 @@ interface PendingGroupInvite {
41
31
  flag: string;
42
32
  subType: string;
43
33
  createdAt: number;
34
+ approve: () => Promise<void>;
35
+ reject: (reason?: string) => Promise<void>;
44
36
  }
45
37
 
46
38
  const PENDING_TTL_MS = 24 * 60 * 60 * 1000;
@@ -66,7 +58,7 @@ function getNotifyOwners(config: AdminConfig): number[] {
66
58
 
67
59
  /** 注册所有事件通知处理器 */
68
60
  export function registerNotificationHandlers(
69
- ctx: MiokiContext,
61
+ ctx: MiokuContext,
70
62
  getConfig: () => AdminConfig,
71
63
  ) {
72
64
  const pendingFriendRequests: PendingFriendRequest[] = [];
@@ -121,8 +113,8 @@ export function registerNotificationHandlers(
121
113
  return true;
122
114
  }
123
115
 
124
- function buildNotifyMessage(payload: NotifyPayload): any[] {
125
- const message: any[] = [];
116
+ function buildNotifyMessage(payload: NotifyPayload): MessageSegment[] {
117
+ const message: MessageSegment[] = [];
126
118
  if (payload.avatarUrl) {
127
119
  message.push(ctx.segment.image(payload.avatarUrl));
128
120
  }
@@ -139,82 +131,60 @@ export function registerNotificationHandlers(
139
131
  return message.length > 0 ? message : [ctx.segment.text("")];
140
132
  }
141
133
 
142
- function normalizeIncomingSegments(segments: RecvElement[]): any[] {
134
+ function normalizeIncomingSegments(segments: readonly MessageSegment[]): MessageSegment[] {
143
135
  if (!Array.isArray(segments)) return [];
144
136
  return segments
145
137
  .map((seg) => {
146
- if (!seg || typeof seg !== "object") return null;
147
- const type = String(seg.type || "");
148
-
149
- if (!type) return null;
150
-
151
- if (type === "text") {
152
- const text = String((seg as RecvTextElement).text || "");
153
- return text ? ctx.segment.text(text) : null;
154
- }
155
-
156
- if (type === "image" || type === "record" || type === "video") {
157
- const mediaSeg = seg as
158
- | RecvImageElement
159
- | RecvRecordElement
160
- | RecvVideoElement;
161
- const source = String(mediaSeg.url || mediaSeg.file || "").trim();
162
- if (!source) return null;
163
- if (type === "image") {
164
- return ctx.segment.image(source);
138
+ const data = seg.data as Record<string, unknown>;
139
+ switch (seg.type) {
140
+ case "text": {
141
+ const text = String(data.text ?? "").trim();
142
+ return text ? ctx.segment.text(text) : null;
165
143
  }
166
- if (type === "record") {
167
- return (ctx.segment as any).record(source);
144
+ case "image": {
145
+ const source = String(data.url ?? data.file ?? "").trim();
146
+ return source ? ctx.segment.image(source) : null;
168
147
  }
169
- return (ctx.segment as any).video(source);
170
- }
171
-
172
- if (type === "file") {
173
- const fileSeg = seg as RecvFileElement;
174
- const source = String(fileSeg.url || fileSeg.file || "").trim();
175
- if (!source) return null;
176
- return (ctx.segment as any).file(source);
177
- }
178
-
179
- if (type === "at") {
180
- const qq = (seg as RecvAtElement).qq;
181
- if (qq == null) return null;
182
- return ctx.segment.at(String(qq));
183
- }
184
-
185
- if (type === "face") {
186
- const id = (seg as RecvFaceElement).id;
187
- if (id == null) return null;
188
- return ctx.segment.face(Number(id));
189
- }
190
-
191
- if (type === "reply") {
192
- const id = (seg as RecvReplyElement).id;
193
- if (id == null) return null;
194
- return ctx.segment.reply(String(id));
195
- }
196
-
197
- if (type === "forward") {
198
- const id = (seg as RecvForwardElement).id;
199
- if (id == null) return null;
200
- return (ctx.segment as any).forward?.(String(id)) ?? null;
201
- }
202
-
203
- if (type === "json") {
204
- const data = (seg as RecvJsonElement).data;
205
- if (type === "json" && ctx.segment.json) {
206
- return ctx.segment.json(data);
148
+ case "record": {
149
+ const source = String(data.file ?? data.url ?? "").trim();
150
+ return source ? ctx.segment.raw("record", { file: source }) : null;
151
+ }
152
+ case "video": {
153
+ const source = String(data.file ?? data.url ?? "").trim();
154
+ return source ? ctx.segment.raw("video", { file: source }) : null;
155
+ }
156
+ case "file": {
157
+ const source = String(data.file ?? data.url ?? "").trim();
158
+ return source ? ctx.segment.raw("file", { file: source }) : null;
159
+ }
160
+ case "at": {
161
+ const target = String(data.qq ?? data.target ?? "");
162
+ return target ? ctx.segment.at(target) : null;
163
+ }
164
+ case "face": {
165
+ const id = data.id;
166
+ return id == null ? null : ctx.segment.raw("face", { id: String(id) });
167
+ }
168
+ case "reply": {
169
+ const id = data.message_id ?? data.id;
170
+ return id == null ? null : ctx.segment.reply(String(id));
207
171
  }
208
- return null;
172
+ case "forward": {
173
+ const id = data.id;
174
+ return id == null ? null : ctx.segment.raw("forward", { id: String(id) });
175
+ }
176
+ case "json": {
177
+ return ctx.segment.raw("json", data);
178
+ }
179
+ default:
180
+ return seg;
209
181
  }
210
-
211
- return null;
212
182
  })
213
- .filter(Boolean);
183
+ .filter((seg): seg is MessageSegment => seg !== null);
214
184
  }
215
185
 
216
- function isOwnerPrivateMessage(event: PrivateMessageEvent): boolean {
217
- if (ctx.isOwner?.(event)) {
186
+ function isOwnerPrivateMessage(event: MessageEvent): boolean {
187
+ if (ctx.isMaster?.(event)) {
218
188
  return true;
219
189
  }
220
190
  const userId = Number(event.user_id || 0);
@@ -224,19 +194,18 @@ export function registerNotificationHandlers(
224
194
  return owners().includes(userId);
225
195
  }
226
196
 
227
- async function sendNotify(selfId: number, payload: NotifyPayload) {
228
- const bot = ctx.pickBot(selfId);
197
+ async function sendNotify(bot: import("mioku").Bot | undefined, payload: NotifyPayload) {
229
198
  if (!bot) return;
230
199
  for (const ownerId of owners()) {
231
200
  try {
232
- await bot.sendPrivateMsg(ownerId, buildNotifyMessage(payload));
201
+ await bot.sendMessage({ type: "private", user_id: ownerId}, buildNotifyMessage(payload));
233
202
  } catch (err) {
234
203
  ctx.logger.error(`admin notify owner ${ownerId} failed: ${err}`);
235
204
  }
236
205
  }
237
206
  }
238
207
 
239
- function pushPendingFriendRequest(event: FriendRequestEvent) {
208
+ function pushPendingFriendRequest(event: RequestEvent) {
240
209
  const selfId = Number(event.self_id || 0);
241
210
  const userId = Number(event.user_id || 0);
242
211
  const flag = String(event.flag || "").trim();
@@ -246,11 +215,13 @@ export function registerNotificationHandlers(
246
215
  userId,
247
216
  flag,
248
217
  createdAt: Date.now(),
218
+ approve: () => event.approve(),
219
+ reject: (reason?: string) => event.reject(reason),
249
220
  });
250
221
  prunePendingRequests();
251
222
  }
252
223
 
253
- function pushPendingGroupInvite(event: GroupInviteRequestEvent) {
224
+ function pushPendingGroupInvite(event: RequestEvent) {
254
225
  const selfId = Number(event.self_id || 0);
255
226
  const groupId = Number(event.group_id || 0);
256
227
  const userId = Number(event.user_id || 0);
@@ -264,6 +235,8 @@ export function registerNotificationHandlers(
264
235
  flag,
265
236
  subType,
266
237
  createdAt: Date.now(),
238
+ approve: () => event.approve(),
239
+ reject: (reason?: string) => event.reject(reason),
267
240
  });
268
241
  prunePendingRequests();
269
242
  }
@@ -299,12 +272,12 @@ export function registerNotificationHandlers(
299
272
  return undefined;
300
273
  }
301
274
 
302
- function extractTextFromSegments(segments: RecvElement[]): string {
275
+ function extractTextFromSegments(segments: readonly MessageSegment[]): string {
303
276
  if (!Array.isArray(segments)) return "";
304
277
  return segments
305
278
  .map((seg) => {
306
279
  if (seg.type !== "text") return "";
307
- return String((seg as RecvTextElement).text || "");
280
+ return String((seg.data as Record<string, unknown>).text ?? "");
308
281
  })
309
282
  .join("")
310
283
  .trim();
@@ -313,7 +286,7 @@ export function registerNotificationHandlers(
313
286
  async function resolveQuotedText(event: MessageEvent): Promise<string> {
314
287
  if (!event.quote_id) return "";
315
288
  try {
316
- const quoted = await event.getQuoteMsg();
289
+ const quoted = await event.bot.getMessage(event.quote_id);
317
290
  return extractTextFromSegments(quoted?.message || []);
318
291
  } catch {
319
292
  return "";
@@ -369,13 +342,10 @@ export function registerNotificationHandlers(
369
342
  return null;
370
343
  }
371
344
 
372
- function extractReplyPayloadSegments(event: MessageEvent): any[] {
373
- return normalizeIncomingSegments(event?.message || []).filter(
374
- (seg: any) => {
375
- const type = String(seg?.type || "");
376
- return type !== "reply";
377
- },
378
- );
345
+ function extractReplyPayloadSegments(event: MessageEvent): MessageSegment[] {
346
+ return normalizeIncomingSegments(event?.message || []).filter((seg) => {
347
+ return seg.type !== "reply";
348
+ });
379
349
  }
380
350
 
381
351
  function isApproveText(text: string): boolean {
@@ -389,7 +359,7 @@ export function registerNotificationHandlers(
389
359
  }
390
360
 
391
361
  async function notifyGroupInvite(
392
- event: GroupInviteRequestEvent,
362
+ event: RequestEvent,
393
363
  ): Promise<void> {
394
364
  if (!getConfig().notifyGroupInvite) return;
395
365
 
@@ -405,7 +375,7 @@ export function registerNotificationHandlers(
405
375
  pushPendingGroupInvite(event);
406
376
 
407
377
  const comment = event.comment || "无";
408
- await sendNotify(selfId, {
378
+ await sendNotify(event.bot, {
409
379
  avatarUrl: getGroupAvatarUrl(groupId),
410
380
  lines: [
411
381
  "[群邀请]",
@@ -417,26 +387,27 @@ export function registerNotificationHandlers(
417
387
  });
418
388
  }
419
389
 
420
- async function notifyGroupBan(event: GroupBanNoticeEvent): Promise<void> {
390
+ async function notifyGroupBan(event: NoticeEvent): Promise<void> {
421
391
  const selfId = Number(event.self_id || 0);
422
392
  const groupId = Number(event.group_id || 0);
423
393
  const userId = Number(event.user_id || 0);
424
- const duration = Number(event.duration || 0);
394
+ const rawBan = event.raw as { action_type?: string; duration?: number } | undefined;
395
+ const duration = Number(rawBan?.duration || 0);
425
396
  if (!selfId || !groupId) return;
426
397
  if (userId !== selfId) return;
427
398
 
428
399
  const operatorId = Number(event.operator_id || 0);
429
- const isUnban = event.action_type === "lift_ban";
400
+ const isUnban = rawBan?.action_type === "lift_ban";
430
401
  if (isUnban) {
431
402
  if (!getConfig().notifyGroupUnban) return;
432
403
  } else if (!getConfig().notifyGroupBan) {
433
404
  return;
434
405
  }
435
406
 
436
- const eventKey = `group-ban:${selfId}:${groupId}:${operatorId}:${duration}:${event.action_type}:${Number(event.time || 0)}`;
407
+ const eventKey = `group-ban:${selfId}:${groupId}:${operatorId}:${duration}:${rawBan?.action_type}:${Number(event.time || 0)}`;
437
408
  if (!markEventOnce(eventKey)) return;
438
409
 
439
- await sendNotify(selfId, {
410
+ await sendNotify(event.bot, {
440
411
  avatarUrl: getGroupAvatarUrl(groupId),
441
412
  lines: [
442
413
  isUnban ? "[Bot被解除禁言]" : "[Bot被禁言]",
@@ -449,14 +420,15 @@ export function registerNotificationHandlers(
449
420
  }
450
421
 
451
422
  async function notifyGroupKick(
452
- event: GroupDecreaseNoticeEvent,
423
+ event: NoticeEvent,
453
424
  ): Promise<void> {
454
425
  if (!getConfig().notifyGroupKick) return;
455
426
 
456
427
  const selfId = Number(event.self_id || 0);
457
428
  const groupId = Number(event.group_id || 0);
458
429
  const userId = Number(event.user_id || 0);
459
- const leaveType = String((event as any).action_type || "").trim();
430
+ const rawKick = event.raw as { action_type?: string } | undefined;
431
+ const leaveType = String(rawKick?.action_type || "").trim();
460
432
  if (!selfId || !groupId) return;
461
433
  if (userId !== selfId) return;
462
434
  if (leaveType !== "kick" && leaveType !== "kick_me") return;
@@ -465,7 +437,7 @@ export function registerNotificationHandlers(
465
437
  const eventKey = `group-kick:${selfId}:${groupId}:${operatorId}:${leaveType}:${Number(event.time || 0)}`;
466
438
  if (!markEventOnce(eventKey)) return;
467
439
 
468
- await sendNotify(selfId, {
440
+ await sendNotify(event.bot, {
469
441
  avatarUrl:
470
442
  operatorId > 0 ? getAvatarUrl(operatorId) : getGroupAvatarUrl(groupId),
471
443
  lines: ["[Bot被踢]", `群号:${groupId}`, `操作者QQ:${operatorId}`],
@@ -473,16 +445,16 @@ export function registerNotificationHandlers(
473
445
  }
474
446
 
475
447
  // 好友私聊消息通知
476
- ctx.handle("message.private", async (event: PrivateMessageEvent) => {
448
+ ctx.handle("message.private", async (event) => {
477
449
  if (!getConfig().notifyFriendMsg) return;
478
450
  if (event.user_id === event.self_id) return;
479
451
  if (isOwnerPrivateMessage(event)) return;
480
452
 
481
- const userId = event.user_id;
482
- const nickname = event.sender?.nickname || String(userId);
453
+ const userId = String(event.user_id ?? "");
454
+ const nickname = event.sender?.nickname || userId;
483
455
  const rawSegments = normalizeIncomingSegments(event.message || []);
484
456
 
485
- await sendNotify(event.self_id, {
457
+ await sendNotify(event.bot, {
486
458
  avatarUrl: getAvatarUrl(userId),
487
459
  lines: [
488
460
  "[好友消息]",
@@ -496,14 +468,14 @@ export function registerNotificationHandlers(
496
468
  });
497
469
 
498
470
  // 好友申请通知
499
- ctx.handle("request.friend", async (event: FriendRequestEvent) => {
471
+ ctx.handle("request.friend", async (event) => {
500
472
  pushPendingFriendRequest(event);
501
473
  if (!getConfig().notifyFriendRequest) return;
502
474
 
503
- const userId = event.user_id;
475
+ const userId = String(event.user_id ?? "");
504
476
  const comment = event.comment || "无";
505
477
 
506
- await sendNotify(event.self_id, {
478
+ await sendNotify(event.bot, {
507
479
  avatarUrl: getAvatarUrl(userId),
508
480
  lines: [
509
481
  "[好友申请]",
@@ -515,27 +487,27 @@ export function registerNotificationHandlers(
515
487
  });
516
488
 
517
489
  // 群邀请通知
518
- ctx.handle("request.group.invite", async (event: GroupInviteRequestEvent) => {
490
+ ctx.handle("request.group.invite", async (event) => {
519
491
  await notifyGroupInvite(event);
520
492
  });
521
493
 
522
494
  // Bot被禁言通知
523
- ctx.handle("notice.group.ban", async (event: GroupBanNoticeEvent) => {
495
+ ctx.handle("notice.group.ban", async (event) => {
524
496
  await notifyGroupBan(event);
525
497
  });
526
498
 
527
499
  // Bot被踢通知
528
500
  ctx.handle(
529
501
  "notice.group.decrease",
530
- async (event: GroupDecreaseNoticeEvent) => {
502
+ async (event) => {
531
503
  await notifyGroupKick(event);
532
504
  },
533
505
  );
534
506
 
535
507
  // 引用回复处理
536
- ctx.handle("message", async (event: MessageEvent) => {
508
+ ctx.handle("message", async (event) => {
537
509
  if (event.message_type !== "private") return;
538
- if (!ctx.isOwner?.(event)) return;
510
+ if (!ctx.isMaster?.(event)) return;
539
511
 
540
512
  const quotedText = await resolveQuotedText(event);
541
513
  if (!quotedText) {
@@ -549,7 +521,7 @@ export function registerNotificationHandlers(
549
521
  const text = (ctx.text(event) || "").trim();
550
522
 
551
523
  const selfId = Number(event.self_id || 0);
552
- const bot = ctx.pickBot(selfId);
524
+ const bot = event.bot;
553
525
  if (!bot) {
554
526
  await event.reply("Bot不可用", true);
555
527
  return;
@@ -562,7 +534,7 @@ export function registerNotificationHandlers(
562
534
  return;
563
535
  }
564
536
  try {
565
- await bot.sendPrivateMsg(target.userId, payload);
537
+ await bot.sendMessage({ type: "private", user_id: target.userId}, payload);
566
538
  await event.reply("done");
567
539
  } catch (err) {
568
540
  ctx.logger.error(
@@ -585,10 +557,11 @@ export function registerNotificationHandlers(
585
557
  }
586
558
 
587
559
  try {
588
- await bot.api("set_friend_add_request", {
589
- flag: pending.flag,
590
- approve: isApproveText(text),
591
- });
560
+ if (isApproveText(text)) {
561
+ await pending.approve();
562
+ } else {
563
+ await pending.reject();
564
+ }
592
565
  await event.reply("done");
593
566
  } catch (err) {
594
567
  ctx.logger.error(
@@ -605,10 +578,7 @@ export function registerNotificationHandlers(
605
578
  return;
606
579
  }
607
580
  try {
608
- await bot.api("set_group_leave", {
609
- group_id: target.groupId,
610
- is_dismiss: false,
611
- });
581
+ await bot.leaveGroup(String(target.groupId), false);
612
582
  await event.reply("done");
613
583
  } catch (err) {
614
584
  ctx.logger.error(
@@ -636,11 +606,11 @@ export function registerNotificationHandlers(
636
606
  }
637
607
 
638
608
  try {
639
- await bot.api("set_group_add_request", {
640
- flag: pending.flag,
641
- sub_type: pending.subType || "invite",
642
- approve: isApproveText(text),
643
- });
609
+ if (isApproveText(text)) {
610
+ await pending.approve();
611
+ } else {
612
+ await pending.reject();
613
+ }
644
614
  await event.reply("done");
645
615
  } catch (err) {
646
616
  ctx.logger.error(