napcat-sdk 0.12.2 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -52,7 +52,7 @@ const CONSOLE_LOGGER = {
52
52
  //#endregion
53
53
  //#region package.json
54
54
  var name$1 = "napcat-sdk";
55
- var version$1 = "0.12.2";
55
+ var version$1 = "0.14.0";
56
56
 
57
57
  //#endregion
58
58
  //#region src/segment.ts
@@ -123,7 +123,11 @@ const DEFAULT_NAPCAT_OPTIONS = {
123
123
  host: "localhost",
124
124
  port: 3001,
125
125
  logger: CONSOLE_LOGGER,
126
- token: ""
126
+ token: "",
127
+ reconnect: true,
128
+ reconnectInterval: 1e3,
129
+ maxReconnectAttempts: Infinity,
130
+ maxReconnectInterval: 3e4
127
131
  };
128
132
  var NapCat = class {
129
133
  /** WebSocket 实例 */
@@ -158,6 +162,14 @@ var NapCat = class {
158
162
  };
159
163
  /** Cookies 缓存 */
160
164
  #cookieCache = /* @__PURE__ */ new Map();
165
+ /** 当前重连尝试次数 */
166
+ #reconnectAttempts = 0;
167
+ /** 重连定时器 */
168
+ #reconnectTimer = null;
169
+ /** 是否正在重连 */
170
+ #reconnecting = false;
171
+ /** 是否手动关闭 */
172
+ #manualClose = false;
161
173
  static ABSTRACT_LOGGER = ABSTRACT_LOGGER;
162
174
  static CONSOLE_LOGGER = CONSOLE_LOGGER;
163
175
  constructor(options = {}) {
@@ -174,7 +186,11 @@ var NapCat = class {
174
186
  host: this.options.host || DEFAULT_NAPCAT_OPTIONS.host,
175
187
  port: this.options.port || DEFAULT_NAPCAT_OPTIONS.port,
176
188
  logger: this.options.logger || DEFAULT_NAPCAT_OPTIONS.logger,
177
- token: this.options.token || DEFAULT_NAPCAT_OPTIONS.token
189
+ token: this.options.token || DEFAULT_NAPCAT_OPTIONS.token,
190
+ reconnect: this.options.reconnect ?? DEFAULT_NAPCAT_OPTIONS.reconnect,
191
+ reconnectInterval: this.options.reconnectInterval || DEFAULT_NAPCAT_OPTIONS.reconnectInterval,
192
+ maxReconnectAttempts: this.options.maxReconnectAttempts ?? DEFAULT_NAPCAT_OPTIONS.maxReconnectAttempts,
193
+ maxReconnectInterval: this.options.maxReconnectInterval || DEFAULT_NAPCAT_OPTIONS.maxReconnectInterval
178
194
  };
179
195
  }
180
196
  /** WebSocket 实例 */
@@ -253,6 +269,25 @@ var NapCat = class {
253
269
  return value;
254
270
  });
255
271
  }
272
+ /** 设置在线状态,并发出相应事件 */
273
+ #setOnlineStatus(online) {
274
+ if (this.#online === online) return;
275
+ const wasOnline = this.#online;
276
+ this.#online = online;
277
+ if (online && !wasOnline) {
278
+ this.logger.info(`机器人上线: ${this.#nickname}(${this.#uin})`);
279
+ this.#event.emit("napcat.online", {
280
+ user_id: this.#uin,
281
+ nickname: this.#nickname
282
+ });
283
+ } else if (!online && wasOnline) {
284
+ this.logger.info(`机器人下线: ${this.#nickname}(${this.#uin})`);
285
+ this.#event.emit("napcat.offline", {
286
+ user_id: this.#uin,
287
+ nickname: this.#nickname
288
+ });
289
+ }
290
+ }
256
291
  /** 标准化可发送消息元素 */
257
292
  normalizeSendable(msg) {
258
293
  return [msg].flat(2).map((item) => {
@@ -272,16 +307,42 @@ var NapCat = class {
272
307
  });
273
308
  }
274
309
  /** 等待服务器响应操作 */
275
- #waitForAction(echoId) {
310
+ #waitForAction(echoId, action, timeout = 3e4) {
276
311
  const eventName = `echo#${echoId}`;
277
312
  return new Promise((resolve, reject) => {
313
+ let timeoutId = null;
314
+ const cleanup = () => {
315
+ if (timeoutId) {
316
+ clearTimeout(timeoutId);
317
+ timeoutId = null;
318
+ }
319
+ this.#echoEvent.off(eventName, handle);
320
+ };
278
321
  const handle = (data) => {
279
322
  if (!data || data.echo !== echoId) return;
280
- this.#echoEvent.off(eventName, handle);
323
+ cleanup();
281
324
  if (data.retcode === 0) resolve(data.data);
282
- else reject(`API 错误: ${data.message}`);
325
+ else {
326
+ const error = `API 错误: ${data.message}`;
327
+ this.#event.emit("napcat.api_error", {
328
+ action,
329
+ error: data.message || "Unknown error",
330
+ retcode: data.retcode
331
+ });
332
+ reject(new Error(error));
333
+ }
283
334
  };
284
335
  this.#echoEvent.on(eventName, handle);
336
+ timeoutId = setTimeout(() => {
337
+ cleanup();
338
+ const error = `API 请求超时: ${action}`;
339
+ this.#event.emit("napcat.api_timeout", {
340
+ action,
341
+ echo: echoId,
342
+ timeout
343
+ });
344
+ reject(new Error(error));
345
+ }, timeout);
285
346
  });
286
347
  }
287
348
  /** 构建群对象 */
@@ -401,9 +462,9 @@ var NapCat = class {
401
462
  if (data.sub_type === "connect") {
402
463
  const { app_name, app_version, protocol_version } = await this.getVersionInfo();
403
464
  const { nickname, user_id } = await this.getLoginInfo();
404
- this.#online = true;
405
465
  this.#uin = user_id;
406
466
  this.#nickname = nickname;
467
+ this.#setOnlineStatus(true);
407
468
  this.#event.emit("napcat.connected", {
408
469
  user_id: this.#uin,
409
470
  nickname: this.#nickname,
@@ -614,12 +675,22 @@ var NapCat = class {
614
675
  this.#ensureWsConnection(this.#ws);
615
676
  this.logger.debug(`调用 API: ${action},参数: ${JSON.stringify(params)}`);
616
677
  const echo = this.#echoId();
617
- this.#ws.send(JSON.stringify({
618
- echo,
619
- action,
620
- params
621
- }));
622
- return this.#waitForAction(echo);
678
+ try {
679
+ this.#ws.send(JSON.stringify({
680
+ echo,
681
+ action,
682
+ params
683
+ }));
684
+ return this.#waitForAction(echo, action);
685
+ } catch (error) {
686
+ const errorMsg = error?.message || String(error);
687
+ this.logger.error(`发送 API 请求失败: ${errorMsg}`);
688
+ this.#event.emit("napcat.api_error", {
689
+ action,
690
+ error: errorMsg
691
+ });
692
+ return Promise.reject(/* @__PURE__ */ new Error(`发送 API 请求失败: ${errorMsg}`));
693
+ }
623
694
  }
624
695
  /**
625
696
  * 给好友名片点赞
@@ -866,10 +937,49 @@ var NapCat = class {
866
937
  const { bkn } = await this.getCookie("vip.qq.com");
867
938
  return bkn;
868
939
  }
869
- /** 启动 NapCat SDK 实例,建立 WebSocket 连接 */
870
- async run() {
871
- const { logger: _, token: __, ...config } = this.#config;
872
- this.logger.debug(`启动配置: ${JSON.stringify(config)}`);
940
+ /** 计算重连延迟(指数退避) */
941
+ #getReconnectDelay() {
942
+ const { reconnectInterval, maxReconnectInterval } = this.#config;
943
+ const delay = reconnectInterval * Math.pow(2, this.#reconnectAttempts);
944
+ return Math.min(delay, maxReconnectInterval);
945
+ }
946
+ /** 清除重连定时器 */
947
+ #clearReconnectTimer() {
948
+ if (this.#reconnectTimer) {
949
+ clearTimeout(this.#reconnectTimer);
950
+ this.#reconnectTimer = null;
951
+ }
952
+ }
953
+ /** 调度重连 */
954
+ #scheduleReconnect() {
955
+ const { reconnect, maxReconnectAttempts } = this.#config;
956
+ if (!reconnect || this.#manualClose) return;
957
+ if (this.#reconnectAttempts >= maxReconnectAttempts) {
958
+ this.logger.error(`重连失败,已达到最大重连次数 ${maxReconnectAttempts}`);
959
+ this.#event.emit("napcat.reconnect_failed", {
960
+ attempt: this.#reconnectAttempts,
961
+ maxAttempts: maxReconnectAttempts
962
+ });
963
+ return;
964
+ }
965
+ this.#reconnecting = true;
966
+ this.#reconnectAttempts++;
967
+ const delay = this.#getReconnectDelay();
968
+ this.logger.info(`将在 ${delay}ms 后尝试第 ${this.#reconnectAttempts} 次重连`);
969
+ this.#event.emit("napcat.reconnecting", {
970
+ attempt: this.#reconnectAttempts,
971
+ maxAttempts: maxReconnectAttempts,
972
+ delay
973
+ });
974
+ this.#clearReconnectTimer();
975
+ this.#reconnectTimer = setTimeout(() => {
976
+ this.#connect().catch((err) => {
977
+ this.logger.error(`重连失败: ${err?.message || err}`);
978
+ });
979
+ }, delay);
980
+ }
981
+ /** 建立 WebSocket 连接 */
982
+ #connect() {
873
983
  return new Promise((resolve, reject) => {
874
984
  const ws = new WebSocket(this.#buildWsUrl());
875
985
  ws.onmessage = (event) => {
@@ -888,33 +998,57 @@ var NapCat = class {
888
998
  this.#bindInternalEvents(data);
889
999
  };
890
1000
  ws.onclose = () => {
891
- this.#online = false;
1001
+ this.#setOnlineStatus(false);
892
1002
  this.logger.debug("WebSocket 已断开连接");
893
1003
  this.#event.emit("ws.close");
1004
+ this.#event.emit("napcat.disconnected", { manual: this.#manualClose });
1005
+ if (!this.#manualClose) this.#scheduleReconnect();
894
1006
  };
895
1007
  ws.onerror = (event) => {
896
- this.#online = false;
1008
+ this.#setOnlineStatus(false);
897
1009
  const msg = `WebSocket 发生错误,请确认 NapCat 服务已启动,且端口、访问令牌正确`;
898
1010
  this.logger.debug(msg);
899
1011
  this.#event.emit("ws.error", event);
900
- reject(new Error(msg));
1012
+ this.#event.emit("napcat.disconnected", {
1013
+ manual: false,
1014
+ reason: msg
1015
+ });
1016
+ if (!this.#reconnecting) reject(new Error(msg));
901
1017
  };
902
1018
  ws.onopen = () => {
903
1019
  this.logger.info(`WebSocket 已连接,NapCat SDK 实例已启动`);
904
1020
  this.#event.emit("ws.open");
1021
+ if (this.#reconnecting) {
1022
+ this.logger.info(`第 ${this.#reconnectAttempts} 次重连成功`);
1023
+ this.#event.emit("napcat.reconnected", { attempt: this.#reconnectAttempts });
1024
+ this.#reconnecting = false;
1025
+ this.#reconnectAttempts = 0;
1026
+ }
905
1027
  resolve();
906
1028
  };
907
1029
  this.#ws = ws;
908
1030
  });
909
1031
  }
1032
+ /** 启动 NapCat SDK 实例,建立 WebSocket 连接 */
1033
+ async run() {
1034
+ const { logger: _, token: __, ...config } = this.#config;
1035
+ this.logger.debug(`启动配置: ${JSON.stringify(config)}`);
1036
+ this.#manualClose = false;
1037
+ return this.#connect();
1038
+ }
910
1039
  /** 销毁 NapCat SDK 实例,关闭 WebSocket 连接 */
911
1040
  close() {
1041
+ this.logger.info("正在关闭 NapCat SDK 实例...");
1042
+ this.#event.emit("napcat.closing");
1043
+ this.#manualClose = true;
1044
+ this.#clearReconnectTimer();
912
1045
  if (this.#ws) {
913
- this.logger.info("正在销毁 NapCat SDK 实例...");
914
1046
  this.#ws.close();
915
1047
  this.#ws = null;
916
1048
  this.logger.info("NapCat SDK 实例已销毁");
917
1049
  } else this.logger.warn("NapCat SDK 实例未初始化");
1050
+ this.#reconnecting = false;
1051
+ this.#reconnectAttempts = 0;
918
1052
  }
919
1053
  };
