@napuketto/adapter 0.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.
@@ -0,0 +1,3695 @@
1
+ import { a as ActionRegistry, n as BaseProtocolAdapter, r as BaseAction } from "../core-Bj5L8WeZ.mjs";
2
+ import { ChatType, GrayTipSubType, GroupApi, GroupNotifyMsgType, NTGroupMemberRole, NTGroupRequestOperateTypes, TicketApi, TipGroupElementType, WebHonorType, kernelError, toCanonicalElements } from "@napuketto/kernel";
3
+ import { z } from "zod";
4
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
5
+ import { basename, join } from "node:path";
6
+ import { HttpClient, HttpServer, WsClient, WsServer } from "@napuketto/network";
7
+ //#region src/onebot11/action/error-map.ts
8
+ /** OB11 错误码映射表(send_msg 等所有 OB11 动作共用)。 */
9
+ const ob11ErrorCodeMap = {
10
+ SEND_FAILED: 100,
11
+ PERMISSION_DENIED: 101,
12
+ NOT_FOUND: 102,
13
+ TIMEOUT: 103,
14
+ NOT_LOGIN: 104,
15
+ INVALID_PARAM: 105,
16
+ INVALID_STATE: 106,
17
+ UNKNOWN: 999
18
+ };
19
+ //#endregion
20
+ //#region src/onebot11/action/friend/delete-friend.ts
21
+ /**
22
+ * delete_friend 动作:删除好友(P2-11 接 kernel FriendApi.deleteFriend)
23
+ */
24
+ const deleteFriendSchema = z.object({ user_id: z.number() });
25
+ /** 删除好友(P2-11 接 kernel deleteFriend)。 */
26
+ var DeleteFriendAction = class extends BaseAction {
27
+ name = "delete_friend";
28
+ schema = deleteFriendSchema;
29
+ errorCodeMap = ob11ErrorCodeMap;
30
+ deps;
31
+ constructor(deps) {
32
+ super();
33
+ this.deps = deps;
34
+ }
35
+ async _handle(payload) {
36
+ const uid = (await this.deps.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
37
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
38
+ await this.deps.friendApi.deleteFriend(uid);
39
+ return null;
40
+ }
41
+ };
42
+ //#endregion
43
+ //#region src/onebot11/action/friend/get-doubt-friends-add-request.ts
44
+ const getDoubtFriendsAddRequestSchema = z.object({ count: z.number().optional() });
45
+ /** 默认获取数量。 */
46
+ const DEFAULT_COUNT$3 = 50;
47
+ /** 获取可疑好友申请(P2-11 接 kernel getDoubtFriendRequest)。 */
48
+ var GetDoubtFriendsAddRequestAction = class extends BaseAction {
49
+ name = "get_doubt_friends_add_request";
50
+ schema = getDoubtFriendsAddRequestSchema;
51
+ errorCodeMap = ob11ErrorCodeMap;
52
+ friendApi;
53
+ constructor(friendApi) {
54
+ super();
55
+ this.friendApi = friendApi;
56
+ }
57
+ _handle(payload) {
58
+ return this.friendApi.getDoubtFriendRequest(payload.count ?? DEFAULT_COUNT$3);
59
+ }
60
+ };
61
+ //#endregion
62
+ //#region src/onebot11/action/friend/get-friend-list.ts
63
+ const getFriendListSchema = z.object({
64
+ /** 是否忽略缓存(go-cqhttp 扩展)。 */
65
+ no_cache: z.boolean().optional() });
66
+ /** 获取好友列表(P2-4 接 kernel apis/friend)。 */
67
+ var GetFriendListAction = class extends BaseAction {
68
+ name = "get_friend_list";
69
+ schema = getFriendListSchema;
70
+ errorCodeMap = ob11ErrorCodeMap;
71
+ friendApi;
72
+ constructor(friendApi) {
73
+ super();
74
+ this.friendApi = friendApi;
75
+ }
76
+ async _handle(_payload) {
77
+ return (await this.friendApi.getFriendList()).map((f) => {
78
+ const info = {
79
+ user_id: Number(f.uin),
80
+ nickname: f.nickname
81
+ };
82
+ if (f.remark !== "") info.remark = f.remark;
83
+ return info;
84
+ });
85
+ }
86
+ };
87
+ //#endregion
88
+ //#region src/onebot11/action/friend/get-friends-with-category.ts
89
+ const getFriendsWithCategorySchema = z.object({});
90
+ /** 获取好友列表(含分类,P2-11 接 kernel getFriendCategories)。 */
91
+ var GetFriendsWithCategoryAction = class extends BaseAction {
92
+ name = "get_friends_with_category";
93
+ schema = getFriendsWithCategorySchema;
94
+ errorCodeMap = ob11ErrorCodeMap;
95
+ friendApi;
96
+ constructor(friendApi) {
97
+ super();
98
+ this.friendApi = friendApi;
99
+ }
100
+ _handle(_payload) {
101
+ return this.friendApi.getFriendCategories();
102
+ }
103
+ };
104
+ //#endregion
105
+ //#region src/onebot11/action/friend/get-stranger-info.ts
106
+ const getStrangerInfoSchema = z.object({
107
+ user_id: z.number(),
108
+ no_cache: z.boolean().optional()
109
+ });
110
+ /** 获取陌生人信息(P2-15 接 kernel ProfileApi)。 */
111
+ var GetStrangerInfoAction = class extends BaseAction {
112
+ name = "get_stranger_info";
113
+ schema = getStrangerInfoSchema;
114
+ errorCodeMap = ob11ErrorCodeMap;
115
+ profileApi;
116
+ constructor(profileApi) {
117
+ super();
118
+ this.profileApi = profileApi;
119
+ }
120
+ async _handle(payload) {
121
+ return {
122
+ ...await this.profileApi.getStrangerInfo(String(payload.user_id)),
123
+ user_id: payload.user_id
124
+ };
125
+ }
126
+ };
127
+ //#endregion
128
+ //#region src/onebot11/action/friend/send-like.ts
129
+ /**
130
+ * send_like 动作:点赞(P2-14 接 kernel ProfileLikeApi.sendLike)
131
+ */
132
+ const sendLikeSchema = z.object({
133
+ user_id: z.number(),
134
+ times: z.number().optional()
135
+ });
136
+ /** 点赞(P2-14 接 kernel ProfileLikeApi)。 */
137
+ var SendLikeAction = class extends BaseAction {
138
+ name = "send_like";
139
+ schema = sendLikeSchema;
140
+ errorCodeMap = ob11ErrorCodeMap;
141
+ deps;
142
+ constructor(deps) {
143
+ super();
144
+ this.deps = deps;
145
+ }
146
+ async _handle(payload) {
147
+ const uid = (await this.deps.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
148
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
149
+ await this.deps.profileLikeApi.sendLike(uid, payload.times ?? 1);
150
+ return null;
151
+ }
152
+ };
153
+ //#endregion
154
+ //#region src/onebot11/action/friend/set-doubt-friends-add-request.ts
155
+ const setDoubtFriendsAddRequestSchema = z.object({
156
+ flag: z.string(),
157
+ approve: z.boolean().optional()
158
+ });
159
+ /** 处理可疑好友申请(P2-11 接 kernel handleDoubtFriendRequest)。 */
160
+ var SetDoubtFriendsAddRequestAction = class extends BaseAction {
161
+ name = "set_doubt_friends_add_request";
162
+ schema = setDoubtFriendsAddRequestSchema;
163
+ errorCodeMap = ob11ErrorCodeMap;
164
+ friendApi;
165
+ constructor(friendApi) {
166
+ super();
167
+ this.friendApi = friendApi;
168
+ }
169
+ _handle(payload) {
170
+ this.friendApi.handleDoubtFriendRequest(payload.flag);
171
+ return Promise.resolve(null);
172
+ }
173
+ };
174
+ //#endregion
175
+ //#region src/onebot11/action/friend/set-friend-add-request.ts
176
+ /**
177
+ * set_friend_add_request 动作:处理加好友请求(P2-11)
178
+ *
179
+ * flag=reqTime(NapCat 约定,需从好友请求事件上报中获取)→ getBuddyReqList
180
+ * 匹配 → handleFriendRequest(notify, approve) + optional remark。
181
+ */
182
+ const setFriendAddRequestSchema = z.object({
183
+ flag: z.string(),
184
+ approve: z.boolean().optional(),
185
+ remark: z.string().optional()
186
+ });
187
+ /** 处理加好友请求(P2-11 接 kernel FriendApi)。 */
188
+ var SetFriendAddRequestAction = class extends BaseAction {
189
+ name = "set_friend_add_request";
190
+ schema = setFriendAddRequestSchema;
191
+ errorCodeMap = ob11ErrorCodeMap;
192
+ friendApi;
193
+ constructor(friendApi) {
194
+ super();
195
+ this.friendApi = friendApi;
196
+ }
197
+ async _handle(payload) {
198
+ const notify = (await this.friendApi.getBuddyReqList()).find((req) => req.reqTime === payload.flag);
199
+ if (notify === void 0) throw kernelError("未找到对应的好友请求(flag 无效或已过期)", "NOT_FOUND");
200
+ await this.friendApi.handleFriendRequest(notify, payload.approve !== false);
201
+ if (payload.remark !== void 0) this.friendApi.setFriendRemark(notify.friendUid, payload.remark);
202
+ return null;
203
+ }
204
+ };
205
+ //#endregion
206
+ //#region src/onebot11/action/friend/set-friend-remark.ts
207
+ /**
208
+ * set_friend_remark 动作:设置好友备注(P2-11 接 kernel FriendApi.setFriendRemark)
209
+ */
210
+ const setFriendRemarkSchema = z.object({
211
+ user_id: z.number(),
212
+ remark: z.string()
213
+ });
214
+ /** 设置好友备注(P2-11 接 kernel setFriendRemark)。 */
215
+ var SetFriendRemarkAction = class extends BaseAction {
216
+ name = "set_friend_remark";
217
+ schema = setFriendRemarkSchema;
218
+ errorCodeMap = ob11ErrorCodeMap;
219
+ deps;
220
+ constructor(deps) {
221
+ super();
222
+ this.deps = deps;
223
+ }
224
+ async _handle(payload) {
225
+ const uid = await this.resolveUid(payload.user_id);
226
+ this.deps.friendApi.setFriendRemark(uid, payload.remark);
227
+ return null;
228
+ }
229
+ /** user_id(uin)→ uid。 */
230
+ async resolveUid(userId) {
231
+ const uid = (await this.deps.uinToUid([String(userId)])).get(String(userId));
232
+ if (uid === void 0) throw kernelError(`用户 ${userId} 的 uid 解析失败`, "INVALID_PARAM");
233
+ return uid;
234
+ }
235
+ };
236
+ //#endregion
237
+ //#region src/onebot11/helper/message-unique.ts
238
+ /** OB11 message_id 上限(int32 max = 0x7FFF_FFFF)。 */
239
+ const INT32_MAX = 2147483647;
240
+ /** int32 下限。 */
241
+ const INT32_MIN = 1;
242
+ var MessageUnique = class {
243
+ /** NT msgId → OB11 message_id。 */
244
+ msgIdToInt = /* @__PURE__ */ new Map();
245
+ /** OB11 message_id → NT msgId。 */
246
+ intToMsgId = /* @__PURE__ */ new Map();
247
+ /** NT msgId → Peer(delete_msg / get_msg 等只有 message_id 时反查用)。 */
248
+ msgIdToPeer = /* @__PURE__ */ new Map();
249
+ /** 递增计数器。 */
250
+ cursor = 1;
251
+ /** 已释放的槽位(可复用)。 */
252
+ freed = /* @__PURE__ */ new Set();
253
+ /**
254
+ * 为新 NT 消息分配 OB11 message_id(幂等:同一 msgId 返回同一 id)。
255
+ * peer 可选:传入则记录,供 message_id → peer 反查。
256
+ */
257
+ alloc(msgId, peer) {
258
+ const existing = this.msgIdToInt.get(msgId);
259
+ if (existing !== void 0) {
260
+ if (peer !== void 0) this.msgIdToPeer.set(msgId, peer);
261
+ return existing;
262
+ }
263
+ const id = this.nextFreeId();
264
+ this.msgIdToInt.set(msgId, id);
265
+ this.intToMsgId.set(id, msgId);
266
+ if (peer !== void 0) this.msgIdToPeer.set(msgId, peer);
267
+ this.freed.delete(id);
268
+ return id;
269
+ }
270
+ /** OB11 message_id → NT msgId。 */
271
+ getMsgId(messageId) {
272
+ return this.intToMsgId.get(messageId);
273
+ }
274
+ /** NT msgId → OB11 message_id(未分配返回 undefined)。 */
275
+ getMessageId(msgId) {
276
+ return this.msgIdToInt.get(msgId);
277
+ }
278
+ /** NT msgId → Peer(alloc 时未记录返回 undefined)。 */
279
+ getPeer(msgId) {
280
+ return this.msgIdToPeer.get(msgId);
281
+ }
282
+ /** 释放 NT msgId 占用的槽位(消息过期/删除时调用,可选)。 */
283
+ release(msgId) {
284
+ const id = this.msgIdToInt.get(msgId);
285
+ if (id === void 0) return;
286
+ this.msgIdToInt.delete(msgId);
287
+ this.intToMsgId.delete(id);
288
+ this.msgIdToPeer.delete(msgId);
289
+ this.freed.add(id);
290
+ }
291
+ /** 取下一个可用 id:优先释放池,否则递增(溢出后线性扫描空洞)。 */
292
+ nextFreeId() {
293
+ for (const id of this.freed) return id;
294
+ if (this.cursor > INT32_MAX) {
295
+ for (let i = INT32_MIN; i <= INT32_MAX; i += 1) if (!this.intToMsgId.has(i)) {
296
+ this.cursor = i + 1;
297
+ return i;
298
+ }
299
+ throw kernelError("MessageUnique 槽位耗尽(>2^31 条消息)", "INVALID_STATE");
300
+ }
301
+ const id = this.cursor;
302
+ this.cursor += 1;
303
+ return id;
304
+ }
305
+ };
306
+ /**
307
+ * 从 OB11 message_id 反查 NT msgId + Peer。
308
+ * delete_msg / get_msg / set_msg_emoji_like / fetch_ptt_text / 精华消息等
309
+ * 只有 message_id 参数的动作共用(消息不存在抛 KernelError NOT_FOUND)。
310
+ */
311
+ function resolveMsgIdAndPeer(messageId, unique) {
312
+ let shortId;
313
+ if (typeof messageId === "number") shortId = messageId;
314
+ else shortId = Number(messageId);
315
+ const msgId = unique.getMsgId(shortId);
316
+ if (msgId === void 0) throw kernelError(`消息 ${messageId} 不存在`, "NOT_FOUND");
317
+ const peer = unique.getPeer(msgId);
318
+ if (peer === void 0) throw kernelError(`消息 ${messageId} 无会话记录`, "NOT_FOUND");
319
+ return {
320
+ msgId,
321
+ peer
322
+ };
323
+ }
324
+ //#endregion
325
+ //#region src/onebot11/action/group/delete-essence-msg.ts
326
+ /**
327
+ * delete_essence_msg 动作:取消精华消息(P2-10 接 kernel GroupApi.removeGroupEssence)
328
+ */
329
+ const deleteEssenceMsgSchema = z.object({ message_id: z.union([z.number(), z.string()]) });
330
+ /** 取消精华消息(P2-10 接 kernel removeGroupEssence)。 */
331
+ var DeleteEssenceMsgAction = class extends BaseAction {
332
+ name = "delete_essence_msg";
333
+ schema = deleteEssenceMsgSchema;
334
+ errorCodeMap = ob11ErrorCodeMap;
335
+ deps;
336
+ constructor(deps) {
337
+ super();
338
+ this.deps = deps;
339
+ }
340
+ async _handle(payload) {
341
+ const { msgId, peer } = resolveMsgIdAndPeer(payload.message_id, this.deps.messageUnique);
342
+ if (peer.chatType !== ChatType.GROUP) throw kernelError("精华消息仅支持群聊消息", "INVALID_PARAM");
343
+ await this.deps.groupApi.removeGroupEssence(peer.peerUid, msgId);
344
+ return null;
345
+ }
346
+ };
347
+ //#endregion
348
+ //#region src/onebot11/action/group/get-essence-msg-list.ts
349
+ const getEssenceMsgListSchema = z.object({ group_id: z.number() });
350
+ /** 文本段类型(msg_content.msg_type)。 */
351
+ const MSG_TYPE_TEXT = 1;
352
+ /** 图片段类型(msg_content.msg_type)。 */
353
+ const MSG_TYPE_IMAGE = 3;
354
+ /** 获取群精华消息列表(P2-15 接 kernel WebApi)。 */
355
+ var GetEssenceMsgListAction = class extends BaseAction {
356
+ name = "get_essence_msg_list";
357
+ schema = getEssenceMsgListSchema;
358
+ errorCodeMap = ob11ErrorCodeMap;
359
+ webApi;
360
+ constructor(webApi) {
361
+ super();
362
+ this.webApi = webApi;
363
+ }
364
+ async _handle(payload) {
365
+ const list = await this.webApi.getEssenceMsgList(String(payload.group_id));
366
+ const out = [];
367
+ for (const item of list) {
368
+ const content = [];
369
+ for (const part of item.msg_content ?? []) {
370
+ const seg = toSegment(part);
371
+ if (seg !== null) content.push(seg);
372
+ }
373
+ out.push({
374
+ msg_seq: item.msg_seq,
375
+ msg_random: item.msg_random,
376
+ sender_id: Number(item.sender_uin),
377
+ sender_nick: item.sender_nick,
378
+ operator_id: Number(item.add_digest_uin),
379
+ operator_nick: item.add_digest_nick,
380
+ operator_time: item.add_digest_time,
381
+ message_id: 0,
382
+ content
383
+ });
384
+ }
385
+ return out;
386
+ }
387
+ };
388
+ /** msg_content 项 → OB11 段(1=text 3=image,纯函数)。 */
389
+ function toSegment(part) {
390
+ if (part.msg_type === MSG_TYPE_TEXT) return {
391
+ type: "text",
392
+ data: { text: part.text ?? "" }
393
+ };
394
+ if (part.msg_type === MSG_TYPE_IMAGE) return {
395
+ type: "image",
396
+ data: { file: part.image_url ?? "" }
397
+ };
398
+ return null;
399
+ }
400
+ //#endregion
401
+ //#region src/onebot11/action/group/get-group-add-request.ts
402
+ const getGroupAddRequestSchema = z.object({ count: z.number().optional() });
403
+ /** 默认获取数量。 */
404
+ const DEFAULT_COUNT$2 = 100;
405
+ /** 获取未处理群申请(P2-15)。 */
406
+ var GetGroupAddRequestAction = class extends BaseAction {
407
+ name = "get_group_add_request";
408
+ schema = getGroupAddRequestSchema;
409
+ errorCodeMap = ob11ErrorCodeMap;
410
+ groupNotifyApi;
411
+ constructor(groupNotifyApi) {
412
+ super();
413
+ this.groupNotifyApi = groupNotifyApi;
414
+ }
415
+ async _handle(payload) {
416
+ return (await this.groupNotifyApi.getSingleScreenNotifies(false, payload.count ?? DEFAULT_COUNT$2)).map(toGroupAddRequestItem);
417
+ }
418
+ };
419
+ /** 获取被忽略群申请(P2-15)。 */
420
+ var GetGroupIgnoredNotifiesAction = class extends BaseAction {
421
+ name = "get_group_ignored_notifies";
422
+ schema = getGroupAddRequestSchema;
423
+ errorCodeMap = ob11ErrorCodeMap;
424
+ groupNotifyApi;
425
+ constructor(groupNotifyApi) {
426
+ super();
427
+ this.groupNotifyApi = groupNotifyApi;
428
+ }
429
+ async _handle(payload) {
430
+ return (await this.groupNotifyApi.getSingleScreenNotifies(true, payload.count ?? DEFAULT_COUNT$2)).map(toGroupAddRequestItem);
431
+ }
432
+ };
433
+ /** GroupNotify → OB11 群请求项(纯函数)。 */
434
+ function toGroupAddRequestItem(notify) {
435
+ const { seq, type, status, postscript, user1, group } = notify;
436
+ let groupCode = 0;
437
+ let groupName = "";
438
+ if (group !== void 0) {
439
+ const { groupCode: code, groupName: name } = group;
440
+ groupCode = Number(code);
441
+ groupName = name;
442
+ }
443
+ let userId = 0;
444
+ let userNick = "";
445
+ if (user1 !== void 0) {
446
+ const { uid, nickName } = user1;
447
+ userId = Number(uid);
448
+ userNick = nickName;
449
+ }
450
+ return {
451
+ flag: seq,
452
+ group_id: groupCode,
453
+ group_name: groupName,
454
+ user_id: userId,
455
+ user_nick: userNick,
456
+ type,
457
+ checked: status !== 1,
458
+ postscript: postscript ?? ""
459
+ };
460
+ }
461
+ //#endregion
462
+ //#region src/onebot11/action/group/get-group-at-all-remain.ts
463
+ const getGroupAtAllRemainSchema = z.object({ group_id: z.number() });
464
+ /** 获取群 @全体成员 剩余次数(P2-10 接 kernel getGroupRemainAtTimes)。 */
465
+ var GetGroupAtAllRemainAction = class extends BaseAction {
466
+ name = "get_group_at_all_remain";
467
+ schema = getGroupAtAllRemainSchema;
468
+ errorCodeMap = ob11ErrorCodeMap;
469
+ groupApi;
470
+ constructor(groupApi) {
471
+ super();
472
+ this.groupApi = groupApi;
473
+ }
474
+ async _handle(payload) {
475
+ const remain = await this.groupApi.getGroupRemainAtTimes(String(payload.group_id));
476
+ return {
477
+ can_at_all: remain.canAtAll,
478
+ remain_at_all_count_for_uin: remain.remainAtAllCountForUin,
479
+ remain_at_all_count_for_group: remain.remainAtAllCountForGroup
480
+ };
481
+ }
482
+ };
483
+ //#endregion
484
+ //#region src/onebot11/action/group/get-group-honor-info.ts
485
+ const getGroupHonorInfoSchema = z.object({
486
+ group_id: z.number(),
487
+ type: z.string().optional()
488
+ });
489
+ /** 获取群荣誉信息(P2-15 接 kernel WebApi)。 */
490
+ var GetGroupHonorInfoAction = class extends BaseAction {
491
+ name = "get_group_honor_info";
492
+ schema = getGroupHonorInfoSchema;
493
+ errorCodeMap = ob11ErrorCodeMap;
494
+ webApi;
495
+ constructor(webApi) {
496
+ super();
497
+ this.webApi = webApi;
498
+ }
499
+ _handle(payload) {
500
+ const type = mapHonorType(payload.type);
501
+ return this.webApi.getGroupHonorInfo(String(payload.group_id), type);
502
+ }
503
+ };
504
+ /** type 字符串 → WebHonorType(talkative/performer/legend/emotion/all,纯函数)。 */
505
+ function mapHonorType(raw) {
506
+ if (raw === "talkative") return WebHonorType.TALKATIVE;
507
+ if (raw === "performer") return WebHonorType.PERFORMER;
508
+ if (raw === "legend") return WebHonorType.LEGEND;
509
+ if (raw === "emotion") return WebHonorType.EMOTION;
510
+ return WebHonorType.ALL;
511
+ }
512
+ //#endregion
513
+ //#region src/onebot11/helper/translate.ts
514
+ /**
515
+ * OB11 翻译辅助(NT 实体 → OB11 结构,P2-4)
516
+ *
517
+ * 纯函数(ADR-008):只读入参,不调 API、不读缓存。
518
+ * 群成员/群信息等 NT 实体 → OB11 返回结构的薄映射。
519
+ */
520
+ /** NT Group → OB11 GroupInfo。 */
521
+ function toOb11GroupInfo(group) {
522
+ const info = {
523
+ group_id: Number(group.groupCode),
524
+ group_name: group.groupName
525
+ };
526
+ if (typeof group.memberCount === "number") info.member_count = group.memberCount;
527
+ if (typeof group.maxMember === "number") info.max_member_count = group.maxMember;
528
+ return info;
529
+ }
530
+ /** NT GroupDetailInfo → OB11 GroupInfo(getGroupDetailInfo / GroupCache 用)。 */
531
+ function toOb11GroupInfoDetail(detail) {
532
+ const info = {
533
+ group_id: Number(detail.groupCode),
534
+ group_name: detail.groupName
535
+ };
536
+ if (typeof detail.memberNum === "number") info.member_count = detail.memberNum;
537
+ if (typeof detail.maxMemberNum === "number") info.max_member_count = detail.maxMemberNum;
538
+ return info;
539
+ }
540
+ /** 禁言秒 → 毫秒(shut_up_timestamp 单位)。 */
541
+ const SEC_TO_MS = 1e3;
542
+ /** NT GroupMember → OB11 GroupMemberInfo(uin 由 uidToUin 映射补全)。 */
543
+ function toOb11GroupMemberInfo(groupCode, member, uidToUin) {
544
+ let uinStr = member.uin;
545
+ if (uinStr === "") uinStr = uidToUin.get(member.uid) ?? member.uid;
546
+ const info = {
547
+ group_id: Number(groupCode),
548
+ user_id: Number(uinStr),
549
+ nickname: member.nick,
550
+ role: GroupApi.roleToString(member.role)
551
+ };
552
+ if (member.cardName !== "") info.card = member.cardName;
553
+ if (member.memberSpecialTitle !== void 0 && member.memberSpecialTitle !== "") {
554
+ info.title = member.memberSpecialTitle;
555
+ info.special_title = member.memberSpecialTitle;
556
+ }
557
+ if (member.shutUpTime > 0) info.shut_up_timestamp = member.shutUpTime * SEC_TO_MS;
558
+ if (member.joinTime !== "" && member.joinTime !== "0") info.join_time = Number(member.joinTime);
559
+ if (member.lastSpeakTime !== "" && member.lastSpeakTime !== "0") info.last_sent_time = Number(member.lastSpeakTime);
560
+ if (typeof member.age === "number") info.age = member.age;
561
+ return info;
562
+ }
563
+ //#endregion
564
+ //#region src/onebot11/action/group/get-group-info.ts
565
+ /**
566
+ * get_group_info 动作:获取群信息(P2-4 接 kernel GroupApi;P2-17 读缓存)
567
+ */
568
+ const getGroupInfoSchema = z.object({
569
+ group_id: z.number(),
570
+ /** 是否忽略缓存(go-cqhttp 扩展)。 */
571
+ no_cache: z.boolean().optional()
572
+ });
573
+ /** 获取群信息(P2-4 接 kernel apis/group;P2-17 优先读 GroupCache)。 */
574
+ var GetGroupInfoAction = class extends BaseAction {
575
+ name = "get_group_info";
576
+ schema = getGroupInfoSchema;
577
+ errorCodeMap = ob11ErrorCodeMap;
578
+ deps;
579
+ constructor(deps) {
580
+ super();
581
+ this.deps = deps;
582
+ }
583
+ async _handle(payload) {
584
+ const groupCode = String(payload.group_id);
585
+ if (payload.no_cache !== true && this.deps.groupCache !== void 0) return toOb11GroupInfoDetail(await this.deps.groupCache.getGroupDetail(groupCode));
586
+ return toOb11GroupInfoDetail(await this.deps.groupApi.getGroupInfo(groupCode));
587
+ }
588
+ };
589
+ //#endregion
590
+ //#region src/onebot11/action/group/get-group-list.ts
591
+ const getGroupListSchema = z.object({
592
+ /** 是否忽略缓存(go-cqhttp 扩展)。 */
593
+ no_cache: z.boolean().optional() });
594
+ /** 获取群列表(P2-4 接 kernel apis/group)。 */
595
+ var GetGroupListAction = class extends BaseAction {
596
+ name = "get_group_list";
597
+ schema = getGroupListSchema;
598
+ errorCodeMap = ob11ErrorCodeMap;
599
+ groupApi;
600
+ constructor(groupApi) {
601
+ super();
602
+ this.groupApi = groupApi;
603
+ }
604
+ async _handle(payload) {
605
+ return (await this.groupApi.getGroupList(payload.no_cache === true)).map(toOb11GroupInfo);
606
+ }
607
+ };
608
+ //#endregion
609
+ //#region src/onebot11/action/group/get-group-member-info.ts
610
+ /**
611
+ * get_group_member_info 动作:获取群成员信息(P2-4 接 kernel GroupApi;P2-17 读缓存)
612
+ */
613
+ const getGroupMemberInfoSchema = z.object({
614
+ group_id: z.number(),
615
+ user_id: z.number(),
616
+ /** 是否忽略缓存(go-cqhttp 扩展)。 */
617
+ no_cache: z.boolean().optional()
618
+ });
619
+ /** 获取群成员信息(P2-4 接 kernel apis/group;P2-17 优先读 GroupCache)。 */
620
+ var GetGroupMemberInfoAction = class extends BaseAction {
621
+ name = "get_group_member_info";
622
+ schema = getGroupMemberInfoSchema;
623
+ errorCodeMap = ob11ErrorCodeMap;
624
+ deps;
625
+ constructor(deps) {
626
+ super();
627
+ this.deps = deps;
628
+ }
629
+ async _handle(payload) {
630
+ const groupCode = String(payload.group_id);
631
+ const uid = (await this.deps.groupApi.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
632
+ if (uid === void 0) throw kernelError(`成员 ${payload.user_id} 不在群 ${payload.group_id}`, "NOT_FOUND");
633
+ const member = await this.resolveMember(groupCode, uid, payload.no_cache === true);
634
+ if (member === void 0) throw kernelError(`成员 ${payload.user_id} 不在群 ${payload.group_id}`, "NOT_FOUND");
635
+ return toOb11GroupMemberInfo(groupCode, member, await this.deps.groupApi.uidToUin([uid]));
636
+ }
637
+ /** 读缓存(缺省)或直查 api(no_cache=true / 未装配缓存)。 */
638
+ async resolveMember(groupCode, uid, noCache) {
639
+ if (noCache || this.deps.groupCache === void 0) {
640
+ const [member] = await this.deps.groupApi.getGroupMemberInfo(groupCode, [uid]);
641
+ return member;
642
+ }
643
+ return await this.deps.groupCache.getMember(groupCode, uid);
644
+ }
645
+ };
646
+ //#endregion
647
+ //#region src/onebot11/action/group/get-group-member-list.ts
648
+ const getGroupMemberListSchema = z.object({
649
+ group_id: z.number(),
650
+ /** 是否忽略缓存(go-cqhttp 扩展)。 */
651
+ no_cache: z.boolean().optional()
652
+ });
653
+ /** 获取群成员列表(P2-4 接 kernel apis/group;P2-17 优先读 GroupCache)。 */
654
+ var GetGroupMemberListAction = class extends BaseAction {
655
+ name = "get_group_member_list";
656
+ schema = getGroupMemberListSchema;
657
+ errorCodeMap = ob11ErrorCodeMap;
658
+ deps;
659
+ constructor(deps) {
660
+ super();
661
+ this.deps = deps;
662
+ }
663
+ async _handle(payload) {
664
+ const groupCode = String(payload.group_id);
665
+ const noCache = payload.no_cache === true;
666
+ let members;
667
+ if (noCache || this.deps.groupCache === void 0) members = await this.deps.groupApi.getGroupMemberList(groupCode, noCache);
668
+ else members = await this.deps.groupCache.getMembers(groupCode);
669
+ const uinMap = await this.deps.groupApi.uidToUin(members.map((m) => m.uid));
670
+ return members.map((m) => toOb11GroupMemberInfo(groupCode, m, uinMap));
671
+ }
672
+ };
673
+ //#endregion
674
+ //#region src/onebot11/action/group/get-group-shut-list.ts
675
+ /**
676
+ * get_group_shut_list 动作:获取群禁言列表(P2-13 接 kernel GroupNotifyApi)
677
+ *
678
+ * getGroupShutUpMemberList → [{ user_id, nickname, shut_up_time }](uin 经 uidToUin)。
679
+ */
680
+ const getGroupShutListSchema = z.object({ group_id: z.number() });
681
+ /** 获取群禁言列表(P2-13 接 kernel GroupNotifyApi)。 */
682
+ var GetGroupShutListAction = class extends BaseAction {
683
+ name = "get_group_shut_list";
684
+ schema = getGroupShutListSchema;
685
+ errorCodeMap = ob11ErrorCodeMap;
686
+ deps;
687
+ constructor(deps) {
688
+ super();
689
+ this.deps = deps;
690
+ }
691
+ async _handle(payload) {
692
+ const members = await this.deps.groupNotifyApi.getGroupShutUpMemberList(String(payload.group_id));
693
+ const uids = members.map((m) => m.uid);
694
+ let uinMap = /* @__PURE__ */ new Map();
695
+ if (uids.length > 0) uinMap = await this.deps.uidToUin(uids);
696
+ const out = [];
697
+ for (const member of members) out.push({
698
+ user_id: Number(uinMap.get(member.uid) ?? member.uin ?? member.uid),
699
+ nickname: member.nick,
700
+ shut_up_time: member.shutUpTime
701
+ });
702
+ return out;
703
+ }
704
+ };
705
+ //#endregion
706
+ //#region src/onebot11/action/group/get-group-system-msg.ts
707
+ const getGroupSystemMsgSchema = z.object({ count: z.number().optional() });
708
+ /** 默认获取数量。 */
709
+ const DEFAULT_COUNT$1 = 50;
710
+ /** 获取群系统消息(P2-13 接 kernel GroupNotifyApi)。 */
711
+ var GetGroupSystemMsgAction = class extends BaseAction {
712
+ name = "get_group_system_msg";
713
+ schema = getGroupSystemMsgSchema;
714
+ errorCodeMap = ob11ErrorCodeMap;
715
+ deps;
716
+ constructor(deps) {
717
+ super();
718
+ this.deps = deps;
719
+ }
720
+ async _handle(payload) {
721
+ const count = payload.count ?? DEFAULT_COUNT$1;
722
+ const notifies = await this.deps.groupNotifyApi.getSingleScreenNotifies(false, count);
723
+ const uinMap = await this.collectUinMap(notifies);
724
+ const invited = [];
725
+ const joined = [];
726
+ for (const notify of notifies) {
727
+ const info = toMessageInfo(notify, uinMap);
728
+ if (notify.type === GroupNotifyMsgType.INVITED_BY_MEMBER) invited.push(info);
729
+ else if (notify.type === GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS) joined.push(info);
730
+ }
731
+ const result = {
732
+ invited_requests: invited,
733
+ join_requests: joined
734
+ };
735
+ result["InvitedRequest"] = invited;
736
+ return result;
737
+ }
738
+ /** 收集全部涉及的 uid 批量转 uin(循环外一次请求)。 */
739
+ async collectUinMap(notifies) {
740
+ const uids = [];
741
+ for (const notify of notifies) {
742
+ const { user1, user2 } = notify;
743
+ if (user1 !== void 0) {
744
+ const { uid } = user1;
745
+ if (uid !== "") uids.push(uid);
746
+ }
747
+ if (user2 !== void 0) {
748
+ const { uid } = user2;
749
+ if (uid !== "") uids.push(uid);
750
+ }
751
+ }
752
+ if (uids.length === 0) return /* @__PURE__ */ new Map();
753
+ return await this.deps.uidToUin(uids);
754
+ }
755
+ };
756
+ /** GroupNotify → OB11 群系统消息结构(纯函数,uin 已批量转换)。 */
757
+ function toMessageInfo(notify, uinMap) {
758
+ const { seq, status, postscript, user1, user2, group } = notify;
759
+ let user1Uid = "";
760
+ if (user1 !== void 0) {
761
+ const { uid } = user1;
762
+ user1Uid = uid;
763
+ }
764
+ let user2Uid = "";
765
+ if (user2 !== void 0) {
766
+ const { uid } = user2;
767
+ user2Uid = uid;
768
+ }
769
+ let groupCode = 0;
770
+ let groupName = "";
771
+ if (group !== void 0) {
772
+ const { groupCode: code, groupName: name } = group;
773
+ groupCode = Number(code);
774
+ groupName = name;
775
+ }
776
+ let invitorUin = Number(user1Uid);
777
+ const mapped1 = uinMap.get(user1Uid);
778
+ if (mapped1 !== void 0) invitorUin = Number(mapped1);
779
+ let actor = Number(user2Uid);
780
+ const mapped2 = uinMap.get(user2Uid);
781
+ if (mapped2 !== void 0) actor = Number(mapped2);
782
+ let invitorNick = "";
783
+ if (user1 !== void 0) {
784
+ const { nickName } = user1;
785
+ invitorNick = nickName;
786
+ }
787
+ return {
788
+ request_id: Number(seq),
789
+ invitor_uin: invitorUin,
790
+ invitor_nick: invitorNick,
791
+ group_id: groupCode,
792
+ message: postscript ?? "",
793
+ group_name: groupName,
794
+ checked: status !== 1,
795
+ actor,
796
+ requester_nick: invitorNick
797
+ };
798
+ }
799
+ //#endregion
800
+ //#region src/onebot11/action/group/group-files-op.ts
801
+ const createGroupFileFolderSchema = z.object({
802
+ group_id: z.number(),
803
+ folder_name: z.string()
804
+ });
805
+ /** 创建群文件夹(P2-14)。 */
806
+ var CreateGroupFileFolderAction = class extends BaseAction {
807
+ name = "create_group_file_folder";
808
+ schema = createGroupFileFolderSchema;
809
+ errorCodeMap = ob11ErrorCodeMap;
810
+ richMediaApi;
811
+ constructor(richMediaApi) {
812
+ super();
813
+ this.richMediaApi = richMediaApi;
814
+ }
815
+ async _handle(payload) {
816
+ return { folder_id: await this.richMediaApi.createGroupFolder(String(payload.group_id), payload.folder_name) };
817
+ }
818
+ };
819
+ const deleteGroupFileSchema = z.object({
820
+ group_id: z.number(),
821
+ file_id: z.string(),
822
+ /** 兼容 go-cqhttp 的 file_ids 数组(取第一个)。 */
823
+ file_ids: z.array(z.string()).optional()
824
+ });
825
+ /** 删除群文件(P2-14)。 */
826
+ var DeleteGroupFileAction = class extends BaseAction {
827
+ name = "delete_group_file";
828
+ schema = deleteGroupFileSchema;
829
+ errorCodeMap = ob11ErrorCodeMap;
830
+ richMediaApi;
831
+ constructor(richMediaApi) {
832
+ super();
833
+ this.richMediaApi = richMediaApi;
834
+ }
835
+ async _handle(payload) {
836
+ const ids = payload.file_ids ?? [payload.file_id];
837
+ await this.richMediaApi.deleteGroupFile(String(payload.group_id), ids);
838
+ return null;
839
+ }
840
+ };
841
+ const deleteGroupFolderSchema = z.object({
842
+ group_id: z.number(),
843
+ folder_id: z.string()
844
+ });
845
+ /** 删除群文件夹(P2-14)。 */
846
+ var DeleteGroupFolderAction = class extends BaseAction {
847
+ name = "delete_group_folder";
848
+ schema = deleteGroupFolderSchema;
849
+ errorCodeMap = ob11ErrorCodeMap;
850
+ richMediaApi;
851
+ constructor(richMediaApi) {
852
+ super();
853
+ this.richMediaApi = richMediaApi;
854
+ }
855
+ async _handle(payload) {
856
+ await this.richMediaApi.deleteGroupFolder(String(payload.group_id), payload.folder_id);
857
+ return null;
858
+ }
859
+ };
860
+ const renameGroupFileSchema = z.object({
861
+ group_id: z.number(),
862
+ file_id: z.string(),
863
+ new_name: z.string()
864
+ });
865
+ /** 重命名群文件(P2-14)。 */
866
+ var RenameGroupFileAction = class extends BaseAction {
867
+ name = "rename_group_file";
868
+ schema = renameGroupFileSchema;
869
+ errorCodeMap = ob11ErrorCodeMap;
870
+ richMediaApi;
871
+ constructor(richMediaApi) {
872
+ super();
873
+ this.richMediaApi = richMediaApi;
874
+ }
875
+ async _handle(payload) {
876
+ await this.richMediaApi.renameGroupFile(String(payload.group_id), payload.file_id, payload.new_name);
877
+ return null;
878
+ }
879
+ };
880
+ const moveGroupFileSchema = z.object({
881
+ group_id: z.number(),
882
+ file_id: z.string(),
883
+ file_ids: z.array(z.string()).optional(),
884
+ /** 目标文件夹 ID(空为根目录)。 */
885
+ folder_id: z.string().optional()
886
+ });
887
+ /** 移动群文件(P2-14)。 */
888
+ var MoveGroupFileAction = class extends BaseAction {
889
+ name = "move_group_file";
890
+ schema = moveGroupFileSchema;
891
+ errorCodeMap = ob11ErrorCodeMap;
892
+ richMediaApi;
893
+ constructor(richMediaApi) {
894
+ super();
895
+ this.richMediaApi = richMediaApi;
896
+ }
897
+ async _handle(payload) {
898
+ const ids = payload.file_ids ?? [payload.file_id];
899
+ await this.richMediaApi.moveGroupFile(String(payload.group_id), ids, payload.folder_id ?? "");
900
+ return null;
901
+ }
902
+ };
903
+ const transGroupFileSchema = z.object({
904
+ group_id: z.number(),
905
+ file_id: z.string()
906
+ });
907
+ /** 转存群文件(P2-14)。 */
908
+ var TransGroupFileAction = class extends BaseAction {
909
+ name = "trans_group_file";
910
+ schema = transGroupFileSchema;
911
+ errorCodeMap = ob11ErrorCodeMap;
912
+ richMediaApi;
913
+ constructor(richMediaApi) {
914
+ super();
915
+ this.richMediaApi = richMediaApi;
916
+ }
917
+ async _handle(payload) {
918
+ await this.richMediaApi.transGroupFile(String(payload.group_id), payload.file_id);
919
+ return null;
920
+ }
921
+ };
922
+ //#endregion
923
+ //#region src/onebot11/action/group/group-files-query.ts
924
+ const getGroupRootFilesSchema = z.object({
925
+ group_id: z.number(),
926
+ file_count: z.number().optional()
927
+ });
928
+ /** 默认文件数量。 */
929
+ const DEFAULT_FILE_COUNT = 50;
930
+ /** 获取群根目录文件列表(P2-14 接 kernel RichMediaApi)。 */
931
+ var GetGroupRootFilesAction = class extends BaseAction {
932
+ name = "get_group_root_files";
933
+ schema = getGroupRootFilesSchema;
934
+ errorCodeMap = ob11ErrorCodeMap;
935
+ richMediaApi;
936
+ constructor(richMediaApi) {
937
+ super();
938
+ this.richMediaApi = richMediaApi;
939
+ }
940
+ async _handle(payload) {
941
+ return splitFilesAndFolders(await this.richMediaApi.getGroupFileList(String(payload.group_id), "", payload.file_count ?? DEFAULT_FILE_COUNT));
942
+ }
943
+ };
944
+ const getGroupFilesByFolderSchema = z.object({
945
+ group_id: z.number(),
946
+ folder_id: z.string(),
947
+ file_count: z.number().optional()
948
+ });
949
+ /** 获取群指定文件夹文件列表(P2-14)。 */
950
+ var GetGroupFilesByFolderAction = class extends BaseAction {
951
+ name = "get_group_files_by_folder";
952
+ schema = getGroupFilesByFolderSchema;
953
+ errorCodeMap = ob11ErrorCodeMap;
954
+ richMediaApi;
955
+ constructor(richMediaApi) {
956
+ super();
957
+ this.richMediaApi = richMediaApi;
958
+ }
959
+ async _handle(payload) {
960
+ return splitFilesAndFolders(await this.richMediaApi.getGroupFileList(String(payload.group_id), payload.folder_id, payload.file_count ?? DEFAULT_FILE_COUNT));
961
+ }
962
+ };
963
+ const getGroupFileSystemInfoSchema = z.object({ group_id: z.number() });
964
+ /** 群文件系统信息(P2-14)。 */
965
+ var GetGroupFileSystemInfoAction = class extends BaseAction {
966
+ name = "get_group_file_system_info";
967
+ schema = getGroupFileSystemInfoSchema;
968
+ errorCodeMap = ob11ErrorCodeMap;
969
+ richMediaApi;
970
+ constructor(richMediaApi) {
971
+ super();
972
+ this.richMediaApi = richMediaApi;
973
+ }
974
+ async _handle(payload) {
975
+ const info = await this.richMediaApi.getGroupFileSystemInfo(String(payload.group_id));
976
+ return {
977
+ file_count: info.fileCount,
978
+ limit_count: info.limitCount,
979
+ used_space: info.usedSpace,
980
+ total_space: info.totalSpace
981
+ };
982
+ }
983
+ };
984
+ /** 列表拆分 files/folders(fileInfo/folderInfo 取其一,纯函数)。 */
985
+ function splitFilesAndFolders(list) {
986
+ const files = [];
987
+ const folders = [];
988
+ for (const item of list) {
989
+ const file = item.fileInfo;
990
+ if (file === void 0) {
991
+ const folder = item.folderInfo;
992
+ if (folder !== void 0) folders.push(toGroupFolderInfo(folder));
993
+ } else {
994
+ const out = toGroupFileInfo(file);
995
+ files.push(out);
996
+ }
997
+ }
998
+ return {
999
+ files,
1000
+ folders
1001
+ };
1002
+ }
1003
+ /** GroupFileItemInfo → OB11 文件结构(纯函数)。 */
1004
+ function toGroupFileInfo(file) {
1005
+ const out = {
1006
+ file_id: file.fileId,
1007
+ file_name: file.fileName,
1008
+ file_size: file.fileSize
1009
+ };
1010
+ if (file.uploaderUin !== void 0) out.uploader = Number(file.uploaderUin);
1011
+ if (file.uploadTime !== void 0) out.upload_time = file.uploadTime;
1012
+ if (file.modifyTime !== void 0) out.modify_time = file.modifyTime;
1013
+ return out;
1014
+ }
1015
+ /** KernelFolderInfo → OB11 文件夹结构(纯函数)。 */
1016
+ function toGroupFolderInfo(folder) {
1017
+ return {
1018
+ folder_id: folder.folderId,
1019
+ folder_name: folder.folderName
1020
+ };
1021
+ }
1022
+ //#endregion
1023
+ //#region src/onebot11/action/group/set-essence-msg.ts
1024
+ /**
1025
+ * set_essence_msg 动作:设置精华消息(P2-10 接 kernel GroupApi.addGroupEssence)
1026
+ *
1027
+ * message_id → msgId + peer(MessageUnique 反查,需群消息)→ addGroupEssence。
1028
+ */
1029
+ const setEssenceMsgSchema = z.object({ message_id: z.union([z.number(), z.string()]) });
1030
+ /** 设置精华消息(P2-10 接 kernel addGroupEssence)。 */
1031
+ var SetEssenceMsgAction = class extends BaseAction {
1032
+ name = "set_essence_msg";
1033
+ schema = setEssenceMsgSchema;
1034
+ errorCodeMap = ob11ErrorCodeMap;
1035
+ deps;
1036
+ constructor(deps) {
1037
+ super();
1038
+ this.deps = deps;
1039
+ }
1040
+ async _handle(payload) {
1041
+ const { msgId, peer } = resolveMsgIdAndPeer(payload.message_id, this.deps.messageUnique);
1042
+ if (peer.chatType !== ChatType.GROUP) throw kernelError("精华消息仅支持群聊消息", "INVALID_PARAM");
1043
+ await this.deps.groupApi.addGroupEssence(peer.peerUid, msgId);
1044
+ return null;
1045
+ }
1046
+ };
1047
+ //#endregion
1048
+ //#region src/onebot11/action/group/set-group-add-request.ts
1049
+ /**
1050
+ * set_group_add_request 动作:处理加群请求(P2-13 接 kernel GroupNotifyApi)
1051
+ *
1052
+ * flag=seq(群请求事件上报的 flag)→ getSingleScreenNotifies(doubt, count)
1053
+ * 匹配 → handleGroupRequest(approve=true→同意 / false→拒绝,reason 默认空格)。
1054
+ */
1055
+ const setGroupAddRequestSchema = z.object({
1056
+ flag: z.string(),
1057
+ approve: z.boolean().optional(),
1058
+ reason: z.string().optional(),
1059
+ count: z.number().optional()
1060
+ });
1061
+ /** 默认搜索通知数量。 */
1062
+ const DEFAULT_COUNT = 100;
1063
+ /** 处理加群请求(P2-13 接 kernel GroupNotifyApi)。 */
1064
+ var SetGroupAddRequestAction = class extends BaseAction {
1065
+ name = "set_group_add_request";
1066
+ schema = setGroupAddRequestSchema;
1067
+ errorCodeMap = ob11ErrorCodeMap;
1068
+ groupNotifyApi;
1069
+ constructor(groupNotifyApi) {
1070
+ super();
1071
+ this.groupNotifyApi = groupNotifyApi;
1072
+ }
1073
+ async _handle(payload) {
1074
+ const count = payload.count ?? DEFAULT_COUNT;
1075
+ const notify = await this.findNotify(payload.flag, count);
1076
+ if (notify === null) throw kernelError("未找到对应的群请求(flag 无效或已过期)", "NOT_FOUND");
1077
+ let operateType = NTGroupRequestOperateTypes.KREFUSE;
1078
+ if (payload.approve !== false) operateType = NTGroupRequestOperateTypes.KAGREE;
1079
+ await this.groupNotifyApi.handleGroupRequest(false, notify, operateType, payload.reason ?? " ");
1080
+ return null;
1081
+ }
1082
+ /** 按 seq 匹配通知(先非可疑,后可疑)。 */
1083
+ async findNotify(flag, count) {
1084
+ const hit = (await this.groupNotifyApi.getSingleScreenNotifies(false, count)).find((item) => item.seq === flag);
1085
+ if (hit !== void 0) return hit;
1086
+ return (await this.groupNotifyApi.getSingleScreenNotifies(true, count)).find((item) => item.seq === flag) ?? null;
1087
+ }
1088
+ };
1089
+ //#endregion
1090
+ //#region src/onebot11/action/group/set-group-admin.ts
1091
+ /**
1092
+ * set_group_admin 动作:设置群管理员(P2-10 接 kernel GroupApi.setMemberRole)
1093
+ *
1094
+ * enable=true 设为管理员,false 取消;user_id → uinToUid。
1095
+ */
1096
+ const setGroupAdminSchema = z.object({
1097
+ group_id: z.number(),
1098
+ user_id: z.number(),
1099
+ /** 是否设为管理员。 */
1100
+ enable: z.boolean().default(true)
1101
+ });
1102
+ /** 设置群管理员(P2-10 接 kernel setMemberRole)。 */
1103
+ var SetGroupAdminAction = class extends BaseAction {
1104
+ name = "set_group_admin";
1105
+ schema = setGroupAdminSchema;
1106
+ errorCodeMap = ob11ErrorCodeMap;
1107
+ groupApi;
1108
+ constructor(groupApi) {
1109
+ super();
1110
+ this.groupApi = groupApi;
1111
+ }
1112
+ async _handle(payload) {
1113
+ const uid = (await this.groupApi.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
1114
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
1115
+ let role = NTGroupMemberRole.MEMBER;
1116
+ if (payload.enable) role = NTGroupMemberRole.ADMIN;
1117
+ this.groupApi.setMemberRole(String(payload.group_id), uid, role);
1118
+ return null;
1119
+ }
1120
+ };
1121
+ //#endregion
1122
+ //#region src/onebot11/action/group/set-group-ban.ts
1123
+ /**
1124
+ * set_group_ban 动作:群组单人禁言(P2-10 接 kernel GroupApi.setMemberShutUp)
1125
+ *
1126
+ * duration 秒(0 解除禁言);user_id → uinToUid。
1127
+ */
1128
+ const setGroupBanSchema = z.object({
1129
+ group_id: z.number(),
1130
+ user_id: z.number(),
1131
+ /** 禁言时长(秒),0 解除。 */
1132
+ duration: z.number().default(30)
1133
+ });
1134
+ /** 群组单人禁言(P2-10 接 kernel setMemberShutUp)。 */
1135
+ var SetGroupBanAction = class extends BaseAction {
1136
+ name = "set_group_ban";
1137
+ schema = setGroupBanSchema;
1138
+ errorCodeMap = ob11ErrorCodeMap;
1139
+ groupApi;
1140
+ constructor(groupApi) {
1141
+ super();
1142
+ this.groupApi = groupApi;
1143
+ }
1144
+ async _handle(payload) {
1145
+ const uid = (await this.groupApi.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
1146
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
1147
+ await this.groupApi.setMemberShutUp(String(payload.group_id), [{
1148
+ uid,
1149
+ duration: payload.duration
1150
+ }]);
1151
+ return null;
1152
+ }
1153
+ };
1154
+ //#endregion
1155
+ //#region src/onebot11/action/group/set-group-card.ts
1156
+ /**
1157
+ * set_group_card 动作:设置群名片(P2-10 接 kernel GroupApi.setMemberCardName)
1158
+ */
1159
+ const setGroupCardSchema = z.object({
1160
+ group_id: z.number(),
1161
+ user_id: z.number(),
1162
+ /** 群名片(空串清除)。 */
1163
+ card: z.string().optional().default("")
1164
+ });
1165
+ /** 设置群名片(P2-10 接 kernel setMemberCardName)。 */
1166
+ var SetGroupCardAction = class extends BaseAction {
1167
+ name = "set_group_card";
1168
+ schema = setGroupCardSchema;
1169
+ errorCodeMap = ob11ErrorCodeMap;
1170
+ groupApi;
1171
+ constructor(groupApi) {
1172
+ super();
1173
+ this.groupApi = groupApi;
1174
+ }
1175
+ async _handle(payload) {
1176
+ const uid = (await this.groupApi.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
1177
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
1178
+ this.groupApi.setMemberCardName(String(payload.group_id), uid, payload.card);
1179
+ return null;
1180
+ }
1181
+ };
1182
+ //#endregion
1183
+ //#region src/onebot11/action/group/set-group-kick.ts
1184
+ /**
1185
+ * set_group_kick 动作:群组踢人(P2-10 接 kernel GroupApi.kickMember)
1186
+ *
1187
+ * user_id(uin)→ uinToUid → kickMember(kickMemberV2)。
1188
+ */
1189
+ const setGroupKickSchema = z.object({
1190
+ group_id: z.number(),
1191
+ user_id: z.number(),
1192
+ /** 是否拒绝加群请求(拉黑)。 */
1193
+ reject_add_request: z.boolean().optional(),
1194
+ /** 踢人理由。 */
1195
+ kick_reason: z.string().optional()
1196
+ });
1197
+ /** 群组踢人(P2-10 接 kernel kickMember)。 */
1198
+ var SetGroupKickAction = class extends BaseAction {
1199
+ name = "set_group_kick";
1200
+ schema = setGroupKickSchema;
1201
+ errorCodeMap = ob11ErrorCodeMap;
1202
+ groupApi;
1203
+ constructor(groupApi) {
1204
+ super();
1205
+ this.groupApi = groupApi;
1206
+ }
1207
+ async _handle(payload) {
1208
+ const uid = await this.resolveUid(payload.user_id);
1209
+ await this.groupApi.kickMember(String(payload.group_id), [uid], payload.reject_add_request === true, payload.kick_reason ?? "");
1210
+ return null;
1211
+ }
1212
+ /** user_id(uin)→ uid。 */
1213
+ async resolveUid(userId) {
1214
+ const uid = (await this.groupApi.uinToUid([String(userId)])).get(String(userId));
1215
+ if (uid === void 0) throw kernelError(`用户 ${userId} 的 uid 解析失败`, "INVALID_PARAM");
1216
+ return uid;
1217
+ }
1218
+ };
1219
+ //#endregion
1220
+ //#region src/onebot11/action/group/set-group-leave.ts
1221
+ const setGroupLeaveSchema = z.object({
1222
+ group_id: z.number(),
1223
+ /** 是否解散群(仅群主可用)。 */
1224
+ is_dismiss: z.boolean().optional().default(false)
1225
+ });
1226
+ /** 退出群聊(P2-10 接 kernel quitGroup)。 */
1227
+ var SetGroupLeaveAction = class extends BaseAction {
1228
+ name = "set_group_leave";
1229
+ schema = setGroupLeaveSchema;
1230
+ errorCodeMap = ob11ErrorCodeMap;
1231
+ groupApi;
1232
+ constructor(groupApi) {
1233
+ super();
1234
+ this.groupApi = groupApi;
1235
+ }
1236
+ async _handle(payload) {
1237
+ await this.groupApi.quitGroup(String(payload.group_id), payload.is_dismiss);
1238
+ return null;
1239
+ }
1240
+ };
1241
+ //#endregion
1242
+ //#region src/onebot11/action/group/set-group-name.ts
1243
+ const setGroupNameSchema = z.object({
1244
+ group_id: z.number(),
1245
+ group_name: z.string()
1246
+ });
1247
+ /** 修改群名(P2-10 接 kernel modifyGroupName)。 */
1248
+ var SetGroupNameAction = class extends BaseAction {
1249
+ name = "set_group_name";
1250
+ schema = setGroupNameSchema;
1251
+ errorCodeMap = ob11ErrorCodeMap;
1252
+ groupApi;
1253
+ constructor(groupApi) {
1254
+ super();
1255
+ this.groupApi = groupApi;
1256
+ }
1257
+ async _handle(payload) {
1258
+ await this.groupApi.modifyGroupName(String(payload.group_id), payload.group_name);
1259
+ return null;
1260
+ }
1261
+ };
1262
+ //#endregion
1263
+ //#region src/onebot11/action/group/set-group-whole-ban.ts
1264
+ const setGroupWholeBanSchema = z.object({
1265
+ group_id: z.number(),
1266
+ /** 是否开启全员禁言。 */
1267
+ enable: z.boolean().default(true)
1268
+ });
1269
+ /** 群组全员禁言(P2-10 接 kernel setGroupShutUp)。 */
1270
+ var SetGroupWholeBanAction = class extends BaseAction {
1271
+ name = "set_group_whole_ban";
1272
+ schema = setGroupWholeBanSchema;
1273
+ errorCodeMap = ob11ErrorCodeMap;
1274
+ groupApi;
1275
+ constructor(groupApi) {
1276
+ super();
1277
+ this.groupApi = groupApi;
1278
+ }
1279
+ async _handle(payload) {
1280
+ await this.groupApi.setGroupShutUp(String(payload.group_id), payload.enable);
1281
+ return null;
1282
+ }
1283
+ };
1284
+ //#endregion
1285
+ //#region src/onebot11/action/message/delete-msg.ts
1286
+ /**
1287
+ * delete_msg 动作:撤回消息(P2-10 接 kernel MsgApi.recallMessage)
1288
+ *
1289
+ * OB11 标准 delete_msg 只有 message_id;peer 经 MessageUnique 反查。
1290
+ * 群聊管理员 / 私聊 2 分钟内可撤回。
1291
+ */
1292
+ const deleteMsgSchema = z.object({ message_id: z.union([z.number(), z.string()]) });
1293
+ /** 撤回消息(P2-10 接 kernel recallMessage)。 */
1294
+ var DeleteMsgAction = class extends BaseAction {
1295
+ name = "delete_msg";
1296
+ schema = deleteMsgSchema;
1297
+ errorCodeMap = ob11ErrorCodeMap;
1298
+ deps;
1299
+ constructor(deps) {
1300
+ super();
1301
+ this.deps = deps;
1302
+ }
1303
+ async _handle(payload) {
1304
+ const { msgId, peer } = resolveMsgIdAndPeer(payload.message_id, this.deps.messageUnique);
1305
+ await this.deps.msgApi.recallMessage(peer, [msgId]);
1306
+ return null;
1307
+ }
1308
+ };
1309
+ //#endregion
1310
+ //#region src/onebot11/action/message/fetch-ptt-text.ts
1311
+ /**
1312
+ * fetch_ptt_text 动作:获取语音转文字结果(NapCat 扩展,P2-10)
1313
+ *
1314
+ * message_id → msgId + peer → MsgApi.fetchPttText(内部:拉消息 → 找 PTT 元素
1315
+ * → translatePtt2Text → 再拉取读 pttElement.text)。
1316
+ */
1317
+ const fetchPttTextSchema = z.object({ message_id: z.union([z.number(), z.string()]) });
1318
+ /** 获取语音转文字结果(P2-10 接 kernel fetchPttText)。 */
1319
+ var FetchPttTextAction = class extends BaseAction {
1320
+ name = "fetch_ptt_text";
1321
+ schema = fetchPttTextSchema;
1322
+ errorCodeMap = ob11ErrorCodeMap;
1323
+ deps;
1324
+ constructor(deps) {
1325
+ super();
1326
+ this.deps = deps;
1327
+ }
1328
+ async _handle(payload) {
1329
+ const { msgId, peer } = resolveMsgIdAndPeer(payload.message_id, this.deps.messageUnique);
1330
+ return { text: await this.deps.msgApi.fetchPttText(msgId, peer) };
1331
+ }
1332
+ };
1333
+ //#endregion
1334
+ //#region src/onebot11/action/message/forward-single-msg.ts
1335
+ /**
1336
+ * forward_group_single_msg / forward_friend_single_msg 动作:单条转发(P2-12)
1337
+ *
1338
+ * message_id 反查源 msgId + peer;group_id/user_id 为目标 →
1339
+ * MsgApi.forwardSingleMessage(srcPeer, [msgId], dstPeer)。
1340
+ */
1341
+ const forwardSingleMsgSchema = z.object({
1342
+ message_id: z.union([z.number(), z.string()]),
1343
+ group_id: z.number().optional(),
1344
+ user_id: z.number().optional()
1345
+ });
1346
+ /** 解析目标 Peer(group_id 直通;user_id 经 uin→uid)。 */
1347
+ async function resolveTargetPeer(payload, deps) {
1348
+ if (payload.group_id !== void 0) return {
1349
+ chatType: ChatType.GROUP,
1350
+ peerUid: String(payload.group_id)
1351
+ };
1352
+ if (payload.user_id !== void 0) {
1353
+ const uid = (await deps.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
1354
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
1355
+ return {
1356
+ chatType: ChatType.C2C,
1357
+ peerUid: uid
1358
+ };
1359
+ }
1360
+ throw kernelError("单条转发需要 group_id 或 user_id", "INVALID_PARAM");
1361
+ }
1362
+ /** 单条转发基类(两个动作共用实现)。 */
1363
+ var ForwardSingleMsgBase = class extends BaseAction {
1364
+ errorCodeMap = ob11ErrorCodeMap;
1365
+ deps;
1366
+ constructor(deps) {
1367
+ super();
1368
+ this.deps = deps;
1369
+ }
1370
+ async _handle(payload) {
1371
+ const { msgId, peer: sourcePeer } = resolveMsgIdAndPeer(payload.message_id, this.deps.messageUnique);
1372
+ const dstPeer = await resolveTargetPeer(payload, this.deps);
1373
+ await this.deps.msgApi.forwardSingleMessage(sourcePeer, [msgId], dstPeer);
1374
+ return null;
1375
+ }
1376
+ };
1377
+ /** 转发单条消息到群(P2-12)。 */
1378
+ var ForwardGroupSingleMsgAction = class extends ForwardSingleMsgBase {
1379
+ name = "forward_group_single_msg";
1380
+ schema = forwardSingleMsgSchema;
1381
+ };
1382
+ /** 转发单条消息到好友(P2-12)。 */
1383
+ var ForwardFriendSingleMsgAction = class extends ForwardSingleMsgBase {
1384
+ name = "forward_friend_single_msg";
1385
+ schema = forwardSingleMsgSchema;
1386
+ };
1387
+ //#endregion
1388
+ //#region src/onebot11/helper/config.ts
1389
+ /**
1390
+ * OneBot 11 协议配置(zod schema,归属本包,ADR-012)
1391
+ * 协议配置 schema 在各自协议包,kernel 只提供 ConfigBase 基类。
1392
+ *
1393
+ * 2026-08-07 多实例化(P2-18):对齐 NapCat——httpServers / httpPostUrls / wsServers /
1394
+ * wsReverseUrls 四个数组实例(每实例可覆盖全局 token);旧单对象字段 http/httpPost/ws/
1395
+ * wsReverse 废弃(zod strip 静默忽略,不兼容迁移)。
1396
+ */
1397
+ /** HTTP 反向服务器默认端口。 */
1398
+ const DEFAULT_HTTP_PORT = 3e3;
1399
+ /** 反向 WS server 默认端口。 */
1400
+ const DEFAULT_WS_PORT = 3001;
1401
+ /** 心跳 meta 事件默认间隔(毫秒)。 */
1402
+ const DEFAULT_HEARTBEAT_INTERVAL_MS = 3e3;
1403
+ /** WS 传输 ping 默认间隔(毫秒)。 */
1404
+ const DEFAULT_WS_HEARTBEAT_MS = 3e4;
1405
+ /** WS 反向断线重连默认延迟(毫秒)。 */
1406
+ const DEFAULT_RECONNECT_DELAY_MS = 5e3;
1407
+ /** 消息内容格式(NapCat messagePostFormat)。 */
1408
+ const MESSAGE_FORMATS = ["array", "string"];
1409
+ /** HTTP 反向服务器实例(第三方 POST 指令入口)。 */
1410
+ const httpServerSchema = z.object({
1411
+ enabled: z.boolean().default(false),
1412
+ host: z.string().default("127.0.0.1"),
1413
+ port: z.number().int().default(DEFAULT_HTTP_PORT),
1414
+ /** 实例级 token,覆盖全局 token(缺省继承全局)。 */
1415
+ token: z.string().optional()
1416
+ });
1417
+ /** HTTP 正向上报实例(Webhook 事件推送)。 */
1418
+ const httpPostSchema = z.object({
1419
+ enabled: z.boolean().default(false),
1420
+ url: z.string().optional(),
1421
+ /** 实例级 token,覆盖全局 token(缺省继承全局)。 */
1422
+ token: z.string().optional(),
1423
+ /** 上报超时(毫秒),缺省不超时。 */
1424
+ timeoutMs: z.number().int().optional()
1425
+ });
1426
+ /** 反向 WS server 实例(第三方 WS 连入)。 */
1427
+ const wsServerSchema = z.object({
1428
+ enabled: z.boolean().default(false),
1429
+ host: z.string().default("127.0.0.1"),
1430
+ port: z.number().int().default(DEFAULT_WS_PORT),
1431
+ /** 实例级 token,覆盖全局 token(缺省继承全局)。 */
1432
+ token: z.string().optional(),
1433
+ /** WS ping 间隔(毫秒)。 */
1434
+ heartbeatInterval: z.number().int().default(DEFAULT_WS_HEARTBEAT_MS)
1435
+ });
1436
+ /** 正向 WS client 实例(主动连接第三方,双向)。 */
1437
+ const wsReverseSchema = z.object({
1438
+ enabled: z.boolean().default(false),
1439
+ url: z.string().optional(),
1440
+ /** 实例级 token,覆盖全局 token(缺省继承全局)。 */
1441
+ token: z.string().optional(),
1442
+ /** 断线重连延迟(毫秒)。 */
1443
+ reconnectDelayMs: z.number().int().default(DEFAULT_RECONNECT_DELAY_MS),
1444
+ /** 最大重连次数(缺省无限)。 */
1445
+ maxReconnectAttempts: z.number().int().optional(),
1446
+ /** wss:// 是否校验证书(自签证书场景设 false,对齐 NapCat enableSelfSigned)。 */
1447
+ rejectUnauthorized: z.boolean().default(true),
1448
+ /** WS ping 间隔(毫秒)。 */
1449
+ heartbeatInterval: z.number().int().default(DEFAULT_WS_HEARTBEAT_MS)
1450
+ });
1451
+ /** OB11 配置 schema。 */
1452
+ const ob11ConfigSchema = z.object({
1453
+ /** 鉴权 token(全局默认,实例未指定时继承)。 */
1454
+ token: z.string().optional(),
1455
+ /** 心跳 meta 事件间隔(毫秒),0 关闭心跳。 */
1456
+ heartbeatInterval: z.number().int().default(DEFAULT_HEARTBEAT_INTERVAL_MS),
1457
+ /** 是否上报机器人自己发的消息(缺省 false = OB11 规范行为)。 */
1458
+ reportSelfMessage: z.boolean().default(false),
1459
+ /** 消息内容格式:array = 消息段数组(标准),string = CQ 码字符串。 */
1460
+ messagePostFormat: z.enum(MESSAGE_FORMATS).default("array"),
1461
+ /** HTTP 反向服务器列表。 */
1462
+ httpServers: z.array(httpServerSchema).default([]),
1463
+ /** HTTP 正向上报列表。 */
1464
+ httpPostUrls: z.array(httpPostSchema).default([]),
1465
+ /** 反向 WS server 列表。 */
1466
+ wsServers: z.array(wsServerSchema).default([]),
1467
+ /** 正向 WS client 列表。 */
1468
+ wsReverseUrls: z.array(wsReverseSchema).default([])
1469
+ });
1470
+ //#endregion
1471
+ //#region src/onebot11/helper/cqcode.ts
1472
+ /**
1473
+ * CQ 码编解码(OneBot 11 消息段序列化格式)
1474
+ *
1475
+ * 纯函数、无 OB11 类型依赖:本文件只处理「文本 ↔ CQ 码片段」的通用编解码,
1476
+ * segment 级别的映射在 data.ts(OB11Constructor)。
1477
+ *
1478
+ * 转义规则(OneBot 11 规范):
1479
+ * - 纯文本:& → &amp;,[ → &#91;,] → &#93;
1480
+ * - 参数值:额外 , → &#44;
1481
+ */
1482
+ /** CQ 码片段正则([CQ:xxx] 或 [CQ:xxx,k=v,...])。 */
1483
+ const CQ_CODE_REGEX = /\[CQ:[^\]]*\]/g;
1484
+ /** 解析单个 CQ 码文本 → 结构化 CqCode。 */
1485
+ function parseCqCode(raw) {
1486
+ const body = raw.slice(4, -1);
1487
+ const firstComma = body.indexOf(",");
1488
+ let type = body;
1489
+ if (firstComma !== -1) type = body.slice(0, firstComma);
1490
+ const params = {};
1491
+ if (firstComma !== -1) for (const pair of body.slice(firstComma + 1).split(",")) {
1492
+ const eq = pair.indexOf("=");
1493
+ if (eq > 0) params[pair.slice(0, eq)] = unescapeCqText(pair.slice(eq + 1));
1494
+ }
1495
+ return {
1496
+ type,
1497
+ params
1498
+ };
1499
+ }
1500
+ /** 转义纯文本(& [ ];& 必须先转,避免二次转义)。 */
1501
+ function escapeCqText(text) {
1502
+ return text.replaceAll("&", "&amp;").replaceAll("[", "&#91;").replaceAll("]", "&#93;");
1503
+ }
1504
+ /** 转义 CQ 码参数值(& [ ] ,)。 */
1505
+ function escapeCqParam(value) {
1506
+ return escapeCqText(value).replaceAll(",", "&#44;");
1507
+ }
1508
+ /** 反转义(&#44; &#93; &#91; &amp;;&amp; 必须最后解,避免二次转义误伤)。 */
1509
+ function unescapeCqText(text) {
1510
+ return text.replaceAll("&#44;", ",").replaceAll("&#93;", "]").replaceAll("&#91;", "[").replaceAll("&amp;", "&");
1511
+ }
1512
+ /** 编码单个 CQ 码(undefined 参数自动省略)。 */
1513
+ function encodeCqCode(type, params) {
1514
+ const pairs = [];
1515
+ for (const [key, value] of Object.entries(params)) if (value !== void 0) pairs.push(`${key}=${escapeCqParam(String(value))}`);
1516
+ if (pairs.length === 0) return `[CQ:${type}]`;
1517
+ return `[CQ:${type},${pairs.join(",")}]`;
1518
+ }
1519
+ /** 解析一条消息文本 → 文本片段与 CQ 码片段的混合数组(文本已反转义)。 */
1520
+ function parseCqMessage(text) {
1521
+ const parts = [];
1522
+ let lastIndex = 0;
1523
+ for (const match of text.matchAll(CQ_CODE_REGEX)) {
1524
+ const index = match.index ?? 0;
1525
+ if (index > lastIndex) parts.push(unescapeCqText(text.slice(lastIndex, index)));
1526
+ parts.push(parseCqCode(match[0] ?? ""));
1527
+ lastIndex = index + match[0].length;
1528
+ }
1529
+ if (lastIndex < text.length) parts.push(unescapeCqText(text.slice(lastIndex)));
1530
+ return parts;
1531
+ }
1532
+ /** 将混合片段数组序列化回消息文本(parseCqMessage 的逆操作)。 */
1533
+ function serializeCqParts(parts) {
1534
+ let out = "";
1535
+ for (const part of parts) if (typeof part === "string") out += escapeCqText(part);
1536
+ else out += encodeCqCode(part.type, part.params);
1537
+ return out;
1538
+ }
1539
+ //#endregion
1540
+ //#region src/onebot11/helper/data.ts
1541
+ /** OB11 媒体段 data(image/record/video 共用,url 可选)。 */
1542
+ function mediaData(file, url) {
1543
+ const data = { file };
1544
+ if (url !== void 0) data.url = url;
1545
+ return data;
1546
+ }
1547
+ /** OB11 at 段 data(name 可选)。 */
1548
+ function atData(qq, name) {
1549
+ const data = { qq };
1550
+ if (name !== void 0) data.name = name;
1551
+ return data;
1552
+ }
1553
+ /** canonical at 元素(display 可选)。 */
1554
+ function canonicalAt(target, display) {
1555
+ const el = {
1556
+ type: "at",
1557
+ target
1558
+ };
1559
+ if (display !== void 0) el.display = display;
1560
+ return el;
1561
+ }
1562
+ /** canonical 媒体元素(image/voice/video,url 可选;type 为联合需断言收窄)。 */
1563
+ function canonicalMedia(type, path, url) {
1564
+ const el = {
1565
+ type,
1566
+ path
1567
+ };
1568
+ if (url !== void 0) el.url = url;
1569
+ return el;
1570
+ }
1571
+ /** canonical json/xml 的 raw → OB11 data 字符串(字符串原样,对象序列化)。 */
1572
+ function rawToString(raw) {
1573
+ if (typeof raw === "string") return raw;
1574
+ return JSON.stringify(raw);
1575
+ }
1576
+ /** canonical 元素 → OB11 segment(null = OB11 无法表达,跳过)。 */
1577
+ function canonicalToSegment(el) {
1578
+ if (el.type === "text") return {
1579
+ type: "text",
1580
+ data: { text: el.text }
1581
+ };
1582
+ if (el.type === "at") return {
1583
+ type: "at",
1584
+ data: atData(el.target, el.display)
1585
+ };
1586
+ if (el.type === "image") return {
1587
+ type: "image",
1588
+ data: mediaData(el.path, el.url)
1589
+ };
1590
+ if (el.type === "face") return {
1591
+ type: "face",
1592
+ data: { id: el.id }
1593
+ };
1594
+ if (el.type === "voice") return {
1595
+ type: "record",
1596
+ data: mediaData(el.path, el.url)
1597
+ };
1598
+ if (el.type === "video") return {
1599
+ type: "video",
1600
+ data: mediaData(el.path, el.url)
1601
+ };
1602
+ if (el.type === "reply") return {
1603
+ type: "reply",
1604
+ data: { id: el.messageId }
1605
+ };
1606
+ if (el.type === "forward") return {
1607
+ type: "forward",
1608
+ data: { id: el.messageIds[0] ?? "" }
1609
+ };
1610
+ if (el.type === "json") return {
1611
+ type: "json",
1612
+ data: { data: rawToString(el.raw) }
1613
+ };
1614
+ if (el.type === "xml") return {
1615
+ type: "xml",
1616
+ data: { data: rawToString(el.raw) }
1617
+ };
1618
+ return null;
1619
+ }
1620
+ /** OB11 segment → canonical 元素。 */
1621
+ function segmentToCanonical(seg) {
1622
+ if (seg.type === "text" || seg.type === "string") return {
1623
+ type: "text",
1624
+ text: seg.data.text
1625
+ };
1626
+ if (seg.type === "at") return canonicalAt(seg.data.qq, seg.data.name);
1627
+ if (seg.type === "face") return {
1628
+ type: "face",
1629
+ id: seg.data.id
1630
+ };
1631
+ if (seg.type === "image") return canonicalMedia("image", seg.data.file, seg.data.url);
1632
+ if (seg.type === "record") return canonicalMedia("voice", seg.data.file, seg.data.url);
1633
+ if (seg.type === "video") return canonicalMedia("video", seg.data.file, seg.data.url);
1634
+ if (seg.type === "reply") return {
1635
+ type: "reply",
1636
+ messageId: seg.data.id
1637
+ };
1638
+ if (seg.type === "forward") return {
1639
+ type: "forward",
1640
+ messageIds: [seg.data.id]
1641
+ };
1642
+ if (seg.type === "json") return {
1643
+ type: "json",
1644
+ raw: seg.data.data
1645
+ };
1646
+ return {
1647
+ type: "xml",
1648
+ raw: seg.data.data
1649
+ };
1650
+ }
1651
+ /** 已知 CQ 类型 → segment 构造器。 */
1652
+ const CQ_SEGMENT_BUILDERS = {
1653
+ text: (params) => ({
1654
+ type: "text",
1655
+ data: { text: params["text"] ?? "" }
1656
+ }),
1657
+ at: (params) => ({
1658
+ type: "at",
1659
+ data: atData(params["qq"] ?? "", params["name"])
1660
+ }),
1661
+ face: (params) => ({
1662
+ type: "face",
1663
+ data: { id: params["id"] ?? "" }
1664
+ }),
1665
+ image: (params) => ({
1666
+ type: "image",
1667
+ data: mediaData(params["file"] ?? "", params["url"])
1668
+ }),
1669
+ record: (params) => ({
1670
+ type: "record",
1671
+ data: mediaData(params["file"] ?? "", params["url"])
1672
+ }),
1673
+ video: (params) => ({
1674
+ type: "video",
1675
+ data: mediaData(params["file"] ?? "", params["url"])
1676
+ }),
1677
+ reply: (params) => ({
1678
+ type: "reply",
1679
+ data: { id: params["id"] ?? "" }
1680
+ }),
1681
+ forward: (params) => ({
1682
+ type: "forward",
1683
+ data: { id: params["id"] ?? "" }
1684
+ }),
1685
+ json: (params) => ({
1686
+ type: "json",
1687
+ data: { data: params["data"] ?? "" }
1688
+ }),
1689
+ xml: (params) => ({
1690
+ type: "xml",
1691
+ data: { data: params["data"] ?? "" }
1692
+ })
1693
+ };
1694
+ /** CQ 码片段 → OB11 segment(未知类型保留原文为 text 段,往返不丢数据)。 */
1695
+ function cqCodeToSegment(code) {
1696
+ const builder = CQ_SEGMENT_BUILDERS[code.type];
1697
+ if (builder === void 0) return {
1698
+ type: "text",
1699
+ data: { text: encodeCqCode(code.type, code.params) }
1700
+ };
1701
+ return builder(code.params);
1702
+ }
1703
+ /** canonical 元素数组 → OB11 segment 数组(无法表达的元素静默跳过)。 */
1704
+ function canonicalToSegments(elements) {
1705
+ const segments = [];
1706
+ for (const el of elements) {
1707
+ const seg = canonicalToSegment(el);
1708
+ if (seg !== null) segments.push(seg);
1709
+ }
1710
+ return segments;
1711
+ }
1712
+ /** OB11 segment 数组 → canonical 元素数组。 */
1713
+ function segmentsToCanonical(segments) {
1714
+ const elements = [];
1715
+ for (const seg of segments) {
1716
+ const el = segmentToCanonical(seg);
1717
+ if (el !== null) elements.push(el);
1718
+ }
1719
+ return elements;
1720
+ }
1721
+ /** OB11 segment 数组 → CQ 码字符串(text 段转义拼接,特殊段编码)。 */
1722
+ function segmentsToCqMessage(segments) {
1723
+ let out = "";
1724
+ for (const seg of segments) if (seg.type === "text" || seg.type === "string") out += escapeCqText(seg.data.text);
1725
+ else out += encodeCqCode(seg.type, seg.data);
1726
+ return out;
1727
+ }
1728
+ /**
1729
+ * 收集 canonical 元素里需要转换的 at uid / reply NT msgId(接收方向)。
1730
+ * 调用方据此批量 uidToUin(一次异步调用),避免逐元素查询。
1731
+ */
1732
+ function collectReceiveNeeds(elements) {
1733
+ const atUids = /* @__PURE__ */ new Set();
1734
+ const replyMsgIds = /* @__PURE__ */ new Set();
1735
+ for (const el of elements) if (el.type === "at" && el.target !== "all") atUids.add(el.target);
1736
+ else if (el.type === "reply") replyMsgIds.add(el.messageId);
1737
+ return {
1738
+ atUids: [...atUids],
1739
+ replyMsgIds: [...replyMsgIds]
1740
+ };
1741
+ }
1742
+ /**
1743
+ * canonical 元素数组 → 应用接收方向 ID 转换(at uid→uin、reply NT msgId→OB11 id)。
1744
+ * 转换失败的元素原样保留(uid 未解析 / msgId 未映射——不阻塞上报)。
1745
+ */
1746
+ function applyReceiveContext(elements, ctx) {
1747
+ if (ctx.uidToUin === void 0 && ctx.msgIdToOb11Id === void 0) return elements;
1748
+ const out = [];
1749
+ for (const el of elements) {
1750
+ if (el.type === "at" && el.target !== "all") {
1751
+ const uin = ctx.uidToUin?.get(el.target);
1752
+ out.push(uin !== void 0 ? {
1753
+ ...el,
1754
+ target: uin
1755
+ } : el);
1756
+ continue;
1757
+ }
1758
+ if (el.type === "reply") {
1759
+ const id = ctx.msgIdToOb11Id?.(el.messageId);
1760
+ out.push(id !== void 0 ? {
1761
+ ...el,
1762
+ messageId: String(id)
1763
+ } : el);
1764
+ continue;
1765
+ }
1766
+ out.push(el);
1767
+ }
1768
+ return out;
1769
+ }
1770
+ /**
1771
+ * canonical 元素数组 → 应用发送方向 ID 转换(at uin→uid、reply OB11 id→NT msgId)。
1772
+ * reply 反查不到时原样透传(兼容客户端直接给 NT msgId 的输入,不报错)。
1773
+ */
1774
+ function applySendContext(elements, ctx) {
1775
+ if (ctx.uinToUid === void 0 && ctx.ob11IdToMsgId === void 0) return elements;
1776
+ const out = [];
1777
+ for (const el of elements) {
1778
+ if (el.type === "at" && el.target !== "all") {
1779
+ const uid = ctx.uinToUid?.get(el.target);
1780
+ out.push(uid !== void 0 ? {
1781
+ ...el,
1782
+ target: uid
1783
+ } : el);
1784
+ continue;
1785
+ }
1786
+ if (el.type === "reply") {
1787
+ const num = Number(el.messageId);
1788
+ if (!Number.isNaN(num)) {
1789
+ const msgId = ctx.ob11IdToMsgId?.(num);
1790
+ if (msgId !== void 0) {
1791
+ out.push({
1792
+ ...el,
1793
+ messageId: msgId
1794
+ });
1795
+ continue;
1796
+ }
1797
+ }
1798
+ out.push(el);
1799
+ continue;
1800
+ }
1801
+ out.push(el);
1802
+ }
1803
+ return out;
1804
+ }
1805
+ /** CQ 码字符串 → OB11 segment 数组(未知 CQ 类型保留为 text 段原文)。 */
1806
+ function cqMessageToSegments(text) {
1807
+ const segments = [];
1808
+ for (const part of parseCqMessage(text)) if (typeof part === "string") {
1809
+ if (part.length > 0) segments.push({
1810
+ type: "text",
1811
+ data: { text: part }
1812
+ });
1813
+ } else {
1814
+ const seg = cqCodeToSegment(part);
1815
+ if (seg !== null) segments.push(seg);
1816
+ }
1817
+ return segments;
1818
+ }
1819
+ /** canonical 元素数组 → CQ 码字符串。 */
1820
+ function canonicalToCqMessage(elements) {
1821
+ return segmentsToCqMessage(canonicalToSegments(elements));
1822
+ }
1823
+ /** CQ 码字符串 → canonical 元素数组。 */
1824
+ function cqMessageToCanonical(text) {
1825
+ return segmentsToCanonical(cqMessageToSegments(text));
1826
+ }
1827
+ //#endregion
1828
+ //#region src/onebot11/helper/message-info.ts
1829
+ /** 毫秒 → 秒(Unix 时间戳)。 */
1830
+ const MS_TO_SEC$3 = 1e3;
1831
+ /** RawMessage → OB11 消息信息(message_id 经 MessageUnique 映射)。
1832
+ * ctx(可选):接收方向 ID 转换上下文(at uid→uin、reply NT msgId→OB11 id,P2-19)。 */
1833
+ function toOb11MessageInfo(msg, unique, ctx = {}) {
1834
+ const elements = applyReceiveContext(toCanonicalElements(msg), ctx);
1835
+ let messageType = "private";
1836
+ if (msg.chatType === ChatType.GROUP) messageType = "group";
1837
+ const info = {
1838
+ message_id: unique.alloc(msg.msgId, {
1839
+ chatType: msg.chatType,
1840
+ peerUid: msg.peerUid
1841
+ }),
1842
+ message_type: messageType,
1843
+ sender: {
1844
+ user_id: Number(msg.senderUin),
1845
+ nickname: msg.sendNickName
1846
+ },
1847
+ time: Math.floor(Number(msg.msgTime) / MS_TO_SEC$3),
1848
+ message: canonicalToSegments(elements),
1849
+ raw_message: canonicalToCqMessage(elements)
1850
+ };
1851
+ if (msg.chatType === ChatType.GROUP) {
1852
+ info.group_id = Number(msg.peerUid);
1853
+ const { sender } = info;
1854
+ sender.role = "member";
1855
+ if (msg.sendMemberName !== void 0) sender.card = msg.sendMemberName;
1856
+ } else info.user_id = Number(msg.senderUin);
1857
+ return info;
1858
+ }
1859
+ //#endregion
1860
+ //#region src/onebot11/helper/notice.ts
1861
+ /**
1862
+ * OB11 notice 事件翻译(P2-7,2026-08-05)
1863
+ *
1864
+ * NT QQ 中群成员变动/撤回等系统事件通过**消息的灰色提示元素(grayTip)**广播。
1865
+ * 本模块把 RawMessage 里的 grayTip 翻译为 OB11 notice 事件(纯函数,ADR-008)。
1866
+ *
1867
+ * 支持:
1868
+ * - group_recall(撤回,grayTip.subElementType=REVOKE)
1869
+ * - group_increase / group_decrease(群成员变动,subElementType=GROUP + TipGroupElement.type)
1870
+ * - group_admin(管理员变更,TipGroupElement.type=BLOCK/UNBLOCK 的 role 语义)
1871
+ * - group_ban(禁言,TipGroupElement.type=SHUT_UP)
1872
+ *
1873
+ * user_id/operator_id 都是 uin:接收 uidToUin Map(调用方批量转换后传入,保持纯函数)。
1874
+ */
1875
+ /** 毫秒 → 秒(Unix 时间戳)。 */
1876
+ const MS_TO_SEC$2 = 1e3;
1877
+ /** 检查消息是否含可翻译的 grayTip 元素。 */
1878
+ function hasGrayTip(msg) {
1879
+ return msg.elements.some((el) => el.grayTipElement !== void 0);
1880
+ }
1881
+ /** 收集 grayTip 涉及的 uid(批量 uidToUin 用)。 */
1882
+ function collectGrayTipUids(msg) {
1883
+ const uids = /* @__PURE__ */ new Set();
1884
+ for (const el of msg.elements) {
1885
+ const g = el.grayTipElement;
1886
+ if (g === void 0) continue;
1887
+ const revoke = g.revokeElement;
1888
+ if (revoke?.operatorUid !== void 0 && revoke.operatorUid !== "") uids.add(revoke.operatorUid);
1889
+ const grp = g.groupElement;
1890
+ if (grp === void 0) continue;
1891
+ if (grp.memberUid !== void 0 && grp.memberUid !== "") uids.add(grp.memberUid);
1892
+ if (grp.adminUid !== void 0 && grp.adminUid !== "") uids.add(grp.adminUid);
1893
+ if (grp.shutUp?.admin?.uid !== void 0 && grp.shutUp.admin.uid !== "") uids.add(grp.shutUp.admin.uid);
1894
+ if (grp.shutUp?.member?.uid !== void 0 && grp.shutUp.member.uid !== "") uids.add(grp.shutUp.member.uid);
1895
+ }
1896
+ return [...uids];
1897
+ }
1898
+ /** uid → uin(上下文映射缺省退化为 uid)。 */
1899
+ function toUin(uid, ctx) {
1900
+ const uin = ctx.uidToUin.get(uid);
1901
+ return Number(uin ?? uid);
1902
+ }
1903
+ /** 基础字段(time/self_id/post_type)。 */
1904
+ function base(msg, ctx) {
1905
+ return {
1906
+ time: Math.floor(Number(msg.msgTime) / MS_TO_SEC$2),
1907
+ self_id: Number(ctx.selfUin),
1908
+ post_type: "notice",
1909
+ group_id: Number(msg.peerUid)
1910
+ };
1911
+ }
1912
+ /** 撤回事件(group_recall)。 */
1913
+ function toRecall(msg, g, ctx) {
1914
+ if (g?.revokeElement === void 0) return null;
1915
+ const revoke = g.revokeElement;
1916
+ return {
1917
+ ...base(msg, ctx),
1918
+ notice_type: "group_recall",
1919
+ user_id: toUin(revoke.operatorUid, ctx),
1920
+ operator_id: toUin(revoke.operatorUid, ctx),
1921
+ message_id: Number(msg.msgSeq)
1922
+ };
1923
+ }
1924
+ /** 群成员变动(group_increase / group_decrease / group_admin / group_ban)。 */
1925
+ function toGroupChange(msg, g, ctx) {
1926
+ const grp = g?.groupElement;
1927
+ if (grp === void 0 || grp.type === void 0) return null;
1928
+ const groupId = Number(msg.peerUid);
1929
+ const time = Math.floor(Number(msg.msgTime) / MS_TO_SEC$2);
1930
+ const selfId = Number(ctx.selfUin);
1931
+ const memberUid = grp.memberUid ?? "";
1932
+ const adminUid = grp.adminUid ?? "";
1933
+ switch (grp.type) {
1934
+ case TipGroupElementType.MEMBER_ADD: return {
1935
+ time,
1936
+ self_id: selfId,
1937
+ post_type: "notice",
1938
+ notice_type: "group_increase",
1939
+ sub_type: adminUid === memberUid ? "approve" : "invite",
1940
+ group_id: groupId,
1941
+ operator_id: toUin(adminUid, ctx),
1942
+ user_id: toUin(memberUid, ctx)
1943
+ };
1944
+ case TipGroupElementType.QUIT: return {
1945
+ time,
1946
+ self_id: selfId,
1947
+ post_type: "notice",
1948
+ notice_type: "group_decrease",
1949
+ sub_type: "leave",
1950
+ group_id: groupId,
1951
+ operator_id: toUin(adminUid, ctx),
1952
+ user_id: toUin(memberUid, ctx)
1953
+ };
1954
+ case TipGroupElementType.BLOCK:
1955
+ case TipGroupElementType.UNBLOCK: return {
1956
+ time,
1957
+ self_id: selfId,
1958
+ post_type: "notice",
1959
+ notice_type: "group_admin",
1960
+ sub_type: grp.type === TipGroupElementType.BLOCK ? "set" : "unset",
1961
+ group_id: groupId,
1962
+ user_id: toUin(memberUid === "" ? adminUid : memberUid, ctx)
1963
+ };
1964
+ case TipGroupElementType.SHUT_UP: {
1965
+ const shutUp = grp.shutUp;
1966
+ return {
1967
+ time,
1968
+ self_id: selfId,
1969
+ post_type: "notice",
1970
+ notice_type: "group_ban",
1971
+ sub_type: Number(shutUp?.duration ?? 0) > 0 ? "ban" : "lift_ban",
1972
+ group_id: groupId,
1973
+ operator_id: toUin(shutUp?.admin?.uid ?? adminUid, ctx),
1974
+ user_id: toUin(shutUp?.member?.uid ?? memberUid, ctx),
1975
+ duration: Number(shutUp?.duration ?? 0)
1976
+ };
1977
+ }
1978
+ default: return null;
1979
+ }
1980
+ }
1981
+ /** RawMessage → OB11 notice 事件(无 grayTip 返回 null)。 */
1982
+ function toOb11NoticeEvent(msg, ctx) {
1983
+ for (const el of msg.elements) {
1984
+ const g = el.grayTipElement;
1985
+ if (g === void 0) continue;
1986
+ const subType = g.subElementType;
1987
+ if (subType === GrayTipSubType.REVOKE) {
1988
+ const recall = toRecall(msg, g, ctx);
1989
+ if (recall !== null) return recall;
1990
+ }
1991
+ if (subType === GrayTipSubType.GROUP) {
1992
+ const change = toGroupChange(msg, g, ctx);
1993
+ if (change !== null) return change;
1994
+ }
1995
+ }
1996
+ return null;
1997
+ }
1998
+ //#endregion
1999
+ //#region src/onebot11/action/message/get-forward-msg.ts
2000
+ /**
2001
+ * get_forward_msg 动作:获取合并转发内容(P2-12 接 kernel MsgApi.fetchForwardMessage)
2002
+ *
2003
+ * message_id / id → 反查 msgId + peer → fetchForwardMessage(getMultiMsg)→
2004
+ * 每条 toOb11MessageInfo → { messages }。
2005
+ */
2006
+ const getForwardMsgSchema = z.object({
2007
+ message_id: z.union([z.number(), z.string()]).optional(),
2008
+ id: z.union([z.number(), z.string()]).optional()
2009
+ });
2010
+ /** 获取合并转发内容(P2-12 接 kernel fetchForwardMessage)。 */
2011
+ var GetForwardMsgAction = class extends BaseAction {
2012
+ name = "get_forward_msg";
2013
+ schema = getForwardMsgSchema;
2014
+ errorCodeMap = ob11ErrorCodeMap;
2015
+ deps;
2016
+ constructor(deps) {
2017
+ super();
2018
+ this.deps = deps;
2019
+ }
2020
+ async _handle(payload) {
2021
+ const id = payload.message_id ?? payload.id;
2022
+ if (id === void 0) throw kernelError("get_forward_msg 需要 message_id 或 id", "INVALID_PARAM");
2023
+ const { msgId, peer } = resolveMsgIdAndPeer(id, this.deps.messageUnique);
2024
+ return { messages: (await this.deps.msgApi.fetchForwardMessage(peer, msgId)).map((msg) => toOb11MessageInfo(msg, this.deps.messageUnique)) };
2025
+ }
2026
+ };
2027
+ //#endregion
2028
+ //#region src/onebot11/action/message/get-friend-msg-history.ts
2029
+ /**
2030
+ * get_friend_msg_history 动作:获取私聊历史消息(NapCat 扩展,P2-10)
2031
+ *
2032
+ * user_id → uin→uid → Peer{ C2C } → fetchMessages → 数组翻译。
2033
+ */
2034
+ const getFriendMsgHistorySchema = z.object({
2035
+ user_id: z.number(),
2036
+ message_seq: z.union([z.number(), z.string()]).optional(),
2037
+ count: z.number().default(20),
2038
+ reverse_order: z.boolean().optional(),
2039
+ reverseOrder: z.boolean().optional()
2040
+ });
2041
+ /** 获取私聊历史消息(P2-10 接 kernel fetchMessages)。 */
2042
+ var GetFriendMsgHistoryAction = class extends BaseAction {
2043
+ name = "get_friend_msg_history";
2044
+ schema = getFriendMsgHistorySchema;
2045
+ errorCodeMap = ob11ErrorCodeMap;
2046
+ deps;
2047
+ constructor(deps) {
2048
+ super();
2049
+ this.deps = deps;
2050
+ }
2051
+ async _handle(payload) {
2052
+ const uid = (await this.deps.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
2053
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
2054
+ const peer = {
2055
+ chatType: ChatType.C2C,
2056
+ peerUid: uid
2057
+ };
2058
+ let startMsgId;
2059
+ if (payload.message_seq !== void 0) {
2060
+ const raw = String(payload.message_seq);
2061
+ const shortId = Number(raw);
2062
+ if (Number.isFinite(shortId)) startMsgId = this.deps.messageUnique.getMsgId(shortId);
2063
+ startMsgId ??= raw;
2064
+ }
2065
+ const opts = { count: payload.count };
2066
+ if (startMsgId !== void 0) opts.msgId = startMsgId;
2067
+ const msgs = await this.deps.msgApi.fetchMessages(peer, opts);
2068
+ if (msgs.length === 0) throw kernelError(`消息 ${payload.message_seq ?? "0"} 不存在`, "NOT_FOUND");
2069
+ const atUids = /* @__PURE__ */ new Set();
2070
+ for (const m of msgs) {
2071
+ const { atUids: uids } = collectReceiveNeeds(toCanonicalElements(m));
2072
+ for (const u of uids) atUids.add(u);
2073
+ }
2074
+ let uidToUin;
2075
+ if (atUids.size > 0) try {
2076
+ uidToUin = await this.deps.uidToUin([...atUids]);
2077
+ } catch {}
2078
+ const ctx = {
2079
+ ...uidToUin !== void 0 ? { uidToUin } : {},
2080
+ msgIdToOb11Id: (m) => this.deps.messageUnique.getMessageId(m)
2081
+ };
2082
+ return { messages: msgs.map((msg) => toOb11MessageInfo(msg, this.deps.messageUnique, ctx)) };
2083
+ }
2084
+ };
2085
+ //#endregion
2086
+ //#region src/onebot11/action/message/get-group-msg-history.ts
2087
+ /**
2088
+ * get_group_msg_history 动作:获取群历史消息(go-cqhttp 扩展,P2-10)
2089
+ *
2090
+ * group_id → Peer{ GROUP } → MsgApi.fetchMessages(message_seq 起,count 条)
2091
+ * → 数组翻译为 OB11 消息信息。
2092
+ */
2093
+ const getGroupMsgHistorySchema = z.object({
2094
+ group_id: z.number(),
2095
+ /** 起始消息序号(message_seq,缺省从最新拉)。 */
2096
+ message_seq: z.union([z.number(), z.string()]).optional(),
2097
+ count: z.number().default(20),
2098
+ /** 是否反向排序(NapCat 扩展)。 */
2099
+ reverse_order: z.boolean().optional(),
2100
+ reverseOrder: z.boolean().optional()
2101
+ });
2102
+ /** 获取群历史消息(P2-10 接 kernel fetchMessages)。 */
2103
+ var GetGroupMsgHistoryAction = class extends BaseAction {
2104
+ name = "get_group_msg_history";
2105
+ schema = getGroupMsgHistorySchema;
2106
+ errorCodeMap = ob11ErrorCodeMap;
2107
+ deps;
2108
+ constructor(deps) {
2109
+ super();
2110
+ this.deps = deps;
2111
+ }
2112
+ async _handle(payload) {
2113
+ const peer = {
2114
+ chatType: ChatType.GROUP,
2115
+ peerUid: String(payload.group_id)
2116
+ };
2117
+ let startMsgId;
2118
+ if (payload.message_seq !== void 0) {
2119
+ const raw = String(payload.message_seq);
2120
+ const shortId = Number(raw);
2121
+ if (Number.isFinite(shortId)) startMsgId = this.deps.messageUnique.getMsgId(shortId);
2122
+ startMsgId ??= raw;
2123
+ }
2124
+ const opts = { count: payload.count };
2125
+ if (startMsgId !== void 0) opts.msgId = startMsgId;
2126
+ const msgs = await this.deps.msgApi.fetchMessages(peer, opts);
2127
+ if (msgs.length === 0) throw kernelError(`消息 ${payload.message_seq ?? "0"} 不存在`, "NOT_FOUND");
2128
+ const atUids = /* @__PURE__ */ new Set();
2129
+ for (const m of msgs) {
2130
+ const { atUids: uids } = collectReceiveNeeds(toCanonicalElements(m));
2131
+ for (const u of uids) atUids.add(u);
2132
+ }
2133
+ let uidToUin;
2134
+ if (atUids.size > 0) try {
2135
+ uidToUin = await this.deps.uidToUin([...atUids]);
2136
+ } catch {}
2137
+ const ctx = {
2138
+ ...uidToUin !== void 0 ? { uidToUin } : {},
2139
+ msgIdToOb11Id: (m) => this.deps.messageUnique.getMessageId(m)
2140
+ };
2141
+ return { messages: msgs.map((msg) => toOb11MessageInfo(msg, this.deps.messageUnique, ctx)) };
2142
+ }
2143
+ };
2144
+ //#endregion
2145
+ //#region src/onebot11/action/message/get-media.ts
2146
+ /**
2147
+ * get_image / get_record 动作:获取图片/语音文件信息(P2-14,简化版)
2148
+ *
2149
+ * message_id 反查 → fetchMsgsByMsgId → 找 PIC/PTT 元素 → 返回元素已有路径与 URL。
2150
+ * 不做主动下载/转码(NapCat 走 downloadRichMedia 事件驱动下载,待后续接入)。
2151
+ */
2152
+ const getMediaSchema = z.object({
2153
+ /** CQ 码 file 字段或 message_id(简化:message_id 反查)。 */
2154
+ file: z.string().optional(),
2155
+ message_id: z.union([z.number(), z.string()]).optional()
2156
+ });
2157
+ /** 从消息元素提取媒体路径与 URL(PIC/PTT,纯函数)。 */
2158
+ function extractMediaPath(element) {
2159
+ const pic = element.picElement;
2160
+ if (pic !== void 0) {
2161
+ const out = {};
2162
+ const path = pic.sourcePath ?? pic.picPath;
2163
+ if (path !== void 0) out.path = path;
2164
+ if (pic.picUrl !== void 0) out.url = pic.picUrl;
2165
+ return out;
2166
+ }
2167
+ const ptt = element.pttElement;
2168
+ if (ptt !== void 0 && ptt.filePath !== void 0) return { path: ptt.filePath };
2169
+ return {};
2170
+ }
2171
+ /** 获取图片信息(P2-14)。 */
2172
+ var GetImageAction = class extends BaseAction {
2173
+ name = "get_image";
2174
+ schema = getMediaSchema;
2175
+ errorCodeMap = ob11ErrorCodeMap;
2176
+ deps;
2177
+ constructor(deps) {
2178
+ super();
2179
+ this.deps = deps;
2180
+ }
2181
+ _handle(payload) {
2182
+ return this.resolveMedia(payload, "图片", "get_image");
2183
+ }
2184
+ /** 反查消息并提取媒体元素路径。 */
2185
+ async resolveMedia(payload, label, actionName) {
2186
+ const id = payload.message_id ?? payload.file;
2187
+ if (id === void 0) throw kernelError(`${actionName} 需要 message_id 或 file`, "INVALID_PARAM");
2188
+ const { msgId, peer } = resolveMsgIdAndPeer(id, this.deps.messageUnique);
2189
+ const [first] = await this.deps.msgApi.fetchMsgsByMsgId(peer, [msgId]);
2190
+ if (first === void 0) throw kernelError(`消息 ${id} 不存在或已被撤回`, "NOT_FOUND");
2191
+ let found;
2192
+ for (const el of first.elements) {
2193
+ const media = extractMediaPath(el);
2194
+ if (media.path !== void 0 || media.url !== void 0) {
2195
+ found = media;
2196
+ break;
2197
+ }
2198
+ }
2199
+ if (found === void 0) throw kernelError(`消息 ${id} 不包含${label}`, "NOT_FOUND");
2200
+ const result = {};
2201
+ if (found.path !== void 0) result.file = found.path;
2202
+ if (found.url !== void 0) result.url = found.url;
2203
+ return result;
2204
+ }
2205
+ };
2206
+ /** 获取语音信息(P2-14)。 */
2207
+ var GetRecordAction = class extends BaseAction {
2208
+ name = "get_record";
2209
+ schema = getMediaSchema;
2210
+ errorCodeMap = ob11ErrorCodeMap;
2211
+ deps;
2212
+ constructor(deps) {
2213
+ super();
2214
+ this.deps = deps;
2215
+ }
2216
+ async _handle(payload) {
2217
+ const id = payload.message_id ?? payload.file;
2218
+ if (id === void 0) throw kernelError("get_record 需要 message_id 或 file", "INVALID_PARAM");
2219
+ const { msgId, peer } = resolveMsgIdAndPeer(id, this.deps.messageUnique);
2220
+ const [first] = await this.deps.msgApi.fetchMsgsByMsgId(peer, [msgId]);
2221
+ if (first === void 0) throw kernelError(`消息 ${id} 不存在或已被撤回`, "NOT_FOUND");
2222
+ for (const el of first.elements) {
2223
+ const ptt = el.pttElement;
2224
+ if (ptt !== void 0 && ptt.filePath !== void 0) return { file: ptt.filePath };
2225
+ }
2226
+ throw kernelError(`消息 ${id} 不包含语音`, "NOT_FOUND");
2227
+ }
2228
+ };
2229
+ //#endregion
2230
+ //#region src/onebot11/action/message/get-msg.ts
2231
+ /**
2232
+ * get_msg 动作:获取消息详情(P2-10 接 kernel MsgApi.fetchMsgsByMsgId)
2233
+ *
2234
+ * message_id → msgId + peer(MessageUnique 反查)→ 拉消息 → OB11 消息信息结构。
2235
+ */
2236
+ const getMsgSchema = z.object({ message_id: z.union([z.number(), z.string()]) });
2237
+ /** 获取消息详情(P2-10 接 kernel fetchMsgsByMsgId)。 */
2238
+ var GetMsgAction = class extends BaseAction {
2239
+ name = "get_msg";
2240
+ schema = getMsgSchema;
2241
+ errorCodeMap = ob11ErrorCodeMap;
2242
+ deps;
2243
+ constructor(deps) {
2244
+ super();
2245
+ this.deps = deps;
2246
+ }
2247
+ async _handle(payload) {
2248
+ const { msgId, peer } = resolveMsgIdAndPeer(payload.message_id, this.deps.messageUnique);
2249
+ const [msg] = await this.deps.msgApi.fetchMsgsByMsgId(peer, [msgId]);
2250
+ if (msg === void 0) throw kernelError(`消息 ${payload.message_id} 不存在或已被撤回`, "NOT_FOUND");
2251
+ const { atUids } = collectReceiveNeeds(toCanonicalElements(msg));
2252
+ let uidToUin;
2253
+ if (atUids.length > 0) try {
2254
+ uidToUin = await this.deps.uidToUin(atUids);
2255
+ } catch {}
2256
+ const ctx = {
2257
+ ...uidToUin !== void 0 ? { uidToUin } : {},
2258
+ msgIdToOb11Id: (m) => this.deps.messageUnique.getMessageId(m)
2259
+ };
2260
+ return toOb11MessageInfo(msg, this.deps.messageUnique, ctx);
2261
+ }
2262
+ };
2263
+ //#endregion
2264
+ //#region src/onebot11/action/message/mark-msg-as-read.ts
2265
+ /**
2266
+ * mark_msg_as_read 动作:标记消息已读(P2-10 接 kernel MsgApi.markRead)
2267
+ *
2268
+ * OB11 标准 mark_msg_as_read 以 user_id 为参数;NapCat 扩展同时支持 group_id
2269
+ * (mark_private_msg_as_read / mark_group_msg_as_read 由 adapter 层同名动作或
2270
+ * 语义别名处理)。user_id → C2C peer;group_id → GROUP peer。
2271
+ */
2272
+ const markMsgAsReadSchema = z.object({
2273
+ user_id: z.number().optional(),
2274
+ group_id: z.number().optional()
2275
+ }).refine((v) => v.user_id !== void 0 || v.group_id !== void 0, { message: "mark_msg_as_read 需要 user_id 或 group_id" });
2276
+ /** 标记消息已读(P2-10 接 kernel markRead)。 */
2277
+ var MarkMsgAsReadAction = class extends BaseAction {
2278
+ name = "mark_msg_as_read";
2279
+ schema = markMsgAsReadSchema;
2280
+ errorCodeMap = ob11ErrorCodeMap;
2281
+ deps;
2282
+ constructor(deps) {
2283
+ super();
2284
+ this.deps = deps;
2285
+ }
2286
+ async _handle(payload) {
2287
+ if (payload.group_id !== void 0) {
2288
+ await this.deps.msgApi.markRead({
2289
+ chatType: ChatType.GROUP,
2290
+ peerUid: String(payload.group_id)
2291
+ });
2292
+ return null;
2293
+ }
2294
+ if (payload.user_id !== void 0) {
2295
+ const uid = (await this.deps.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
2296
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
2297
+ await this.deps.msgApi.markRead({
2298
+ chatType: ChatType.C2C,
2299
+ peerUid: uid
2300
+ });
2301
+ }
2302
+ return null;
2303
+ }
2304
+ };
2305
+ //#endregion
2306
+ //#region src/onebot11/action/message/mark-msg-as-read-aliases.ts
2307
+ /**
2308
+ * mark_private_msg_as_read / mark_group_msg_as_read 动作:标记会话已读(P2-13)
2309
+ *
2310
+ * mark_msg_as_read 的细分别名(NapCat 扩展):
2311
+ * - mark_private_msg_as_read:user_id → C2C markRead
2312
+ * - mark_group_msg_as_read:group_id → GROUP markRead
2313
+ */
2314
+ const markPrivateMsgAsReadSchema = z.object({ user_id: z.number() });
2315
+ const markGroupMsgAsReadSchema = z.object({ group_id: z.number() });
2316
+ /** 标记私聊已读(P2-13)。 */
2317
+ var MarkPrivateMsgAsReadAction = class extends BaseAction {
2318
+ name = "mark_private_msg_as_read";
2319
+ schema = markPrivateMsgAsReadSchema;
2320
+ errorCodeMap = ob11ErrorCodeMap;
2321
+ deps;
2322
+ constructor(deps) {
2323
+ super();
2324
+ this.deps = deps;
2325
+ }
2326
+ async _handle(payload) {
2327
+ const uid = (await this.deps.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
2328
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
2329
+ await this.deps.msgApi.markRead({
2330
+ chatType: ChatType.C2C,
2331
+ peerUid: uid
2332
+ });
2333
+ return null;
2334
+ }
2335
+ };
2336
+ /** 标记群聊已读(P2-13)。 */
2337
+ var MarkGroupMsgAsReadAction = class extends BaseAction {
2338
+ name = "mark_group_msg_as_read";
2339
+ schema = markGroupMsgAsReadSchema;
2340
+ errorCodeMap = ob11ErrorCodeMap;
2341
+ deps;
2342
+ constructor(deps) {
2343
+ super();
2344
+ this.deps = deps;
2345
+ }
2346
+ async _handle(payload) {
2347
+ await this.deps.msgApi.markRead({
2348
+ chatType: ChatType.GROUP,
2349
+ peerUid: String(payload.group_id)
2350
+ });
2351
+ return null;
2352
+ }
2353
+ };
2354
+ //#endregion
2355
+ //#region src/onebot11/action/message/send-forward-msg.ts
2356
+ /**
2357
+ * send_group_forward_msg / send_private_forward_msg 动作:发送合并转发(P2-12)
2358
+ *
2359
+ * messages 每项为 node 元素 `{ type: "node", data: { id } }`——id 是此前
2360
+ * send_msg 返回的 OB11 message_id。经 MessageUnique 反查源 msgId + peer,
2361
+ * 组装到目标 peer(群直通 / 私聊 uinToUid)→ MsgApi.sendForwardMessage。
2362
+ */
2363
+ const forwardNodeSchema = z.object({
2364
+ type: z.literal("node").optional(),
2365
+ data: z.object({ id: z.union([z.number(), z.string()]) }).optional()
2366
+ });
2367
+ const sendGroupForwardMsgSchema = z.object({
2368
+ group_id: z.number(),
2369
+ messages: z.array(z.unknown()).default([])
2370
+ });
2371
+ const sendPrivateForwardMsgSchema = z.object({
2372
+ user_id: z.number(),
2373
+ messages: z.array(z.unknown()).default([])
2374
+ });
2375
+ /** 解析 node 元素列表 → 源消息 (msgId, peer) 列表(id 反查,跳过无法解析的项)。 */
2376
+ function resolveSourceMessages(messages, unique) {
2377
+ const out = [];
2378
+ for (const raw of messages) {
2379
+ const parsed = forwardNodeSchema.safeParse(raw);
2380
+ if (parsed.success) {
2381
+ const id = parsed.data.data?.id;
2382
+ if (id !== void 0) {
2383
+ const msgId = unique.getMsgId(Number(id));
2384
+ if (msgId !== void 0) {
2385
+ const peer = unique.getPeer(msgId);
2386
+ if (peer !== void 0) out.push({
2387
+ msgId,
2388
+ peer
2389
+ });
2390
+ }
2391
+ }
2392
+ }
2393
+ }
2394
+ return out;
2395
+ }
2396
+ /** 发送群合并转发(P2-12 接 kernel sendForwardMessage)。 */
2397
+ var SendGroupForwardMsgAction = class extends BaseAction {
2398
+ name = "send_group_forward_msg";
2399
+ schema = sendGroupForwardMsgSchema;
2400
+ errorCodeMap = ob11ErrorCodeMap;
2401
+ deps;
2402
+ constructor(deps) {
2403
+ super();
2404
+ this.deps = deps;
2405
+ }
2406
+ async _handle(payload) {
2407
+ const sources = resolveSourceMessages(payload.messages, this.deps.messageUnique);
2408
+ const [firstSource] = sources;
2409
+ if (firstSource === void 0) throw kernelError("合并转发需要至少一条可解析的源消息(node.id)", "INVALID_PARAM");
2410
+ const target = {
2411
+ chatType: ChatType.GROUP,
2412
+ peerUid: String(payload.group_id)
2413
+ };
2414
+ const { msgId } = await this.deps.msgApi.sendForwardMessage(target, firstSource.peer, sources.map((s) => s.msgId));
2415
+ return { message_id: this.deps.messageUnique.alloc(msgId, target) };
2416
+ }
2417
+ };
2418
+ /** 发送私聊合并转发(P2-12)。 */
2419
+ var SendPrivateForwardMsgAction = class extends BaseAction {
2420
+ name = "send_private_forward_msg";
2421
+ schema = sendPrivateForwardMsgSchema;
2422
+ errorCodeMap = ob11ErrorCodeMap;
2423
+ deps;
2424
+ constructor(deps) {
2425
+ super();
2426
+ this.deps = deps;
2427
+ }
2428
+ async _handle(payload) {
2429
+ const sources = resolveSourceMessages(payload.messages, this.deps.messageUnique);
2430
+ const [firstSource] = sources;
2431
+ if (firstSource === void 0) throw kernelError("合并转发需要至少一条可解析的源消息(node.id)", "INVALID_PARAM");
2432
+ const uid = (await this.deps.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
2433
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
2434
+ const target = {
2435
+ chatType: ChatType.C2C,
2436
+ peerUid: uid
2437
+ };
2438
+ const { msgId } = await this.deps.msgApi.sendForwardMessage(target, firstSource.peer, sources.map((s) => s.msgId));
2439
+ return { message_id: this.deps.messageUnique.alloc(msgId, target) };
2440
+ }
2441
+ };
2442
+ //#endregion
2443
+ //#region src/onebot11/action/message/send-msg.ts
2444
+ /**
2445
+ * send_msg 动作:发送消息(群聊/私聊)+ 共享发送核心 sendOb11Message
2446
+ *
2447
+ * P2-3 真实化:注入 kernel MsgApi,message 参数(CQ 码字符串或 segment 数组)
2448
+ * 翻译为 canonical 元素 → MsgApi.sendMessage → 返回真实 message_id。
2449
+ * send_private_msg / send_group_msg 复用 sendOb11Message(P2-10)。
2450
+ *
2451
+ * 群聊:group_id → Peer{ chatType: GROUP, peerUid: String(group_id) }(群消息 peerUid=群号)。
2452
+ * 私聊:user_id 经 uin→uid → Peer{ chatType: C2C, peerUid: uid }。
2453
+ */
2454
+ const sendMsgSchema = z.object({
2455
+ message_type: z.enum(["group", "private"]).optional(),
2456
+ user_id: z.number().optional(),
2457
+ group_id: z.number().optional(),
2458
+ message: z.union([z.string(), z.array(z.unknown())]),
2459
+ auto_escape: z.boolean().optional()
2460
+ });
2461
+ /** 解析目标 Peer(group_id 直通;user_id 经 uin→uid)。 */
2462
+ async function resolvePeer(payload, deps) {
2463
+ if (payload.group_id !== void 0) return {
2464
+ chatType: ChatType.GROUP,
2465
+ peerUid: String(payload.group_id)
2466
+ };
2467
+ if (payload.user_id !== void 0) {
2468
+ const uid = (await deps.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
2469
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
2470
+ return {
2471
+ chatType: ChatType.C2C,
2472
+ peerUid: uid
2473
+ };
2474
+ }
2475
+ throw kernelError("send_msg 需要 group_id 或 user_id", "INVALID_PARAM");
2476
+ }
2477
+ /** 共享发送核心:解析 Peer → canonical 翻译(含 auto_escape)→ sendMessage → 映射 message_id。 */
2478
+ async function sendOb11Message(payload, deps) {
2479
+ const peer = await resolvePeer(payload, deps);
2480
+ let canonical;
2481
+ if (Array.isArray(payload.message)) canonical = segmentsToCanonical(payload.message);
2482
+ else canonical = cqMessageToCanonical(payload.message);
2483
+ const atUins = [];
2484
+ for (const el of canonical) if (el.type === "at" && el.target !== "all") atUins.push(el.target);
2485
+ let uinToUid;
2486
+ if (atUins.length > 0) try {
2487
+ uinToUid = await deps.uinToUid(atUins);
2488
+ } catch {}
2489
+ canonical = applySendContext(canonical, {
2490
+ ...uinToUid !== void 0 ? { uinToUid } : {},
2491
+ ob11IdToMsgId: (id) => deps.messageUnique.getMsgId(id)
2492
+ });
2493
+ if (payload.auto_escape === true) canonical = canonical.map((el) => {
2494
+ if (el.type === "text") return {
2495
+ ...el,
2496
+ text: escapeText(el.text)
2497
+ };
2498
+ return el;
2499
+ });
2500
+ const { msgId } = await deps.msgApi.sendMessage(peer, canonical);
2501
+ return { message_id: deps.messageUnique.alloc(msgId, peer) };
2502
+ }
2503
+ /** 发送消息(P2-3 接 kernel apis/msg,返回真实 message_id)。 */
2504
+ var SendMsgAction = class extends BaseAction {
2505
+ name = "send_msg";
2506
+ schema = sendMsgSchema;
2507
+ errorCodeMap = ob11ErrorCodeMap;
2508
+ deps;
2509
+ constructor(deps) {
2510
+ super();
2511
+ this.deps = deps;
2512
+ }
2513
+ _handle(payload) {
2514
+ return sendOb11Message(payload, this.deps);
2515
+ }
2516
+ };
2517
+ /** CQ 特殊字符转义(auto_escape,&、[、]、, 前置 &amp;)。 */
2518
+ function escapeText(text) {
2519
+ return text.replaceAll("&", "&amp;").replaceAll("[", "&#91;").replaceAll("]", "&#93;").replaceAll(",", "&#44;");
2520
+ }
2521
+ //#endregion
2522
+ //#region src/onebot11/action/message/send-group-msg.ts
2523
+ /**
2524
+ * send_group_msg 动作:发送群聊消息(复用 sendOb11Message 核心)
2525
+ */
2526
+ const sendGroupMsgSchema = z.object({
2527
+ group_id: z.number(),
2528
+ message: z.union([z.string(), z.array(z.unknown())]),
2529
+ auto_escape: z.boolean().optional()
2530
+ });
2531
+ /** 发送群聊消息(P2-10 复用 sendOb11Message)。 */
2532
+ var SendGroupMsgAction = class extends BaseAction {
2533
+ name = "send_group_msg";
2534
+ schema = sendGroupMsgSchema;
2535
+ errorCodeMap = ob11ErrorCodeMap;
2536
+ deps;
2537
+ constructor(deps) {
2538
+ super();
2539
+ this.deps = deps;
2540
+ }
2541
+ _handle(payload) {
2542
+ return sendOb11Message(payload, this.deps);
2543
+ }
2544
+ };
2545
+ //#endregion
2546
+ //#region src/onebot11/action/message/send-private-msg.ts
2547
+ /**
2548
+ * send_private_msg 动作:发送私聊消息(复用 sendOb11Message 核心)
2549
+ */
2550
+ const sendPrivateMsgSchema = z.object({
2551
+ user_id: z.number(),
2552
+ message: z.union([z.string(), z.array(z.unknown())]),
2553
+ auto_escape: z.boolean().optional()
2554
+ });
2555
+ /** 发送私聊消息(P2-10 复用 sendOb11Message)。 */
2556
+ var SendPrivateMsgAction = class extends BaseAction {
2557
+ name = "send_private_msg";
2558
+ schema = sendPrivateMsgSchema;
2559
+ errorCodeMap = ob11ErrorCodeMap;
2560
+ deps;
2561
+ constructor(deps) {
2562
+ super();
2563
+ this.deps = deps;
2564
+ }
2565
+ _handle(payload) {
2566
+ return sendOb11Message(payload, this.deps);
2567
+ }
2568
+ };
2569
+ //#endregion
2570
+ //#region src/onebot11/action/message/set-input-status.ts
2571
+ /**
2572
+ * set_input_status 动作:发送输入状态(NapCat 扩展,P2-11)
2573
+ *
2574
+ * user_id → uinToUid → MsgApi.setInputStatus(peer, eventType)。
2575
+ * eventType:1=输入中,0=停止输入。
2576
+ */
2577
+ const setInputStatusSchema = z.object({
2578
+ user_id: z.number(),
2579
+ /** 输入事件类型:1=输入中,0=停止。 */
2580
+ event_type: z.number().optional()
2581
+ });
2582
+ /** 输入中事件类型。 */
2583
+ const EVENT_TYPE_TYPING = 1;
2584
+ /** 发送输入状态(P2-11 接 kernel setInputStatus)。 */
2585
+ var SetInputStatusAction = class extends BaseAction {
2586
+ name = "set_input_status";
2587
+ schema = setInputStatusSchema;
2588
+ errorCodeMap = ob11ErrorCodeMap;
2589
+ deps;
2590
+ constructor(deps) {
2591
+ super();
2592
+ this.deps = deps;
2593
+ }
2594
+ async _handle(payload) {
2595
+ const uid = (await this.deps.uinToUid([String(payload.user_id)])).get(String(payload.user_id));
2596
+ if (uid === void 0) throw kernelError(`用户 ${payload.user_id} 的 uid 解析失败`, "INVALID_PARAM");
2597
+ await this.deps.msgApi.setInputStatus({
2598
+ chatType: ChatType.C2C,
2599
+ peerUid: uid
2600
+ }, payload.event_type ?? EVENT_TYPE_TYPING);
2601
+ return null;
2602
+ }
2603
+ };
2604
+ //#endregion
2605
+ //#region src/onebot11/action/message/set-msg-emoji-like.ts
2606
+ /**
2607
+ * set_msg_emoji_like 动作:消息表情表态(NapCat 扩展,P2-10)
2608
+ *
2609
+ * message_id → msgId + peer → 拉消息取 msgSeq → MsgApi.setMsgEmojiLike。
2610
+ */
2611
+ const setMsgEmojiLikeSchema = z.object({
2612
+ message_id: z.union([z.number(), z.string()]),
2613
+ /** 表情 ID(如 105 点赞)。 */
2614
+ emoji_id: z.number(),
2615
+ /** 表情类型(默认 1)。 */
2616
+ emoji_type: z.number().optional(),
2617
+ /** 是否点赞(false 取消)。 */
2618
+ like: z.boolean().optional()
2619
+ });
2620
+ /** 消息表情表态(P2-10 接 kernel setMsgEmojiLike)。 */
2621
+ var SetMsgEmojiLikeAction = class extends BaseAction {
2622
+ name = "set_msg_emoji_like";
2623
+ schema = setMsgEmojiLikeSchema;
2624
+ errorCodeMap = ob11ErrorCodeMap;
2625
+ deps;
2626
+ constructor(deps) {
2627
+ super();
2628
+ this.deps = deps;
2629
+ }
2630
+ async _handle(payload) {
2631
+ const { msgId, peer } = resolveMsgIdAndPeer(payload.message_id, this.deps.messageUnique);
2632
+ const [msg] = await this.deps.msgApi.fetchMsgsByMsgId(peer, [msgId]);
2633
+ if (msg === void 0) throw kernelError(`消息 ${payload.message_id} 不存在或已被撤回`, "NOT_FOUND");
2634
+ await this.deps.msgApi.setMsgEmojiLike(peer, {
2635
+ msgSeq: msg.msgSeq,
2636
+ emojiId: String(payload.emoji_id),
2637
+ emojiType: String(payload.emoji_type ?? 1),
2638
+ like: payload.like ?? true
2639
+ });
2640
+ return null;
2641
+ }
2642
+ };
2643
+ //#endregion
2644
+ //#region src/onebot11/action/system/can-send-image.ts
2645
+ /**
2646
+ * can_send_image 动作:是否可以发送图片(本地 true,P2-11)
2647
+ */
2648
+ const canSendImageSchema = z.object({});
2649
+ /** 是否可以发送图片(本地 true,P2-11)。 */
2650
+ var CanSendImageAction = class extends BaseAction {
2651
+ name = "can_send_image";
2652
+ schema = canSendImageSchema;
2653
+ errorCodeMap = ob11ErrorCodeMap;
2654
+ _handle(_payload) {
2655
+ return Promise.resolve({ yes: true });
2656
+ }
2657
+ };
2658
+ //#endregion
2659
+ //#region src/onebot11/action/system/can-send-record.ts
2660
+ /**
2661
+ * can_send_record 动作:是否可以发送语音(本地 true,P2-11)
2662
+ */
2663
+ const canSendRecordSchema = z.object({});
2664
+ /** 是否可以发送语音(本地 true,P2-11)。 */
2665
+ var CanSendRecordAction = class extends BaseAction {
2666
+ name = "can_send_record";
2667
+ schema = canSendRecordSchema;
2668
+ errorCodeMap = ob11ErrorCodeMap;
2669
+ _handle(_payload) {
2670
+ return Promise.resolve({ yes: true });
2671
+ }
2672
+ };
2673
+ //#endregion
2674
+ //#region src/onebot11/action/system/clean-cache.ts
2675
+ /**
2676
+ * clean_cache 动作:清理缓存(本地组装,P2-11)
2677
+ *
2678
+ * cleanCache 回调由装配方注入(boot.cjs 接 kernel PathWrapper.clearCache)。
2679
+ * 未配置时明确报错(不静默)。
2680
+ */
2681
+ const cleanCacheSchema = z.object({});
2682
+ /** 清理缓存(P2-11)。 */
2683
+ var CleanCacheAction = class extends BaseAction {
2684
+ name = "clean_cache";
2685
+ schema = cleanCacheSchema;
2686
+ errorCodeMap = ob11ErrorCodeMap;
2687
+ deps;
2688
+ constructor(deps) {
2689
+ super();
2690
+ this.deps = deps;
2691
+ }
2692
+ async _handle(_payload) {
2693
+ if (this.deps.cleanCache === void 0) throw kernelError("clean_cache 未配置(装配方未注入清理回调)", "INVALID_STATE");
2694
+ await this.deps.cleanCache();
2695
+ return null;
2696
+ }
2697
+ };
2698
+ //#endregion
2699
+ //#region src/onebot11/action/system/download-file.ts
2700
+ /**
2701
+ * download_file 动作:下载文件到缓存目录(P2-12)
2702
+ *
2703
+ * url → fetch 下载 → 存 deps.system.cacheDir(缺省抛错)→ 返回 { file }。
2704
+ * 文件名:download-<timestamp>-<basename>(headers 等扩展字段忽略)。
2705
+ */
2706
+ const downloadFileSchema = z.object({
2707
+ url: z.string(),
2708
+ thread_count: z.number().optional(),
2709
+ headers: z.record(z.string(), z.string()).optional()
2710
+ });
2711
+ /** 下载文件到缓存目录(P2-12)。 */
2712
+ var DownloadFileAction = class extends BaseAction {
2713
+ name = "download_file";
2714
+ schema = downloadFileSchema;
2715
+ errorCodeMap = ob11ErrorCodeMap;
2716
+ deps;
2717
+ constructor(deps) {
2718
+ super();
2719
+ this.deps = deps;
2720
+ }
2721
+ async _handle(payload) {
2722
+ const { cacheDir } = this.deps;
2723
+ if (cacheDir === void 0 || cacheDir === "") throw kernelError("download_file 未配置缓存目录(装配方未注入)", "INVALID_STATE");
2724
+ const safeName = basename(new URL(payload.url).pathname) || "download.bin";
2725
+ const filePath = join(cacheDir, `download-${Date.now()}-${safeName}`);
2726
+ mkdirSync(cacheDir, { recursive: true });
2727
+ const init = {};
2728
+ if (payload.headers !== void 0) init.headers = payload.headers;
2729
+ const res = await fetch(payload.url, init);
2730
+ if (!res.ok) throw new Error(`下载失败: ${res.status} ${res.statusText}`);
2731
+ const buf = new Uint8Array(await res.arrayBuffer());
2732
+ writeFileSync(filePath, buf);
2733
+ return { file: filePath };
2734
+ }
2735
+ };
2736
+ //#endregion
2737
+ //#region src/onebot11/action/system/get-clientkey.ts
2738
+ const getClientkeySchema = z.object({});
2739
+ /** 获取 clientKey(P2-13 接 kernel TicketApi)。 */
2740
+ var GetClientkeyAction = class extends BaseAction {
2741
+ name = "get_clientkey";
2742
+ schema = getClientkeySchema;
2743
+ errorCodeMap = ob11ErrorCodeMap;
2744
+ ticketApi;
2745
+ constructor(ticketApi) {
2746
+ super();
2747
+ this.ticketApi = ticketApi;
2748
+ }
2749
+ async _handle(_payload) {
2750
+ const raw = await this.ticketApi.getClientKey();
2751
+ return {
2752
+ clientKey: raw.clientKey,
2753
+ keyIndex: raw.keyIndex,
2754
+ expireTime: raw.expireTime,
2755
+ url: raw.url
2756
+ };
2757
+ }
2758
+ };
2759
+ //#endregion
2760
+ //#region src/onebot11/action/system/get-cookies.ts
2761
+ /**
2762
+ * get_cookies 动作:获取 cookies(P2-13 接 kernel TicketApi.getCookies)
2763
+ *
2764
+ * domain 缺省 v2.qq.com(NapCat 行为);user_id 缺省用机器人自身 uin。
2765
+ */
2766
+ const getCookiesSchema = z.object({
2767
+ domain: z.string().optional(),
2768
+ user_id: z.number().optional()
2769
+ });
2770
+ /** 默认域名。 */
2771
+ const DEFAULT_DOMAIN$1 = "v2.qq.com";
2772
+ /** 获取 cookies(P2-13 接 kernel TicketApi.getCookies)。 */
2773
+ var GetCookiesAction = class extends BaseAction {
2774
+ name = "get_cookies";
2775
+ schema = getCookiesSchema;
2776
+ errorCodeMap = ob11ErrorCodeMap;
2777
+ deps;
2778
+ constructor(deps) {
2779
+ super();
2780
+ this.deps = deps;
2781
+ }
2782
+ _handle(payload) {
2783
+ const domain = payload.domain ?? DEFAULT_DOMAIN$1;
2784
+ let uin = this.deps.selfUin;
2785
+ if (payload.user_id !== void 0) uin = String(payload.user_id);
2786
+ return this.deps.ticketApi.getCookies(domain, uin);
2787
+ }
2788
+ };
2789
+ //#endregion
2790
+ //#region src/onebot11/action/system/get-credentials.ts
2791
+ /**
2792
+ * get_csrf_token / get_credentials 动作(P2-15 接 kernel TicketApi)
2793
+ *
2794
+ * - get_csrf_token:qun.qq.com cookies 的 skey → bkn(csrf 等价物)
2795
+ * - get_credentials:指定域名 cookies + bkn → { cookies, csrf_token }
2796
+ */
2797
+ const getCsrfTokenSchema = z.object({});
2798
+ /** 默认域名(bkn 计算用)。 */
2799
+ const DEFAULT_DOMAIN = "qun.qq.com";
2800
+ /** 获取 csrf_token(bkn,P2-15)。 */
2801
+ var GetCsrfTokenAction = class extends BaseAction {
2802
+ name = "get_csrf_token";
2803
+ schema = getCsrfTokenSchema;
2804
+ errorCodeMap = ob11ErrorCodeMap;
2805
+ deps;
2806
+ constructor(deps) {
2807
+ super();
2808
+ this.deps = deps;
2809
+ }
2810
+ async _handle(_payload) {
2811
+ const skey = (await this.deps.ticketApi.getCookies(DEFAULT_DOMAIN, this.deps.selfUin))["skey"] ?? "";
2812
+ return { token: Number(TicketApi.getBkn(skey)) };
2813
+ }
2814
+ };
2815
+ const getCredentialsSchema = z.object({ domain: z.string().optional() });
2816
+ /** 获取凭据(cookies + csrf_token,P2-15)。 */
2817
+ var GetCredentialsAction = class extends BaseAction {
2818
+ name = "get_credentials";
2819
+ schema = getCredentialsSchema;
2820
+ errorCodeMap = ob11ErrorCodeMap;
2821
+ deps;
2822
+ constructor(deps) {
2823
+ super();
2824
+ this.deps = deps;
2825
+ }
2826
+ async _handle(payload) {
2827
+ const domain = payload.domain ?? DEFAULT_DOMAIN;
2828
+ const cookies = await this.deps.ticketApi.getCookies(domain, this.deps.selfUin);
2829
+ return {
2830
+ cookies,
2831
+ csrf_token: Number(TicketApi.getBkn(cookies["skey"] ?? ""))
2832
+ };
2833
+ }
2834
+ };
2835
+ //#endregion
2836
+ //#region src/onebot11/action/system/get-login-info.ts
2837
+ /**
2838
+ * get_login_info 动作:获取登录信息(P2-4 注入 self)
2839
+ */
2840
+ const getLoginInfoSchema = z.object({});
2841
+ /** 获取登录信息(self 由装配方注入,P2-5 接 kernel selfInfo 维护后取真实昵称)。 */
2842
+ var GetLoginInfoAction = class extends BaseAction {
2843
+ name = "get_login_info";
2844
+ schema = getLoginInfoSchema;
2845
+ errorCodeMap = ob11ErrorCodeMap;
2846
+ self;
2847
+ constructor(self) {
2848
+ super();
2849
+ this.self = self;
2850
+ }
2851
+ _handle(_payload) {
2852
+ return Promise.resolve({
2853
+ user_id: Number(this.self.uin),
2854
+ nickname: this.self.nickname
2855
+ });
2856
+ }
2857
+ };
2858
+ //#endregion
2859
+ //#region src/onebot11/action/system/get-robot-uin-range.ts
2860
+ /**
2861
+ * get_robot_uin_range 动作:获取机器人 QQ 号范围(本地组装,P2-11)
2862
+ *
2863
+ * NapCat 从配置返回;我们给通用范围(min/max)。
2864
+ */
2865
+ const getRobotUinRangeSchema = z.object({});
2866
+ /** QQ 号下限。 */
2867
+ const UIN_MIN = 10001;
2868
+ /** QQ 号上限。 */
2869
+ const UIN_MAX = 4294967295;
2870
+ /** 获取机器人 QQ 号范围(P2-11 本地组装)。 */
2871
+ var GetRobotUinRangeAction = class extends BaseAction {
2872
+ name = "get_robot_uin_range";
2873
+ schema = getRobotUinRangeSchema;
2874
+ errorCodeMap = ob11ErrorCodeMap;
2875
+ _handle(_payload) {
2876
+ return Promise.resolve({
2877
+ min: UIN_MIN,
2878
+ max: UIN_MAX
2879
+ });
2880
+ }
2881
+ };
2882
+ //#endregion
2883
+ //#region src/onebot11/action/system/get-status.ts
2884
+ /**
2885
+ * get_status 动作:获取运行状态(本地组装,P2-11)
2886
+ *
2887
+ * 返回与心跳 status 同构的 OB11Status(online/good + 扩展字段)。
2888
+ */
2889
+ const getStatusSchema = z.object({});
2890
+ /** 获取运行状态(本地组装,P2-11)。 */
2891
+ var GetStatusAction = class extends BaseAction {
2892
+ name = "get_status";
2893
+ schema = getStatusSchema;
2894
+ errorCodeMap = ob11ErrorCodeMap;
2895
+ _handle(_payload) {
2896
+ return Promise.resolve({
2897
+ online: true,
2898
+ good: true
2899
+ });
2900
+ }
2901
+ };
2902
+ //#endregion
2903
+ //#region src/onebot11/action/system/get-version-info.ts
2904
+ /**
2905
+ * get_version_info 动作:获取版本信息(本地组装,P2-11)
2906
+ *
2907
+ * appVersion 由装配方注入(kernel wrapper 版本或 NAPUTO_QQ_VERSION)。
2908
+ */
2909
+ const getVersionInfoSchema = z.object({});
2910
+ /** 获取版本信息(本地组装,P2-11)。 */
2911
+ var GetVersionInfoAction = class extends BaseAction {
2912
+ name = "get_version_info";
2913
+ schema = getVersionInfoSchema;
2914
+ errorCodeMap = ob11ErrorCodeMap;
2915
+ deps;
2916
+ constructor(deps) {
2917
+ super();
2918
+ this.deps = deps;
2919
+ }
2920
+ _handle(_payload) {
2921
+ return Promise.resolve({
2922
+ app_name: "napuketto-qq",
2923
+ app_version: this.deps.appVersion,
2924
+ protocol_version: "v11"
2925
+ });
2926
+ }
2927
+ };
2928
+ //#endregion
2929
+ //#region src/onebot11/action/system/process-control.ts
2930
+ /**
2931
+ * bot_exit / set_restart 动作:退出 / 重启(P2-12)
2932
+ *
2933
+ * exit/restart 回调由装配方注入(boot.cjs 接进程控制)。未配置时明确报错。
2934
+ */
2935
+ const botExitSchema = z.object({});
2936
+ /** 退出机器人进程(P2-12)。 */
2937
+ var BotExitAction = class extends BaseAction {
2938
+ name = "bot_exit";
2939
+ schema = botExitSchema;
2940
+ errorCodeMap = ob11ErrorCodeMap;
2941
+ deps;
2942
+ constructor(deps) {
2943
+ super();
2944
+ this.deps = deps;
2945
+ }
2946
+ async _handle(_payload) {
2947
+ if (this.deps.exit === void 0) throw kernelError("bot_exit 未配置(装配方未注入退出回调)", "INVALID_STATE");
2948
+ await this.deps.exit();
2949
+ return null;
2950
+ }
2951
+ };
2952
+ /** 重启机器人(P2-12;重启交给装配方,缺省退化为退出)。 */
2953
+ var SetRestartAction = class extends BaseAction {
2954
+ name = "set_restart";
2955
+ schema = botExitSchema;
2956
+ errorCodeMap = ob11ErrorCodeMap;
2957
+ deps;
2958
+ constructor(deps) {
2959
+ super();
2960
+ this.deps = deps;
2961
+ }
2962
+ async _handle(_payload) {
2963
+ const restart = this.deps.restart ?? this.deps.exit;
2964
+ if (restart === void 0) throw kernelError("set_restart 未配置(装配方未注入重启回调)", "INVALID_STATE");
2965
+ await restart();
2966
+ return null;
2967
+ }
2968
+ };
2969
+ //#endregion
2970
+ //#region src/onebot11/action/system/profile-actions.ts
2971
+ /** 资料类动作(P2-14):set_self_longnick / set_qq_profile / set_qq_avatar
2972
+ */
2973
+ /** URL 前缀(头像在线文件识别)。 */
2974
+ const URL_PREFIX = /^https?:\/\//;
2975
+ const setSelfLongnickSchema = z.object({ longNick: z.string() });
2976
+ /** 设置个性签名(P2-14 接 kernel ProfileApi.setLongNick)。 */
2977
+ var SetSelfLongnickAction = class extends BaseAction {
2978
+ name = "set_self_longnick";
2979
+ schema = setSelfLongnickSchema;
2980
+ errorCodeMap = ob11ErrorCodeMap;
2981
+ profileApi;
2982
+ constructor(profileApi) {
2983
+ super();
2984
+ this.profileApi = profileApi;
2985
+ }
2986
+ async _handle(payload) {
2987
+ await this.profileApi.setLongNick(payload.longNick);
2988
+ return null;
2989
+ }
2990
+ };
2991
+ const setQQProfileSchema = z.object({
2992
+ nickname: z.string(),
2993
+ personal_note: z.string().optional(),
2994
+ sex: z.union([z.number(), z.string()]).optional()
2995
+ });
2996
+ /** 设置 QQ 资料(P2-14;nickname → setNickName,personal_note → setLongNick,sex 忽略)。 */
2997
+ var SetQQProfileAction = class extends BaseAction {
2998
+ name = "set_qq_profile";
2999
+ schema = setQQProfileSchema;
3000
+ errorCodeMap = ob11ErrorCodeMap;
3001
+ profileApi;
3002
+ constructor(profileApi) {
3003
+ super();
3004
+ this.profileApi = profileApi;
3005
+ }
3006
+ async _handle(payload) {
3007
+ await this.profileApi.setNickName(payload.nickname);
3008
+ if (payload.personal_note !== void 0) await this.profileApi.setLongNick(payload.personal_note);
3009
+ return null;
3010
+ }
3011
+ };
3012
+ const setQQAvatarSchema = z.object({
3013
+ /** 本地路径(URL 需先下载,由装配方 cacheDir 支持)。 */
3014
+ file: z.string() });
3015
+ /** 设置 QQ 头像(P2-14 接 kernel ProfileApi.setHeader)。 */
3016
+ var SetQQAvatarAction = class extends BaseAction {
3017
+ name = "set_qq_avatar";
3018
+ schema = setQQAvatarSchema;
3019
+ errorCodeMap = ob11ErrorCodeMap;
3020
+ deps;
3021
+ constructor(deps) {
3022
+ super();
3023
+ this.deps = deps;
3024
+ }
3025
+ async _handle(payload) {
3026
+ let filePath = payload.file;
3027
+ if (URL_PREFIX.test(filePath)) filePath = await this.downloadToCache(filePath);
3028
+ if (!existsSync(filePath)) throw kernelError(`头像文件不存在: ${filePath}`, "NOT_FOUND");
3029
+ await this.deps.profileApi.setHeader(filePath);
3030
+ return null;
3031
+ }
3032
+ /** URL 下载到缓存目录(cacheDir 缺省抛错)。 */
3033
+ async downloadToCache(url) {
3034
+ const { cacheDir } = this.deps;
3035
+ if (cacheDir === void 0 || cacheDir === "") throw kernelError("set_qq_avatar 处理 URL 需要缓存目录(装配方未注入)", "INVALID_STATE");
3036
+ const safeName = basename(new URL(url).pathname) || "avatar.bin";
3037
+ const filePath = join(cacheDir, `avatar-${Date.now()}-${safeName}`);
3038
+ const res = await fetch(url);
3039
+ if (!res.ok) throw new Error(`头像下载失败: ${res.status} ${res.statusText}`);
3040
+ const buf = new Uint8Array(await res.arrayBuffer());
3041
+ writeFileSync(filePath, buf);
3042
+ return filePath;
3043
+ }
3044
+ };
3045
+ //#endregion
3046
+ //#region src/onebot11/action/system/set-diy-online-status.ts
3047
+ const setDiyOnlineStatusSchema = z.object({
3048
+ status: z.number().optional(),
3049
+ /** 自定义状态文案。 */
3050
+ wording: z.string(),
3051
+ /** 表情 ID。 */
3052
+ face_id: z.string().optional(),
3053
+ /** 表情类型。 */
3054
+ face_type: z.string().optional()
3055
+ });
3056
+ /** 默认在线状态值。 */
3057
+ const STATUS_ONLINE$1 = 10;
3058
+ /** 设置自定义在线状态(P2-12 接 kernel setOnlineStatus customStatus)。 */
3059
+ var SetDiyOnlineStatusAction = class extends BaseAction {
3060
+ name = "set_diy_online_status";
3061
+ schema = setDiyOnlineStatusSchema;
3062
+ errorCodeMap = ob11ErrorCodeMap;
3063
+ msgApi;
3064
+ constructor(msgApi) {
3065
+ super();
3066
+ this.msgApi = msgApi;
3067
+ }
3068
+ async _handle(payload) {
3069
+ const customStatus = {
3070
+ faceId: payload.face_id ?? "",
3071
+ wording: payload.wording,
3072
+ faceType: payload.face_type ?? "1"
3073
+ };
3074
+ await this.msgApi.setOnlineStatus({
3075
+ status: payload.status ?? STATUS_ONLINE$1,
3076
+ extStatus: 0,
3077
+ batteryStatus: 0,
3078
+ customStatus
3079
+ });
3080
+ return null;
3081
+ }
3082
+ };
3083
+ //#endregion
3084
+ //#region src/onebot11/action/system/set-online-status.ts
3085
+ const setOnlineStatusSchema = z.object({
3086
+ status: z.number().optional(),
3087
+ ext_status: z.number().optional(),
3088
+ battery_status: z.number().optional()
3089
+ });
3090
+ /** 默认在线状态值。 */
3091
+ const STATUS_ONLINE = 10;
3092
+ /** 设置在线状态(P2-12 接 kernel setOnlineStatus)。 */
3093
+ var SetOnlineStatusAction = class extends BaseAction {
3094
+ name = "set_online_status";
3095
+ schema = setOnlineStatusSchema;
3096
+ errorCodeMap = ob11ErrorCodeMap;
3097
+ msgApi;
3098
+ constructor(msgApi) {
3099
+ super();
3100
+ this.msgApi = msgApi;
3101
+ }
3102
+ async _handle(payload) {
3103
+ await this.msgApi.setOnlineStatus({
3104
+ status: payload.status ?? STATUS_ONLINE,
3105
+ extStatus: payload.ext_status ?? 0,
3106
+ batteryStatus: payload.battery_status ?? 0
3107
+ });
3108
+ return null;
3109
+ }
3110
+ };
3111
+ //#endregion
3112
+ //#region src/onebot11/action/system/translate-en2zh.ts
3113
+ const translateEn2ZhSchema = z.object({ words: z.array(z.string()) });
3114
+ /** 英文单词翻译(P2-14)。 */
3115
+ var TranslateEn2ZhAction = class extends BaseAction {
3116
+ name = "translate_en2zh";
3117
+ schema = translateEn2ZhSchema;
3118
+ errorCodeMap = ob11ErrorCodeMap;
3119
+ richMediaApi;
3120
+ constructor(richMediaApi) {
3121
+ super();
3122
+ this.richMediaApi = richMediaApi;
3123
+ }
3124
+ async _handle(payload) {
3125
+ return { words: await this.richMediaApi.translateWords(payload.words) };
3126
+ }
3127
+ };
3128
+ //#endregion
3129
+ //#region src/onebot11/action/index.ts
3130
+ /**
3131
+ * OneBot 11 动作注册表(ADR-013 延伸)
3132
+ * 各协议维护自己的 ActionRegistry,由协议 adapter 挂到请求分发。
3133
+ * P2-16:deps 收敛为 { api: OneBotApi } 单聚合对象(基础设施第一项)。
3134
+ */
3135
+ /** 构建 OB11 动作注册表(所有 OB11 动作在此注册,按组拆分控制行数)。 */
3136
+ function createOb11ActionRegistry(deps) {
3137
+ const registry = new ActionRegistry();
3138
+ registerMsgActions(registry, deps);
3139
+ registerForwardActions(registry, deps);
3140
+ registerQueryActions(registry, deps);
3141
+ registerGroupActions(registry, deps);
3142
+ registerFriendActions(registry, deps);
3143
+ registerSystemActions(registry, deps);
3144
+ registerGroupNotifyActions(registry, deps);
3145
+ registerTicketActions(registry, deps);
3146
+ registerProfileActions(registry, deps);
3147
+ registerGroupFileActions(registry, deps);
3148
+ registerWebActions(registry, deps);
3149
+ return registry;
3150
+ }
3151
+ /** 群空间 web / csrf / 陌生人 / 群请求动作(P2-15)。 */
3152
+ function registerWebActions(registry, deps) {
3153
+ registry.register(new GetStrangerInfoAction(deps.api.profileApi));
3154
+ registry.register(new GetCsrfTokenAction(deps.api));
3155
+ registry.register(new GetCredentialsAction(deps.api));
3156
+ registry.register(new GetGroupAddRequestAction(deps.api.groupNotifyApi));
3157
+ registry.register(new GetGroupIgnoredNotifiesAction(deps.api.groupNotifyApi));
3158
+ registry.register(new GetEssenceMsgListAction(deps.api.webApi));
3159
+ registry.register(new GetGroupHonorInfoAction(deps.api.webApi));
3160
+ }
3161
+ /** 资料/点赞/翻译动作(P2-14)。 */
3162
+ function registerProfileActions(registry, deps) {
3163
+ registry.register(new SetSelfLongnickAction(deps.api.profileApi));
3164
+ registry.register(new SetQQProfileAction(deps.api.profileApi));
3165
+ registry.register(new SetQQAvatarAction(deps.api));
3166
+ registry.register(new TranslateEn2ZhAction(deps.api.richMediaApi));
3167
+ registry.register(new SendLikeAction(deps.api));
3168
+ }
3169
+ /** 群文件动作(P2-14)。 */
3170
+ function registerGroupFileActions(registry, deps) {
3171
+ registry.register(new GetGroupRootFilesAction(deps.api.richMediaApi));
3172
+ registry.register(new GetGroupFilesByFolderAction(deps.api.richMediaApi));
3173
+ registry.register(new GetGroupFileSystemInfoAction(deps.api.richMediaApi));
3174
+ registry.register(new CreateGroupFileFolderAction(deps.api.richMediaApi));
3175
+ registry.register(new DeleteGroupFileAction(deps.api.richMediaApi));
3176
+ registry.register(new DeleteGroupFolderAction(deps.api.richMediaApi));
3177
+ registry.register(new RenameGroupFileAction(deps.api.richMediaApi));
3178
+ registry.register(new MoveGroupFileAction(deps.api.richMediaApi));
3179
+ registry.register(new TransGroupFileAction(deps.api.richMediaApi));
3180
+ }
3181
+ /** 群通知/禁言列表动作(P2-13)。 */
3182
+ function registerGroupNotifyActions(registry, deps) {
3183
+ registry.register(new SetGroupAddRequestAction(deps.api.groupNotifyApi));
3184
+ registry.register(new GetGroupSystemMsgAction(deps.api));
3185
+ registry.register(new GetGroupShutListAction(deps.api));
3186
+ }
3187
+ /** 票据动作(P2-13)。 */
3188
+ function registerTicketActions(registry, deps) {
3189
+ registry.register(new GetClientkeyAction(deps.api.ticketApi));
3190
+ registry.register(new GetCookiesAction(deps.api));
3191
+ }
3192
+ /** 合并转发 / 单条转发 / 在线状态(P2-12)。 */
3193
+ function registerForwardActions(registry, deps) {
3194
+ registry.register(new SendGroupForwardMsgAction(deps.api));
3195
+ registry.register(new SendPrivateForwardMsgAction(deps.api));
3196
+ registry.register(new GetForwardMsgAction(deps.api));
3197
+ registry.register(new ForwardGroupSingleMsgAction(deps.api));
3198
+ registry.register(new ForwardFriendSingleMsgAction(deps.api));
3199
+ registry.register(new SetOnlineStatusAction(deps.api.msgApi));
3200
+ registry.register(new SetDiyOnlineStatusAction(deps.api.msgApi));
3201
+ }
3202
+ /** 消息类动作(P2-3 / P2-10 / P2-11)。 */
3203
+ function registerMsgActions(registry, deps) {
3204
+ registry.register(new SendMsgAction(deps.api));
3205
+ registry.register(new SendPrivateMsgAction(deps.api));
3206
+ registry.register(new SendGroupMsgAction(deps.api));
3207
+ registry.register(new DeleteMsgAction(deps.api));
3208
+ registry.register(new GetMsgAction(deps.api));
3209
+ registry.register(new GetGroupMsgHistoryAction(deps.api));
3210
+ registry.register(new GetFriendMsgHistoryAction(deps.api));
3211
+ registry.register(new MarkMsgAsReadAction(deps.api));
3212
+ registry.register(new MarkPrivateMsgAsReadAction(deps.api));
3213
+ registry.register(new MarkGroupMsgAsReadAction(deps.api));
3214
+ registry.register(new SetMsgEmojiLikeAction(deps.api));
3215
+ registry.register(new FetchPttTextAction(deps.api));
3216
+ registry.register(new SetInputStatusAction(deps.api));
3217
+ registry.register(new GetImageAction(deps.api));
3218
+ registry.register(new GetRecordAction(deps.api));
3219
+ }
3220
+ /** 查询类动作(P2-4;P2-17 群信息/成员动作读 GroupCache)。 */
3221
+ function registerQueryActions(registry, deps) {
3222
+ registry.register(new GetLoginInfoAction(deps.api.self));
3223
+ registry.register(new GetGroupInfoAction(deps.api));
3224
+ registry.register(new GetGroupListAction(deps.api.groupApi));
3225
+ registry.register(new GetGroupMemberInfoAction(deps.api));
3226
+ registry.register(new GetGroupMemberListAction(deps.api));
3227
+ registry.register(new GetFriendListAction(deps.api.friendApi));
3228
+ }
3229
+ /** 群管类动作(P2-10)。 */
3230
+ function registerGroupActions(registry, deps) {
3231
+ registry.register(new SetGroupKickAction(deps.api.groupApi));
3232
+ registry.register(new SetGroupBanAction(deps.api.groupApi));
3233
+ registry.register(new SetGroupWholeBanAction(deps.api.groupApi));
3234
+ registry.register(new SetGroupAdminAction(deps.api.groupApi));
3235
+ registry.register(new SetGroupCardAction(deps.api.groupApi));
3236
+ registry.register(new SetGroupNameAction(deps.api.groupApi));
3237
+ registry.register(new SetGroupLeaveAction(deps.api.groupApi));
3238
+ registry.register(new SetEssenceMsgAction(deps.api));
3239
+ registry.register(new DeleteEssenceMsgAction(deps.api));
3240
+ registry.register(new GetGroupAtAllRemainAction(deps.api.groupApi));
3241
+ }
3242
+ /** 好友类动作(P2-11)。 */
3243
+ function registerFriendActions(registry, deps) {
3244
+ registry.register(new SetFriendAddRequestAction(deps.api.friendApi));
3245
+ registry.register(new SetFriendRemarkAction(deps.api));
3246
+ registry.register(new DeleteFriendAction(deps.api));
3247
+ registry.register(new GetFriendsWithCategoryAction(deps.api.friendApi));
3248
+ registry.register(new GetDoubtFriendsAddRequestAction(deps.api.friendApi));
3249
+ registry.register(new SetDoubtFriendsAddRequestAction(deps.api.friendApi));
3250
+ }
3251
+ /** 系统类动作(P2-11 / P2-12)。 */
3252
+ function registerSystemActions(registry, deps) {
3253
+ registry.register(new GetStatusAction());
3254
+ registry.register(new GetVersionInfoAction(deps.api));
3255
+ registry.register(new CleanCacheAction(deps.api));
3256
+ registry.register(new CanSendImageAction());
3257
+ registry.register(new CanSendRecordAction());
3258
+ registry.register(new GetRobotUinRangeAction());
3259
+ registry.register(new DownloadFileAction(deps.api));
3260
+ registry.register(new BotExitAction(deps.api));
3261
+ registry.register(new SetRestartAction(deps.api));
3262
+ }
3263
+ //#endregion
3264
+ //#region src/onebot11/api/one-bot-api.ts
3265
+ /**
3266
+ * OneBot 11 动作统一依赖聚合(P2-16)。
3267
+ * 各动作经 `Pick<OneBotApi, ...>` 取所需成员;注册处只构造一次本对象。
3268
+ */
3269
+ var OneBotApi = class {
3270
+ /** kernel 消息 API(send_msg 等消息类动作用)。 */
3271
+ msgApi;
3272
+ /** kernel 群 API。 */
3273
+ groupApi;
3274
+ /** kernel 群通知 API(群请求/禁言列表用)。 */
3275
+ groupNotifyApi;
3276
+ /** kernel 好友 API。 */
3277
+ friendApi;
3278
+ /** kernel 票据 API(get_clientkey/get_cookies 用)。 */
3279
+ ticketApi;
3280
+ /** kernel 富媒体 API(群文件/翻译用)。 */
3281
+ richMediaApi;
3282
+ /** kernel 资料 API(签名/昵称/头像用)。 */
3283
+ profileApi;
3284
+ /** kernel 点赞 API(send_like 用)。 */
3285
+ profileLikeApi;
3286
+ /** kernel 群空间 web API(精华/荣誉用)。 */
3287
+ webApi;
3288
+ /** 群/成员缓存(ADR-008;翻译层只读消费,缺失惰性回填)。 */
3289
+ groupCache;
3290
+ /** OB11 message_id ↔ NT msgId 双向映射(收链路与动作共用同一映射空间)。 */
3291
+ messageUnique;
3292
+ /** 登录身份(get_login_info 用)。 */
3293
+ self;
3294
+ /** 机器人自身 uin(get_cookies / csrf 用)。 */
3295
+ selfUin;
3296
+ /** 运行版本(get_version_info 用)。 */
3297
+ appVersion;
3298
+ /** 缓存清理回调(clean_cache 用)。 */
3299
+ cleanCache;
3300
+ /** 缓存目录(download_file 用)。 */
3301
+ cacheDir;
3302
+ /** 进程退出回调(bot_exit 用)。 */
3303
+ exit;
3304
+ /** 进程重启回调(set_restart 用)。 */
3305
+ restart;
3306
+ constructor(opts) {
3307
+ this.msgApi = opts.msgApi;
3308
+ this.groupApi = opts.groupApi;
3309
+ this.groupNotifyApi = opts.groupNotifyApi;
3310
+ this.friendApi = opts.friendApi;
3311
+ this.ticketApi = opts.ticketApi;
3312
+ this.richMediaApi = opts.richMediaApi;
3313
+ this.profileApi = opts.profileApi;
3314
+ this.profileLikeApi = opts.profileLikeApi;
3315
+ this.webApi = opts.webApi;
3316
+ this.groupCache = opts.groupCache;
3317
+ this.messageUnique = new MessageUnique();
3318
+ this.self = opts.self;
3319
+ this.selfUin = opts.self.uin;
3320
+ this.appVersion = opts.system.appVersion;
3321
+ this.cleanCache = opts.system.cleanCache;
3322
+ this.cacheDir = opts.system.cacheDir;
3323
+ this.exit = opts.system.exit;
3324
+ this.restart = opts.system.restart;
3325
+ }
3326
+ /** uin→uid 转换(委托 groupApi;私聊目标/成员 user_id 用)。 */
3327
+ uinToUid(uins) {
3328
+ return this.groupApi.uinToUid(uins);
3329
+ }
3330
+ /** uid→uin 转换(委托 groupApi;notice/grayTip 用)。 */
3331
+ uidToUin(uids) {
3332
+ return this.groupApi.uidToUin(uids);
3333
+ }
3334
+ };
3335
+ //#endregion
3336
+ //#region src/onebot11/helper/message-event.ts
3337
+ /** 毫秒 → 秒(Unix 时间戳)。 */
3338
+ const MS_TO_SEC$1 = 1e3;
3339
+ /** RawMessage → OB11 消息事件(message_id 经 MessageUnique 映射并记录 peer)。
3340
+ * messageFormat 决定 message 字段格式:array = 消息段数组(标准),string = CQ 码字符串。
3341
+ * ctx(可选):接收方向 ID 转换上下文(at uid→uin、reply NT msgId→OB11 id,P2-19)。 */
3342
+ function toOb11MessageEvent(msg, selfUin, unique, messageFormat = "array", ctx = {}) {
3343
+ const elements = applyReceiveContext(toCanonicalElements(msg), ctx);
3344
+ const segments = canonicalToSegments(elements);
3345
+ const time = Math.floor(Number(msg.msgTime) / MS_TO_SEC$1);
3346
+ const selfId = Number(selfUin);
3347
+ const userId = Number(msg.senderUin);
3348
+ const base = {
3349
+ time,
3350
+ self_id: selfId,
3351
+ post_type: "message",
3352
+ message_id: unique.alloc(msg.msgId, {
3353
+ chatType: msg.chatType,
3354
+ peerUid: msg.peerUid
3355
+ }),
3356
+ message: messageFormat === "string" ? canonicalToCqMessage(elements) : segments,
3357
+ raw_message: canonicalToCqMessage(elements),
3358
+ font: 0
3359
+ };
3360
+ if (msg.chatType === ChatType.GROUP) {
3361
+ const sender = {
3362
+ user_id: userId,
3363
+ nickname: msg.sendNickName,
3364
+ role: "member"
3365
+ };
3366
+ if (msg.sendMemberName !== void 0) sender.card = msg.sendMemberName;
3367
+ return {
3368
+ ...base,
3369
+ message_type: "group",
3370
+ sub_type: "normal",
3371
+ group_id: Number(msg.peerUid),
3372
+ user_id: userId,
3373
+ sender
3374
+ };
3375
+ }
3376
+ let subType = "friend";
3377
+ if (msg.chatType === ChatType.C2C_TEMP) subType = "group";
3378
+ const sender = {
3379
+ user_id: userId,
3380
+ nickname: msg.sendNickName
3381
+ };
3382
+ return {
3383
+ ...base,
3384
+ message_type: "private",
3385
+ sub_type: subType,
3386
+ user_id: userId,
3387
+ sender
3388
+ };
3389
+ }
3390
+ //#endregion
3391
+ //#region src/onebot11/transport.ts
3392
+ /**
3393
+ * OB11 传输装配(P2-5,2026-08-05)
3394
+ *
3395
+ * 按 OB11Config 创建/装配 network 传输适配器:
3396
+ * - HTTP 反向(http.enabled):HttpServer 接收第三方调用 → handleRequest → 响应
3397
+ * - WS 反向(ws.enabled):WsServer 第三方连入 → handleRequest(echo 透传)+ 事件广播
3398
+ * - HTTP 正向(httpPost.enabled):HttpClient 事件上报(fire-and-forget)
3399
+ * - WS 正向(wsReverse.enabled):WsClient 主动连第三方(双向)
3400
+ *
3401
+ * 鉴权:token 存在时校验 Authorization: Bearer <token> / access_token 查询参数。
3402
+ * 返回 transports(事件上报用,注册到 broadcaster)与 close(停止时关闭全部)。
3403
+ */
3404
+ /** Authorization 头前缀。 */
3405
+ const BEARER_PREFIX = "Bearer ";
3406
+ /** 校验 URL 查询参数里的 access_token(WS client 连接 URL 可能带)。 */
3407
+ function hasAccessTokenQuery(url, token) {
3408
+ try {
3409
+ return new URL(url).searchParams.get("access_token") === token;
3410
+ } catch {
3411
+ return false;
3412
+ }
3413
+ }
3414
+ /** 校验 Authorization: Bearer <token> 头。 */
3415
+ function checkBearer(auth, token) {
3416
+ if (auth === void 0 || !auth.startsWith(BEARER_PREFIX)) return false;
3417
+ return auth.slice(7) === token;
3418
+ }
3419
+ /** 构造鉴权钩子(token 未配置则不鉴权)。 */
3420
+ function makeAuthorize(token) {
3421
+ if (token === void 0 || token === "") return;
3422
+ return (ctx) => {
3423
+ if (checkBearer(ctx.headers["authorization"] ?? ctx.headers["Authorization"], token) || ctx.headers["authorization"] === token) return true;
3424
+ return hasAccessTokenQuery(ctx.url, token);
3425
+ };
3426
+ }
3427
+ /** 按配置装配 OB11 传输。 */
3428
+ function assembleOb11Transports(opts) {
3429
+ const { config, broadcaster, handleRequest } = opts;
3430
+ const servers = [];
3431
+ const transports = [];
3432
+ assembleHttpServers(config, handleRequest, servers);
3433
+ assembleWsServers(config, handleRequest, servers);
3434
+ assembleHttpPosts(config, transports);
3435
+ assembleWsReverses(config, handleRequest, transports);
3436
+ for (const t of transports) broadcaster.register(t);
3437
+ for (const s of servers) broadcaster.register(s);
3438
+ return {
3439
+ servers,
3440
+ transports,
3441
+ close: async () => {
3442
+ await Promise.all([...servers, ...transports].map((t) => t.close()));
3443
+ for (const t of [...servers, ...transports]) broadcaster.unregister(t);
3444
+ }
3445
+ };
3446
+ }
3447
+ /** 装配 HTTP 反向 server 列表(每实例一个 HttpServer,共享 handleRequest)。 */
3448
+ function assembleHttpServers(config, handleRequest, servers) {
3449
+ for (const item of config.httpServers) if (item.enabled) {
3450
+ const options = {
3451
+ host: item.host,
3452
+ port: item.port
3453
+ };
3454
+ const authorize = makeAuthorize(item.token ?? config.token);
3455
+ if (authorize !== void 0) options.authorize = authorize;
3456
+ const server = new HttpServer(options);
3457
+ server.onRequest = handleRequest;
3458
+ servers.push(server);
3459
+ }
3460
+ }
3461
+ /** 装配反向 WS server 列表(每实例一个 WsServer,心跳 ping + 鉴权)。 */
3462
+ function assembleWsServers(config, handleRequest, servers) {
3463
+ for (const item of config.wsServers) if (item.enabled) {
3464
+ const options = {
3465
+ host: item.host,
3466
+ port: item.port,
3467
+ heartbeat: { intervalMs: item.heartbeatInterval }
3468
+ };
3469
+ const authorize = makeAuthorize(item.token ?? config.token);
3470
+ if (authorize !== void 0) options.authorize = authorize;
3471
+ const server = new WsServer(options);
3472
+ server.onRequest = handleRequest;
3473
+ servers.push(server);
3474
+ }
3475
+ }
3476
+ /** 装配 HTTP 正向上报 client 列表(fire-and-forget)。 */
3477
+ function assembleHttpPosts(config, transports) {
3478
+ for (const item of config.httpPostUrls) if (item.enabled && item.url !== void 0) {
3479
+ const headers = authorizeHeader(item.token ?? config.token);
3480
+ const options = { url: item.url };
3481
+ if (headers !== void 0) options.headers = headers;
3482
+ if (item.timeoutMs !== void 0) options.timeoutMs = item.timeoutMs;
3483
+ transports.push(new HttpClient(options));
3484
+ }
3485
+ }
3486
+ /** 装配正向 WS client 列表(双向,心跳 + 重连 + 证书选项)。 */
3487
+ function assembleWsReverses(config, handleRequest, transports) {
3488
+ for (const item of config.wsReverseUrls) if (item.enabled && item.url !== void 0) {
3489
+ const headers = authorizeHeader(item.token ?? config.token);
3490
+ const reconnect = {
3491
+ enabled: true,
3492
+ delayMs: item.reconnectDelayMs
3493
+ };
3494
+ if (item.maxReconnectAttempts !== void 0) reconnect.maxAttempts = item.maxReconnectAttempts;
3495
+ const options = {
3496
+ url: item.url,
3497
+ heartbeat: { intervalMs: item.heartbeatInterval },
3498
+ reconnect,
3499
+ rejectUnauthorized: item.rejectUnauthorized
3500
+ };
3501
+ if (headers !== void 0) options.headers = headers;
3502
+ const client = new WsClient(options);
3503
+ client.onRequest = handleRequest;
3504
+ transports.push(client);
3505
+ }
3506
+ }
3507
+ /** token → Authorization 头(client 上报/连接用)。 */
3508
+ function authorizeHeader(token) {
3509
+ if (token === void 0 || token === "") return;
3510
+ return { authorization: `${BEARER_PREFIX}${token}` };
3511
+ }
3512
+ //#endregion
3513
+ //#region src/onebot11/adapter.ts
3514
+ /** 毫秒 → 秒(Unix 时间戳)。 */
3515
+ const MS_TO_SEC = 1e3;
3516
+ /** OneBot 11 协议适配器。 */
3517
+ var NapukettoOneBot11Adapter = class extends BaseProtocolAdapter {
3518
+ protocol = "onebot11";
3519
+ configSchema = ob11ConfigSchema;
3520
+ msgChannel;
3521
+ selfUin;
3522
+ oneBotApi;
3523
+ registry;
3524
+ unsubscribe = null;
3525
+ transports = null;
3526
+ heartbeatTimer = null;
3527
+ reportSelfMessage = false;
3528
+ messageFormat = "array";
3529
+ constructor(opts) {
3530
+ super({
3531
+ config: opts.config,
3532
+ broadcaster: opts.broadcaster,
3533
+ hooks: {
3534
+ onStart: (config) => this.startTransports(config),
3535
+ onStop: () => this.stopAll(),
3536
+ onReload: () => {
3537
+ return Promise.resolve();
3538
+ }
3539
+ }
3540
+ });
3541
+ this.msgChannel = opts.msgChannel;
3542
+ this.selfUin = opts.self.uin;
3543
+ this.oneBotApi = new OneBotApi(opts);
3544
+ this.registry = createOb11ActionRegistry({ api: this.oneBotApi });
3545
+ }
3546
+ /** 启动传输:装配(HTTP/WS)+ 打开 server/client + 广播 lifecycle enable + 起心跳。 */
3547
+ async startTransports(config) {
3548
+ this.reportSelfMessage = config.reportSelfMessage;
3549
+ this.messageFormat = config.messagePostFormat;
3550
+ const broadcaster = this.getBroadcaster();
3551
+ if (broadcaster !== void 0) {
3552
+ this.transports = assembleOb11Transports({
3553
+ config,
3554
+ broadcaster,
3555
+ handleRequest: (req, respond) => {
3556
+ this.handleRequest(req, respond).catch((err) => {
3557
+ let message = String(err);
3558
+ if (err instanceof Error) message = err.message;
3559
+ respond({
3560
+ status: "failed",
3561
+ retcode: 999,
3562
+ data: null,
3563
+ message
3564
+ });
3565
+ });
3566
+ }
3567
+ });
3568
+ await Promise.all(this.transports.servers.map((s) => s.open()));
3569
+ await Promise.all(this.transports.transports.map((t) => t.open()));
3570
+ }
3571
+ this.subscribe();
3572
+ this.broadcastEvent({
3573
+ time: Math.floor(Date.now() / MS_TO_SEC),
3574
+ self_id: Number(this.selfUin),
3575
+ post_type: "meta_event",
3576
+ meta_event_type: "lifecycle",
3577
+ sub_type: "enable"
3578
+ });
3579
+ this.startHeartbeat(config.heartbeatInterval);
3580
+ }
3581
+ /** 心跳 meta 事件(interval 毫秒,0 关闭)。 */
3582
+ startHeartbeat(intervalMs) {
3583
+ if (intervalMs <= 0) return;
3584
+ this.heartbeatTimer = setInterval(() => {
3585
+ this.broadcastEvent({
3586
+ time: Math.floor(Date.now() / MS_TO_SEC),
3587
+ self_id: Number(this.selfUin),
3588
+ post_type: "meta_event",
3589
+ meta_event_type: "heartbeat",
3590
+ interval: intervalMs,
3591
+ status: {
3592
+ online: true,
3593
+ good: true
3594
+ }
3595
+ });
3596
+ }, intervalMs);
3597
+ }
3598
+ /** 停止:心跳 + 传输 + 退订。 */
3599
+ async stopAll() {
3600
+ if (this.heartbeatTimer !== null) {
3601
+ clearInterval(this.heartbeatTimer);
3602
+ this.heartbeatTimer = null;
3603
+ }
3604
+ this.unsubscribeAll();
3605
+ if (this.transports !== null) {
3606
+ await this.transports.close();
3607
+ this.transports = null;
3608
+ }
3609
+ }
3610
+ /** 订阅 kernel 消息事件(幂等)。 */
3611
+ subscribe() {
3612
+ if (this.unsubscribe !== null) return;
3613
+ this.unsubscribe = this.msgChannel.on("Msg/onRecvMsg", (msgs) => {
3614
+ const list = Array.isArray(msgs) ? msgs : [msgs];
3615
+ for (const msg of list) {
3616
+ if (!msg || typeof msg !== "object") continue;
3617
+ if (hasGrayTip(msg)) {
3618
+ this.broadcastNotice(msg).catch(() => {});
3619
+ continue;
3620
+ }
3621
+ if (!this.reportSelfMessage && String(msg.senderUin) === this.selfUin) continue;
3622
+ this.broadcastMessageEvent(msg);
3623
+ }
3624
+ });
3625
+ }
3626
+ /**
3627
+ * 广播消息事件(P2-19:接收方向 ID 转换)。
3628
+ * 收集 at uid → 一次批量 uidToUin → 构造上下文 → 翻译广播。
3629
+ * 翻译失败退化为原样(不阻塞上报)。
3630
+ */
3631
+ async broadcastMessageEvent(msg) {
3632
+ const { atUids } = collectReceiveNeeds(toCanonicalElements(msg));
3633
+ let uidToUin;
3634
+ if (atUids.length > 0) try {
3635
+ uidToUin = await this.oneBotApi.uidToUin(atUids);
3636
+ } catch {}
3637
+ const ctx = {
3638
+ ...uidToUin !== void 0 ? { uidToUin } : {},
3639
+ msgIdToOb11Id: (msgId) => this.oneBotApi.messageUnique.getMessageId(msgId)
3640
+ };
3641
+ this.broadcastEvent(toOb11MessageEvent(msg, this.selfUin, this.oneBotApi.messageUnique, this.messageFormat, ctx));
3642
+ }
3643
+ /** 广播 grayTip → notice 事件(批量 uidToUin 后翻译,纯函数)。 */
3644
+ async broadcastNotice(msg) {
3645
+ const uids = collectGrayTipUids(msg);
3646
+ let uidToUin = /* @__PURE__ */ new Map();
3647
+ if (uids.length > 0) uidToUin = await this.oneBotApi.uidToUin(uids);
3648
+ const notice = toOb11NoticeEvent(msg, {
3649
+ selfUin: this.selfUin,
3650
+ uidToUin
3651
+ });
3652
+ if (notice !== null) this.broadcastEvent(notice);
3653
+ }
3654
+ /** 退订(幂等)。 */
3655
+ unsubscribeAll() {
3656
+ this.unsubscribe?.();
3657
+ this.unsubscribe = null;
3658
+ }
3659
+ /**
3660
+ * 请求分发(挂到 network transport 的 onRequest):
3661
+ * OB11 标准请求 { action, params, echo } → 动作注册表 → handle(HTTP)/websocketHandle(WS)。
3662
+ */
3663
+ async handleRequest(req, respond) {
3664
+ const { action: rawAction, params, echo } = req ?? {};
3665
+ let action = "";
3666
+ if (typeof rawAction === "string") action = rawAction;
3667
+ if (action === "") {
3668
+ respond({
3669
+ status: "failed",
3670
+ retcode: 404,
3671
+ data: null,
3672
+ message: "请求缺少 action"
3673
+ });
3674
+ return;
3675
+ }
3676
+ const act = this.registry.get(action);
3677
+ if (act === void 0) {
3678
+ respond({
3679
+ status: "failed",
3680
+ retcode: 404,
3681
+ data: null,
3682
+ message: `未知动作: ${action}`
3683
+ });
3684
+ return;
3685
+ }
3686
+ let result;
3687
+ if (echo === void 0) result = await act.handle(params);
3688
+ else result = await act.websocketHandle(params, echo);
3689
+ respond(result);
3690
+ }
3691
+ };
3692
+ //#endregion
3693
+ export { MessageUnique, NapukettoOneBot11Adapter, OneBotApi, assembleOb11Transports, canonicalToCqMessage, canonicalToSegments, cqMessageToCanonical, cqMessageToSegments, createOb11ActionRegistry, encodeCqCode, escapeCqParam, escapeCqText, ob11ConfigSchema, ob11ErrorCodeMap, parseCqMessage, segmentsToCanonical, segmentsToCqMessage, serializeCqParts, unescapeCqText };
3694
+
3695
+ //# sourceMappingURL=index.mjs.map