mioki 0.14.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { EventMap, GroupMessageEvent, LogLevel, Logger, MessageEvent, NapCat, PrivateMessageEvent, RecvElement, RecvImageElement, Sendable } from "napcat-sdk";
1
+ import { EventMap, GroupMessageEvent, LogLevel, Logger, MessageEvent, NapCat, NoticeEvent, PrivateMessageEvent, RecvElement, RecvImageElement, RequestEvent, Sendable } from "napcat-sdk";
2
2
  import { Low } from "lowdb";
3
3
  import { Jiti } from "jiti";
4
4
  import prettyMs from "pretty-ms";
@@ -642,23 +642,50 @@ type RemoveBotParam<T> = { [K in keyof T]: T[K] extends ((...args: any[]) => any
642
642
  type OmitBotParamFromFunc<Func extends (bot: NapCat, ...args: any[]) => any> = Func extends ((bot: NapCat, ...args: infer A) => infer Return) ? (...args: A) => Return : never;
643
643
  declare function bindBot<Params extends Array<any> = any[], Return$1 = any>(bot: NapCat, func: (bot: NapCat, ...args: Params) => Return$1): OmitBotParamFromFunc<(bot: NapCat, ...args: Params) => Return$1>;
644
644
  /**
645
- * 消息去重器
646
- * 处理多个 bot 在同一个群时,同一消息只处理一次
645
+ * 需要去重的事件类型
646
+ */
647
+ type DeduplicableEvent = MessageEvent | RequestEvent | NoticeEvent;
648
+ /**
649
+ * 去重器
650
+ * 处理多个 bot 在相同场景下,同一事件只处理一次
647
651
  */
648
- declare class MessageDeduplicator {
649
- private processedMessages;
652
+ declare class Deduplicator {
653
+ private processedEvents;
650
654
  private maxSize;
651
655
  /**
652
- * 生成消息唯一键
653
- * 对于群消息:使用 group_id:user_id:time
654
- * 对于私聊消息:使用 private:user_id:time
656
+ * 获取事件类型键
657
+ */
658
+ private getEventTypeKey;
659
+ private getGroupMessageKey;
660
+ private getPrivateMessageKey;
661
+ private getNoticeGroupKey;
662
+ private getRequestKey;
663
+ /**
664
+ * 生成事件唯一键
655
665
  */
656
666
  private getKey;
667
+ /**
668
+ * 检查事件是否已处理过
669
+ * @param event
670
+ * @param scope
671
+ */
672
+ isProcessed(event: DeduplicableEvent, scope?: string): boolean;
673
+ /**
674
+ * 标记事件为已处理
675
+ * @param event
676
+ * @param scope 需与 isProcessed 一致
677
+ */
678
+ markProcessed(event: DeduplicableEvent, scope?: string): void;
679
+ }
680
+ /**
681
+ * 消息去重器
682
+ * @deprecated 请使用 Deduplicator,它支持更多事件类型
683
+ */
684
+ declare class MessageDeduplicator extends Deduplicator {
657
685
  isProcessed(event: GroupMessageEvent | PrivateMessageEvent): boolean;
658
686
  markProcessed(event: GroupMessageEvent | PrivateMessageEvent): void;
659
- clear(): void;
660
687
  }
661
- declare const deduplicator: MessageDeduplicator;
688
+ declare const deduplicator: Deduplicator;
662
689
  /**
663
690
  * Mioki 上下文对象,包含 Mioki 运行时的信息和方法
664
691
  */
@@ -674,15 +701,15 @@ interface MiokiContext extends Services, Configs, Utils, RemoveBotParam<Actions>
674
701
  /** 通过域名获取 Cookies */
675
702
  getCookie: NapCat['getCookie'];
676
703
  /** 注册事件处理器 */
677
- handle: <EventName extends keyof EventMap>(eventName: EventName, handler: (event: EventMap[EventName]) => any) => void;
704
+ handle: <EventName extends keyof EventMap>(eventName: EventName, handler: (event: EventMap[EventName]) => any, options?: HandleOptions) => () => void;
678
705
  /** 注册定时任务 */
679
706
  cron: (cronExpression: string, handler: (ctx: MiokiContext, task: TaskContext) => any) => ScheduledTask;
680
707
  /** 待清理的函数集合,在插件卸载时会被调用 */
681
708
  clears: Set<(() => any) | null | undefined>;
682
709
  /** 日志器 */
683
710
  logger: Logger;
684
- /** 消息去重器 */
685
- deduplicator: MessageDeduplicator;
711
+ /** 事件去重器 */
712
+ deduplicator: Deduplicator;
686
713
  }
687
714
  declare const runtimePlugins: Map<string, {
688
715
  name: string;
@@ -692,6 +719,16 @@ declare const runtimePlugins: Map<string, {
692
719
  plugin: MiokiPlugin;
693
720
  disable: () => any;
694
721
  }>;
722
+ /**
723
+ * 事件处理器选项
724
+ */
725
+ interface HandleOptions {
726
+ /**
727
+ * 是否启用自动去重
728
+ * @default true
729
+ */
730
+ deduplicate?: boolean;
731
+ }
695
732
  interface MiokiPlugin {
696
733
  /** 插件 ID,请保持唯一,一般为插件目录名称,框架内部通过这个识别不同的插件 */
697
734
  name: string;
@@ -729,5 +766,5 @@ declare function findLocalPlugins(): Promise<{
729
766
  //#region src/builtins/index.d.ts
730
767
  declare const BUILTIN_PLUGINS: MiokiPlugin[];
731
768
  //#endregion
732
- export { AnyFunc, ArchMap, Arrayable, Awaitable, BOT_CWD, BUILTIN_PLUGINS, BotStatus, CORE_PLUGINS, ChromeUA, CreateCmdOptions, ExtendedNapCat, Gettable, HasMessage, MessageDeduplicator, MiokiConfig, MiokiContext, MiokiCoreServiceContrib, MiokiPlugin, MiokiServices, MiokiStatus, NapCatConfig, NapCatInstanceConfig, Noop, OmitBotParamFromFunc, PureObject, START_TIME, StartOptions, StatusFormatter, SystemMap, addService, base64Decode, base64Encode, bindBot, botConfig, box, clamp, colorize, colors, connectedBots, createCmd, createDB, createForwardMsg, createStore, dayjs, dedent, deduplicator, definePlugin, enablePlugin, ensureBuffer, ensurePluginDir, filesize, filter, find, findLocalPlugins, formatDuration, formatMiokiStatus, formatQQLevel, fs, getAbsPluginDir, getAuthCodeViaTicket, getBfaceUrl, getGTk, getGroupAvatarLink, getImage, getImageUrl, getLogFilePath, getMentionedImage, getMentionedImageUrl, getMentionedUserId, getMinicoTokenViaAuthCode, getMiokiLogger, getMiokiStatus, getQQAvatarLink, getQuoteImage, getQuoteImageUrl, getQuoteMsg, getQuoteText, getTerminalInput, getViolationRecords, hasRight, isAdmin, isBoolean, isDefined, isFunction, isGroupMsg, isInPm2, isNumber, isObject, isOwner, isOwnerOrAdmin, isPrivateMsg, isString, jiti, localNum, localeDate, localeTime, logger, match, md5, mri, noNullish, normalizeNapCatConfig, noticeAdmins, noticeFriends, noticeGroups, noticeMainOwner, noticeOwners, path, prettyMs, qs, queryDevToolsLoginStatus, randomId, randomInt, randomItem, randomItems, readMiokiConfig, readPackageJson, requestLoginViaDevTools, runWithErrorHandler, runWithReaction, runtimePlugins, services, signArk, start, string2argv, stringifyError, stripAnsi, systemInfo, text, toArray, toMsgId, unique, updateBotCWD, updateBotConfig, uploadImageToCollection, uploadImageToGroupHomework, uploadImageToGroupNotice, uuid, wait, writePackageJson };
769
+ export { AnyFunc, ArchMap, Arrayable, Awaitable, BOT_CWD, BUILTIN_PLUGINS, BotStatus, CORE_PLUGINS, ChromeUA, CreateCmdOptions, DeduplicableEvent, Deduplicator, ExtendedNapCat, Gettable, HandleOptions, HasMessage, MessageDeduplicator, MiokiConfig, MiokiContext, MiokiCoreServiceContrib, MiokiPlugin, MiokiServices, MiokiStatus, NapCatConfig, NapCatInstanceConfig, Noop, OmitBotParamFromFunc, PureObject, START_TIME, StartOptions, StatusFormatter, SystemMap, addService, base64Decode, base64Encode, bindBot, botConfig, box, clamp, colorize, colors, connectedBots, createCmd, createDB, createForwardMsg, createStore, dayjs, dedent, deduplicator, definePlugin, enablePlugin, ensureBuffer, ensurePluginDir, filesize, filter, find, findLocalPlugins, formatDuration, formatMiokiStatus, formatQQLevel, fs, getAbsPluginDir, getAuthCodeViaTicket, getBfaceUrl, getGTk, getGroupAvatarLink, getImage, getImageUrl, getLogFilePath, getMentionedImage, getMentionedImageUrl, getMentionedUserId, getMinicoTokenViaAuthCode, getMiokiLogger, getMiokiStatus, getQQAvatarLink, getQuoteImage, getQuoteImageUrl, getQuoteMsg, getQuoteText, getTerminalInput, getViolationRecords, hasRight, isAdmin, isBoolean, isDefined, isFunction, isGroupMsg, isInPm2, isNumber, isObject, isOwner, isOwnerOrAdmin, isPrivateMsg, isString, jiti, localNum, localeDate, localeTime, logger, match, md5, mri, noNullish, normalizeNapCatConfig, noticeAdmins, noticeFriends, noticeGroups, noticeMainOwner, noticeOwners, path, prettyMs, qs, queryDevToolsLoginStatus, randomId, randomInt, randomItem, randomItems, readMiokiConfig, readPackageJson, requestLoginViaDevTools, runWithErrorHandler, runWithReaction, runtimePlugins, services, signArk, start, string2argv, stringifyError, stripAnsi, systemInfo, text, toArray, toMsgId, unique, updateBotCWD, updateBotConfig, uploadImageToCollection, uploadImageToGroupHomework, uploadImageToGroupNotice, uuid, wait, writePackageJson };
733
770
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ import path from "node:path";
3
3
  import mri from "mri";
4
4
  import { BinaryLike, BinaryToTextEncoding } from "node:crypto";
5
5
  import { Low } from "lowdb";
6
- import { EventMap, GroupMessageEvent, LogLevel, Logger, MessageEvent, NapCat, PrivateMessageEvent, RecvElement, RecvImageElement, Sendable } from "napcat-sdk";
6
+ import { EventMap, GroupMessageEvent, LogLevel, Logger, MessageEvent, NapCat, NoticeEvent, PrivateMessageEvent, RecvElement, RecvImageElement, RequestEvent, Sendable } from "napcat-sdk";
7
7
  import { Jiti } from "jiti";
8
8
  import { string2argv } from "string2argv";
9
9
  import prettyMs from "pretty-ms";
@@ -640,23 +640,50 @@ type RemoveBotParam<T> = { [K in keyof T]: T[K] extends ((...args: any[]) => any
640
640
  type OmitBotParamFromFunc<Func extends (bot: NapCat, ...args: any[]) => any> = Func extends ((bot: NapCat, ...args: infer A) => infer Return) ? (...args: A) => Return : never;
641
641
  declare function bindBot<Params extends Array<any> = any[], Return$1 = any>(bot: NapCat, func: (bot: NapCat, ...args: Params) => Return$1): OmitBotParamFromFunc<(bot: NapCat, ...args: Params) => Return$1>;
642
642
  /**
643
- * 消息去重器
644
- * 处理多个 bot 在同一个群时,同一消息只处理一次
643
+ * 需要去重的事件类型
644
+ */
645
+ type DeduplicableEvent = MessageEvent | RequestEvent | NoticeEvent;
646
+ /**
647
+ * 去重器
648
+ * 处理多个 bot 在相同场景下,同一事件只处理一次
645
649
  */
646
- declare class MessageDeduplicator {
647
- private processedMessages;
650
+ declare class Deduplicator {
651
+ private processedEvents;
648
652
  private maxSize;
649
653
  /**
650
- * 生成消息唯一键
651
- * 对于群消息:使用 group_id:user_id:time
652
- * 对于私聊消息:使用 private:user_id:time
654
+ * 获取事件类型键
655
+ */
656
+ private getEventTypeKey;
657
+ private getGroupMessageKey;
658
+ private getPrivateMessageKey;
659
+ private getNoticeGroupKey;
660
+ private getRequestKey;
661
+ /**
662
+ * 生成事件唯一键
653
663
  */
654
664
  private getKey;
665
+ /**
666
+ * 检查事件是否已处理过
667
+ * @param event
668
+ * @param scope
669
+ */
670
+ isProcessed(event: DeduplicableEvent, scope?: string): boolean;
671
+ /**
672
+ * 标记事件为已处理
673
+ * @param event
674
+ * @param scope 需与 isProcessed 一致
675
+ */
676
+ markProcessed(event: DeduplicableEvent, scope?: string): void;
677
+ }
678
+ /**
679
+ * 消息去重器
680
+ * @deprecated 请使用 Deduplicator,它支持更多事件类型
681
+ */
682
+ declare class MessageDeduplicator extends Deduplicator {
655
683
  isProcessed(event: GroupMessageEvent | PrivateMessageEvent): boolean;
656
684
  markProcessed(event: GroupMessageEvent | PrivateMessageEvent): void;
657
- clear(): void;
658
685
  }
659
- declare const deduplicator: MessageDeduplicator;
686
+ declare const deduplicator: Deduplicator;
660
687
  /**
661
688
  * Mioki 上下文对象,包含 Mioki 运行时的信息和方法
662
689
  */
@@ -672,15 +699,15 @@ interface MiokiContext extends Services, Configs, Utils, RemoveBotParam<Actions>
672
699
  /** 通过域名获取 Cookies */
673
700
  getCookie: NapCat['getCookie'];
674
701
  /** 注册事件处理器 */
675
- handle: <EventName extends keyof EventMap>(eventName: EventName, handler: (event: EventMap[EventName]) => any) => void;
702
+ handle: <EventName extends keyof EventMap>(eventName: EventName, handler: (event: EventMap[EventName]) => any, options?: HandleOptions) => () => void;
676
703
  /** 注册定时任务 */
677
704
  cron: (cronExpression: string, handler: (ctx: MiokiContext, task: TaskContext) => any) => ScheduledTask;
678
705
  /** 待清理的函数集合,在插件卸载时会被调用 */
679
706
  clears: Set<(() => any) | null | undefined>;
680
707
  /** 日志器 */
681
708
  logger: Logger;
682
- /** 消息去重器 */
683
- deduplicator: MessageDeduplicator;
709
+ /** 事件去重器 */
710
+ deduplicator: Deduplicator;
684
711
  }
685
712
  declare const runtimePlugins: Map<string, {
686
713
  name: string;
@@ -690,6 +717,16 @@ declare const runtimePlugins: Map<string, {
690
717
  plugin: MiokiPlugin;
691
718
  disable: () => any;
692
719
  }>;
720
+ /**
721
+ * 事件处理器选项
722
+ */
723
+ interface HandleOptions {
724
+ /**
725
+ * 是否启用自动去重
726
+ * @default true
727
+ */
728
+ deduplicate?: boolean;
729
+ }
693
730
  interface MiokiPlugin {
694
731
  /** 插件 ID,请保持唯一,一般为插件目录名称,框架内部通过这个识别不同的插件 */
695
732
  name: string;
@@ -727,5 +764,5 @@ declare function findLocalPlugins(): Promise<{
727
764
  //#region src/builtins/index.d.ts
728
765
  declare const BUILTIN_PLUGINS: MiokiPlugin[];
729
766
  //#endregion
730
- export { AnyFunc, ArchMap, Arrayable, Awaitable, BOT_CWD, BUILTIN_PLUGINS, BotStatus, CORE_PLUGINS, ChromeUA, CreateCmdOptions, ExtendedNapCat, Gettable, HasMessage, MessageDeduplicator, MiokiConfig, MiokiContext, MiokiCoreServiceContrib, MiokiPlugin, MiokiServices, MiokiStatus, NapCatConfig, NapCatInstanceConfig, Noop, OmitBotParamFromFunc, PureObject, START_TIME, StartOptions, StatusFormatter, SystemMap, addService, base64Decode, base64Encode, bindBot, botConfig, box, clamp, colorize, colors, connectedBots, createCmd, createDB, createForwardMsg, createStore, dayjs, dedent, deduplicator, definePlugin, enablePlugin, ensureBuffer, ensurePluginDir, filesize, filter, find, findLocalPlugins, formatDuration, formatMiokiStatus, formatQQLevel, fs, getAbsPluginDir, getAuthCodeViaTicket, getBfaceUrl, getGTk, getGroupAvatarLink, getImage, getImageUrl, getLogFilePath, getMentionedImage, getMentionedImageUrl, getMentionedUserId, getMinicoTokenViaAuthCode, getMiokiLogger, getMiokiStatus, getQQAvatarLink, getQuoteImage, getQuoteImageUrl, getQuoteMsg, getQuoteText, getTerminalInput, getViolationRecords, hasRight, isAdmin, isBoolean, isDefined, isFunction, isGroupMsg, isInPm2, isNumber, isObject, isOwner, isOwnerOrAdmin, isPrivateMsg, isString, jiti, localNum, localeDate, localeTime, logger, match, md5, mri, noNullish, normalizeNapCatConfig, noticeAdmins, noticeFriends, noticeGroups, noticeMainOwner, noticeOwners, path, prettyMs, qs, queryDevToolsLoginStatus, randomId, randomInt, randomItem, randomItems, readMiokiConfig, readPackageJson, requestLoginViaDevTools, runWithErrorHandler, runWithReaction, runtimePlugins, services, signArk, start, string2argv, stringifyError, stripAnsi, systemInfo, text, toArray, toMsgId, unique, updateBotCWD, updateBotConfig, uploadImageToCollection, uploadImageToGroupHomework, uploadImageToGroupNotice, uuid, wait, writePackageJson };
767
+ export { AnyFunc, ArchMap, Arrayable, Awaitable, BOT_CWD, BUILTIN_PLUGINS, BotStatus, CORE_PLUGINS, ChromeUA, CreateCmdOptions, DeduplicableEvent, Deduplicator, ExtendedNapCat, Gettable, HandleOptions, HasMessage, MessageDeduplicator, MiokiConfig, MiokiContext, MiokiCoreServiceContrib, MiokiPlugin, MiokiServices, MiokiStatus, NapCatConfig, NapCatInstanceConfig, Noop, OmitBotParamFromFunc, PureObject, START_TIME, StartOptions, StatusFormatter, SystemMap, addService, base64Decode, base64Encode, bindBot, botConfig, box, clamp, colorize, colors, connectedBots, createCmd, createDB, createForwardMsg, createStore, dayjs, dedent, deduplicator, definePlugin, enablePlugin, ensureBuffer, ensurePluginDir, filesize, filter, find, findLocalPlugins, formatDuration, formatMiokiStatus, formatQQLevel, fs, getAbsPluginDir, getAuthCodeViaTicket, getBfaceUrl, getGTk, getGroupAvatarLink, getImage, getImageUrl, getLogFilePath, getMentionedImage, getMentionedImageUrl, getMentionedUserId, getMinicoTokenViaAuthCode, getMiokiLogger, getMiokiStatus, getQQAvatarLink, getQuoteImage, getQuoteImageUrl, getQuoteMsg, getQuoteText, getTerminalInput, getViolationRecords, hasRight, isAdmin, isBoolean, isDefined, isFunction, isGroupMsg, isInPm2, isNumber, isObject, isOwner, isOwnerOrAdmin, isPrivateMsg, isString, jiti, localNum, localeDate, localeTime, logger, match, md5, mri, noNullish, normalizeNapCatConfig, noticeAdmins, noticeFriends, noticeGroups, noticeMainOwner, noticeOwners, path, prettyMs, qs, queryDevToolsLoginStatus, randomId, randomInt, randomItem, randomItems, readMiokiConfig, readPackageJson, requestLoginViaDevTools, runWithErrorHandler, runWithReaction, runtimePlugins, services, signArk, start, string2argv, stringifyError, stripAnsi, systemInfo, text, toArray, toMsgId, unique, updateBotCWD, updateBotConfig, uploadImageToCollection, uploadImageToGroupHomework, uploadImageToGroupNotice, uuid, wait, writePackageJson };
731
768
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./chunk-BiucMVzj.mjs";
2
- import { t as version } from "./package-DFYh9fsp.mjs";
2
+ import { t as version } from "./package-75_Caljc.mjs";
3
3
  import fs, { default as fs$1 } from "node:fs";
4
4
  import util from "node:util";
5
5
  import path, { default as path$1 } from "node:path";
@@ -1213,36 +1213,100 @@ function bindBot(bot, func) {
1213
1213
  return (...args) => func(bot, ...args);
1214
1214
  }
1215
1215
  /**
1216
- * 消息去重器
1217
- * 处理多个 bot 在同一个群时,同一消息只处理一次
1216
+ * 去重器
1217
+ * 处理多个 bot 在相同场景下,同一事件只处理一次
1218
1218
  */
1219
- var MessageDeduplicator = class {
1220
- processedMessages = /* @__PURE__ */ new Set();
1219
+ var Deduplicator = class {
1220
+ processedEvents = /* @__PURE__ */ new Set();
1221
1221
  maxSize = 1e3;
1222
1222
  /**
1223
- * 生成消息唯一键
1224
- * 对于群消息:使用 group_id:user_id:time
1225
- * 对于私聊消息:使用 private:user_id:time
1223
+ * 获取事件类型键
1226
1224
  */
1227
- getKey(event) {
1228
- if (event.message_type === "group") return `group:${event.group_id}:${event.user_id}:${event.time}`;
1229
- else return `private:${event.user_id}:${event.time}`;
1225
+ getEventTypeKey(e) {
1226
+ const { post_type } = e;
1227
+ if (post_type === "message") return `msg:${e.message_type}`;
1228
+ if (post_type === "request") {
1229
+ if (e.request_type === "friend") return "req:friend";
1230
+ return `req:group:${e.sub_type ?? "unknown"}`;
1231
+ }
1232
+ if (post_type === "notice") {
1233
+ if (e.notice_type === "group") return `notice:group:${e.sub_type}`;
1234
+ return `notice:${e.notice_type}:${e.sub_type}`;
1235
+ }
1236
+ return "unknown";
1230
1237
  }
1231
- isProcessed(event) {
1232
- return this.processedMessages.has(this.getKey(event));
1238
+ getGroupMessageKey(e) {
1239
+ const groupId = e.group_id ?? "_";
1240
+ const userId = e.user_id ?? "_";
1241
+ const time = e.time ?? "_";
1242
+ const raw = e.raw_message ?? "_";
1243
+ return `msg:group:${groupId}:${userId}:${time}:${crypto.createHash("md5").update(raw).digest("hex")}`;
1233
1244
  }
1234
- markProcessed(event) {
1235
- if (this.processedMessages.size >= this.maxSize) {
1236
- const first = this.processedMessages.values().next();
1237
- if (!first.done) this.processedMessages.delete(first.value);
1245
+ getPrivateMessageKey(e) {
1246
+ const userId = e.user_id ?? "_";
1247
+ const targetId = e.target_id ?? "_";
1248
+ const time = e.time ?? "_";
1249
+ const raw = e.raw_message ?? "_";
1250
+ return `msg:private:${userId}:${targetId}:${time}:${crypto.createHash("md5").update(raw).digest("hex")}`;
1251
+ }
1252
+ getNoticeGroupKey(e) {
1253
+ return `${this.getEventTypeKey(e)}:${e.group_id ?? "_"}:${e.user_id ?? "_"}:${"operator_id" in e ? e.operator_id ?? "_" : "_"}:${"target_id" in e ? e.target_id ?? "_" : "_"}:${e.sub_type ?? "_"}:${"action_type" in e ? e.action_type ?? "_" : "_"}:${"duration" in e ? e.duration ?? "_" : "_"}:${e.time ?? "_"}`;
1254
+ }
1255
+ getRequestKey(e) {
1256
+ const typeKey = this.getEventTypeKey(e);
1257
+ const userId = e.user_id ?? "_";
1258
+ const groupId = "group_id" in e ? e.group_id ?? "_" : "_";
1259
+ const time = e.time ?? "_";
1260
+ const comment = e.comment ?? "_";
1261
+ return `${typeKey}:${userId}:${groupId}:${time}:${comment ? crypto.createHash("md5").update(comment).digest("hex") : "_"}`;
1262
+ }
1263
+ /**
1264
+ * 生成事件唯一键
1265
+ */
1266
+ getKey(e) {
1267
+ const typeKey = this.getEventTypeKey(e);
1268
+ if (typeKey === "msg:group") return this.getGroupMessageKey(e);
1269
+ if (typeKey === "msg:private") return this.getPrivateMessageKey(e);
1270
+ if (typeKey.startsWith("notice:group:")) return this.getNoticeGroupKey(e);
1271
+ if (typeKey.startsWith("req:")) return this.getRequestKey(e);
1272
+ return "";
1273
+ }
1274
+ /**
1275
+ * 检查事件是否已处理过
1276
+ * @param event
1277
+ * @param scope
1278
+ */
1279
+ isProcessed(event, scope) {
1280
+ const key = scope ? `${this.getKey(event)}:${scope}` : this.getKey(event);
1281
+ return this.processedEvents.has(key);
1282
+ }
1283
+ /**
1284
+ * 标记事件为已处理
1285
+ * @param event
1286
+ * @param scope 需与 isProcessed 一致
1287
+ */
1288
+ markProcessed(event, scope) {
1289
+ const key = scope ? `${this.getKey(event)}:${scope}` : this.getKey(event);
1290
+ if (this.processedEvents.size >= this.maxSize) {
1291
+ const first = this.processedEvents.values().next();
1292
+ if (!first.done) this.processedEvents.delete(first.value);
1238
1293
  }
1239
- this.processedMessages.add(this.getKey(event));
1294
+ this.processedEvents.add(key);
1240
1295
  }
1241
- clear() {
1242
- this.processedMessages.clear();
1296
+ };
1297
+ /**
1298
+ * 消息去重器
1299
+ * @deprecated 请使用 Deduplicator,它支持更多事件类型
1300
+ */
1301
+ var MessageDeduplicator = class extends Deduplicator {
1302
+ isProcessed(event) {
1303
+ return super.isProcessed(event);
1304
+ }
1305
+ markProcessed(event) {
1306
+ super.markProcessed(event);
1243
1307
  }
1244
1308
  };
1245
- const deduplicator = new MessageDeduplicator();
1309
+ const deduplicator = new Deduplicator();
1246
1310
  const runtimePlugins = /* @__PURE__ */ new Map();
1247
1311
  const buildRemovedActions = (bot) => Object.fromEntries(Object.entries(actions_exports).map(([k, v]) => [k, bindBot(bot, v)]));
1248
1312
  /**
@@ -1264,6 +1328,24 @@ function isMessageEvent(event) {
1264
1328
  return isGroupMessageEvent(event) || isPrivateMessageEvent(event);
1265
1329
  }
1266
1330
  /**
1331
+ * 检查事件是否是请求事件
1332
+ */
1333
+ function isRequestEvent(event) {
1334
+ return event?.post_type === "request";
1335
+ }
1336
+ /**
1337
+ * 检查事件是否是群通知事件
1338
+ */
1339
+ function isGroupNoticeEvent(event) {
1340
+ return event?.post_type === "notice" && event?.notice_type === "group";
1341
+ }
1342
+ /**
1343
+ * 检查事件是否需要去重
1344
+ */
1345
+ function isDeduplicableEvent(event) {
1346
+ return isMessageEvent(event) || isRequestEvent(event) || isGroupNoticeEvent(event);
1347
+ }
1348
+ /**
1267
1349
  * 定义一个 Mioki 插件
1268
1350
  * @param plugin Mioki 插件对象
1269
1351
  * @returns Mioki 插件对象
@@ -1314,22 +1396,26 @@ async function enablePlugin(bots, plugin, type = "external") {
1314
1396
  clears.add(remove);
1315
1397
  return remove;
1316
1398
  },
1317
- handle: (eventName, handler) => {
1399
+ handle: (eventName, handler, options = {}) => {
1318
1400
  logger$1.debug(`Registering event handler for event: ${String(eventName)}`);
1401
+ const { deduplicate = true } = options;
1402
+ const dedupeScope = `${name}:${String(eventName)}:${crypto.randomUUID()}`;
1319
1403
  const unsubscribes = [];
1320
1404
  for (const bot$1 of bots) {
1321
- const wrappedHandler = (event) => {
1322
- if (isMessageEvent(event)) {
1323
- const messageEvent = event;
1324
- if (isPrivateMessageEvent(messageEvent)) {
1325
- if (messageEvent.self_id !== bot$1.bot_id) return;
1326
- }
1327
- if (isGroupMessageEvent(messageEvent)) {
1328
- if (deduplicator.isProcessed(messageEvent)) return;
1329
- deduplicator.markProcessed(messageEvent);
1330
- }
1405
+ const wrappedHandler = (e) => {
1406
+ if (isPrivateMessageEvent(e)) {
1407
+ if (e.self_id !== bot$1.bot_id) return;
1408
+ }
1409
+ const senderUserId = e.user_id;
1410
+ const senderOperatorId = e.operator_id;
1411
+ const isFromConnectedBot = senderUserId && bots.some((b) => b.bot_id === senderUserId);
1412
+ const isFromConnectedBotOperator = senderOperatorId && bots.some((b) => b.bot_id === senderOperatorId);
1413
+ if (isFromConnectedBot || isFromConnectedBotOperator) return;
1414
+ if (deduplicate && isDeduplicableEvent(e)) {
1415
+ if (deduplicator.isProcessed(e, dedupeScope)) return;
1416
+ deduplicator.markProcessed(e, dedupeScope);
1331
1417
  }
1332
- handler(event);
1418
+ handler(e);
1333
1419
  };
1334
1420
  bot$1.on(eventName, wrappedHandler);
1335
1421
  const unsubscribe = () => {
@@ -2045,5 +2131,5 @@ async function start(options = {}) {
2045
2131
  }
2046
2132
 
2047
2133
  //#endregion
2048
- export { ArchMap, BOT_CWD, BUILTIN_PLUGINS, CORE_PLUGINS, ChromeUA, MessageDeduplicator, START_TIME, SystemMap, addService, base64Decode, base64Encode, bindBot, botConfig, box, clamp, colorize, colors, connectedBots, createCmd, createDB, createForwardMsg, createStore, dayjs, dedent, deduplicator, definePlugin, enablePlugin, ensureBuffer, ensurePluginDir, filesize, filter, find, findLocalPlugins, formatDuration, formatMiokiStatus, formatQQLevel, fs, getAbsPluginDir, getAuthCodeViaTicket, getBfaceUrl, getGTk, getGroupAvatarLink, getImage, getImageUrl, getLogFilePath, getMentionedImage, getMentionedImageUrl, getMentionedUserId, getMinicoTokenViaAuthCode, getMiokiLogger, getMiokiStatus, getQQAvatarLink, getQuoteImage, getQuoteImageUrl, getQuoteMsg, getQuoteText, getTerminalInput, getViolationRecords, hasRight, isAdmin, isBoolean, isDefined, isFunction, isGroupMsg, isInPm2, isNumber, isObject, isOwner, isOwnerOrAdmin, isPrivateMsg, isString, jiti, localNum, localeDate, localeTime, logger, match, md5, mri, noNullish, normalizeNapCatConfig, noticeAdmins, noticeFriends, noticeGroups, noticeMainOwner, noticeOwners, path, prettyMs, qs, queryDevToolsLoginStatus, randomId, randomInt, randomItem, randomItems, readMiokiConfig, readPackageJson, requestLoginViaDevTools, runWithErrorHandler, runWithReaction, runtimePlugins, services, signArk, start, string2argv, stringifyError, stripAnsi, systemInfo, text, toArray, toMsgId, unique, updateBotCWD, updateBotConfig, uploadImageToCollection, uploadImageToGroupHomework, uploadImageToGroupNotice, uuid, wait, writePackageJson };
2134
+ export { ArchMap, BOT_CWD, BUILTIN_PLUGINS, CORE_PLUGINS, ChromeUA, Deduplicator, MessageDeduplicator, START_TIME, SystemMap, addService, base64Decode, base64Encode, bindBot, botConfig, box, clamp, colorize, colors, connectedBots, createCmd, createDB, createForwardMsg, createStore, dayjs, dedent, deduplicator, definePlugin, enablePlugin, ensureBuffer, ensurePluginDir, filesize, filter, find, findLocalPlugins, formatDuration, formatMiokiStatus, formatQQLevel, fs, getAbsPluginDir, getAuthCodeViaTicket, getBfaceUrl, getGTk, getGroupAvatarLink, getImage, getImageUrl, getLogFilePath, getMentionedImage, getMentionedImageUrl, getMentionedUserId, getMinicoTokenViaAuthCode, getMiokiLogger, getMiokiStatus, getQQAvatarLink, getQuoteImage, getQuoteImageUrl, getQuoteMsg, getQuoteText, getTerminalInput, getViolationRecords, hasRight, isAdmin, isBoolean, isDefined, isFunction, isGroupMsg, isInPm2, isNumber, isObject, isOwner, isOwnerOrAdmin, isPrivateMsg, isString, jiti, localNum, localeDate, localeTime, logger, match, md5, mri, noNullish, normalizeNapCatConfig, noticeAdmins, noticeFriends, noticeGroups, noticeMainOwner, noticeOwners, path, prettyMs, qs, queryDevToolsLoginStatus, randomId, randomInt, randomItem, randomItems, readMiokiConfig, readPackageJson, requestLoginViaDevTools, runWithErrorHandler, runWithReaction, runtimePlugins, services, signArk, start, string2argv, stringifyError, stripAnsi, systemInfo, text, toArray, toMsgId, unique, updateBotCWD, updateBotConfig, uploadImageToCollection, uploadImageToGroupHomework, uploadImageToGroupNotice, uuid, wait, writePackageJson };
2049
2135
  //# sourceMappingURL=index.mjs.map