920
1054
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ABSTRACT_LOGGER: Logger","CONSOLE_LOGGER: Logger","name: string","pkg.name","version: string","pkg.version","DEFAULT_NAPCAT_OPTIONS: Required<OptionalProps<NapcatOptions>>","options: NapcatOptions","#stat","#config","#ws","#uin","#nickname","crypto","#echoEvent","#groupCache","#friendCache","name","#nicknameCache","quote_id: string | null","#transformOneBotMessage","#buildFriend","#wrapReply","#buildGroup","#bindInternalEvents","#safeStringify","#event","#online","#buildPrivateMessageEvent","#buildGroupMessageEvent","err: any","#ensureWsConnection","#echoId","#waitForAction","#cookieCache","#buildWsUrl","NAPCAT_NOTICE_NOTIFY_MAP: Record<string, { notice_type: string; sub_type: string }>","NAPCAT_NOTICE_EVENT_MAP: Record<string, { notice_type: string; sub_type: string }>"],"sources":["../src/logger.ts","../package.json","../src/segment.ts","../src/napcat.ts"],"sourcesContent":["import { styleText } from 'node:util'\n\nexport type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'trace'\n\nexport type Logger = Record<LogLevel, (...args: unknown[]) => void>\n\nexport const noop = (): void => {}\n\nexport const ABSTRACT_LOGGER: Logger = {\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n trace: noop,\n}\n\nconst time = () => styleText('dim', `[${new Date().toLocaleTimeString()}]`)\n\nexport const CONSOLE_LOGGER: Logger = {\n error: (...args: any[]) => console.error(`${time()} ${styleText('redBright', '[ERROR]')}`, ...args),\n warn: (...args: any[]) => console.warn(`${time()} ${styleText('yellowBright', '[WARN]')}`, ...args),\n info: (...args: any[]) => console.info(`${time()} ${styleText('greenBright', '[INFO]')}`, ...args),\n debug: (...args: any[]) => console.debug(`${time()} ${styleText('blueBright', '[DEBUG]')}`, ...args),\n trace: (...args: any[]) => console.debug(`${time()} ${styleText('dim', '[TRACE]')}`, ...args),\n}\n","","import type { ExtractByType, SendElement } from './types'\n\nfunction createSegment<T extends SendElement['type'], D>(type: T, data: D): SendElement {\n return { type, ...data } as SendElement\n}\n\n/**\n * 消息片段构造器\n */\nexport const segment = {\n /** 创建一个文本消息片段 */\n text: (text: string): SendElement => createSegment('text', { text }),\n /** 创建一个艾特消息片段 */\n at: (qq: 'all' | (string & {}) | number): SendElement => createSegment('at', { qq }),\n /** 创建一个 QQ 表情消息片段 */\n face: (id: number): SendElement => createSegment('face', { id }),\n /** 创建一个回复消息片段 */\n reply: (id: string): SendElement => createSegment('reply', { id }),\n /** 创建一个图片消息片段 */\n image: (\n file: string | Buffer,\n options?: Omit<ExtractByType<SendElement, 'image'>, 'type' | 'file'> & { local?: boolean },\n ): SendElement => {\n const isLocal = options?.local ?? false\n\n const fileValue =\n file instanceof Buffer\n ? `base64://${file.toString('base64')}`\n : typeof file === 'string'\n ? isLocal\n ? `file:///${file.replace(/^\\s*(file:\\/\\/\\/)+/, '')}`\n : file\n : file\n\n return createSegment('image', { file: fileValue, ...options })\n },\n /** 创建一个语音消息片段 */\n record: (file: string, options?: Omit<ExtractByType<SendElement, 'record'>, 'type' | 'file'>): SendElement =>\n createSegment('record', { file, ...options }),\n /** 创建一个视频消息片段 */\n video: (file: string, options?: Omit<ExtractByType<SendElement, 'video'>, 'type' | 'file'>): SendElement =>\n createSegment('video', { file, ...options }),\n /** 创建一个动态表情消息片段 */\n mface: (options: Omit<ExtractByType<SendElement, 'mface'>, 'type'>): SendElement =>\n createSegment('mface', { ...options }),\n /** 创建一个大表情消息片段 */\n bface: (id: number): SendElement => createSegment('bface', { id }),\n /** 创建一个 联系人/群 分享消息片段 */\n contact: (type: 'qq' | 'group', id: string): SendElement => createSegment('contact', { id, sub_type: type }),\n /** 创建一个戳一戳消息片段 */\n poke: (): SendElement => createSegment('poke', {}),\n /** 创建一个音乐消息片段 */\n music: (platform: 'qq' | '163' | 'kugou' | 'migu' | 'kuwo', id: string): SendElement =>\n createSegment('music', { platform, id }),\n /** 创建一个自定义音乐消息片段 */\n musicCustom: (\n title: string,\n audio: string,\n url: string,\n options?: Omit<ExtractByType<SendElement, 'music'>, 'type' | 'platform' | 'url' | 'audio' | 'title'>,\n ): SendElement => createSegment('music', { platform: 'custom', url, audio, title, ...options }),\n /** 创建一个合并转发消息片段 */\n node: (options: Partial<ExtractByType<SendElement, 'node'>>): SendElement => createSegment('node', { ...options }),\n /** 创建一个合并转发消息片段 */\n forward: (id: string): SendElement => createSegment('forward', { id }),\n /** 创建一个 JSON 消息片段 */\n json: (data: string): SendElement => createSegment('json', { data }),\n /** 创建一个文件消息片段 */\n file: (file: string, options?: Omit<ExtractByType<SendElement, 'file'>, 'type' | 'file'>): SendElement =>\n createSegment('file', { file, ...options }),\n /** 创建一个 Markdown 消息片段 */\n markdown: (): SendElement => createSegment('markdown', {}),\n /** 创建一个轻应用消息片段 */\n lightapp: (): SendElement => createSegment('lightapp', {}),\n}\n","import crypto from 'node:crypto'\nimport mitt from 'mitt'\nimport pkg from '../package.json' with { type: 'json' }\nimport { segment } from './segment'\nimport { ABSTRACT_LOGGER, CONSOLE_LOGGER } from './logger'\n\nimport type { Emitter } from 'mitt'\nimport type { Logger } from './logger'\nimport type {\n API,\n Arrayable,\n EventMap,\n Friend,\n FriendWithInfo,\n Group,\n GroupMemberInfo,\n GroupMessageEvent,\n GroupWithInfo,\n NapcatOptions,\n NormalizedElementToSend,\n OptionalProps,\n PrivateMessageEvent,\n RecvElement,\n Sendable,\n Stat,\n} from './types'\n\nexport const name: string = pkg.name\nexport const version: string = pkg.version\n\nconst DEFAULT_NAPCAT_OPTIONS: Required<OptionalProps<NapcatOptions>> = {\n protocol: 'ws',\n host: 'localhost',\n port: 3001,\n logger: CONSOLE_LOGGER,\n token: '',\n}\n\nexport class NapCat {\n /** WebSocket 实例 */\n #ws: WebSocket | null = null\n /** 事件发射器 */\n #event: Emitter<EventMap & Record<string | symbol, unknown>> = mitt()\n /** Echo 事件发射器 */\n #echoEvent: Emitter<Record<string, unknown>> = mitt()\n /** 机器人 ID */\n #uin: number = 0\n /** 机器人昵称 */\n #nickname: string = ''\n /** 机器人状态 */\n #online: boolean = false\n /** nickname 缓存 */\n #nicknameCache = new Map<number, string>()\n /** friend 缓存 */\n #friendCache = new Map<number, Friend>()\n /** group 缓存 */\n #groupCache = new Map<number, Group>()\n /** 消息数据 */\n #stat: Stat = {\n start_time: Date.now(),\n recv: { group: 0, private: 0 },\n send: { group: 0, private: 0 },\n }\n /** Cookies 缓存 */\n #cookieCache = new Map<\n string,\n {\n uin: number\n pskey: string\n skey: string\n gtk: string\n bkn: string\n cookie: string\n legacyCookie: string\n }\n >()\n\n public static ABSTRACT_LOGGER: Logger = ABSTRACT_LOGGER\n public static CONSOLE_LOGGER: Logger = CONSOLE_LOGGER\n\n constructor(private readonly options: NapcatOptions = {}) {}\n\n /** 统计数据 */\n get stat(): Stat {\n return this.#stat\n }\n\n /** 配置项 */\n get #config(): Required<NapcatOptions> {\n return {\n protocol: this.options.protocol || DEFAULT_NAPCAT_OPTIONS.protocol,\n host: this.options.host || DEFAULT_NAPCAT_OPTIONS.host,\n port: this.options.port || DEFAULT_NAPCAT_OPTIONS.port,\n logger: this.options.logger || DEFAULT_NAPCAT_OPTIONS.logger,\n token: this.options.token || DEFAULT_NAPCAT_OPTIONS.token,\n }\n }\n\n /** WebSocket 实例 */\n get ws(): WebSocket {\n if (!this.#ws) {\n this.logger.error('WebSocket 未连接')\n throw new Error('WebSocket 未连接')\n }\n\n return this.#ws\n }\n\n /** 日志记录器 */\n get logger(): Logger {\n return this.#config.logger\n }\n\n /** 消息段构建器 */\n get segment(): typeof segment {\n return segment\n }\n\n /**\n * 机器人 QQ 号\n *\n * @deprecated 建议使用 `uin` 属性\n */\n get user_id(): number {\n return this.uin\n }\n\n /**\n * 机器人 QQ 号\n */\n get uin(): number {\n return this.#uin\n }\n\n /**\n * 机器人昵称\n */\n get nickname(): string {\n return this.#nickname\n }\n\n /** 生成唯一的 echo ID */\n #echoId() {\n return crypto.randomBytes(16).toString('hex')\n }\n\n /** 构建 WebSocket 连接地址 */\n #buildWsUrl(): string {\n const { protocol, host, port, token } = this.#config\n return `${protocol}://${host}:${port}?access_token=${token}`\n }\n\n /** 包装回复消息 */\n #wrapReply(sendable: Arrayable<Sendable>, message_id?: number, reply?: boolean): Sendable[] {\n const sendableList = typeof sendable === 'string' ? [sendable] : [sendable].flat()\n\n if (reply && message_id) {\n return [segment.reply(String(message_id)), ...sendableList]\n }\n\n return sendableList\n }\n\n /** 确保 WebSocket 已连接 */\n #ensureWsConnection(ws: WebSocket | null): asserts ws is WebSocket {\n if (!ws) {\n this.logger.error('WebSocket 未连接')\n throw new Error('WebSocket 未连接')\n }\n\n if (ws.readyState !== WebSocket.OPEN) {\n this.logger.error('WebSocket 未打开')\n throw new Error('WebSocket 未打开')\n }\n }\n\n /** 安全的 JSON 序列化,处理循环引用和不可序列化的值 */\n #safeStringify(obj: any): string {\n const seen = new WeakSet()\n return JSON.stringify(obj, (key, value) => {\n // 过滤掉内部的 timeout 引用\n if (key === '__timeout_id__') {\n return undefined\n }\n // 过滤掉函数\n if (typeof value === 'function') {\n return undefined\n }\n // 过滤掉 napcat 实例引用\n if (key === 'napcat') {\n return undefined\n }\n // 处理对象类型的循环引用\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return '[Circular]'\n }\n seen.add(value)\n }\n return value\n })\n }\n\n /** 标准化可发送消息元素 */\n normalizeSendable(msg: Arrayable<Sendable>): NormalizedElementToSend[] {\n return [msg].flat(2).map((item) => {\n if (typeof item === 'string') {\n return { type: 'text', data: { text: item } }\n }\n if (item.type === 'at') {\n return { type: 'at', data: { qq: String(item.qq) } }\n }\n const { type, ...data } = item\n return { type, data } as NormalizedElementToSend\n })\n }\n\n /** 等待服务器响应操作 */\n #waitForAction<T extends any>(echoId: string) {\n const eventName = `echo#${echoId}`\n\n return new Promise<T>((resolve, reject) => {\n const handle = (data: any) => {\n if (!data || data.echo !== echoId) return\n\n this.#echoEvent.off(eventName, handle)\n\n if (data.retcode === 0) {\n resolve(data.data as T)\n } else {\n reject(`API 错误: ${data.message}`)\n }\n }\n\n this.#echoEvent.on(eventName, handle)\n })\n }\n\n /** 构建群对象 */\n #buildGroup<T extends object>(\n group_id: number,\n group_name: string = '',\n extraInfo: T = {} as T,\n forceUpdate = false,\n ): Group & T {\n const cache = this.#groupCache.get(group_id)\n\n if (cache) {\n if (!forceUpdate) {\n return cache as Group & T\n }\n\n clearTimeout((cache as any).__timeout_id__)\n }\n\n const timer = setTimeout(() => this.#groupCache.delete(group_id), 1000 * 60 * 10) // 10 分钟后清除缓存\n\n const group = {\n ...extraInfo,\n group_id,\n group_name,\n napcat: this,\n sign: this.setGroupSign.bind(this, group_id),\n setTitle: this.setGroupSpecialTitle.bind(this, group_id),\n setCard: this.setGroupCard.bind(this, group_id),\n setEssence: this.setEssenceMsg.bind(this),\n delEssence: this.deleteEssenceMsg.bind(this),\n getInfo: this.getGroupInfo.bind(this, group_id),\n getMemberList: this.getGroupMemberList.bind(this, group_id),\n getMemberInfo: this.getGroupMemberInfo.bind(this, group_id),\n recall: this.recallMsg.bind(this),\n ban: this.setGroupBan.bind(this, group_id),\n sendMsg: this.sendGroupMsg.bind(this, group_id),\n pickMember: this.getGroupMemberInfo.bind(this, group_id),\n kick: this.kickGroupMember.bind(this, group_id),\n __timeout_id__: timer,\n }\n\n this.#groupCache.set(group_id, group)\n\n return group\n }\n\n /** 构建好友对象 */\n #buildFriend<T extends object>(\n user_id: number,\n nickname: string = '',\n extraInfo: T = {} as T,\n forceUpdate = false,\n ): Friend & T {\n const cache = this.#friendCache.get(user_id)\n\n const name = nickname || this.#nicknameCache.get(user_id) || cache?.nickname || ''\n this.#nicknameCache.set(user_id, name)\n\n if (cache) {\n if (!forceUpdate) {\n return cache as Friend & T\n }\n\n clearTimeout((cache as any).__timeout_id__)\n }\n\n const id = setTimeout(() => this.#friendCache.delete(user_id), 1000 * 60 * 10) // 10 分钟后清除缓存\n\n const friend = {\n ...extraInfo,\n user_id,\n nickname: name,\n napcat: this,\n delete: this.deleteFriend.bind(this, user_id),\n sendMsg: this.sendPrivateMsg.bind(this, user_id),\n getInfo: this.getStrangerInfo.bind(this, user_id),\n __timeout_id__: id,\n }\n\n this.#friendCache.set(user_id, friend)\n\n return friend\n }\n\n #transformOneBotMessage(message: any[]): RecvElement[] {\n return (message || []).filter((e) => e.type !== 'reply').map((el: any) => ({ type: el.type, ...el.data }))\n }\n\n /** 构建私聊消息事件 */\n #buildPrivateMessageEvent(event: Omit<PrivateMessageEvent, 'message'> & { message: any[] }): PrivateMessageEvent {\n const quote_id: string | null = event.message.find((el: any) => el.type === 'reply')?.data?.id || null\n\n if (event.sender.nickname) {\n this.#nicknameCache.set(event.sender.user_id, event.sender.nickname)\n }\n\n const target = event.target_id\n ? { user_id: event.target_id, nickname: this.#nicknameCache.get(event.target_id) || '' }\n : { user_id: event.sender.user_id, nickname: event.sender.nickname }\n\n return {\n ...event,\n quote_id,\n getQuoteMsg: () => this.getMsg(quote_id) as Promise<PrivateMessageEvent | null>,\n message: this.#transformOneBotMessage(event.message),\n friend: this.#buildFriend(target.user_id, target.nickname),\n reply: (sendable: Arrayable<Sendable>, reply = false) =>\n this.sendPrivateMsg(target.user_id, this.#wrapReply(sendable, event.message_id, reply)),\n }\n }\n\n /** 构建群消息事件对象 */\n #buildGroupMessageEvent(event: Omit<GroupMessageEvent, 'message'> & { message: any[] }): GroupMessageEvent {\n const quote_id: string | null = event.message.find((el: any) => el.type === 'reply')?.data?.id || null\n\n if (event.sender.nickname) {\n this.#nicknameCache.set(event.sender.user_id, event.sender.nickname)\n }\n\n return {\n ...event,\n quote_id,\n getQuoteMsg: () => this.getMsg(quote_id) as Promise<GroupMessageEvent | null>,\n getSenderMemberInfo: this.getGroupMemberInfo.bind(this, event.group_id, event.sender.user_id),\n message: this.#transformOneBotMessage(event.message),\n group: this.#buildGroup(event.group_id, event.group_name || ''),\n recall: this.recallMsg.bind(this, event.message_id),\n addReaction: this.addReaction.bind(this, event.message_id),\n delReaction: this.delReaction.bind(this, event.message_id),\n setEssence: this.setEssenceMsg.bind(this, event.message_id),\n delEssence: this.deleteEssenceMsg.bind(this, event.message_id),\n reply: (sendable: Arrayable<Sendable>, reply = false) =>\n this.sendGroupMsg(event.group_id, this.#wrapReply(sendable, event.message_id, reply)),\n }\n }\n\n /** 绑定内部事件处理器 */\n async #bindInternalEvents(data: any) {\n if (data.echo) {\n this.#echoEvent.emit(`echo#${data.echo}`, data)\n return\n }\n\n if (data.post_type) {\n switch (data.post_type) {\n case 'meta_event': {\n this.logger.trace(`收到 meta_event: ${this.#safeStringify(data)}`)\n\n this.#event.emit('meta_event', data)\n\n if (data.meta_event_type) {\n this.#event.emit(`meta_event.${data.meta_event_type}`, data)\n\n this.logger.trace('收到 meta_event_type: ', data.meta_event_type)\n\n if (data.sub_type) {\n if (data.sub_type === 'connect') {\n const { app_name, app_version, protocol_version } = await this.getVersionInfo()\n const { nickname, user_id } = await this.getLoginInfo()\n\n this.#online = true\n this.#uin = user_id\n this.#nickname = nickname\n\n this.#event.emit('napcat.connected', {\n user_id: this.#uin,\n nickname: this.#nickname,\n app_name,\n app_version,\n protocol_version,\n timestamp: data.time * 1000,\n })\n }\n\n this.#event.emit(`meta_event.${data.meta_event_type}.${data.sub_type}`, data)\n }\n }\n\n break\n }\n\n case 'message': {\n if (data.message_type === 'private') {\n this.#stat.recv.private++\n data = this.#buildPrivateMessageEvent(data)\n } else {\n this.#stat.recv.group++\n data = this.#buildGroupMessageEvent(data)\n }\n\n this.#event.emit('message', data)\n\n const msg = this.stringifyMessage(data.message)\n\n const group = data.group ? `${data.group_name}(${data.group_id})` : ''\n const sender = `${data.sender.nickname}(${data.sender.user_id})`\n\n switch (data.message_type) {\n case 'private': {\n this.#event.emit('message.private', data)\n this.#event.emit(`message.private.${data.sub_type}`, data)\n this.logger.trace(`收到私聊消息: ${this.#safeStringify(data)}`)\n this.logger.info(`[私:${sender}] ${msg}`)\n break\n }\n\n case 'group': {\n this.#event.emit('message.group', data)\n this.#event.emit(`message.group.${data.sub_type}`, data)\n this.logger.trace(`收到群消息: ${this.#safeStringify(data)}`)\n this.logger.info(`[群:${group}] ${sender}: ${msg}`)\n break\n }\n\n default: {\n this.logger.debug(`收到未知消息类型: ${this.#safeStringify(data)}`)\n\n break\n }\n }\n\n break\n }\n\n case 'message_sent': {\n if (data.message_type === 'private') {\n this.#stat.send.private++\n data = this.#buildPrivateMessageEvent(data)\n } else {\n this.#stat.send.group++\n data = this.#buildGroupMessageEvent(data)\n }\n\n this.#event.emit('message_sent', data)\n this.logger.trace(`收到 message_sent: ${this.#safeStringify(data)}`)\n\n if (data.message_type) {\n this.#event.emit(`message_sent.${data.message_type}`, data)\n\n if (data.sub_type) {\n this.#event.emit(`message_sent.${data.message_type}.${data.sub_type}`, data)\n }\n\n const msg = this.stringifyMessage(data.message)\n\n if (data.message_type === 'group' && data.group_id) {\n this.logger.info(`[>>>:群:${data.group_name}(${data.group_id})] ${msg}`)\n } else {\n this.logger.info(`[>>>:私:${data.friend.nickname}(${data.friend.user_id})] ${msg}`)\n }\n }\n\n break\n }\n\n case 'notice': {\n this.logger.trace(`收到通知: ${this.#safeStringify(data)}`)\n\n if (!data.notice_type) {\n this.logger.debug(`收到未知通知类型: ${this.#safeStringify(data)}`)\n break\n }\n\n const isNotify = data.notice_type === 'notify'\n const isPoke = data.sub_type === 'poke'\n const isGroup = !!data.group_id\n\n const { notice_type, sub_type } = isNotify\n ? isPoke\n ? { notice_type: isGroup ? 'group' : 'friend', sub_type: 'poke' }\n : NAPCAT_NOTICE_NOTIFY_MAP[data.sub_type] || {}\n : NAPCAT_NOTICE_EVENT_MAP[data.notice_type] || {}\n\n data.original_notice_type = data.notice_type\n data.notice_type = notice_type || data.notice_type\n\n if (data.sub_type && data.sub_type !== sub_type) {\n data.action_type = data.sub_type\n }\n\n data.sub_type = sub_type || data.sub_type\n\n if (isGroup) {\n data.group = this.#buildGroup(data.group_id, data.group_name || '')\n } else {\n data.friend = this.#buildFriend(data.user_id, data.nickname || '')\n }\n\n this.#event.emit('notice', data)\n\n if (notice_type) {\n this.#event.emit(`notice.${notice_type}`, data)\n if (sub_type) {\n this.#event.emit(`notice.${notice_type}.${sub_type}`, data)\n }\n }\n\n break\n }\n\n case 'request': {\n this.logger.trace(`收到请求: ${this.#safeStringify(data)}`)\n\n if (data.request_type === 'friend') {\n data.reject = (reason?: string) =>\n this.api('set_friend_add_request', { flag: data.flag, approve: false, reason })\n data.approve = () => this.api('set_friend_add_request', { flag: data.flag, approve: true })\n }\n\n if (data.request_type === 'group') {\n data.reject = (reason?: string) =>\n this.api('set_group_add_request', { flag: data.flag, approve: false, reason })\n data.approve = () => this.api('set_group_add_request', { flag: data.flag, approve: true })\n }\n\n this.#event.emit('request', data)\n\n if (data.request_type) {\n this.#event.emit(`request.${data.request_type}`, data)\n if (data.sub_type) {\n this.#event.emit(`request.${data.request_type}.${data.sub_type}`, data)\n }\n }\n\n break\n }\n\n default: {\n this.logger.debug(`收到: ${this.#safeStringify(data)}`)\n this.#event.emit(data.post_type, data)\n return\n }\n }\n\n return\n }\n }\n\n stringifyMessage(message: RecvElement[]): string {\n return message\n .map((el) => {\n switch (el.type) {\n case 'text':\n return el.text\n case 'at':\n return `{at:${el.qq}}`\n case 'face':\n return `{face:${el.id}}`\n case 'image':\n return `{image:${el.file},${el.url}}`\n case 'json':\n return `{json:${el.data}}`\n case 'rps':\n case 'dice':\n return `{dice:${el.result}}`\n case 'file':\n case 'video':\n case 'record':\n return `{${el.type}:${el.url}}`\n default:\n return `{${el.type}}`\n }\n })\n .join('')\n }\n\n /** 获取一个群的信息,可以用于发送群消息等操作 */\n async pickGroup(group_id: number, forceUpdate: boolean = false): Promise<GroupWithInfo | null> {\n try {\n const cache = this.#groupCache.get(group_id)\n\n if (cache && !forceUpdate && 'member_count' in cache) {\n return cache as GroupWithInfo\n }\n\n const groupInfo = await this.api<ReturnType<Group['getInfo']>>('get_group_info', { group_id })\n return this.#buildGroup(group_id, groupInfo.group_name, groupInfo, true)\n } catch (err: any) {\n this.logger.warn(`获取群 ${group_id} 信息失败: ${err?.message || err}`)\n return this.#buildGroup(group_id, '-', {}) as GroupWithInfo\n }\n }\n\n /** 获取一个好友的信息,可以用于发送私聊消息等操作 */\n async pickFriend(user_id: number): Promise<FriendWithInfo | null> {\n try {\n const cache = this.#friendCache.get(user_id)\n\n if (cache && 'uin' in cache) {\n return cache as FriendWithInfo\n }\n\n const friendInfo = await this.api<ReturnType<Friend['getInfo']>>('get_stranger_info', { user_id })\n return this.#buildFriend(user_id, friendInfo.nickname, friendInfo, true)\n } catch (err: any) {\n this.logger.warn(`获取好友 ${user_id} 信息失败: ${err?.message || err}`)\n // return this.#buildFriend(user_id, '', {}) as FriendWithInfo\n return this.#buildFriend(user_id, '-', {}) as FriendWithInfo\n }\n }\n\n /**\n * 注册「一次性」事件监听器,支持主类型或者点分子类型\n *\n * 如: `notice`、`message.private`、`request.group.invite` 等\n *\n * 如果需要移除监听器,请调用 `off` 方法或者使用返回的函数\n *\n */\n once<T extends keyof EventMap>(type: T, handler: (event: EventMap[NoInfer<T>]) => void): () => void {\n const onceHandler = (event: EventMap[NoInfer<T>]) => {\n handler(event)\n this.#event.off(type, onceHandler)\n }\n\n this.logger.debug(`注册一次性监听器: ${String(type)}`)\n this.#event.on(type, onceHandler)\n return () => this.off(type, handler)\n }\n\n /**\n * 注册事件监听器,支持主类型或者点分子类型\n *\n * 如: `notice`、`message.private`、`request.group.invite` 等\n *\n * 如果需要移除监听器,请调用 `off` 方法或者使用返回的函数\n */\n on<T extends keyof EventMap>(type: T, handler: (event: EventMap[NoInfer<T>]) => void): () => void {\n this.logger.debug(`注册监听器: ${String(type)}`)\n this.#event.on(type, handler)\n return () => this.off(type, handler)\n }\n\n /**\n * 移除事件监听器\n */\n off<T extends keyof EventMap>(type: T, handler: (event: EventMap[NoInfer<T>]) => void): void {\n this.logger.debug(`移除监听器: ${String(type)}`)\n this.#event.off(type, handler)\n }\n\n /**\n * 调用 NapCat API\n */\n api<T extends any>(action: API | (string & {}), params: Record<string, any> = {}): Promise<T> {\n this.#ensureWsConnection(this.#ws)\n this.logger.debug(`调用 API: ${action},参数: ${JSON.stringify(params)}`)\n const echo = this.#echoId()\n this.#ws.send(JSON.stringify({ echo, action, params }))\n return this.#waitForAction<T>(echo)\n }\n\n /**\n * 给好友名片点赞\n */\n async sendLike(user_id: number, times: number = 1): Promise<any> {\n try {\n await this.api<void>('send_like', { user_id, times })\n return true\n } catch {\n return false\n }\n }\n\n /**\n * 获取好友列表\n */\n async getFriendList(): Promise<(Friend & Record<string, any>)[]> {\n const friends = await this.api<Friend[]>('get_friend_list')\n return friends.map((f) => this.#buildFriend(f.user_id, f.nickname, f))\n }\n\n /**\n * 获取群列表\n */\n async getGroupList(): Promise<(Group & Record<string, any>)[]> {\n const groups = await this.api<Group[]>('get_group_list')\n return groups.map((g) => this.#buildGroup(g.group_id, g.group_name, g))\n }\n\n /**\n * 添加消息回应\n */\n addReaction(message_id: number, id: string): Promise<void> {\n return this.api<void>('set_msg_emoji_like', { message_id, emoji_id: id, set: true })\n }\n\n /**\n * 删除消息回应\n */\n delReaction(message_id: number, id: string): Promise<void> {\n return this.api<void>('set_msg_emoji_like', { message_id, emoji_id: id, set: false })\n }\n\n /**\n * 获取消息\n */\n async getMsg(message_id?: number | string | null): Promise<GroupMessageEvent | PrivateMessageEvent | null> {\n if (!message_id) {\n return null\n }\n\n const msg = await this.api<any>('get_msg', { message_id })\n\n if (msg.message_type === 'private') {\n return this.#buildPrivateMessageEvent(msg)\n } else {\n return this.#buildGroupMessageEvent(msg)\n }\n }\n\n /**\n * 删除好友\n */\n deleteFriend(user_id: number, block: boolean = false, both: boolean = false): Promise<void> {\n return this.api<void>('delete_friend', {\n user_id,\n temp_block: block,\n temp_both_del: both,\n })\n }\n\n /**\n * 设置群成员禁言\n */\n setGroupBan(group_id: number, user_id: number, duration: number): Promise<void> {\n return this.api<void>('set_group_ban', { group_id, user_id, duration })\n }\n\n /**\n * 撤回消息\n */\n recallMsg(message_id: number): Promise<void> {\n return this.api<void>('delete_msg', { message_id })\n }\n\n /**\n * 获取陌生人信息\n */\n getStrangerInfo(user_id: number): Promise<any> {\n return this.api<any>('get_stranger_info', { user_id })\n }\n\n /**\n * 发送私聊消息\n */\n sendPrivateMsg(user_id: number, sendable: Arrayable<Sendable>): Promise<{ message_id: number }> {\n return this.api<{ message_id: number }>('send_private_msg', {\n user_id,\n message: this.normalizeSendable(sendable),\n })\n }\n\n /**\n * 发送群消息\n */\n sendGroupMsg(group_id: number, sendable: Arrayable<Sendable>): Promise<{ message_id: number }> {\n return this.api<{ message_id: number }>('send_group_msg', {\n group_id,\n message: this.normalizeSendable(sendable),\n })\n }\n\n /**\n * 获取群信息\n */\n getGroupInfo(group_id: number): Promise<any> {\n return this.api<any>('get_group_info', { group_id })\n }\n\n /**\n * 群签到\n */\n setGroupSign(group_id: number): Promise<any> {\n return this.api<void>('set_group_sign', { group_id })\n }\n\n /**\n * 设置群精华消息\n */\n setEssenceMsg(message_id: number): Promise<void> {\n return this.api<void>('set_essence_msg', { message_id })\n }\n\n /**\n * 删除群精华消息\n */\n deleteEssenceMsg(message_id: number): Promise<void> {\n return this.api<void>('delete_essence_msg', { message_id })\n }\n\n /**\n * 设置群成员名片\n */\n setGroupCard(group_id: number, user_id: number, card: string): Promise<void> {\n return this.api<void>('set_group_card', { group_id, user_id, card })\n }\n\n /**\n * 设置群成员专属头衔\n */\n setGroupSpecialTitle(group_id: number, user_id: number, title: string): Promise<void> {\n return this.api<void>('set_group_special_title', { group_id, user_id, title })\n }\n\n /**\n * 获取群成员列表\n */\n getGroupMemberList(group_id: number): Promise<GroupMemberInfo[]> {\n return this.api<GroupMemberInfo[]>('get_group_member_list', { group_id })\n }\n\n /**\n * 获取群成员信息\n */\n getGroupMemberInfo(group_id: number, user_id: number): Promise<GroupMemberInfo> {\n return this.api<GroupMemberInfo>('get_group_member_info', { group_id, user_id })\n }\n\n /**\n * 踢出群成员\n */\n kickGroupMember(group_id: number, user_id: number, reject_add_request: boolean = false): Promise<void> {\n return this.api<void>('set_group_kick', { group_id, user_id, reject_add_request })\n }\n\n /**\n * 机器人是否在线\n */\n isOnline(): boolean {\n return this.#ws?.readyState === WebSocket.OPEN && this.#online\n }\n\n /**\n * 计算 GTK 值\n */\n getGTk(pskey: string): number {\n let gkt = 5381\n for (let i = 0, len = pskey.length; i < len; ++i) {\n gkt += (gkt << 5) + pskey.charCodeAt(i)\n }\n return gkt & 0x7fffffff\n }\n\n /**\n * 获取 NapCat 原始 Cookie 相关信息\n */\n getNapCatCookies(domain: string): Promise<{ cookies: string; bkn: string }> {\n return this.api<{ cookies: string; bkn: string }>('get_cookies', { domain })\n }\n\n /**\n * 获取版本信息\n */\n getVersionInfo(): Promise<{ app_name: string; protocol_version: string; app_version: string }> {\n return this.api<{ app_name: string; protocol_version: string; app_version: string }>('get_version_info')\n }\n\n /**\n * 获取登录信息\n */\n getLoginInfo(): Promise<{ user_id: number; nickname: string }> {\n return this.api<{ user_id: number; nickname: string }>('get_login_info')\n }\n\n /**\n * 获取 Cookie 相关信息\n */\n async getCookie(domain: string): Promise<{\n uin: number\n pskey: string\n skey: string\n gtk: string\n bkn: string\n cookie: string\n legacyCookie: string\n }> {\n const cache = this.#cookieCache.get(domain)\n\n if (cache) return cache\n\n const { cookies: cookieString, bkn } = await this.getNapCatCookies(domain)\n\n const skey = cookieString.match(/skey=([^;]*)/)?.[1] || ''\n const pskey = cookieString.match(/p_skey=([^;]*)/)?.[1] || ''\n const gtk = this.getGTk(pskey)\n\n const returns = {\n pskey,\n skey,\n uin: this.uin,\n gtk: String(gtk),\n bkn,\n cookie: `uin=${this.uin}; skey=${skey}; p_uin=${this.uin}; p_skey=${pskey};`,\n legacyCookie: `uin=o${this.uin}; skey=${skey}; p_uin=o${this.uin}; p_skey=${pskey};`,\n }\n\n this.#cookieCache.set(domain, returns)\n\n // 1 小时后清除 Cookie 缓存\n setTimeout(\n () => {\n this.#cookieCache.delete(domain)\n },\n 1000 * 60 * 60,\n )\n\n return returns\n }\n\n /**\n * 通过域名获取 Pskey\n */\n async getPskey(domain: string): Promise<string> {\n const { pskey } = await this.getCookie(domain)\n return pskey\n }\n\n /**\n * 获取 Bkn 值\n */\n async getBkn(): Promise<string> {\n const { bkn } = await this.getCookie('vip.qq.com')\n return bkn\n }\n\n /** 启动 NapCat SDK 实例,建立 WebSocket 连接 */\n async run(): Promise<void> {\n const { logger: _, token: __, ...config } = this.#config\n\n this.logger.debug(`启动配置: ${JSON.stringify(config)}`)\n\n return new Promise<void>((resolve, reject) => {\n const ws = new WebSocket(this.#buildWsUrl())\n\n ws.onmessage = (event) => {\n const data = (() => {\n try {\n return JSON.parse(event.data)\n } catch {\n return null\n }\n })() as any\n\n if (!data) {\n this.logger.debug(`收到非 JSON 消息: ${event.data}`)\n return\n }\n\n this.#event.emit('ws.message', data)\n this.#bindInternalEvents(data)\n }\n\n ws.onclose = () => {\n this.#online = false\n this.logger.debug('WebSocket 已断开连接')\n this.#event.emit('ws.close')\n }\n\n ws.onerror = (event) => {\n this.#online = false\n const msg = `WebSocket 发生错误,请确认 NapCat 服务已启动,且端口、访问令牌正确`\n this.logger.debug(msg)\n this.#event.emit('ws.error', event)\n reject(new Error(msg))\n }\n\n ws.onopen = () => {\n this.logger.info(`WebSocket 已连接,NapCat SDK 实例已启动`)\n this.#event.emit('ws.open')\n resolve()\n }\n\n this.#ws = ws\n })\n }\n\n /** 销毁 NapCat SDK 实例,关闭 WebSocket 连接 */\n close(): void {\n if (this.#ws) {\n this.logger.info('正在销毁 NapCat SDK 实例...')\n this.#ws.close()\n this.#ws = null\n this.logger.info('NapCat SDK 实例已销毁')\n } else {\n this.logger.warn('NapCat SDK 实例未初始化')\n }\n }\n}\n\n// ==================== 通知事件映射 ====================\n\n/**\n * NapCat 通知类型映射表(notify 类型)\n * @description 将 NapCat 特有的通知类型映射到标准的 notice_type 和 sub_type\n */\nconst NAPCAT_NOTICE_NOTIFY_MAP: Record<string, { notice_type: string; sub_type: string }> = {\n input_status: {\n notice_type: 'friend',\n sub_type: 'input',\n },\n profile_like: {\n notice_type: 'friend',\n sub_type: 'like',\n },\n title: {\n notice_type: 'group',\n sub_type: 'title',\n },\n}\n\n/**\n * NapCat 通知事件映射表(notice 类型)\n * @description 将 NapCat 的原始通知事件类型映射到标准的 notice_type 和 sub_type\n */\nconst NAPCAT_NOTICE_EVENT_MAP: Record<string, { notice_type: string; sub_type: string }> = {\n friend_add: {\n notice_type: 'friend',\n sub_type: 'increase',\n },\n friend_recall: {\n notice_type: 'friend',\n sub_type: 'recall',\n },\n offline_file: {\n notice_type: 'friend',\n sub_type: 'offline_file',\n },\n client_status: {\n notice_type: 'client',\n sub_type: 'status',\n },\n group_admin: {\n notice_type: 'group',\n sub_type: 'admin',\n },\n group_ban: {\n notice_type: 'group',\n sub_type: 'ban',\n },\n group_card: {\n notice_type: 'group',\n sub_type: 'card',\n },\n group_upload: {\n notice_type: 'group',\n sub_type: 'upload',\n },\n group_decrease: {\n notice_type: 'group',\n sub_type: 'decrease',\n },\n group_increase: {\n notice_type: 'group',\n sub_type: 'increase',\n },\n group_msg_emoji_like: {\n notice_type: 'group',\n sub_type: 'reaction',\n },\n essence: {\n notice_type: 'group',\n sub_type: 'essence',\n },\n group_recall: {\n notice_type: 'group',\n sub_type: 'recall',\n },\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,MAAa,aAAmB;AAEhC,MAAaA,kBAA0B;CACrC,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACP,OAAO;CACR;AAED,MAAM,sCAAuB,OAAO,qBAAI,IAAI,MAAM,EAAC,oBAAoB,CAAC,GAAG;AAE3E,MAAaC,iBAAyB;CACpC,QAAQ,GAAG,SAAgB,QAAQ,MAAM,GAAG,MAAM,CAAC,4BAAa,aAAa,UAAU,IAAI,GAAG,KAAK;CACnG,OAAO,GAAG,SAAgB,QAAQ,KAAK,GAAG,MAAM,CAAC,4BAAa,gBAAgB,SAAS,IAAI,GAAG,KAAK;CACnG,OAAO,GAAG,SAAgB,QAAQ,KAAK,GAAG,MAAM,CAAC,4BAAa,eAAe,SAAS,IAAI,GAAG,KAAK;CAClG,QAAQ,GAAG,SAAgB,QAAQ,MAAM,GAAG,MAAM,CAAC,4BAAa,cAAc,UAAU,IAAI,GAAG,KAAK;CACpG,QAAQ,GAAG,SAAgB,QAAQ,MAAM,GAAG,MAAM,CAAC,4BAAa,OAAO,UAAU,IAAI,GAAG,KAAK;CAC9F;;;;;;;;;AEtBD,SAAS,cAAgD,MAAS,MAAsB;AACtF,QAAO;EAAE;EAAM,GAAG;EAAM;;;;;AAM1B,MAAa,UAAU;CAErB,OAAO,SAA8B,cAAc,QAAQ,EAAE,MAAM,CAAC;CAEpE,KAAK,OAAoD,cAAc,MAAM,EAAE,IAAI,CAAC;CAEpF,OAAO,OAA4B,cAAc,QAAQ,EAAE,IAAI,CAAC;CAEhE,QAAQ,OAA4B,cAAc,SAAS,EAAE,IAAI,CAAC;CAElE,QACE,MACA,YACgB;EAChB,MAAM,UAAU,SAAS,SAAS;AAWlC,SAAO,cAAc,SAAS;GAAE,MAR9B,gBAAgB,SACZ,YAAY,KAAK,SAAS,SAAS,KACnC,OAAO,SAAS,WACd,UACE,WAAW,KAAK,QAAQ,sBAAsB,GAAG,KACjD,OACF;GAEyC,GAAG;GAAS,CAAC;;CAGhE,SAAS,MAAc,YACrB,cAAc,UAAU;EAAE;EAAM,GAAG;EAAS,CAAC;CAE/C,QAAQ,MAAc,YACpB,cAAc,SAAS;EAAE;EAAM,GAAG;EAAS,CAAC;CAE9C,QAAQ,YACN,cAAc,SAAS,EAAE,GAAG,SAAS,CAAC;CAExC,QAAQ,OAA4B,cAAc,SAAS,EAAE,IAAI,CAAC;CAElE,UAAU,MAAsB,OAA4B,cAAc,WAAW;EAAE;EAAI,UAAU;EAAM,CAAC;CAE5G,YAAyB,cAAc,QAAQ,EAAE,CAAC;CAElD,QAAQ,UAAoD,OAC1D,cAAc,SAAS;EAAE;EAAU;EAAI,CAAC;CAE1C,cACE,OACA,OACA,KACA,YACgB,cAAc,SAAS;EAAE,UAAU;EAAU;EAAK;EAAO;EAAO,GAAG;EAAS,CAAC;CAE/F,OAAO,YAAsE,cAAc,QAAQ,EAAE,GAAG,SAAS,CAAC;CAElH,UAAU,OAA4B,cAAc,WAAW,EAAE,IAAI,CAAC;CAEtE,OAAO,SAA8B,cAAc,QAAQ,EAAE,MAAM,CAAC;CAEpE,OAAO,MAAc,YACnB,cAAc,QAAQ;EAAE;EAAM,GAAG;EAAS,CAAC;CAE7C,gBAA6B,cAAc,YAAY,EAAE,CAAC;CAE1D,gBAA6B,cAAc,YAAY,EAAE,CAAC;CAC3D;;;;AC/CD,MAAaC,OAAeC;AAC5B,MAAaC,UAAkBC;AAE/B,MAAMC,yBAAiE;CACrE,UAAU;CACV,MAAM;CACN,MAAM;CACN,QAAQ;CACR,OAAO;CACR;AAED,IAAa,SAAb,MAAoB;;CAElB,MAAwB;;CAExB,4BAAqE;;CAErE,gCAAqD;;CAErD,OAAe;;CAEf,YAAoB;;CAEpB,UAAmB;;CAEnB,iCAAiB,IAAI,KAAqB;;CAE1C,+BAAe,IAAI,KAAqB;;CAExC,8BAAc,IAAI,KAAoB;;CAEtC,QAAc;EACZ,YAAY,KAAK,KAAK;EACtB,MAAM;GAAE,OAAO;GAAG,SAAS;GAAG;EAC9B,MAAM;GAAE,OAAO;GAAG,SAAS;GAAG;EAC/B;;CAED,+BAAe,IAAI,KAWhB;CAEH,OAAc,kBAA0B;CACxC,OAAc,iBAAyB;CAEvC,YAAY,AAAiBC,UAAyB,EAAE,EAAE;EAA7B;;;CAG7B,IAAI,OAAa;AACf,SAAO,MAAKC;;;CAId,KAAIC,SAAmC;AACrC,SAAO;GACL,UAAU,KAAK,QAAQ,YAAY,uBAAuB;GAC1D,MAAM,KAAK,QAAQ,QAAQ,uBAAuB;GAClD,MAAM,KAAK,QAAQ,QAAQ,uBAAuB;GAClD,QAAQ,KAAK,QAAQ,UAAU,uBAAuB;GACtD,OAAO,KAAK,QAAQ,SAAS,uBAAuB;GACrD;;;CAIH,IAAI,KAAgB;AAClB,MAAI,CAAC,MAAKC,IAAK;AACb,QAAK,OAAO,MAAM,gBAAgB;AAClC,SAAM,IAAI,MAAM,gBAAgB;;AAGlC,SAAO,MAAKA;;;CAId,IAAI,SAAiB;AACnB,SAAO,MAAKD,OAAQ;;;CAItB,IAAI,UAA0B;AAC5B,SAAO;;;;;;;CAQT,IAAI,UAAkB;AACpB,SAAO,KAAK;;;;;CAMd,IAAI,MAAc;AAChB,SAAO,MAAKE;;;;;CAMd,IAAI,WAAmB;AACrB,SAAO,MAAKC;;;CAId,UAAU;AACR,SAAOC,oBAAO,YAAY,GAAG,CAAC,SAAS,MAAM;;;CAI/C,cAAsB;EACpB,MAAM,EAAE,UAAU,MAAM,MAAM,UAAU,MAAKJ;AAC7C,SAAO,GAAG,SAAS,KAAK,KAAK,GAAG,KAAK,gBAAgB;;;CAIvD,WAAW,UAA+B,YAAqB,OAA6B;EAC1F,MAAM,eAAe,OAAO,aAAa,WAAW,CAAC,SAAS,GAAG,CAAC,SAAS,CAAC,MAAM;AAElF,MAAI,SAAS,WACX,QAAO,CAAC,QAAQ,MAAM,OAAO,WAAW,CAAC,EAAE,GAAG,aAAa;AAG7D,SAAO;;;CAIT,oBAAoB,IAA+C;AACjE,MAAI,CAAC,IAAI;AACP,QAAK,OAAO,MAAM,gBAAgB;AAClC,SAAM,IAAI,MAAM,gBAAgB;;AAGlC,MAAI,GAAG,eAAe,UAAU,MAAM;AACpC,QAAK,OAAO,MAAM,gBAAgB;AAClC,SAAM,IAAI,MAAM,gBAAgB;;;;CAKpC,eAAe,KAAkB;EAC/B,MAAM,uBAAO,IAAI,SAAS;AAC1B,SAAO,KAAK,UAAU,MAAM,KAAK,UAAU;AAEzC,OAAI,QAAQ,iBACV;AAGF,OAAI,OAAO,UAAU,WACnB;AAGF,OAAI,QAAQ,SACV;AAGF,OAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,QAAI,KAAK,IAAI,MAAM,CACjB,QAAO;AAET,SAAK,IAAI,MAAM;;AAEjB,UAAO;IACP;;;CAIJ,kBAAkB,KAAqD;AACrE,SAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,SAAS;AACjC,OAAI,OAAO,SAAS,SAClB,QAAO;IAAE,MAAM;IAAQ,MAAM,EAAE,MAAM,MAAM;IAAE;AAE/C,OAAI,KAAK,SAAS,KAChB,QAAO;IAAE,MAAM;IAAM,MAAM,EAAE,IAAI,OAAO,KAAK,GAAG,EAAE;IAAE;GAEtD,MAAM,EAAE,MAAM,GAAG,SAAS;AAC1B,UAAO;IAAE;IAAM;IAAM;IACrB;;;CAIJ,eAA8B,QAAgB;EAC5C,MAAM,YAAY,QAAQ;AAE1B,SAAO,IAAI,SAAY,SAAS,WAAW;GACzC,MAAM,UAAU,SAAc;AAC5B,QAAI,CAAC,QAAQ,KAAK,SAAS,OAAQ;AAEnC,UAAKK,UAAW,IAAI,WAAW,OAAO;AAEtC,QAAI,KAAK,YAAY,EACnB,SAAQ,KAAK,KAAU;QAEvB,QAAO,WAAW,KAAK,UAAU;;AAIrC,SAAKA,UAAW,GAAG,WAAW,OAAO;IACrC;;;CAIJ,YACE,UACA,aAAqB,IACrB,YAAe,EAAE,EACjB,cAAc,OACH;EACX,MAAM,QAAQ,MAAKC,WAAY,IAAI,SAAS;AAE5C,MAAI,OAAO;AACT,OAAI,CAAC,YACH,QAAO;AAGT,gBAAc,MAAc,eAAe;;EAG7C,MAAM,QAAQ,iBAAiB,MAAKA,WAAY,OAAO,SAAS,EAAE,MAAO,KAAK,GAAG;EAEjF,MAAM,QAAQ;GACZ,GAAG;GACH;GACA;GACA,QAAQ;GACR,MAAM,KAAK,aAAa,KAAK,MAAM,SAAS;GAC5C,UAAU,KAAK,qBAAqB,KAAK,MAAM,SAAS;GACxD,SAAS,KAAK,aAAa,KAAK,MAAM,SAAS;GAC/C,YAAY,KAAK,cAAc,KAAK,KAAK;GACzC,YAAY,KAAK,iBAAiB,KAAK,KAAK;GAC5C,SAAS,KAAK,aAAa,KAAK,MAAM,SAAS;GAC/C,eAAe,KAAK,mBAAmB,KAAK,MAAM,SAAS;GAC3D,eAAe,KAAK,mBAAmB,KAAK,MAAM,SAAS;GAC3D,QAAQ,KAAK,UAAU,KAAK,KAAK;GACjC,KAAK,KAAK,YAAY,KAAK,MAAM,SAAS;GAC1C,SAAS,KAAK,aAAa,KAAK,MAAM,SAAS;GAC/C,YAAY,KAAK,mBAAmB,KAAK,MAAM,SAAS;GACxD,MAAM,KAAK,gBAAgB,KAAK,MAAM,SAAS;GAC/C,gBAAgB;GACjB;AAED,QAAKA,WAAY,IAAI,UAAU,MAAM;AAErC,SAAO;;;CAIT,aACE,SACA,WAAmB,IACnB,YAAe,EAAE,EACjB,cAAc,OACF;EACZ,MAAM,QAAQ,MAAKC,YAAa,IAAI,QAAQ;EAE5C,MAAMC,SAAO,YAAY,MAAKC,cAAe,IAAI,QAAQ,IAAI,OAAO,YAAY;AAChF,QAAKA,cAAe,IAAI,SAASD,OAAK;AAEtC,MAAI,OAAO;AACT,OAAI,CAAC,YACH,QAAO;AAGT,gBAAc,MAAc,eAAe;;EAG7C,MAAM,KAAK,iBAAiB,MAAKD,YAAa,OAAO,QAAQ,EAAE,MAAO,KAAK,GAAG;EAE9E,MAAM,SAAS;GACb,GAAG;GACH;GACA,UAAUC;GACV,QAAQ;GACR,QAAQ,KAAK,aAAa,KAAK,MAAM,QAAQ;GAC7C,SAAS,KAAK,eAAe,KAAK,MAAM,QAAQ;GAChD,SAAS,KAAK,gBAAgB,KAAK,MAAM,QAAQ;GACjD,gBAAgB;GACjB;AAED,QAAKD,YAAa,IAAI,SAAS,OAAO;AAEtC,SAAO;;CAGT,wBAAwB,SAA+B;AACrD,UAAQ,WAAW,EAAE,EAAE,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,KAAK,QAAa;GAAE,MAAM,GAAG;GAAM,GAAG,GAAG;GAAM,EAAE;;;CAI5G,0BAA0B,OAAuF;EAC/G,MAAMG,WAA0B,MAAM,QAAQ,MAAM,OAAY,GAAG,SAAS,QAAQ,EAAE,MAAM,MAAM;AAElG,MAAI,MAAM,OAAO,SACf,OAAKD,cAAe,IAAI,MAAM,OAAO,SAAS,MAAM,OAAO,SAAS;EAGtE,MAAM,SAAS,MAAM,YACjB;GAAE,SAAS,MAAM;GAAW,UAAU,MAAKA,cAAe,IAAI,MAAM,UAAU,IAAI;GAAI,GACtF;GAAE,SAAS,MAAM,OAAO;GAAS,UAAU,MAAM,OAAO;GAAU;AAEtE,SAAO;GACL,GAAG;GACH;GACA,mBAAmB,KAAK,OAAO,SAAS;GACxC,SAAS,MAAKE,uBAAwB,MAAM,QAAQ;GACpD,QAAQ,MAAKC,YAAa,OAAO,SAAS,OAAO,SAAS;GAC1D,QAAQ,UAA+B,QAAQ,UAC7C,KAAK,eAAe,OAAO,SAAS,MAAKC,UAAW,UAAU,MAAM,YAAY,MAAM,CAAC;GAC1F;;;CAIH,wBAAwB,OAAmF;EACzG,MAAMH,WAA0B,MAAM,QAAQ,MAAM,OAAY,GAAG,SAAS,QAAQ,EAAE,MAAM,MAAM;AAElG,MAAI,MAAM,OAAO,SACf,OAAKD,cAAe,IAAI,MAAM,OAAO,SAAS,MAAM,OAAO,SAAS;AAGtE,SAAO;GACL,GAAG;GACH;GACA,mBAAmB,KAAK,OAAO,SAAS;GACxC,qBAAqB,KAAK,mBAAmB,KAAK,MAAM,MAAM,UAAU,MAAM,OAAO,QAAQ;GAC7F,SAAS,MAAKE,uBAAwB,MAAM,QAAQ;GACpD,OAAO,MAAKG,WAAY,MAAM,UAAU,MAAM,cAAc,GAAG;GAC/D,QAAQ,KAAK,UAAU,KAAK,MAAM,MAAM,WAAW;GACnD,aAAa,KAAK,YAAY,KAAK,MAAM,MAAM,WAAW;GAC1D,aAAa,KAAK,YAAY,KAAK,MAAM,MAAM,WAAW;GAC1D,YAAY,KAAK,cAAc,KAAK,MAAM,MAAM,WAAW;GAC3D,YAAY,KAAK,iBAAiB,KAAK,MAAM,MAAM,WAAW;GAC9D,QAAQ,UAA+B,QAAQ,UAC7C,KAAK,aAAa,MAAM,UAAU,MAAKD,UAAW,UAAU,MAAM,YAAY,MAAM,CAAC;GACxF;;;CAIH,OAAME,mBAAoB,MAAW;AACnC,MAAI,KAAK,MAAM;AACb,SAAKV,UAAW,KAAK,QAAQ,KAAK,QAAQ,KAAK;AAC/C;;AAGF,MAAI,KAAK,WAAW;AAClB,WAAQ,KAAK,WAAb;IACE,KAAK;AACH,UAAK,OAAO,MAAM,kBAAkB,MAAKW,cAAe,KAAK,GAAG;AAEhE,WAAKC,MAAO,KAAK,cAAc,KAAK;AAEpC,SAAI,KAAK,iBAAiB;AACxB,YAAKA,MAAO,KAAK,cAAc,KAAK,mBAAmB,KAAK;AAE5D,WAAK,OAAO,MAAM,wBAAwB,KAAK,gBAAgB;AAE/D,UAAI,KAAK,UAAU;AACjB,WAAI,KAAK,aAAa,WAAW;QAC/B,MAAM,EAAE,UAAU,aAAa,qBAAqB,MAAM,KAAK,gBAAgB;QAC/E,MAAM,EAAE,UAAU,YAAY,MAAM,KAAK,cAAc;AAEvD,cAAKC,SAAU;AACf,cAAKhB,MAAO;AACZ,cAAKC,WAAY;AAEjB,cAAKc,MAAO,KAAK,oBAAoB;SACnC,SAAS,MAAKf;SACd,UAAU,MAAKC;SACf;SACA;SACA;SACA,WAAW,KAAK,OAAO;SACxB,CAAC;;AAGJ,aAAKc,MAAO,KAAK,cAAc,KAAK,gBAAgB,GAAG,KAAK,YAAY,KAAK;;;AAIjF;IAGF,KAAK,WAAW;AACd,SAAI,KAAK,iBAAiB,WAAW;AACnC,YAAKlB,KAAM,KAAK;AAChB,aAAO,MAAKoB,yBAA0B,KAAK;YACtC;AACL,YAAKpB,KAAM,KAAK;AAChB,aAAO,MAAKqB,uBAAwB,KAAK;;AAG3C,WAAKH,MAAO,KAAK,WAAW,KAAK;KAEjC,MAAM,MAAM,KAAK,iBAAiB,KAAK,QAAQ;KAE/C,MAAM,QAAQ,KAAK,QAAQ,GAAG,KAAK,WAAW,GAAG,KAAK,SAAS,KAAK;KACpE,MAAM,SAAS,GAAG,KAAK,OAAO,SAAS,GAAG,KAAK,OAAO,QAAQ;AAE9D,aAAQ,KAAK,cAAb;MACE,KAAK;AACH,aAAKA,MAAO,KAAK,mBAAmB,KAAK;AACzC,aAAKA,MAAO,KAAK,mBAAmB,KAAK,YAAY,KAAK;AAC1D,YAAK,OAAO,MAAM,WAAW,MAAKD,cAAe,KAAK,GAAG;AACzD,YAAK,OAAO,KAAK,MAAM,OAAO,IAAI,MAAM;AACxC;MAGF,KAAK;AACH,aAAKC,MAAO,KAAK,iBAAiB,KAAK;AACvC,aAAKA,MAAO,KAAK,iBAAiB,KAAK,YAAY,KAAK;AACxD,YAAK,OAAO,MAAM,UAAU,MAAKD,cAAe,KAAK,GAAG;AACxD,YAAK,OAAO,KAAK,MAAM,MAAM,IAAI,OAAO,IAAI,MAAM;AAClD;MAGF;AACE,YAAK,OAAO,MAAM,aAAa,MAAKA,cAAe,KAAK,GAAG;AAE3D;;AAIJ;;IAGF,KAAK;AACH,SAAI,KAAK,iBAAiB,WAAW;AACnC,YAAKjB,KAAM,KAAK;AAChB,aAAO,MAAKoB,yBAA0B,KAAK;YACtC;AACL,YAAKpB,KAAM,KAAK;AAChB,aAAO,MAAKqB,uBAAwB,KAAK;;AAG3C,WAAKH,MAAO,KAAK,gBAAgB,KAAK;AACtC,UAAK,OAAO,MAAM,oBAAoB,MAAKD,cAAe,KAAK,GAAG;AAElE,SAAI,KAAK,cAAc;AACrB,YAAKC,MAAO,KAAK,gBAAgB,KAAK,gBAAgB,KAAK;AAE3D,UAAI,KAAK,SACP,OAAKA,MAAO,KAAK,gBAAgB,KAAK,aAAa,GAAG,KAAK,YAAY,KAAK;MAG9E,MAAM,MAAM,KAAK,iBAAiB,KAAK,QAAQ;AAE/C,UAAI,KAAK,iBAAiB,WAAW,KAAK,SACxC,MAAK,OAAO,KAAK,UAAU,KAAK,WAAW,GAAG,KAAK,SAAS,KAAK,MAAM;UAEvE,MAAK,OAAO,KAAK,UAAU,KAAK,OAAO,SAAS,GAAG,KAAK,OAAO,QAAQ,KAAK,MAAM;;AAItF;IAGF,KAAK,UAAU;AACb,UAAK,OAAO,MAAM,SAAS,MAAKD,cAAe,KAAK,GAAG;AAEvD,SAAI,CAAC,KAAK,aAAa;AACrB,WAAK,OAAO,MAAM,aAAa,MAAKA,cAAe,KAAK,GAAG;AAC3D;;KAGF,MAAM,WAAW,KAAK,gBAAgB;KACtC,MAAM,SAAS,KAAK,aAAa;KACjC,MAAM,UAAU,CAAC,CAAC,KAAK;KAEvB,MAAM,EAAE,aAAa,aAAa,WAC9B,SACE;MAAE,aAAa,UAAU,UAAU;MAAU,UAAU;MAAQ,GAC/D,yBAAyB,KAAK,aAAa,EAAE,GAC/C,wBAAwB,KAAK,gBAAgB,EAAE;AAEnD,UAAK,uBAAuB,KAAK;AACjC,UAAK,cAAc,eAAe,KAAK;AAEvC,SAAI,KAAK,YAAY,KAAK,aAAa,SACrC,MAAK,cAAc,KAAK;AAG1B,UAAK,WAAW,YAAY,KAAK;AAEjC,SAAI,QACF,MAAK,QAAQ,MAAKF,WAAY,KAAK,UAAU,KAAK,cAAc,GAAG;SAEnE,MAAK,SAAS,MAAKF,YAAa,KAAK,SAAS,KAAK,YAAY,GAAG;AAGpE,WAAKK,MAAO,KAAK,UAAU,KAAK;AAEhC,SAAI,aAAa;AACf,YAAKA,MAAO,KAAK,UAAU,eAAe,KAAK;AAC/C,UAAI,SACF,OAAKA,MAAO,KAAK,UAAU,YAAY,GAAG,YAAY,KAAK;;AAI/D;;IAGF,KAAK;AACH,UAAK,OAAO,MAAM,SAAS,MAAKD,cAAe,KAAK,GAAG;AAEvD,SAAI,KAAK,iBAAiB,UAAU;AAClC,WAAK,UAAU,WACb,KAAK,IAAI,0BAA0B;OAAE,MAAM,KAAK;OAAM,SAAS;OAAO;OAAQ,CAAC;AACjF,WAAK,gBAAgB,KAAK,IAAI,0BAA0B;OAAE,MAAM,KAAK;OAAM,SAAS;OAAM,CAAC;;AAG7F,SAAI,KAAK,iBAAiB,SAAS;AACjC,WAAK,UAAU,WACb,KAAK,IAAI,yBAAyB;OAAE,MAAM,KAAK;OAAM,SAAS;OAAO;OAAQ,CAAC;AAChF,WAAK,gBAAgB,KAAK,IAAI,yBAAyB;OAAE,MAAM,KAAK;OAAM,SAAS;OAAM,CAAC;;AAG5F,WAAKC,MAAO,KAAK,WAAW,KAAK;AAEjC,SAAI,KAAK,cAAc;AACrB,YAAKA,MAAO,KAAK,WAAW,KAAK,gBAAgB,KAAK;AACtD,UAAI,KAAK,SACP,OAAKA,MAAO,KAAK,WAAW,KAAK,aAAa,GAAG,KAAK,YAAY,KAAK;;AAI3E;IAGF;AACE,UAAK,OAAO,MAAM,OAAO,MAAKD,cAAe,KAAK,GAAG;AACrD,WAAKC,MAAO,KAAK,KAAK,WAAW,KAAK;AACtC;;AAIJ;;;CAIJ,iBAAiB,SAAgC;AAC/C,SAAO,QACJ,KAAK,OAAO;AACX,WAAQ,GAAG,MAAX;IACE,KAAK,OACH,QAAO,GAAG;IACZ,KAAK,KACH,QAAO,OAAO,GAAG,GAAG;IACtB,KAAK,OACH,QAAO,SAAS,GAAG,GAAG;IACxB,KAAK,QACH,QAAO,UAAU,GAAG,KAAK,GAAG,GAAG,IAAI;IACrC,KAAK,OACH,QAAO,SAAS,GAAG,KAAK;IAC1B,KAAK;IACL,KAAK,OACH,QAAO,SAAS,GAAG,OAAO;IAC5B,KAAK;IACL,KAAK;IACL,KAAK,SACH,QAAO,IAAI,GAAG,KAAK,GAAG,GAAG,IAAI;IAC/B,QACE,QAAO,IAAI,GAAG,KAAK;;IAEvB,CACD,KAAK,GAAG;;;CAIb,MAAM,UAAU,UAAkB,cAAuB,OAAsC;AAC7F,MAAI;GACF,MAAM,QAAQ,MAAKX,WAAY,IAAI,SAAS;AAE5C,OAAI,SAAS,CAAC,eAAe,kBAAkB,MAC7C,QAAO;GAGT,MAAM,YAAY,MAAM,KAAK,IAAkC,kBAAkB,EAAE,UAAU,CAAC;AAC9F,UAAO,MAAKQ,WAAY,UAAU,UAAU,YAAY,WAAW,KAAK;WACjEO,KAAU;AACjB,QAAK,OAAO,KAAK,OAAO,SAAS,SAAS,KAAK,WAAW,MAAM;AAChE,UAAO,MAAKP,WAAY,UAAU,KAAK,EAAE,CAAC;;;;CAK9C,MAAM,WAAW,SAAiD;AAChE,MAAI;GACF,MAAM,QAAQ,MAAKP,YAAa,IAAI,QAAQ;AAE5C,OAAI,SAAS,SAAS,MACpB,QAAO;GAGT,MAAM,aAAa,MAAM,KAAK,IAAmC,qBAAqB,EAAE,SAAS,CAAC;AAClG,UAAO,MAAKK,YAAa,SAAS,WAAW,UAAU,YAAY,KAAK;WACjES,KAAU;AACjB,QAAK,OAAO,KAAK,QAAQ,QAAQ,SAAS,KAAK,WAAW,MAAM;AAEhE,UAAO,MAAKT,YAAa,SAAS,KAAK,EAAE,CAAC;;;;;;;;;;;CAY9C,KAA+B,MAAS,SAA4D;EAClG,MAAM,eAAe,UAAgC;AACnD,WAAQ,MAAM;AACd,SAAKK,MAAO,IAAI,MAAM,YAAY;;AAGpC,OAAK,OAAO,MAAM,aAAa,OAAO,KAAK,GAAG;AAC9C,QAAKA,MAAO,GAAG,MAAM,YAAY;AACjC,eAAa,KAAK,IAAI,MAAM,QAAQ;;;;;;;;;CAUtC,GAA6B,MAAS,SAA4D;AAChG,OAAK,OAAO,MAAM,UAAU,OAAO,KAAK,GAAG;AAC3C,QAAKA,MAAO,GAAG,MAAM,QAAQ;AAC7B,eAAa,KAAK,IAAI,MAAM,QAAQ;;;;;CAMtC,IAA8B,MAAS,SAAsD;AAC3F,OAAK,OAAO,MAAM,UAAU,OAAO,KAAK,GAAG;AAC3C,QAAKA,MAAO,IAAI,MAAM,QAAQ;;;;;CAMhC,IAAmB,QAA6B,SAA8B,EAAE,EAAc;AAC5F,QAAKK,mBAAoB,MAAKrB,GAAI;AAClC,OAAK,OAAO,MAAM,WAAW,OAAO,OAAO,KAAK,UAAU,OAAO,GAAG;EACpE,MAAM,OAAO,MAAKsB,QAAS;AAC3B,QAAKtB,GAAI,KAAK,KAAK,UAAU;GAAE;GAAM;GAAQ;GAAQ,CAAC,CAAC;AACvD,SAAO,MAAKuB,cAAkB,KAAK;;;;;CAMrC,MAAM,SAAS,SAAiB,QAAgB,GAAiB;AAC/D,MAAI;AACF,SAAM,KAAK,IAAU,aAAa;IAAE;IAAS;IAAO,CAAC;AACrD,UAAO;UACD;AACN,UAAO;;;;;;CAOX,MAAM,gBAA2D;AAE/D,UADgB,MAAM,KAAK,IAAc,kBAAkB,EAC5C,KAAK,MAAM,MAAKZ,YAAa,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;;;;;CAMxE,MAAM,eAAyD;AAE7D,UADe,MAAM,KAAK,IAAa,iBAAiB,EAC1C,KAAK,MAAM,MAAKE,WAAY,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;;;;;CAMzE,YAAY,YAAoB,IAA2B;AACzD,SAAO,KAAK,IAAU,sBAAsB;GAAE;GAAY,UAAU;GAAI,KAAK;GAAM,CAAC;;;;;CAMtF,YAAY,YAAoB,IAA2B;AACzD,SAAO,KAAK,IAAU,sBAAsB;GAAE;GAAY,UAAU;GAAI,KAAK;GAAO,CAAC;;;;;CAMvF,MAAM,OAAO,YAA8F;AACzG,MAAI,CAAC,WACH,QAAO;EAGT,MAAM,MAAM,MAAM,KAAK,IAAS,WAAW,EAAE,YAAY,CAAC;AAE1D,MAAI,IAAI,iBAAiB,UACvB,QAAO,MAAKK,yBAA0B,IAAI;MAE1C,QAAO,MAAKC,uBAAwB,IAAI;;;;;CAO5C,aAAa,SAAiB,QAAiB,OAAO,OAAgB,OAAsB;AAC1F,SAAO,KAAK,IAAU,iBAAiB;GACrC;GACA,YAAY;GACZ,eAAe;GAChB,CAAC;;;;;CAMJ,YAAY,UAAkB,SAAiB,UAAiC;AAC9E,SAAO,KAAK,IAAU,iBAAiB;GAAE;GAAU;GAAS;GAAU,CAAC;;;;;CAMzE,UAAU,YAAmC;AAC3C,SAAO,KAAK,IAAU,cAAc,EAAE,YAAY,CAAC;;;;;CAMrD,gBAAgB,SAA+B;AAC7C,SAAO,KAAK,IAAS,qBAAqB,EAAE,SAAS,CAAC;;;;;CAMxD,eAAe,SAAiB,UAAgE;AAC9F,SAAO,KAAK,IAA4B,oBAAoB;GAC1D;GACA,SAAS,KAAK,kBAAkB,SAAS;GAC1C,CAAC;;;;;CAMJ,aAAa,UAAkB,UAAgE;AAC7F,SAAO,KAAK,IAA4B,kBAAkB;GACxD;GACA,SAAS,KAAK,kBAAkB,SAAS;GAC1C,CAAC;;;;;CAMJ,aAAa,UAAgC;AAC3C,SAAO,KAAK,IAAS,kBAAkB,EAAE,UAAU,CAAC;;;;;CAMtD,aAAa,UAAgC;AAC3C,SAAO,KAAK,IAAU,kBAAkB,EAAE,UAAU,CAAC;;;;;CAMvD,cAAc,YAAmC;AAC/C,SAAO,KAAK,IAAU,mBAAmB,EAAE,YAAY,CAAC;;;;;CAM1D,iBAAiB,YAAmC;AAClD,SAAO,KAAK,IAAU,sBAAsB,EAAE,YAAY,CAAC;;;;;CAM7D,aAAa,UAAkB,SAAiB,MAA6B;AAC3E,SAAO,KAAK,IAAU,kBAAkB;GAAE;GAAU;GAAS;GAAM,CAAC;;;;;CAMtE,qBAAqB,UAAkB,SAAiB,OAA8B;AACpF,SAAO,KAAK,IAAU,2BAA2B;GAAE;GAAU;GAAS;GAAO,CAAC;;;;;CAMhF,mBAAmB,UAA8C;AAC/D,SAAO,KAAK,IAAuB,yBAAyB,EAAE,UAAU,CAAC;;;;;CAM3E,mBAAmB,UAAkB,SAA2C;AAC9E,SAAO,KAAK,IAAqB,yBAAyB;GAAE;GAAU;GAAS,CAAC;;;;;CAMlF,gBAAgB,UAAkB,SAAiB,qBAA8B,OAAsB;AACrG,SAAO,KAAK,IAAU,kBAAkB;GAAE;GAAU;GAAS;GAAoB,CAAC;;;;;CAMpF,WAAoB;AAClB,SAAO,MAAKnB,IAAK,eAAe,UAAU,QAAQ,MAAKiB;;;;;CAMzD,OAAO,OAAuB;EAC5B,IAAI,MAAM;AACV,OAAK,IAAI,IAAI,GAAG,MAAM,MAAM,QAAQ,IAAI,KAAK,EAAE,EAC7C,SAAQ,OAAO,KAAK,MAAM,WAAW,EAAE;AAEzC,SAAO,MAAM;;;;;CAMf,iBAAiB,QAA2D;AAC1E,SAAO,KAAK,IAAsC,eAAe,EAAE,QAAQ,CAAC;;;;;CAM9E,iBAA+F;AAC7F,SAAO,KAAK,IAAyE,mBAAmB;;;;;CAM1G,eAA+D;AAC7D,SAAO,KAAK,IAA2C,iBAAiB;;;;;CAM1E,MAAM,UAAU,QAQb;EACD,MAAM,QAAQ,MAAKO,YAAa,IAAI,OAAO;AAE3C,MAAI,MAAO,QAAO;EAElB,MAAM,EAAE,SAAS,cAAc,QAAQ,MAAM,KAAK,iBAAiB,OAAO;EAE1E,MAAM,OAAO,aAAa,MAAM,eAAe,GAAG,MAAM;EACxD,MAAM,QAAQ,aAAa,MAAM,iBAAiB,GAAG,MAAM;EAC3D,MAAM,MAAM,KAAK,OAAO,MAAM;EAE9B,MAAM,UAAU;GACd;GACA;GACA,KAAK,KAAK;GACV,KAAK,OAAO,IAAI;GAChB;GACA,QAAQ,OAAO,KAAK,IAAI,SAAS,KAAK,UAAU,KAAK,IAAI,WAAW,MAAM;GAC1E,cAAc,QAAQ,KAAK,IAAI,SAAS,KAAK,WAAW,KAAK,IAAI,WAAW,MAAM;GACnF;AAED,QAAKA,YAAa,IAAI,QAAQ,QAAQ;AAGtC,mBACQ;AACJ,SAAKA,YAAa,OAAO,OAAO;KAElC,MAAO,KAAK,GACb;AAED,SAAO;;;;;CAMT,MAAM,SAAS,QAAiC;EAC9C,MAAM,EAAE,UAAU,MAAM,KAAK,UAAU,OAAO;AAC9C,SAAO;;;;;CAMT,MAAM,SAA0B;EAC9B,MAAM,EAAE,QAAQ,MAAM,KAAK,UAAU,aAAa;AAClD,SAAO;;;CAIT,MAAM,MAAqB;EACzB,MAAM,EAAE,QAAQ,GAAG,OAAO,IAAI,GAAG,WAAW,MAAKzB;AAEjD,OAAK,OAAO,MAAM,SAAS,KAAK,UAAU,OAAO,GAAG;AAEpD,SAAO,IAAI,SAAe,SAAS,WAAW;GAC5C,MAAM,KAAK,IAAI,UAAU,MAAK0B,YAAa,CAAC;AAE5C,MAAG,aAAa,UAAU;IACxB,MAAM,cAAc;AAClB,SAAI;AACF,aAAO,KAAK,MAAM,MAAM,KAAK;aACvB;AACN,aAAO;;QAEP;AAEJ,QAAI,CAAC,MAAM;AACT,UAAK,OAAO,MAAM,gBAAgB,MAAM,OAAO;AAC/C;;AAGF,UAAKT,MAAO,KAAK,cAAc,KAAK;AACpC,UAAKF,mBAAoB,KAAK;;AAGhC,MAAG,gBAAgB;AACjB,UAAKG,SAAU;AACf,SAAK,OAAO,MAAM,kBAAkB;AACpC,UAAKD,MAAO,KAAK,WAAW;;AAG9B,MAAG,WAAW,UAAU;AACtB,UAAKC,SAAU;IACf,MAAM,MAAM;AACZ,SAAK,OAAO,MAAM,IAAI;AACtB,UAAKD,MAAO,KAAK,YAAY,MAAM;AACnC,WAAO,IAAI,MAAM,IAAI,CAAC;;AAGxB,MAAG,eAAe;AAChB,SAAK,OAAO,KAAK,iCAAiC;AAClD,UAAKA,MAAO,KAAK,UAAU;AAC3B,aAAS;;AAGX,SAAKhB,KAAM;IACX;;;CAIJ,QAAc;AACZ,MAAI,MAAKA,IAAK;AACZ,QAAK,OAAO,KAAK,wBAAwB;AACzC,SAAKA,GAAI,OAAO;AAChB,SAAKA,KAAM;AACX,QAAK,OAAO,KAAK,mBAAmB;QAEpC,MAAK,OAAO,KAAK,oBAAoB;;;;;;;AAW3C,MAAM0B,2BAAsF;CAC1F,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACD,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACD,OAAO;EACL,aAAa;EACb,UAAU;EACX;CACF;;;;;AAMD,MAAMC,0BAAqF;CACzF,YAAY;EACV,aAAa;EACb,UAAU;EACX;CACD,eAAe;EACb,aAAa;EACb,UAAU;EACX;CACD,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACD,eAAe;EACb,aAAa;EACb,UAAU;EACX;CACD,aAAa;EACX,aAAa;EACb,UAAU;EACX;CACD,WAAW;EACT,aAAa;EACb,UAAU;EACX;CACD,YAAY;EACV,aAAa;EACb,UAAU;EACX;CACD,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACD,gBAAgB;EACd,aAAa;EACb,UAAU;EACX;CACD,gBAAgB;EACd,aAAa;EACb,UAAU;EACX;CACD,sBAAsB;EACpB,aAAa;EACb,UAAU;EACX;CACD,SAAS;EACP,aAAa;EACb,UAAU;EACX;CACD,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACF"}
1
+ {"version":3,"file":"index.cjs","names":["ABSTRACT_LOGGER: Logger","CONSOLE_LOGGER: Logger","name: string","pkg.name","version: string","pkg.version","DEFAULT_NAPCAT_OPTIONS: Required<OptionalProps<NapCatOptions>>","options: NapCatOptions","#stat","#config","#ws","#uin","#nickname","crypto","#online","#event","timeoutId: NodeJS.Timeout | null","#echoEvent","#groupCache","#friendCache","name","#nicknameCache","quote_id: string | null","#transformOneBotMessage","#buildFriend","#wrapReply","#buildGroup","#bindInternalEvents","#safeStringify","#setOnlineStatus","#buildPrivateMessageEvent","#buildGroupMessageEvent","err: any","#ensureWsConnection","#echoId","#waitForAction","error: any","#cookieCache","#reconnectAttempts","#reconnectTimer","#manualClose","#reconnecting","#getReconnectDelay","#clearReconnectTimer","#connect","#buildWsUrl","#scheduleReconnect","NAPCAT_NOTICE_NOTIFY_MAP: Record<string, { notice_type: string; sub_type: string }>","NAPCAT_NOTICE_EVENT_MAP: Record<string, { notice_type: string; sub_type: string }>"],"sources":["../src/logger.ts","../package.json","../src/segment.ts","../src/napcat.ts"],"sourcesContent":["import { styleText } from 'node:util'\n\nexport type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'trace'\n\nexport type Logger = Record<LogLevel, (...args: unknown[]) => void>\n\nexport const noop = (): void => {}\n\nexport const ABSTRACT_LOGGER: Logger = {\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n trace: noop,\n}\n\nconst time = () => styleText('dim', `[${new Date().toLocaleTimeString()}]`)\n\nexport const CONSOLE_LOGGER: Logger = {\n error: (...args: any[]) => console.error(`${time()} ${styleText('redBright', '[ERROR]')}`, ...args),\n warn: (...args: any[]) => console.warn(`${time()} ${styleText('yellowBright', '[WARN]')}`, ...args),\n info: (...args: any[]) => console.info(`${time()} ${styleText('greenBright', '[INFO]')}`, ...args),\n debug: (...args: any[]) => console.debug(`${time()} ${styleText('blueBright', '[DEBUG]')}`, ...args),\n trace: (...args: any[]) => console.debug(`${time()} ${styleText('dim', '[TRACE]')}`, ...args),\n}\n","","import type { ExtractByType, SendElement } from './types'\n\nfunction createSegment<T extends SendElement['type'], D>(type: T, data: D): SendElement {\n return { type, ...data } as SendElement\n}\n\n/**\n * 消息片段构造器\n */\nexport const segment = {\n /** 创建一个文本消息片段 */\n text: (text: string): SendElement => createSegment('text', { text }),\n /** 创建一个艾特消息片段 */\n at: (qq: 'all' | (string & {}) | number): SendElement => createSegment('at', { qq }),\n /** 创建一个 QQ 表情消息片段 */\n face: (id: number): SendElement => createSegment('face', { id }),\n /** 创建一个回复消息片段 */\n reply: (id: string): SendElement => createSegment('reply', { id }),\n /** 创建一个图片消息片段 */\n image: (\n file: string | Buffer,\n options?: Omit<ExtractByType<SendElement, 'image'>, 'type' | 'file'> & { local?: boolean },\n ): SendElement => {\n const isLocal = options?.local ?? false\n\n const fileValue =\n file instanceof Buffer\n ? `base64://${file.toString('base64')}`\n : typeof file === 'string'\n ? isLocal\n ? `file:///${file.replace(/^\\s*(file:\\/\\/\\/)+/, '')}`\n : file\n : file\n\n return createSegment('image', { file: fileValue, ...options })\n },\n /** 创建一个语音消息片段 */\n record: (file: string, options?: Omit<ExtractByType<SendElement, 'record'>, 'type' | 'file'>): SendElement =>\n createSegment('record', { file, ...options }),\n /** 创建一个视频消息片段 */\n video: (file: string, options?: Omit<ExtractByType<SendElement, 'video'>, 'type' | 'file'>): SendElement =>\n createSegment('video', { file, ...options }),\n /** 创建一个动态表情消息片段 */\n mface: (options: Omit<ExtractByType<SendElement, 'mface'>, 'type'>): SendElement =>\n createSegment('mface', { ...options }),\n /** 创建一个大表情消息片段 */\n bface: (id: number): SendElement => createSegment('bface', { id }),\n /** 创建一个 联系人/群 分享消息片段 */\n contact: (type: 'qq' | 'group', id: string): SendElement => createSegment('contact', { id, sub_type: type }),\n /** 创建一个戳一戳消息片段 */\n poke: (): SendElement => createSegment('poke', {}),\n /** 创建一个音乐消息片段 */\n music: (platform: 'qq' | '163' | 'kugou' | 'migu' | 'kuwo', id: string): SendElement =>\n createSegment('music', { platform, id }),\n /** 创建一个自定义音乐消息片段 */\n musicCustom: (\n title: string,\n audio: string,\n url: string,\n options?: Omit<ExtractByType<SendElement, 'music'>, 'type' | 'platform' | 'url' | 'audio' | 'title'>,\n ): SendElement => createSegment('music', { platform: 'custom', url, audio, title, ...options }),\n /** 创建一个合并转发消息片段 */\n node: (options: Partial<ExtractByType<SendElement, 'node'>>): SendElement => createSegment('node', { ...options }),\n /** 创建一个合并转发消息片段 */\n forward: (id: string): SendElement => createSegment('forward', { id }),\n /** 创建一个 JSON 消息片段 */\n json: (data: string): SendElement => createSegment('json', { data }),\n /** 创建一个文件消息片段 */\n file: (file: string, options?: Omit<ExtractByType<SendElement, 'file'>, 'type' | 'file'>): SendElement =>\n createSegment('file', { file, ...options }),\n /** 创建一个 Markdown 消息片段 */\n markdown: (): SendElement => createSegment('markdown', {}),\n /** 创建一个轻应用消息片段 */\n lightapp: (): SendElement => createSegment('lightapp', {}),\n}\n","import crypto from 'node:crypto'\nimport mitt from 'mitt'\nimport pkg from '../package.json' with { type: 'json' }\nimport { segment } from './segment'\nimport { ABSTRACT_LOGGER, CONSOLE_LOGGER } from './logger'\n\nimport type { Emitter } from 'mitt'\nimport type { Logger } from './logger'\nimport type {\n API,\n Arrayable,\n EventMap,\n Friend,\n FriendWithInfo,\n Group,\n GroupMemberInfo,\n GroupMessageEvent,\n GroupWithInfo,\n NapCatOptions,\n NormalizedElementToSend,\n OptionalProps,\n PrivateMessageEvent,\n RecvElement,\n Sendable,\n Stat,\n} from './types'\n\nexport const name: string = pkg.name\nexport const version: string = pkg.version\n\nconst DEFAULT_NAPCAT_OPTIONS: Required<OptionalProps<NapCatOptions>> = {\n protocol: 'ws',\n host: 'localhost',\n port: 3001,\n logger: CONSOLE_LOGGER,\n token: '',\n reconnect: true,\n reconnectInterval: 1000,\n maxReconnectAttempts: Infinity,\n maxReconnectInterval: 30000,\n}\n\nexport class NapCat {\n /** WebSocket 实例 */\n #ws: WebSocket | null = null\n /** 事件发射器 */\n #event: Emitter<EventMap & Record<string | symbol, unknown>> = mitt()\n /** Echo 事件发射器 */\n #echoEvent: Emitter<Record<string, unknown>> = mitt()\n /** 机器人 ID */\n #uin: number = 0\n /** 机器人昵称 */\n #nickname: string = ''\n /** 机器人状态 */\n #online: boolean = false\n /** nickname 缓存 */\n #nicknameCache = new Map<number, string>()\n /** friend 缓存 */\n #friendCache = new Map<number, Friend>()\n /** group 缓存 */\n #groupCache = new Map<number, Group>()\n /** 消息数据 */\n #stat: Stat = {\n start_time: Date.now(),\n recv: { group: 0, private: 0 },\n send: { group: 0, private: 0 },\n }\n /** Cookies 缓存 */\n #cookieCache = new Map<\n string,\n {\n uin: number\n pskey: string\n skey: string\n gtk: string\n bkn: string\n cookie: string\n legacyCookie: string\n }\n >()\n /** 当前重连尝试次数 */\n #reconnectAttempts: number = 0\n /** 重连定时器 */\n #reconnectTimer: NodeJS.Timeout | null = null\n /** 是否正在重连 */\n #reconnecting: boolean = false\n /** 是否手动关闭 */\n #manualClose: boolean = false\n\n public static ABSTRACT_LOGGER: Logger = ABSTRACT_LOGGER\n public static CONSOLE_LOGGER: Logger = CONSOLE_LOGGER\n\n constructor(private readonly options: NapCatOptions = {}) {}\n\n /** 统计数据 */\n get stat(): Stat {\n return this.#stat\n }\n\n /** 配置项 */\n get #config(): Required<NapCatOptions> {\n return {\n protocol: this.options.protocol || DEFAULT_NAPCAT_OPTIONS.protocol,\n host: this.options.host || DEFAULT_NAPCAT_OPTIONS.host,\n port: this.options.port || DEFAULT_NAPCAT_OPTIONS.port,\n logger: this.options.logger || DEFAULT_NAPCAT_OPTIONS.logger,\n token: this.options.token || DEFAULT_NAPCAT_OPTIONS.token,\n reconnect: this.options.reconnect ?? DEFAULT_NAPCAT_OPTIONS.reconnect,\n reconnectInterval: this.options.reconnectInterval || DEFAULT_NAPCAT_OPTIONS.reconnectInterval,\n maxReconnectAttempts: this.options.maxReconnectAttempts ?? DEFAULT_NAPCAT_OPTIONS.maxReconnectAttempts,\n maxReconnectInterval: this.options.maxReconnectInterval || DEFAULT_NAPCAT_OPTIONS.maxReconnectInterval,\n }\n }\n\n /** WebSocket 实例 */\n get ws(): WebSocket {\n if (!this.#ws) {\n this.logger.error('WebSocket 未连接')\n throw new Error('WebSocket 未连接')\n }\n\n return this.#ws\n }\n\n /** 日志记录器 */\n get logger(): Logger {\n return this.#config.logger\n }\n\n /** 消息段构建器 */\n get segment(): typeof segment {\n return segment\n }\n\n /**\n * 机器人 QQ 号\n *\n * @deprecated 建议使用 `uin` 属性\n */\n get user_id(): number {\n return this.uin\n }\n\n /**\n * 机器人 QQ 号\n */\n get uin(): number {\n return this.#uin\n }\n\n /**\n * 机器人昵称\n */\n get nickname(): string {\n return this.#nickname\n }\n\n /** 生成唯一的 echo ID */\n #echoId() {\n return crypto.randomBytes(16).toString('hex')\n }\n\n /** 构建 WebSocket 连接地址 */\n #buildWsUrl(): string {\n const { protocol, host, port, token } = this.#config\n return `${protocol}://${host}:${port}?access_token=${token}`\n }\n\n /** 包装回复消息 */\n #wrapReply(sendable: Arrayable<Sendable>, message_id?: number, reply?: boolean): Sendable[] {\n const sendableList = typeof sendable === 'string' ? [sendable] : [sendable].flat()\n\n if (reply && message_id) {\n return [segment.reply(String(message_id)), ...sendableList]\n }\n\n return sendableList\n }\n\n /** 确保 WebSocket 已连接 */\n #ensureWsConnection(ws: WebSocket | null): asserts ws is WebSocket {\n if (!ws) {\n this.logger.error('WebSocket 未连接')\n throw new Error('WebSocket 未连接')\n }\n\n if (ws.readyState !== WebSocket.OPEN) {\n this.logger.error('WebSocket 未打开')\n throw new Error('WebSocket 未打开')\n }\n }\n\n /** 安全的 JSON 序列化,处理循环引用和不可序列化的值 */\n #safeStringify(obj: any): string {\n const seen = new WeakSet()\n return JSON.stringify(obj, (key, value) => {\n // 过滤掉内部的 timeout 引用\n if (key === '__timeout_id__') {\n return undefined\n }\n // 过滤掉函数\n if (typeof value === 'function') {\n return undefined\n }\n // 过滤掉 napcat 实例引用\n if (key === 'napcat') {\n return undefined\n }\n // 处理对象类型的循环引用\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return '[Circular]'\n }\n seen.add(value)\n }\n return value\n })\n }\n\n /** 设置在线状态,并发出相应事件 */\n #setOnlineStatus(online: boolean): void {\n if (this.#online === online) {\n return\n }\n\n const wasOnline = this.#online\n this.#online = online\n\n if (online && !wasOnline) {\n this.logger.info(`机器人上线: ${this.#nickname}(${this.#uin})`)\n this.#event.emit('napcat.online', {\n user_id: this.#uin,\n nickname: this.#nickname,\n })\n } else if (!online && wasOnline) {\n this.logger.info(`机器人下线: ${this.#nickname}(${this.#uin})`)\n this.#event.emit('napcat.offline', {\n user_id: this.#uin,\n nickname: this.#nickname,\n })\n }\n }\n\n /** 标准化可发送消息元素 */\n normalizeSendable(msg: Arrayable<Sendable>): NormalizedElementToSend[] {\n return [msg].flat(2).map((item) => {\n if (typeof item === 'string') {\n return { type: 'text', data: { text: item } }\n }\n if (item.type === 'at') {\n return { type: 'at', data: { qq: String(item.qq) } }\n }\n const { type, ...data } = item\n return { type, data } as NormalizedElementToSend\n })\n }\n\n /** 等待服务器响应操作 */\n #waitForAction<T extends any>(echoId: string, action: string, timeout: number = 30_000) {\n const eventName = `echo#${echoId}`\n\n return new Promise<T>((resolve, reject) => {\n let timeoutId: NodeJS.Timeout | null = null\n\n const cleanup = () => {\n if (timeoutId) {\n clearTimeout(timeoutId)\n timeoutId = null\n }\n this.#echoEvent.off(eventName, handle)\n }\n\n const handle = (data: any) => {\n if (!data || data.echo !== echoId) return\n\n cleanup()\n\n if (data.retcode === 0) {\n resolve(data.data as T)\n } else {\n const error = `API 错误: ${data.message}`\n this.#event.emit('napcat.api_error', {\n action,\n error: data.message || 'Unknown error',\n retcode: data.retcode,\n })\n reject(new Error(error))\n }\n }\n\n this.#echoEvent.on(eventName, handle)\n\n timeoutId = setTimeout(() => {\n cleanup()\n const error = `API 请求超时: ${action}`\n this.#event.emit('napcat.api_timeout', {\n action,\n echo: echoId,\n timeout,\n })\n reject(new Error(error))\n }, timeout)\n })\n }\n\n /** 构建群对象 */\n #buildGroup<T extends object>(\n group_id: number,\n group_name: string = '',\n extraInfo: T = {} as T,\n forceUpdate = false,\n ): Group & T {\n const cache = this.#groupCache.get(group_id)\n\n if (cache) {\n if (!forceUpdate) {\n return cache as Group & T\n }\n\n clearTimeout((cache as any).__timeout_id__)\n }\n\n const timer = setTimeout(() => this.#groupCache.delete(group_id), 1000 * 60 * 10) // 10 分钟后清除缓存\n\n const group = {\n ...extraInfo,\n group_id,\n group_name,\n napcat: this,\n sign: this.setGroupSign.bind(this, group_id),\n setTitle: this.setGroupSpecialTitle.bind(this, group_id),\n setCard: this.setGroupCard.bind(this, group_id),\n setEssence: this.setEssenceMsg.bind(this),\n delEssence: this.deleteEssenceMsg.bind(this),\n getInfo: this.getGroupInfo.bind(this, group_id),\n getMemberList: this.getGroupMemberList.bind(this, group_id),\n getMemberInfo: this.getGroupMemberInfo.bind(this, group_id),\n recall: this.recallMsg.bind(this),\n ban: this.setGroupBan.bind(this, group_id),\n sendMsg: this.sendGroupMsg.bind(this, group_id),\n pickMember: this.getGroupMemberInfo.bind(this, group_id),\n kick: this.kickGroupMember.bind(this, group_id),\n __timeout_id__: timer,\n }\n\n this.#groupCache.set(group_id, group)\n\n return group\n }\n\n /** 构建好友对象 */\n #buildFriend<T extends object>(\n user_id: number,\n nickname: string = '',\n extraInfo: T = {} as T,\n forceUpdate = false,\n ): Friend & T {\n const cache = this.#friendCache.get(user_id)\n\n const name = nickname || this.#nicknameCache.get(user_id) || cache?.nickname || ''\n this.#nicknameCache.set(user_id, name)\n\n if (cache) {\n if (!forceUpdate) {\n return cache as Friend & T\n }\n\n clearTimeout((cache as any).__timeout_id__)\n }\n\n const id = setTimeout(() => this.#friendCache.delete(user_id), 1000 * 60 * 10) // 10 分钟后清除缓存\n\n const friend = {\n ...extraInfo,\n user_id,\n nickname: name,\n napcat: this,\n delete: this.deleteFriend.bind(this, user_id),\n sendMsg: this.sendPrivateMsg.bind(this, user_id),\n getInfo: this.getStrangerInfo.bind(this, user_id),\n __timeout_id__: id,\n }\n\n this.#friendCache.set(user_id, friend)\n\n return friend\n }\n\n #transformOneBotMessage(message: any[]): RecvElement[] {\n return (message || []).filter((e) => e.type !== 'reply').map((el: any) => ({ type: el.type, ...el.data }))\n }\n\n /** 构建私聊消息事件 */\n #buildPrivateMessageEvent(event: Omit<PrivateMessageEvent, 'message'> & { message: any[] }): PrivateMessageEvent {\n const quote_id: string | null = event.message.find((el: any) => el.type === 'reply')?.data?.id || null\n\n if (event.sender.nickname) {\n this.#nicknameCache.set(event.sender.user_id, event.sender.nickname)\n }\n\n const target = event.target_id\n ? { user_id: event.target_id, nickname: this.#nicknameCache.get(event.target_id) || '' }\n : { user_id: event.sender.user_id, nickname: event.sender.nickname }\n\n return {\n ...event,\n quote_id,\n getQuoteMsg: () => this.getMsg(quote_id) as Promise<PrivateMessageEvent | null>,\n message: this.#transformOneBotMessage(event.message),\n friend: this.#buildFriend(target.user_id, target.nickname),\n reply: (sendable: Arrayable<Sendable>, reply = false) =>\n this.sendPrivateMsg(target.user_id, this.#wrapReply(sendable, event.message_id, reply)),\n }\n }\n\n /** 构建群消息事件对象 */\n #buildGroupMessageEvent(event: Omit<GroupMessageEvent, 'message'> & { message: any[] }): GroupMessageEvent {\n const quote_id: string | null = event.message.find((el: any) => el.type === 'reply')?.data?.id || null\n\n if (event.sender.nickname) {\n this.#nicknameCache.set(event.sender.user_id, event.sender.nickname)\n }\n\n return {\n ...event,\n quote_id,\n getQuoteMsg: () => this.getMsg(quote_id) as Promise<GroupMessageEvent | null>,\n getSenderMemberInfo: this.getGroupMemberInfo.bind(this, event.group_id, event.sender.user_id),\n message: this.#transformOneBotMessage(event.message),\n group: this.#buildGroup(event.group_id, event.group_name || ''),\n recall: this.recallMsg.bind(this, event.message_id),\n addReaction: this.addReaction.bind(this, event.message_id),\n delReaction: this.delReaction.bind(this, event.message_id),\n setEssence: this.setEssenceMsg.bind(this, event.message_id),\n delEssence: this.deleteEssenceMsg.bind(this, event.message_id),\n reply: (sendable: Arrayable<Sendable>, reply = false) =>\n this.sendGroupMsg(event.group_id, this.#wrapReply(sendable, event.message_id, reply)),\n }\n }\n\n /** 绑定内部事件处理器 */\n async #bindInternalEvents(data: any) {\n if (data.echo) {\n this.#echoEvent.emit(`echo#${data.echo}`, data)\n return\n }\n\n if (data.post_type) {\n switch (data.post_type) {\n case 'meta_event': {\n this.logger.trace(`收到 meta_event: ${this.#safeStringify(data)}`)\n\n this.#event.emit('meta_event', data)\n\n if (data.meta_event_type) {\n this.#event.emit(`meta_event.${data.meta_event_type}`, data)\n\n this.logger.trace('收到 meta_event_type: ', data.meta_event_type)\n\n if (data.sub_type) {\n if (data.sub_type === 'connect') {\n const { app_name, app_version, protocol_version } = await this.getVersionInfo()\n const { nickname, user_id } = await this.getLoginInfo()\n\n this.#uin = user_id\n this.#nickname = nickname\n this.#setOnlineStatus(true)\n\n this.#event.emit('napcat.connected', {\n user_id: this.#uin,\n nickname: this.#nickname,\n app_name,\n app_version,\n protocol_version,\n timestamp: data.time * 1000,\n })\n }\n\n this.#event.emit(`meta_event.${data.meta_event_type}.${data.sub_type}`, data)\n }\n }\n\n break\n }\n\n case 'message': {\n if (data.message_type === 'private') {\n this.#stat.recv.private++\n data = this.#buildPrivateMessageEvent(data)\n } else {\n this.#stat.recv.group++\n data = this.#buildGroupMessageEvent(data)\n }\n\n this.#event.emit('message', data)\n\n const msg = this.stringifyMessage(data.message)\n\n const group = data.group ? `${data.group_name}(${data.group_id})` : ''\n const sender = `${data.sender.nickname}(${data.sender.user_id})`\n\n switch (data.message_type) {\n case 'private': {\n this.#event.emit('message.private', data)\n this.#event.emit(`message.private.${data.sub_type}`, data)\n this.logger.trace(`收到私聊消息: ${this.#safeStringify(data)}`)\n this.logger.info(`[私:${sender}] ${msg}`)\n break\n }\n\n case 'group': {\n this.#event.emit('message.group', data)\n this.#event.emit(`message.group.${data.sub_type}`, data)\n this.logger.trace(`收到群消息: ${this.#safeStringify(data)}`)\n this.logger.info(`[群:${group}] ${sender}: ${msg}`)\n break\n }\n\n default: {\n this.logger.debug(`收到未知消息类型: ${this.#safeStringify(data)}`)\n\n break\n }\n }\n\n break\n }\n\n case 'message_sent': {\n if (data.message_type === 'private') {\n this.#stat.send.private++\n data = this.#buildPrivateMessageEvent(data)\n } else {\n this.#stat.send.group++\n data = this.#buildGroupMessageEvent(data)\n }\n\n this.#event.emit('message_sent', data)\n this.logger.trace(`收到 message_sent: ${this.#safeStringify(data)}`)\n\n if (data.message_type) {\n this.#event.emit(`message_sent.${data.message_type}`, data)\n\n if (data.sub_type) {\n this.#event.emit(`message_sent.${data.message_type}.${data.sub_type}`, data)\n }\n\n const msg = this.stringifyMessage(data.message)\n\n if (data.message_type === 'group' && data.group_id) {\n this.logger.info(`[>>>:群:${data.group_name}(${data.group_id})] ${msg}`)\n } else {\n this.logger.info(`[>>>:私:${data.friend.nickname}(${data.friend.user_id})] ${msg}`)\n }\n }\n\n break\n }\n\n case 'notice': {\n this.logger.trace(`收到通知: ${this.#safeStringify(data)}`)\n\n if (!data.notice_type) {\n this.logger.debug(`收到未知通知类型: ${this.#safeStringify(data)}`)\n break\n }\n\n const isNotify = data.notice_type === 'notify'\n const isPoke = data.sub_type === 'poke'\n const isGroup = !!data.group_id\n\n const { notice_type, sub_type } = isNotify\n ? isPoke\n ? { notice_type: isGroup ? 'group' : 'friend', sub_type: 'poke' }\n : NAPCAT_NOTICE_NOTIFY_MAP[data.sub_type] || {}\n : NAPCAT_NOTICE_EVENT_MAP[data.notice_type] || {}\n\n data.original_notice_type = data.notice_type\n data.notice_type = notice_type || data.notice_type\n\n if (data.sub_type && data.sub_type !== sub_type) {\n data.action_type = data.sub_type\n }\n\n data.sub_type = sub_type || data.sub_type\n\n if (isGroup) {\n data.group = this.#buildGroup(data.group_id, data.group_name || '')\n } else {\n data.friend = this.#buildFriend(data.user_id, data.nickname || '')\n }\n\n this.#event.emit('notice', data)\n\n if (notice_type) {\n this.#event.emit(`notice.${notice_type}`, data)\n if (sub_type) {\n this.#event.emit(`notice.${notice_type}.${sub_type}`, data)\n }\n }\n\n break\n }\n\n case 'request': {\n this.logger.trace(`收到请求: ${this.#safeStringify(data)}`)\n\n if (data.request_type === 'friend') {\n data.reject = (reason?: string) =>\n this.api('set_friend_add_request', { flag: data.flag, approve: false, reason })\n data.approve = () => this.api('set_friend_add_request', { flag: data.flag, approve: true })\n }\n\n if (data.request_type === 'group') {\n data.reject = (reason?: string) =>\n this.api('set_group_add_request', { flag: data.flag, approve: false, reason })\n data.approve = () => this.api('set_group_add_request', { flag: data.flag, approve: true })\n }\n\n this.#event.emit('request', data)\n\n if (data.request_type) {\n this.#event.emit(`request.${data.request_type}`, data)\n if (data.sub_type) {\n this.#event.emit(`request.${data.request_type}.${data.sub_type}`, data)\n }\n }\n\n break\n }\n\n default: {\n this.logger.debug(`收到: ${this.#safeStringify(data)}`)\n this.#event.emit(data.post_type, data)\n return\n }\n }\n\n return\n }\n }\n\n stringifyMessage(message: RecvElement[]): string {\n return message\n .map((el) => {\n switch (el.type) {\n case 'text':\n return el.text\n case 'at':\n return `{at:${el.qq}}`\n case 'face':\n return `{face:${el.id}}`\n case 'image':\n return `{image:${el.file},${el.url}}`\n case 'json':\n return `{json:${el.data}}`\n case 'rps':\n case 'dice':\n return `{dice:${el.result}}`\n case 'file':\n case 'video':\n case 'record':\n return `{${el.type}:${el.url}}`\n default:\n return `{${el.type}}`\n }\n })\n .join('')\n }\n\n /** 获取一个群的信息,可以用于发送群消息等操作 */\n async pickGroup(group_id: number, forceUpdate: boolean = false): Promise<GroupWithInfo | null> {\n try {\n const cache = this.#groupCache.get(group_id)\n\n if (cache && !forceUpdate && 'member_count' in cache) {\n return cache as GroupWithInfo\n }\n\n const groupInfo = await this.api<ReturnType<Group['getInfo']>>('get_group_info', { group_id })\n return this.#buildGroup(group_id, groupInfo.group_name, groupInfo, true)\n } catch (err: any) {\n this.logger.warn(`获取群 ${group_id} 信息失败: ${err?.message || err}`)\n return this.#buildGroup(group_id, '-', {}) as GroupWithInfo\n }\n }\n\n /** 获取一个好友的信息,可以用于发送私聊消息等操作 */\n async pickFriend(user_id: number): Promise<FriendWithInfo | null> {\n try {\n const cache = this.#friendCache.get(user_id)\n\n if (cache && 'uin' in cache) {\n return cache as FriendWithInfo\n }\n\n const friendInfo = await this.api<ReturnType<Friend['getInfo']>>('get_stranger_info', { user_id })\n return this.#buildFriend(user_id, friendInfo.nickname, friendInfo, true)\n } catch (err: any) {\n this.logger.warn(`获取好友 ${user_id} 信息失败: ${err?.message || err}`)\n // return this.#buildFriend(user_id, '', {}) as FriendWithInfo\n return this.#buildFriend(user_id, '-', {}) as FriendWithInfo\n }\n }\n\n /**\n * 注册「一次性」事件监听器,支持主类型或者点分子类型\n *\n * 如: `notice`、`message.private`、`request.group.invite` 等\n *\n * 如果需要移除监听器,请调用 `off` 方法或者使用返回的函数\n *\n */\n once<T extends keyof EventMap>(type: T, handler: (event: EventMap[NoInfer<T>]) => void): () => void {\n const onceHandler = (event: EventMap[NoInfer<T>]) => {\n handler(event)\n this.#event.off(type, onceHandler)\n }\n\n this.logger.debug(`注册一次性监听器: ${String(type)}`)\n this.#event.on(type, onceHandler)\n return () => this.off(type, handler)\n }\n\n /**\n * 注册事件监听器,支持主类型或者点分子类型\n *\n * 如: `notice`、`message.private`、`request.group.invite` 等\n *\n * 如果需要移除监听器,请调用 `off` 方法或者使用返回的函数\n */\n on<T extends keyof EventMap>(type: T, handler: (event: EventMap[NoInfer<T>]) => void): () => void {\n this.logger.debug(`注册监听器: ${String(type)}`)\n this.#event.on(type, handler)\n return () => this.off(type, handler)\n }\n\n /**\n * 移除事件监听器\n */\n off<T extends keyof EventMap>(type: T, handler: (event: EventMap[NoInfer<T>]) => void): void {\n this.logger.debug(`移除监听器: ${String(type)}`)\n this.#event.off(type, handler)\n }\n\n /**\n * 调用 NapCat API\n */\n api<T extends any>(action: API | (string & {}), params: Record<string, any> = {}): Promise<T> {\n this.#ensureWsConnection(this.#ws)\n this.logger.debug(`调用 API: ${action},参数: ${JSON.stringify(params)}`)\n const echo = this.#echoId()\n\n try {\n this.#ws.send(JSON.stringify({ echo, action, params }))\n return this.#waitForAction<T>(echo, action)\n } catch (error: any) {\n const errorMsg = error?.message || String(error)\n this.logger.error(`发送 API 请求失败: ${errorMsg}`)\n this.#event.emit('napcat.api_error', {\n action,\n error: errorMsg,\n })\n return Promise.reject(new Error(`发送 API 请求失败: ${errorMsg}`))\n }\n }\n\n /**\n * 给好友名片点赞\n */\n async sendLike(user_id: number, times: number = 1): Promise<any> {\n try {\n await this.api<void>('send_like', { user_id, times })\n return true\n } catch {\n return false\n }\n }\n\n /**\n * 获取好友列表\n */\n async getFriendList(): Promise<(Friend & Record<string, any>)[]> {\n const friends = await this.api<Friend[]>('get_friend_list')\n return friends.map((f) => this.#buildFriend(f.user_id, f.nickname, f))\n }\n\n /**\n * 获取群列表\n */\n async getGroupList(): Promise<(Group & Record<string, any>)[]> {\n const groups = await this.api<Group[]>('get_group_list')\n return groups.map((g) => this.#buildGroup(g.group_id, g.group_name, g))\n }\n\n /**\n * 添加消息回应\n */\n addReaction(message_id: number, id: string): Promise<void> {\n return this.api<void>('set_msg_emoji_like', { message_id, emoji_id: id, set: true })\n }\n\n /**\n * 删除消息回应\n */\n delReaction(message_id: number, id: string): Promise<void> {\n return this.api<void>('set_msg_emoji_like', { message_id, emoji_id: id, set: false })\n }\n\n /**\n * 获取消息\n */\n async getMsg(message_id?: number | string | null): Promise<GroupMessageEvent | PrivateMessageEvent | null> {\n if (!message_id) {\n return null\n }\n\n const msg = await this.api<any>('get_msg', { message_id })\n\n if (msg.message_type === 'private') {\n return this.#buildPrivateMessageEvent(msg)\n } else {\n return this.#buildGroupMessageEvent(msg)\n }\n }\n\n /**\n * 删除好友\n */\n deleteFriend(user_id: number, block: boolean = false, both: boolean = false): Promise<void> {\n return this.api<void>('delete_friend', {\n user_id,\n temp_block: block,\n temp_both_del: both,\n })\n }\n\n /**\n * 设置群成员禁言\n */\n setGroupBan(group_id: number, user_id: number, duration: number): Promise<void> {\n return this.api<void>('set_group_ban', { group_id, user_id, duration })\n }\n\n /**\n * 撤回消息\n */\n recallMsg(message_id: number): Promise<void> {\n return this.api<void>('delete_msg', { message_id })\n }\n\n /**\n * 获取陌生人信息\n */\n getStrangerInfo(user_id: number): Promise<any> {\n return this.api<any>('get_stranger_info', { user_id })\n }\n\n /**\n * 发送私聊消息\n */\n sendPrivateMsg(user_id: number, sendable: Arrayable<Sendable>): Promise<{ message_id: number }> {\n return this.api<{ message_id: number }>('send_private_msg', {\n user_id,\n message: this.normalizeSendable(sendable),\n })\n }\n\n /**\n * 发送群消息\n */\n sendGroupMsg(group_id: number, sendable: Arrayable<Sendable>): Promise<{ message_id: number }> {\n return this.api<{ message_id: number }>('send_group_msg', {\n group_id,\n message: this.normalizeSendable(sendable),\n })\n }\n\n /**\n * 获取群信息\n */\n getGroupInfo(group_id: number): Promise<any> {\n return this.api<any>('get_group_info', { group_id })\n }\n\n /**\n * 群签到\n */\n setGroupSign(group_id: number): Promise<any> {\n return this.api<void>('set_group_sign', { group_id })\n }\n\n /**\n * 设置群精华消息\n */\n setEssenceMsg(message_id: number): Promise<void> {\n return this.api<void>('set_essence_msg', { message_id })\n }\n\n /**\n * 删除群精华消息\n */\n deleteEssenceMsg(message_id: number): Promise<void> {\n return this.api<void>('delete_essence_msg', { message_id })\n }\n\n /**\n * 设置群成员名片\n */\n setGroupCard(group_id: number, user_id: number, card: string): Promise<void> {\n return this.api<void>('set_group_card', { group_id, user_id, card })\n }\n\n /**\n * 设置群成员专属头衔\n */\n setGroupSpecialTitle(group_id: number, user_id: number, title: string): Promise<void> {\n return this.api<void>('set_group_special_title', { group_id, user_id, title })\n }\n\n /**\n * 获取群成员列表\n */\n getGroupMemberList(group_id: number): Promise<GroupMemberInfo[]> {\n return this.api<GroupMemberInfo[]>('get_group_member_list', { group_id })\n }\n\n /**\n * 获取群成员信息\n */\n getGroupMemberInfo(group_id: number, user_id: number): Promise<GroupMemberInfo> {\n return this.api<GroupMemberInfo>('get_group_member_info', { group_id, user_id })\n }\n\n /**\n * 踢出群成员\n */\n kickGroupMember(group_id: number, user_id: number, reject_add_request: boolean = false): Promise<void> {\n return this.api<void>('set_group_kick', { group_id, user_id, reject_add_request })\n }\n\n /**\n * 机器人是否在线\n */\n isOnline(): boolean {\n return this.#ws?.readyState === WebSocket.OPEN && this.#online\n }\n\n /**\n * 计算 GTK 值\n */\n getGTk(pskey: string): number {\n let gkt = 5381\n for (let i = 0, len = pskey.length; i < len; ++i) {\n gkt += (gkt << 5) + pskey.charCodeAt(i)\n }\n return gkt & 0x7fffffff\n }\n\n /**\n * 获取 NapCat 原始 Cookie 相关信息\n */\n getNapCatCookies(domain: string): Promise<{ cookies: string; bkn: string }> {\n return this.api<{ cookies: string; bkn: string }>('get_cookies', { domain })\n }\n\n /**\n * 获取版本信息\n */\n getVersionInfo(): Promise<{ app_name: string; protocol_version: string; app_version: string }> {\n return this.api<{ app_name: string; protocol_version: string; app_version: string }>('get_version_info')\n }\n\n /**\n * 获取登录信息\n */\n getLoginInfo(): Promise<{ user_id: number; nickname: string }> {\n return this.api<{ user_id: number; nickname: string }>('get_login_info')\n }\n\n /**\n * 获取 Cookie 相关信息\n */\n async getCookie(domain: string): Promise<{\n uin: number\n pskey: string\n skey: string\n gtk: string\n bkn: string\n cookie: string\n legacyCookie: string\n }> {\n const cache = this.#cookieCache.get(domain)\n\n if (cache) return cache\n\n const { cookies: cookieString, bkn } = await this.getNapCatCookies(domain)\n\n const skey = cookieString.match(/skey=([^;]*)/)?.[1] || ''\n const pskey = cookieString.match(/p_skey=([^;]*)/)?.[1] || ''\n const gtk = this.getGTk(pskey)\n\n const returns = {\n pskey,\n skey,\n uin: this.uin,\n gtk: String(gtk),\n bkn,\n cookie: `uin=${this.uin}; skey=${skey}; p_uin=${this.uin}; p_skey=${pskey};`,\n legacyCookie: `uin=o${this.uin}; skey=${skey}; p_uin=o${this.uin}; p_skey=${pskey};`,\n }\n\n this.#cookieCache.set(domain, returns)\n\n // 1 小时后清除 Cookie 缓存\n setTimeout(\n () => {\n this.#cookieCache.delete(domain)\n },\n 1000 * 60 * 60,\n )\n\n return returns\n }\n\n /**\n * 通过域名获取 Pskey\n */\n async getPskey(domain: string): Promise<string> {\n const { pskey } = await this.getCookie(domain)\n return pskey\n }\n\n /**\n * 获取 Bkn 值\n */\n async getBkn(): Promise<string> {\n const { bkn } = await this.getCookie('vip.qq.com')\n return bkn\n }\n\n /** 计算重连延迟(指数退避) */\n #getReconnectDelay(): number {\n const { reconnectInterval, maxReconnectInterval } = this.#config\n const delay = reconnectInterval * Math.pow(2, this.#reconnectAttempts)\n return Math.min(delay, maxReconnectInterval)\n }\n\n /** 清除重连定时器 */\n #clearReconnectTimer(): void {\n if (this.#reconnectTimer) {\n clearTimeout(this.#reconnectTimer)\n this.#reconnectTimer = null\n }\n }\n\n /** 调度重连 */\n #scheduleReconnect(): void {\n const { reconnect, maxReconnectAttempts } = this.#config\n\n if (!reconnect || this.#manualClose) {\n return\n }\n\n if (this.#reconnectAttempts >= maxReconnectAttempts) {\n this.logger.error(`重连失败,已达到最大重连次数 ${maxReconnectAttempts}`)\n this.#event.emit('napcat.reconnect_failed', {\n attempt: this.#reconnectAttempts,\n maxAttempts: maxReconnectAttempts,\n })\n return\n }\n\n this.#reconnecting = true\n this.#reconnectAttempts++\n\n const delay = this.#getReconnectDelay()\n\n this.logger.info(`将在 ${delay}ms 后尝试第 ${this.#reconnectAttempts} 次重连`)\n this.#event.emit('napcat.reconnecting', {\n attempt: this.#reconnectAttempts,\n maxAttempts: maxReconnectAttempts,\n delay,\n })\n\n this.#clearReconnectTimer()\n this.#reconnectTimer = setTimeout(() => {\n this.#connect().catch((err) => {\n this.logger.error(`重连失败: ${err?.message || err}`)\n })\n }, delay)\n }\n\n /** 建立 WebSocket 连接 */\n #connect(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const ws = new WebSocket(this.#buildWsUrl())\n\n ws.onmessage = (event) => {\n const data = (() => {\n try {\n return JSON.parse(event.data)\n } catch {\n return null\n }\n })() as any\n\n if (!data) {\n this.logger.debug(`收到非 JSON 消息: ${event.data}`)\n return\n }\n\n this.#event.emit('ws.message', data)\n this.#bindInternalEvents(data)\n }\n\n ws.onclose = () => {\n this.#setOnlineStatus(false)\n this.logger.debug('WebSocket 已断开连接')\n this.#event.emit('ws.close')\n\n // 发出 napcat.disconnected 事件\n this.#event.emit('napcat.disconnected', {\n manual: this.#manualClose,\n })\n\n // 如果不是手动关闭,尝试重连\n if (!this.#manualClose) {\n this.#scheduleReconnect()\n }\n }\n\n ws.onerror = (event) => {\n this.#setOnlineStatus(false)\n const msg = `WebSocket 发生错误,请确认 NapCat 服务已启动,且端口、访问令牌正确`\n this.logger.debug(msg)\n this.#event.emit('ws.error', event)\n\n // 发出 napcat.disconnected 事件(错误导致的断开)\n this.#event.emit('napcat.disconnected', {\n manual: false,\n reason: msg,\n })\n\n // 如果是首次连接,则 reject\n if (!this.#reconnecting) {\n reject(new Error(msg))\n }\n }\n\n ws.onopen = () => {\n this.logger.info(`WebSocket 已连接,NapCat SDK 实例已启动`)\n this.#event.emit('ws.open')\n\n // 重连成功\n if (this.#reconnecting) {\n this.logger.info(`第 ${this.#reconnectAttempts} 次重连成功`)\n this.#event.emit('napcat.reconnected', {\n attempt: this.#reconnectAttempts,\n })\n this.#reconnecting = false\n this.#reconnectAttempts = 0\n }\n\n resolve()\n }\n\n this.#ws = ws\n })\n }\n\n /** 启动 NapCat SDK 实例,建立 WebSocket 连接 */\n async run(): Promise<void> {\n const { logger: _, token: __, ...config } = this.#config\n\n this.logger.debug(`启动配置: ${JSON.stringify(config)}`)\n\n this.#manualClose = false\n return this.#connect()\n }\n\n /** 销毁 NapCat SDK 实例,关闭 WebSocket 连接 */\n close(): void {\n this.logger.info('正在关闭 NapCat SDK 实例...')\n this.#event.emit('napcat.closing')\n\n this.#manualClose = true\n this.#clearReconnectTimer()\n\n if (this.#ws) {\n this.#ws.close()\n this.#ws = null\n this.logger.info('NapCat SDK 实例已销毁')\n } else {\n this.logger.warn('NapCat SDK 实例未初始化')\n }\n\n // 重置重连状态\n this.#reconnecting = false\n this.#reconnectAttempts = 0\n }\n}\n\n// ==================== 通知事件映射 ====================\n\n/**\n * NapCat 通知类型映射表(notify 类型)\n * @description 将 NapCat 特有的通知类型映射到标准的 notice_type 和 sub_type\n */\nconst NAPCAT_NOTICE_NOTIFY_MAP: Record<string, { notice_type: string; sub_type: string }> = {\n input_status: {\n notice_type: 'friend',\n sub_type: 'input',\n },\n profile_like: {\n notice_type: 'friend',\n sub_type: 'like',\n },\n title: {\n notice_type: 'group',\n sub_type: 'title',\n },\n}\n\n/**\n * NapCat 通知事件映射表(notice 类型)\n * @description 将 NapCat 的原始通知事件类型映射到标准的 notice_type 和 sub_type\n */\nconst NAPCAT_NOTICE_EVENT_MAP: Record<string, { notice_type: string; sub_type: string }> = {\n friend_add: {\n notice_type: 'friend',\n sub_type: 'increase',\n },\n friend_recall: {\n notice_type: 'friend',\n sub_type: 'recall',\n },\n offline_file: {\n notice_type: 'friend',\n sub_type: 'offline_file',\n },\n client_status: {\n notice_type: 'client',\n sub_type: 'status',\n },\n group_admin: {\n notice_type: 'group',\n sub_type: 'admin',\n },\n group_ban: {\n notice_type: 'group',\n sub_type: 'ban',\n },\n group_card: {\n notice_type: 'group',\n sub_type: 'card',\n },\n group_upload: {\n notice_type: 'group',\n sub_type: 'upload',\n },\n group_decrease: {\n notice_type: 'group',\n sub_type: 'decrease',\n },\n group_increase: {\n notice_type: 'group',\n sub_type: 'increase',\n },\n group_msg_emoji_like: {\n notice_type: 'group',\n sub_type: 'reaction',\n },\n essence: {\n notice_type: 'group',\n sub_type: 'essence',\n },\n group_recall: {\n notice_type: 'group',\n sub_type: 'recall',\n },\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,MAAa,aAAmB;AAEhC,MAAaA,kBAA0B;CACrC,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACP,OAAO;CACR;AAED,MAAM,sCAAuB,OAAO,qBAAI,IAAI,MAAM,EAAC,oBAAoB,CAAC,GAAG;AAE3E,MAAaC,iBAAyB;CACpC,QAAQ,GAAG,SAAgB,QAAQ,MAAM,GAAG,MAAM,CAAC,4BAAa,aAAa,UAAU,IAAI,GAAG,KAAK;CACnG,OAAO,GAAG,SAAgB,QAAQ,KAAK,GAAG,MAAM,CAAC,4BAAa,gBAAgB,SAAS,IAAI,GAAG,KAAK;CACnG,OAAO,GAAG,SAAgB,QAAQ,KAAK,GAAG,MAAM,CAAC,4BAAa,eAAe,SAAS,IAAI,GAAG,KAAK;CAClG,QAAQ,GAAG,SAAgB,QAAQ,MAAM,GAAG,MAAM,CAAC,4BAAa,cAAc,UAAU,IAAI,GAAG,KAAK;CACpG,QAAQ,GAAG,SAAgB,QAAQ,MAAM,GAAG,MAAM,CAAC,4BAAa,OAAO,UAAU,IAAI,GAAG,KAAK;CAC9F;;;;;;;;;AEtBD,SAAS,cAAgD,MAAS,MAAsB;AACtF,QAAO;EAAE;EAAM,GAAG;EAAM;;;;;AAM1B,MAAa,UAAU;CAErB,OAAO,SAA8B,cAAc,QAAQ,EAAE,MAAM,CAAC;CAEpE,KAAK,OAAoD,cAAc,MAAM,EAAE,IAAI,CAAC;CAEpF,OAAO,OAA4B,cAAc,QAAQ,EAAE,IAAI,CAAC;CAEhE,QAAQ,OAA4B,cAAc,SAAS,EAAE,IAAI,CAAC;CAElE,QACE,MACA,YACgB;EAChB,MAAM,UAAU,SAAS,SAAS;AAWlC,SAAO,cAAc,SAAS;GAAE,MAR9B,gBAAgB,SACZ,YAAY,KAAK,SAAS,SAAS,KACnC,OAAO,SAAS,WACd,UACE,WAAW,KAAK,QAAQ,sBAAsB,GAAG,KACjD,OACF;GAEyC,GAAG;GAAS,CAAC;;CAGhE,SAAS,MAAc,YACrB,cAAc,UAAU;EAAE;EAAM,GAAG;EAAS,CAAC;CAE/C,QAAQ,MAAc,YACpB,cAAc,SAAS;EAAE;EAAM,GAAG;EAAS,CAAC;CAE9C,QAAQ,YACN,cAAc,SAAS,EAAE,GAAG,SAAS,CAAC;CAExC,QAAQ,OAA4B,cAAc,SAAS,EAAE,IAAI,CAAC;CAElE,UAAU,MAAsB,OAA4B,cAAc,WAAW;EAAE;EAAI,UAAU;EAAM,CAAC;CAE5G,YAAyB,cAAc,QAAQ,EAAE,CAAC;CAElD,QAAQ,UAAoD,OAC1D,cAAc,SAAS;EAAE;EAAU;EAAI,CAAC;CAE1C,cACE,OACA,OACA,KACA,YACgB,cAAc,SAAS;EAAE,UAAU;EAAU;EAAK;EAAO;EAAO,GAAG;EAAS,CAAC;CAE/F,OAAO,YAAsE,cAAc,QAAQ,EAAE,GAAG,SAAS,CAAC;CAElH,UAAU,OAA4B,cAAc,WAAW,EAAE,IAAI,CAAC;CAEtE,OAAO,SAA8B,cAAc,QAAQ,EAAE,MAAM,CAAC;CAEpE,OAAO,MAAc,YACnB,cAAc,QAAQ;EAAE;EAAM,GAAG;EAAS,CAAC;CAE7C,gBAA6B,cAAc,YAAY,EAAE,CAAC;CAE1D,gBAA6B,cAAc,YAAY,EAAE,CAAC;CAC3D;;;;AC/CD,MAAaC,OAAeC;AAC5B,MAAaC,UAAkBC;AAE/B,MAAMC,yBAAiE;CACrE,UAAU;CACV,MAAM;CACN,MAAM;CACN,QAAQ;CACR,OAAO;CACP,WAAW;CACX,mBAAmB;CACnB,sBAAsB;CACtB,sBAAsB;CACvB;AAED,IAAa,SAAb,MAAoB;;CAElB,MAAwB;;CAExB,4BAAqE;;CAErE,gCAAqD;;CAErD,OAAe;;CAEf,YAAoB;;CAEpB,UAAmB;;CAEnB,iCAAiB,IAAI,KAAqB;;CAE1C,+BAAe,IAAI,KAAqB;;CAExC,8BAAc,IAAI,KAAoB;;CAEtC,QAAc;EACZ,YAAY,KAAK,KAAK;EACtB,MAAM;GAAE,OAAO;GAAG,SAAS;GAAG;EAC9B,MAAM;GAAE,OAAO;GAAG,SAAS;GAAG;EAC/B;;CAED,+BAAe,IAAI,KAWhB;;CAEH,qBAA6B;;CAE7B,kBAAyC;;CAEzC,gBAAyB;;CAEzB,eAAwB;CAExB,OAAc,kBAA0B;CACxC,OAAc,iBAAyB;CAEvC,YAAY,AAAiBC,UAAyB,EAAE,EAAE;EAA7B;;;CAG7B,IAAI,OAAa;AACf,SAAO,MAAKC;;;CAId,KAAIC,SAAmC;AACrC,SAAO;GACL,UAAU,KAAK,QAAQ,YAAY,uBAAuB;GAC1D,MAAM,KAAK,QAAQ,QAAQ,uBAAuB;GAClD,MAAM,KAAK,QAAQ,QAAQ,uBAAuB;GAClD,QAAQ,KAAK,QAAQ,UAAU,uBAAuB;GACtD,OAAO,KAAK,QAAQ,SAAS,uBAAuB;GACpD,WAAW,KAAK,QAAQ,aAAa,uBAAuB;GAC5D,mBAAmB,KAAK,QAAQ,qBAAqB,uBAAuB;GAC5E,sBAAsB,KAAK,QAAQ,wBAAwB,uBAAuB;GAClF,sBAAsB,KAAK,QAAQ,wBAAwB,uBAAuB;GACnF;;;CAIH,IAAI,KAAgB;AAClB,MAAI,CAAC,MAAKC,IAAK;AACb,QAAK,OAAO,MAAM,gBAAgB;AAClC,SAAM,IAAI,MAAM,gBAAgB;;AAGlC,SAAO,MAAKA;;;CAId,IAAI,SAAiB;AACnB,SAAO,MAAKD,OAAQ;;;CAItB,IAAI,UAA0B;AAC5B,SAAO;;;;;;;CAQT,IAAI,UAAkB;AACpB,SAAO,KAAK;;;;;CAMd,IAAI,MAAc;AAChB,SAAO,MAAKE;;;;;CAMd,IAAI,WAAmB;AACrB,SAAO,MAAKC;;;CAId,UAAU;AACR,SAAOC,oBAAO,YAAY,GAAG,CAAC,SAAS,MAAM;;;CAI/C,cAAsB;EACpB,MAAM,EAAE,UAAU,MAAM,MAAM,UAAU,MAAKJ;AAC7C,SAAO,GAAG,SAAS,KAAK,KAAK,GAAG,KAAK,gBAAgB;;;CAIvD,WAAW,UAA+B,YAAqB,OAA6B;EAC1F,MAAM,eAAe,OAAO,aAAa,WAAW,CAAC,SAAS,GAAG,CAAC,SAAS,CAAC,MAAM;AAElF,MAAI,SAAS,WACX,QAAO,CAAC,QAAQ,MAAM,OAAO,WAAW,CAAC,EAAE,GAAG,aAAa;AAG7D,SAAO;;;CAIT,oBAAoB,IAA+C;AACjE,MAAI,CAAC,IAAI;AACP,QAAK,OAAO,MAAM,gBAAgB;AAClC,SAAM,IAAI,MAAM,gBAAgB;;AAGlC,MAAI,GAAG,eAAe,UAAU,MAAM;AACpC,QAAK,OAAO,MAAM,gBAAgB;AAClC,SAAM,IAAI,MAAM,gBAAgB;;;;CAKpC,eAAe,KAAkB;EAC/B,MAAM,uBAAO,IAAI,SAAS;AAC1B,SAAO,KAAK,UAAU,MAAM,KAAK,UAAU;AAEzC,OAAI,QAAQ,iBACV;AAGF,OAAI,OAAO,UAAU,WACnB;AAGF,OAAI,QAAQ,SACV;AAGF,OAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,QAAI,KAAK,IAAI,MAAM,CACjB,QAAO;AAET,SAAK,IAAI,MAAM;;AAEjB,UAAO;IACP;;;CAIJ,iBAAiB,QAAuB;AACtC,MAAI,MAAKK,WAAY,OACnB;EAGF,MAAM,YAAY,MAAKA;AACvB,QAAKA,SAAU;AAEf,MAAI,UAAU,CAAC,WAAW;AACxB,QAAK,OAAO,KAAK,UAAU,MAAKF,SAAU,GAAG,MAAKD,IAAK,GAAG;AAC1D,SAAKI,MAAO,KAAK,iBAAiB;IAChC,SAAS,MAAKJ;IACd,UAAU,MAAKC;IAChB,CAAC;aACO,CAAC,UAAU,WAAW;AAC/B,QAAK,OAAO,KAAK,UAAU,MAAKA,SAAU,GAAG,MAAKD,IAAK,GAAG;AAC1D,SAAKI,MAAO,KAAK,kBAAkB;IACjC,SAAS,MAAKJ;IACd,UAAU,MAAKC;IAChB,CAAC;;;;CAKN,kBAAkB,KAAqD;AACrE,SAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,SAAS;AACjC,OAAI,OAAO,SAAS,SAClB,QAAO;IAAE,MAAM;IAAQ,MAAM,EAAE,MAAM,MAAM;IAAE;AAE/C,OAAI,KAAK,SAAS,KAChB,QAAO;IAAE,MAAM;IAAM,MAAM,EAAE,IAAI,OAAO,KAAK,GAAG,EAAE;IAAE;GAEtD,MAAM,EAAE,MAAM,GAAG,SAAS;AAC1B,UAAO;IAAE;IAAM;IAAM;IACrB;;;CAIJ,eAA8B,QAAgB,QAAgB,UAAkB,KAAQ;EACtF,MAAM,YAAY,QAAQ;AAE1B,SAAO,IAAI,SAAY,SAAS,WAAW;GACzC,IAAII,YAAmC;GAEvC,MAAM,gBAAgB;AACpB,QAAI,WAAW;AACb,kBAAa,UAAU;AACvB,iBAAY;;AAEd,UAAKC,UAAW,IAAI,WAAW,OAAO;;GAGxC,MAAM,UAAU,SAAc;AAC5B,QAAI,CAAC,QAAQ,KAAK,SAAS,OAAQ;AAEnC,aAAS;AAET,QAAI,KAAK,YAAY,EACnB,SAAQ,KAAK,KAAU;SAClB;KACL,MAAM,QAAQ,WAAW,KAAK;AAC9B,WAAKF,MAAO,KAAK,oBAAoB;MACnC;MACA,OAAO,KAAK,WAAW;MACvB,SAAS,KAAK;MACf,CAAC;AACF,YAAO,IAAI,MAAM,MAAM,CAAC;;;AAI5B,SAAKE,UAAW,GAAG,WAAW,OAAO;AAErC,eAAY,iBAAiB;AAC3B,aAAS;IACT,MAAM,QAAQ,aAAa;AAC3B,UAAKF,MAAO,KAAK,sBAAsB;KACrC;KACA,MAAM;KACN;KACD,CAAC;AACF,WAAO,IAAI,MAAM,MAAM,CAAC;MACvB,QAAQ;IACX;;;CAIJ,YACE,UACA,aAAqB,IACrB,YAAe,EAAE,EACjB,cAAc,OACH;EACX,MAAM,QAAQ,MAAKG,WAAY,IAAI,SAAS;AAE5C,MAAI,OAAO;AACT,OAAI,CAAC,YACH,QAAO;AAGT,gBAAc,MAAc,eAAe;;EAG7C,MAAM,QAAQ,iBAAiB,MAAKA,WAAY,OAAO,SAAS,EAAE,MAAO,KAAK,GAAG;EAEjF,MAAM,QAAQ;GACZ,GAAG;GACH;GACA;GACA,QAAQ;GACR,MAAM,KAAK,aAAa,KAAK,MAAM,SAAS;GAC5C,UAAU,KAAK,qBAAqB,KAAK,MAAM,SAAS;GACxD,SAAS,KAAK,aAAa,KAAK,MAAM,SAAS;GAC/C,YAAY,KAAK,cAAc,KAAK,KAAK;GACzC,YAAY,KAAK,iBAAiB,KAAK,KAAK;GAC5C,SAAS,KAAK,aAAa,KAAK,MAAM,SAAS;GAC/C,eAAe,KAAK,mBAAmB,KAAK,MAAM,SAAS;GAC3D,eAAe,KAAK,mBAAmB,KAAK,MAAM,SAAS;GAC3D,QAAQ,KAAK,UAAU,KAAK,KAAK;GACjC,KAAK,KAAK,YAAY,KAAK,MAAM,SAAS;GAC1C,SAAS,KAAK,aAAa,KAAK,MAAM,SAAS;GAC/C,YAAY,KAAK,mBAAmB,KAAK,MAAM,SAAS;GACxD,MAAM,KAAK,gBAAgB,KAAK,MAAM,SAAS;GAC/C,gBAAgB;GACjB;AAED,QAAKA,WAAY,IAAI,UAAU,MAAM;AAErC,SAAO;;;CAIT,aACE,SACA,WAAmB,IACnB,YAAe,EAAE,EACjB,cAAc,OACF;EACZ,MAAM,QAAQ,MAAKC,YAAa,IAAI,QAAQ;EAE5C,MAAMC,SAAO,YAAY,MAAKC,cAAe,IAAI,QAAQ,IAAI,OAAO,YAAY;AAChF,QAAKA,cAAe,IAAI,SAASD,OAAK;AAEtC,MAAI,OAAO;AACT,OAAI,CAAC,YACH,QAAO;AAGT,gBAAc,MAAc,eAAe;;EAG7C,MAAM,KAAK,iBAAiB,MAAKD,YAAa,OAAO,QAAQ,EAAE,MAAO,KAAK,GAAG;EAE9E,MAAM,SAAS;GACb,GAAG;GACH;GACA,UAAUC;GACV,QAAQ;GACR,QAAQ,KAAK,aAAa,KAAK,MAAM,QAAQ;GAC7C,SAAS,KAAK,eAAe,KAAK,MAAM,QAAQ;GAChD,SAAS,KAAK,gBAAgB,KAAK,MAAM,QAAQ;GACjD,gBAAgB;GACjB;AAED,QAAKD,YAAa,IAAI,SAAS,OAAO;AAEtC,SAAO;;CAGT,wBAAwB,SAA+B;AACrD,UAAQ,WAAW,EAAE,EAAE,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,KAAK,QAAa;GAAE,MAAM,GAAG;GAAM,GAAG,GAAG;GAAM,EAAE;;;CAI5G,0BAA0B,OAAuF;EAC/G,MAAMG,WAA0B,MAAM,QAAQ,MAAM,OAAY,GAAG,SAAS,QAAQ,EAAE,MAAM,MAAM;AAElG,MAAI,MAAM,OAAO,SACf,OAAKD,cAAe,IAAI,MAAM,OAAO,SAAS,MAAM,OAAO,SAAS;EAGtE,MAAM,SAAS,MAAM,YACjB;GAAE,SAAS,MAAM;GAAW,UAAU,MAAKA,cAAe,IAAI,MAAM,UAAU,IAAI;GAAI,GACtF;GAAE,SAAS,MAAM,OAAO;GAAS,UAAU,MAAM,OAAO;GAAU;AAEtE,SAAO;GACL,GAAG;GACH;GACA,mBAAmB,KAAK,OAAO,SAAS;GACxC,SAAS,MAAKE,uBAAwB,MAAM,QAAQ;GACpD,QAAQ,MAAKC,YAAa,OAAO,SAAS,OAAO,SAAS;GAC1D,QAAQ,UAA+B,QAAQ,UAC7C,KAAK,eAAe,OAAO,SAAS,MAAKC,UAAW,UAAU,MAAM,YAAY,MAAM,CAAC;GAC1F;;;CAIH,wBAAwB,OAAmF;EACzG,MAAMH,WAA0B,MAAM,QAAQ,MAAM,OAAY,GAAG,SAAS,QAAQ,EAAE,MAAM,MAAM;AAElG,MAAI,MAAM,OAAO,SACf,OAAKD,cAAe,IAAI,MAAM,OAAO,SAAS,MAAM,OAAO,SAAS;AAGtE,SAAO;GACL,GAAG;GACH;GACA,mBAAmB,KAAK,OAAO,SAAS;GACxC,qBAAqB,KAAK,mBAAmB,KAAK,MAAM,MAAM,UAAU,MAAM,OAAO,QAAQ;GAC7F,SAAS,MAAKE,uBAAwB,MAAM,QAAQ;GACpD,OAAO,MAAKG,WAAY,MAAM,UAAU,MAAM,cAAc,GAAG;GAC/D,QAAQ,KAAK,UAAU,KAAK,MAAM,MAAM,WAAW;GACnD,aAAa,KAAK,YAAY,KAAK,MAAM,MAAM,WAAW;GAC1D,aAAa,KAAK,YAAY,KAAK,MAAM,MAAM,WAAW;GAC1D,YAAY,KAAK,cAAc,KAAK,MAAM,MAAM,WAAW;GAC3D,YAAY,KAAK,iBAAiB,KAAK,MAAM,MAAM,WAAW;GAC9D,QAAQ,UAA+B,QAAQ,UAC7C,KAAK,aAAa,MAAM,UAAU,MAAKD,UAAW,UAAU,MAAM,YAAY,MAAM,CAAC;GACxF;;;CAIH,OAAME,mBAAoB,MAAW;AACnC,MAAI,KAAK,MAAM;AACb,SAAKV,UAAW,KAAK,QAAQ,KAAK,QAAQ,KAAK;AAC/C;;AAGF,MAAI,KAAK,WAAW;AAClB,WAAQ,KAAK,WAAb;IACE,KAAK;AACH,UAAK,OAAO,MAAM,kBAAkB,MAAKW,cAAe,KAAK,GAAG;AAEhE,WAAKb,MAAO,KAAK,cAAc,KAAK;AAEpC,SAAI,KAAK,iBAAiB;AACxB,YAAKA,MAAO,KAAK,cAAc,KAAK,mBAAmB,KAAK;AAE5D,WAAK,OAAO,MAAM,wBAAwB,KAAK,gBAAgB;AAE/D,UAAI,KAAK,UAAU;AACjB,WAAI,KAAK,aAAa,WAAW;QAC/B,MAAM,EAAE,UAAU,aAAa,qBAAqB,MAAM,KAAK,gBAAgB;QAC/E,MAAM,EAAE,UAAU,YAAY,MAAM,KAAK,cAAc;AAEvD,cAAKJ,MAAO;AACZ,cAAKC,WAAY;AACjB,cAAKiB,gBAAiB,KAAK;AAE3B,cAAKd,MAAO,KAAK,oBAAoB;SACnC,SAAS,MAAKJ;SACd,UAAU,MAAKC;SACf;SACA;SACA;SACA,WAAW,KAAK,OAAO;SACxB,CAAC;;AAGJ,aAAKG,MAAO,KAAK,cAAc,KAAK,gBAAgB,GAAG,KAAK,YAAY,KAAK;;;AAIjF;IAGF,KAAK,WAAW;AACd,SAAI,KAAK,iBAAiB,WAAW;AACnC,YAAKP,KAAM,KAAK;AAChB,aAAO,MAAKsB,yBAA0B,KAAK;YACtC;AACL,YAAKtB,KAAM,KAAK;AAChB,aAAO,MAAKuB,uBAAwB,KAAK;;AAG3C,WAAKhB,MAAO,KAAK,WAAW,KAAK;KAEjC,MAAM,MAAM,KAAK,iBAAiB,KAAK,QAAQ;KAE/C,MAAM,QAAQ,KAAK,QAAQ,GAAG,KAAK,WAAW,GAAG,KAAK,SAAS,KAAK;KACpE,MAAM,SAAS,GAAG,KAAK,OAAO,SAAS,GAAG,KAAK,OAAO,QAAQ;AAE9D,aAAQ,KAAK,cAAb;MACE,KAAK;AACH,aAAKA,MAAO,KAAK,mBAAmB,KAAK;AACzC,aAAKA,MAAO,KAAK,mBAAmB,KAAK,YAAY,KAAK;AAC1D,YAAK,OAAO,MAAM,WAAW,MAAKa,cAAe,KAAK,GAAG;AACzD,YAAK,OAAO,KAAK,MAAM,OAAO,IAAI,MAAM;AACxC;MAGF,KAAK;AACH,aAAKb,MAAO,KAAK,iBAAiB,KAAK;AACvC,aAAKA,MAAO,KAAK,iBAAiB,KAAK,YAAY,KAAK;AACxD,YAAK,OAAO,MAAM,UAAU,MAAKa,cAAe,KAAK,GAAG;AACxD,YAAK,OAAO,KAAK,MAAM,MAAM,IAAI,OAAO,IAAI,MAAM;AAClD;MAGF;AACE,YAAK,OAAO,MAAM,aAAa,MAAKA,cAAe,KAAK,GAAG;AAE3D;;AAIJ;;IAGF,KAAK;AACH,SAAI,KAAK,iBAAiB,WAAW;AACnC,YAAKpB,KAAM,KAAK;AAChB,aAAO,MAAKsB,yBAA0B,KAAK;YACtC;AACL,YAAKtB,KAAM,KAAK;AAChB,aAAO,MAAKuB,uBAAwB,KAAK;;AAG3C,WAAKhB,MAAO,KAAK,gBAAgB,KAAK;AACtC,UAAK,OAAO,MAAM,oBAAoB,MAAKa,cAAe,KAAK,GAAG;AAElE,SAAI,KAAK,cAAc;AACrB,YAAKb,MAAO,KAAK,gBAAgB,KAAK,gBAAgB,KAAK;AAE3D,UAAI,KAAK,SACP,OAAKA,MAAO,KAAK,gBAAgB,KAAK,aAAa,GAAG,KAAK,YAAY,KAAK;MAG9E,MAAM,MAAM,KAAK,iBAAiB,KAAK,QAAQ;AAE/C,UAAI,KAAK,iBAAiB,WAAW,KAAK,SACxC,MAAK,OAAO,KAAK,UAAU,KAAK,WAAW,GAAG,KAAK,SAAS,KAAK,MAAM;UAEvE,MAAK,OAAO,KAAK,UAAU,KAAK,OAAO,SAAS,GAAG,KAAK,OAAO,QAAQ,KAAK,MAAM;;AAItF;IAGF,KAAK,UAAU;AACb,UAAK,OAAO,MAAM,SAAS,MAAKa,cAAe,KAAK,GAAG;AAEvD,SAAI,CAAC,KAAK,aAAa;AACrB,WAAK,OAAO,MAAM,aAAa,MAAKA,cAAe,KAAK,GAAG;AAC3D;;KAGF,MAAM,WAAW,KAAK,gBAAgB;KACtC,MAAM,SAAS,KAAK,aAAa;KACjC,MAAM,UAAU,CAAC,CAAC,KAAK;KAEvB,MAAM,EAAE,aAAa,aAAa,WAC9B,SACE;MAAE,aAAa,UAAU,UAAU;MAAU,UAAU;MAAQ,GAC/D,yBAAyB,KAAK,aAAa,EAAE,GAC/C,wBAAwB,KAAK,gBAAgB,EAAE;AAEnD,UAAK,uBAAuB,KAAK;AACjC,UAAK,cAAc,eAAe,KAAK;AAEvC,SAAI,KAAK,YAAY,KAAK,aAAa,SACrC,MAAK,cAAc,KAAK;AAG1B,UAAK,WAAW,YAAY,KAAK;AAEjC,SAAI,QACF,MAAK,QAAQ,MAAKF,WAAY,KAAK,UAAU,KAAK,cAAc,GAAG;SAEnE,MAAK,SAAS,MAAKF,YAAa,KAAK,SAAS,KAAK,YAAY,GAAG;AAGpE,WAAKT,MAAO,KAAK,UAAU,KAAK;AAEhC,SAAI,aAAa;AACf,YAAKA,MAAO,KAAK,UAAU,eAAe,KAAK;AAC/C,UAAI,SACF,OAAKA,MAAO,KAAK,UAAU,YAAY,GAAG,YAAY,KAAK;;AAI/D;;IAGF,KAAK;AACH,UAAK,OAAO,MAAM,SAAS,MAAKa,cAAe,KAAK,GAAG;AAEvD,SAAI,KAAK,iBAAiB,UAAU;AAClC,WAAK,UAAU,WACb,KAAK,IAAI,0BAA0B;OAAE,MAAM,KAAK;OAAM,SAAS;OAAO;OAAQ,CAAC;AACjF,WAAK,gBAAgB,KAAK,IAAI,0BAA0B;OAAE,MAAM,KAAK;OAAM,SAAS;OAAM,CAAC;;AAG7F,SAAI,KAAK,iBAAiB,SAAS;AACjC,WAAK,UAAU,WACb,KAAK,IAAI,yBAAyB;OAAE,MAAM,KAAK;OAAM,SAAS;OAAO;OAAQ,CAAC;AAChF,WAAK,gBAAgB,KAAK,IAAI,yBAAyB;OAAE,MAAM,KAAK;OAAM,SAAS;OAAM,CAAC;;AAG5F,WAAKb,MAAO,KAAK,WAAW,KAAK;AAEjC,SAAI,KAAK,cAAc;AACrB,YAAKA,MAAO,KAAK,WAAW,KAAK,gBAAgB,KAAK;AACtD,UAAI,KAAK,SACP,OAAKA,MAAO,KAAK,WAAW,KAAK,aAAa,GAAG,KAAK,YAAY,KAAK;;AAI3E;IAGF;AACE,UAAK,OAAO,MAAM,OAAO,MAAKa,cAAe,KAAK,GAAG;AACrD,WAAKb,MAAO,KAAK,KAAK,WAAW,KAAK;AACtC;;AAIJ;;;CAIJ,iBAAiB,SAAgC;AAC/C,SAAO,QACJ,KAAK,OAAO;AACX,WAAQ,GAAG,MAAX;IACE,KAAK,OACH,QAAO,GAAG;IACZ,KAAK,KACH,QAAO,OAAO,GAAG,GAAG;IACtB,KAAK,OACH,QAAO,SAAS,GAAG,GAAG;IACxB,KAAK,QACH,QAAO,UAAU,GAAG,KAAK,GAAG,GAAG,IAAI;IACrC,KAAK,OACH,QAAO,SAAS,GAAG,KAAK;IAC1B,KAAK;IACL,KAAK,OACH,QAAO,SAAS,GAAG,OAAO;IAC5B,KAAK;IACL,KAAK;IACL,KAAK,SACH,QAAO,IAAI,GAAG,KAAK,GAAG,GAAG,IAAI;IAC/B,QACE,QAAO,IAAI,GAAG,KAAK;;IAEvB,CACD,KAAK,GAAG;;;CAIb,MAAM,UAAU,UAAkB,cAAuB,OAAsC;AAC7F,MAAI;GACF,MAAM,QAAQ,MAAKG,WAAY,IAAI,SAAS;AAE5C,OAAI,SAAS,CAAC,eAAe,kBAAkB,MAC7C,QAAO;GAGT,MAAM,YAAY,MAAM,KAAK,IAAkC,kBAAkB,EAAE,UAAU,CAAC;AAC9F,UAAO,MAAKQ,WAAY,UAAU,UAAU,YAAY,WAAW,KAAK;WACjEM,KAAU;AACjB,QAAK,OAAO,KAAK,OAAO,SAAS,SAAS,KAAK,WAAW,MAAM;AAChE,UAAO,MAAKN,WAAY,UAAU,KAAK,EAAE,CAAC;;;;CAK9C,MAAM,WAAW,SAAiD;AAChE,MAAI;GACF,MAAM,QAAQ,MAAKP,YAAa,IAAI,QAAQ;AAE5C,OAAI,SAAS,SAAS,MACpB,QAAO;GAGT,MAAM,aAAa,MAAM,KAAK,IAAmC,qBAAqB,EAAE,SAAS,CAAC;AAClG,UAAO,MAAKK,YAAa,SAAS,WAAW,UAAU,YAAY,KAAK;WACjEQ,KAAU;AACjB,QAAK,OAAO,KAAK,QAAQ,QAAQ,SAAS,KAAK,WAAW,MAAM;AAEhE,UAAO,MAAKR,YAAa,SAAS,KAAK,EAAE,CAAC;;;;;;;;;;;CAY9C,KAA+B,MAAS,SAA4D;EAClG,MAAM,eAAe,UAAgC;AACnD,WAAQ,MAAM;AACd,SAAKT,MAAO,IAAI,MAAM,YAAY;;AAGpC,OAAK,OAAO,MAAM,aAAa,OAAO,KAAK,GAAG;AAC9C,QAAKA,MAAO,GAAG,MAAM,YAAY;AACjC,eAAa,KAAK,IAAI,MAAM,QAAQ;;;;;;;;;CAUtC,GAA6B,MAAS,SAA4D;AAChG,OAAK,OAAO,MAAM,UAAU,OAAO,KAAK,GAAG;AAC3C,QAAKA,MAAO,GAAG,MAAM,QAAQ;AAC7B,eAAa,KAAK,IAAI,MAAM,QAAQ;;;;;CAMtC,IAA8B,MAAS,SAAsD;AAC3F,OAAK,OAAO,MAAM,UAAU,OAAO,KAAK,GAAG;AAC3C,QAAKA,MAAO,IAAI,MAAM,QAAQ;;;;;CAMhC,IAAmB,QAA6B,SAA8B,EAAE,EAAc;AAC5F,QAAKkB,mBAAoB,MAAKvB,GAAI;AAClC,OAAK,OAAO,MAAM,WAAW,OAAO,OAAO,KAAK,UAAU,OAAO,GAAG;EACpE,MAAM,OAAO,MAAKwB,QAAS;AAE3B,MAAI;AACF,SAAKxB,GAAI,KAAK,KAAK,UAAU;IAAE;IAAM;IAAQ;IAAQ,CAAC,CAAC;AACvD,UAAO,MAAKyB,cAAkB,MAAM,OAAO;WACpCC,OAAY;GACnB,MAAM,WAAW,OAAO,WAAW,OAAO,MAAM;AAChD,QAAK,OAAO,MAAM,gBAAgB,WAAW;AAC7C,SAAKrB,MAAO,KAAK,oBAAoB;IACnC;IACA,OAAO;IACR,CAAC;AACF,UAAO,QAAQ,uBAAO,IAAI,MAAM,gBAAgB,WAAW,CAAC;;;;;;CAOhE,MAAM,SAAS,SAAiB,QAAgB,GAAiB;AAC/D,MAAI;AACF,SAAM,KAAK,IAAU,aAAa;IAAE;IAAS;IAAO,CAAC;AACrD,UAAO;UACD;AACN,UAAO;;;;;;CAOX,MAAM,gBAA2D;AAE/D,UADgB,MAAM,KAAK,IAAc,kBAAkB,EAC5C,KAAK,MAAM,MAAKS,YAAa,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;;;;;CAMxE,MAAM,eAAyD;AAE7D,UADe,MAAM,KAAK,IAAa,iBAAiB,EAC1C,KAAK,MAAM,MAAKE,WAAY,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;;;;;CAMzE,YAAY,YAAoB,IAA2B;AACzD,SAAO,KAAK,IAAU,sBAAsB;GAAE;GAAY,UAAU;GAAI,KAAK;GAAM,CAAC;;;;;CAMtF,YAAY,YAAoB,IAA2B;AACzD,SAAO,KAAK,IAAU,sBAAsB;GAAE;GAAY,UAAU;GAAI,KAAK;GAAO,CAAC;;;;;CAMvF,MAAM,OAAO,YAA8F;AACzG,MAAI,CAAC,WACH,QAAO;EAGT,MAAM,MAAM,MAAM,KAAK,IAAS,WAAW,EAAE,YAAY,CAAC;AAE1D,MAAI,IAAI,iBAAiB,UACvB,QAAO,MAAKI,yBAA0B,IAAI;MAE1C,QAAO,MAAKC,uBAAwB,IAAI;;;;;CAO5C,aAAa,SAAiB,QAAiB,OAAO,OAAgB,OAAsB;AAC1F,SAAO,KAAK,IAAU,iBAAiB;GACrC;GACA,YAAY;GACZ,eAAe;GAChB,CAAC;;;;;CAMJ,YAAY,UAAkB,SAAiB,UAAiC;AAC9E,SAAO,KAAK,IAAU,iBAAiB;GAAE;GAAU;GAAS;GAAU,CAAC;;;;;CAMzE,UAAU,YAAmC;AAC3C,SAAO,KAAK,IAAU,cAAc,EAAE,YAAY,CAAC;;;;;CAMrD,gBAAgB,SAA+B;AAC7C,SAAO,KAAK,IAAS,qBAAqB,EAAE,SAAS,CAAC;;;;;CAMxD,eAAe,SAAiB,UAAgE;AAC9F,SAAO,KAAK,IAA4B,oBAAoB;GAC1D;GACA,SAAS,KAAK,kBAAkB,SAAS;GAC1C,CAAC;;;;;CAMJ,aAAa,UAAkB,UAAgE;AAC7F,SAAO,KAAK,IAA4B,kBAAkB;GACxD;GACA,SAAS,KAAK,kBAAkB,SAAS;GAC1C,CAAC;;;;;CAMJ,aAAa,UAAgC;AAC3C,SAAO,KAAK,IAAS,kBAAkB,EAAE,UAAU,CAAC;;;;;CAMtD,aAAa,UAAgC;AAC3C,SAAO,KAAK,IAAU,kBAAkB,EAAE,UAAU,CAAC;;;;;CAMvD,cAAc,YAAmC;AAC/C,SAAO,KAAK,IAAU,mBAAmB,EAAE,YAAY,CAAC;;;;;CAM1D,iBAAiB,YAAmC;AAClD,SAAO,KAAK,IAAU,sBAAsB,EAAE,YAAY,CAAC;;;;;CAM7D,aAAa,UAAkB,SAAiB,MAA6B;AAC3E,SAAO,KAAK,IAAU,kBAAkB;GAAE;GAAU;GAAS;GAAM,CAAC;;;;;CAMtE,qBAAqB,UAAkB,SAAiB,OAA8B;AACpF,SAAO,KAAK,IAAU,2BAA2B;GAAE;GAAU;GAAS;GAAO,CAAC;;;;;CAMhF,mBAAmB,UAA8C;AAC/D,SAAO,KAAK,IAAuB,yBAAyB,EAAE,UAAU,CAAC;;;;;CAM3E,mBAAmB,UAAkB,SAA2C;AAC9E,SAAO,KAAK,IAAqB,yBAAyB;GAAE;GAAU;GAAS,CAAC;;;;;CAMlF,gBAAgB,UAAkB,SAAiB,qBAA8B,OAAsB;AACrG,SAAO,KAAK,IAAU,kBAAkB;GAAE;GAAU;GAAS;GAAoB,CAAC;;;;;CAMpF,WAAoB;AAClB,SAAO,MAAKrB,IAAK,eAAe,UAAU,QAAQ,MAAKI;;;;;CAMzD,OAAO,OAAuB;EAC5B,IAAI,MAAM;AACV,OAAK,IAAI,IAAI,GAAG,MAAM,MAAM,QAAQ,IAAI,KAAK,EAAE,EAC7C,SAAQ,OAAO,KAAK,MAAM,WAAW,EAAE;AAEzC,SAAO,MAAM;;;;;CAMf,iBAAiB,QAA2D;AAC1E,SAAO,KAAK,IAAsC,eAAe,EAAE,QAAQ,CAAC;;;;;CAM9E,iBAA+F;AAC7F,SAAO,KAAK,IAAyE,mBAAmB;;;;;CAM1G,eAA+D;AAC7D,SAAO,KAAK,IAA2C,iBAAiB;;;;;CAM1E,MAAM,UAAU,QAQb;EACD,MAAM,QAAQ,MAAKuB,YAAa,IAAI,OAAO;AAE3C,MAAI,MAAO,QAAO;EAElB,MAAM,EAAE,SAAS,cAAc,QAAQ,MAAM,KAAK,iBAAiB,OAAO;EAE1E,MAAM,OAAO,aAAa,MAAM,eAAe,GAAG,MAAM;EACxD,MAAM,QAAQ,aAAa,MAAM,iBAAiB,GAAG,MAAM;EAC3D,MAAM,MAAM,KAAK,OAAO,MAAM;EAE9B,MAAM,UAAU;GACd;GACA;GACA,KAAK,KAAK;GACV,KAAK,OAAO,IAAI;GAChB;GACA,QAAQ,OAAO,KAAK,IAAI,SAAS,KAAK,UAAU,KAAK,IAAI,WAAW,MAAM;GAC1E,cAAc,QAAQ,KAAK,IAAI,SAAS,KAAK,WAAW,KAAK,IAAI,WAAW,MAAM;GACnF;AAED,QAAKA,YAAa,IAAI,QAAQ,QAAQ;AAGtC,mBACQ;AACJ,SAAKA,YAAa,OAAO,OAAO;KAElC,MAAO,KAAK,GACb;AAED,SAAO;;;;;CAMT,MAAM,SAAS,QAAiC;EAC9C,MAAM,EAAE,UAAU,MAAM,KAAK,UAAU,OAAO;AAC9C,SAAO;;;;;CAMT,MAAM,SAA0B;EAC9B,MAAM,EAAE,QAAQ,MAAM,KAAK,UAAU,aAAa;AAClD,SAAO;;;CAIT,qBAA6B;EAC3B,MAAM,EAAE,mBAAmB,yBAAyB,MAAK5B;EACzD,MAAM,QAAQ,oBAAoB,KAAK,IAAI,GAAG,MAAK6B,kBAAmB;AACtE,SAAO,KAAK,IAAI,OAAO,qBAAqB;;;CAI9C,uBAA6B;AAC3B,MAAI,MAAKC,gBAAiB;AACxB,gBAAa,MAAKA,eAAgB;AAClC,SAAKA,iBAAkB;;;;CAK3B,qBAA2B;EACzB,MAAM,EAAE,WAAW,yBAAyB,MAAK9B;AAEjD,MAAI,CAAC,aAAa,MAAK+B,YACrB;AAGF,MAAI,MAAKF,qBAAsB,sBAAsB;AACnD,QAAK,OAAO,MAAM,kBAAkB,uBAAuB;AAC3D,SAAKvB,MAAO,KAAK,2BAA2B;IAC1C,SAAS,MAAKuB;IACd,aAAa;IACd,CAAC;AACF;;AAGF,QAAKG,eAAgB;AACrB,QAAKH;EAEL,MAAM,QAAQ,MAAKI,mBAAoB;AAEvC,OAAK,OAAO,KAAK,MAAM,MAAM,UAAU,MAAKJ,kBAAmB,MAAM;AACrE,QAAKvB,MAAO,KAAK,uBAAuB;GACtC,SAAS,MAAKuB;GACd,aAAa;GACb;GACD,CAAC;AAEF,QAAKK,qBAAsB;AAC3B,QAAKJ,iBAAkB,iBAAiB;AACtC,SAAKK,SAAU,CAAC,OAAO,QAAQ;AAC7B,SAAK,OAAO,MAAM,SAAS,KAAK,WAAW,MAAM;KACjD;KACD,MAAM;;;CAIX,WAA0B;AACxB,SAAO,IAAI,SAAe,SAAS,WAAW;GAC5C,MAAM,KAAK,IAAI,UAAU,MAAKC,YAAa,CAAC;AAE5C,MAAG,aAAa,UAAU;IACxB,MAAM,cAAc;AAClB,SAAI;AACF,aAAO,KAAK,MAAM,MAAM,KAAK;aACvB;AACN,aAAO;;QAEP;AAEJ,QAAI,CAAC,MAAM;AACT,UAAK,OAAO,MAAM,gBAAgB,MAAM,OAAO;AAC/C;;AAGF,UAAK9B,MAAO,KAAK,cAAc,KAAK;AACpC,UAAKY,mBAAoB,KAAK;;AAGhC,MAAG,gBAAgB;AACjB,UAAKE,gBAAiB,MAAM;AAC5B,SAAK,OAAO,MAAM,kBAAkB;AACpC,UAAKd,MAAO,KAAK,WAAW;AAG5B,UAAKA,MAAO,KAAK,uBAAuB,EACtC,QAAQ,MAAKyB,aACd,CAAC;AAGF,QAAI,CAAC,MAAKA,YACR,OAAKM,mBAAoB;;AAI7B,MAAG,WAAW,UAAU;AACtB,UAAKjB,gBAAiB,MAAM;IAC5B,MAAM,MAAM;AACZ,SAAK,OAAO,MAAM,IAAI;AACtB,UAAKd,MAAO,KAAK,YAAY,MAAM;AAGnC,UAAKA,MAAO,KAAK,uBAAuB;KACtC,QAAQ;KACR,QAAQ;KACT,CAAC;AAGF,QAAI,CAAC,MAAK0B,aACR,QAAO,IAAI,MAAM,IAAI,CAAC;;AAI1B,MAAG,eAAe;AAChB,SAAK,OAAO,KAAK,iCAAiC;AAClD,UAAK1B,MAAO,KAAK,UAAU;AAG3B,QAAI,MAAK0B,cAAe;AACtB,UAAK,OAAO,KAAK,KAAK,MAAKH,kBAAmB,QAAQ;AACtD,WAAKvB,MAAO,KAAK,sBAAsB,EACrC,SAAS,MAAKuB,mBACf,CAAC;AACF,WAAKG,eAAgB;AACrB,WAAKH,oBAAqB;;AAG5B,aAAS;;AAGX,SAAK5B,KAAM;IACX;;;CAIJ,MAAM,MAAqB;EACzB,MAAM,EAAE,QAAQ,GAAG,OAAO,IAAI,GAAG,WAAW,MAAKD;AAEjD,OAAK,OAAO,MAAM,SAAS,KAAK,UAAU,OAAO,GAAG;AAEpD,QAAK+B,cAAe;AACpB,SAAO,MAAKI,SAAU;;;CAIxB,QAAc;AACZ,OAAK,OAAO,KAAK,wBAAwB;AACzC,QAAK7B,MAAO,KAAK,iBAAiB;AAElC,QAAKyB,cAAe;AACpB,QAAKG,qBAAsB;AAE3B,MAAI,MAAKjC,IAAK;AACZ,SAAKA,GAAI,OAAO;AAChB,SAAKA,KAAM;AACX,QAAK,OAAO,KAAK,mBAAmB;QAEpC,MAAK,OAAO,KAAK,oBAAoB;AAIvC,QAAK+B,eAAgB;AACrB,QAAKH,oBAAqB;;;;;;;AAU9B,MAAMS,2BAAsF;CAC1F,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACD,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACD,OAAO;EACL,aAAa;EACb,UAAU;EACX;CACF;;;;;AAMD,MAAMC,0BAAqF;CACzF,YAAY;EACV,aAAa;EACb,UAAU;EACX;CACD,eAAe;EACb,aAAa;EACb,UAAU;EACX;CACD,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACD,eAAe;EACb,aAAa;EACb,UAAU;EACX;CACD,aAAa;EACX,aAAa;EACb,UAAU;EACX;CACD,WAAW;EACT,aAAa;EACb,UAAU;EACX;CACD,YAAY;EACV,aAAa;EACb,UAAU;EACX;CACD,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACD,gBAAgB;EACd,aAAa;EACb,UAAU;EACX;CACD,gBAAgB;EACd,aAAa;EACb,UAAU;EACX;CACD,sBAAsB;EACpB,aAAa;EACb,UAAU;EACX;CACD,SAAS;EACP,aAAa;EACb,UAAU;EACX;CACD,cAAc;EACZ,aAAa;EACb,UAAU;EACX;CACF"}