mioki 0.14.0 → 0.15.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.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,49 @@ 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 getNoticeGroupKey;
661
+ private getRequestKey;
662
+ /**
663
+ * 生成事件唯一键
655
664
  */
656
665
  private getKey;
666
+ /**
667
+ * 检查事件是否已处理过
668
+ * @param event
669
+ * @param scope
670
+ */
671
+ isProcessed(event: DeduplicableEvent, scope?: string): boolean;
672
+ /**
673
+ * 标记事件为已处理
674
+ * @param event
675
+ * @param scope 需与 isProcessed 一致
676
+ */
677
+ markProcessed(event: DeduplicableEvent, scope?: string): void;
678
+ }
679
+ /**
680
+ * 消息去重器
681
+ * @deprecated 请使用 Deduplicator,它支持更多事件类型
682
+ */
683
+ declare class MessageDeduplicator extends Deduplicator {
657
684
  isProcessed(event: GroupMessageEvent | PrivateMessageEvent): boolean;
658
685
  markProcessed(event: GroupMessageEvent | PrivateMessageEvent): void;
659
- clear(): void;
660
686
  }
661
- declare const deduplicator: MessageDeduplicator;
687
+ declare const deduplicator: Deduplicator;
662
688
  /**
663
689
  * Mioki 上下文对象,包含 Mioki 运行时的信息和方法
664
690
  */
@@ -674,15 +700,15 @@ interface MiokiContext extends Services, Configs, Utils, RemoveBotParam<Actions>
674
700
  /** 通过域名获取 Cookies */
675
701
  getCookie: NapCat['getCookie'];
676
702
  /** 注册事件处理器 */
677
- handle: <EventName extends keyof EventMap>(eventName: EventName, handler: (event: EventMap[EventName]) => any) => void;
703
+ handle: <EventName extends keyof EventMap>(eventName: EventName, handler: (event: EventMap[EventName]) => any, options?: HandleOptions) => () => void;
678
704
  /** 注册定时任务 */
679
705
  cron: (cronExpression: string, handler: (ctx: MiokiContext, task: TaskContext) => any) => ScheduledTask;
680
706
  /** 待清理的函数集合,在插件卸载时会被调用 */
681
707
  clears: Set<(() => any) | null | undefined>;
682
708
  /** 日志器 */
683
709
  logger: Logger;
684
- /** 消息去重器 */
685
- deduplicator: MessageDeduplicator;
710
+ /** 事件去重器 */
711
+ deduplicator: Deduplicator;
686
712
  }
687
713
  declare const runtimePlugins: Map<string, {
688
714
  name: string;
@@ -692,6 +718,16 @@ declare const runtimePlugins: Map<string, {
692
718
  plugin: MiokiPlugin;
693
719
  disable: () => any;
694
720
  }>;
721
+ /**
722
+ * 事件处理器选项
723
+ */
724
+ interface HandleOptions {
725
+ /**
726
+ * 是否启用自动去重
727
+ * @default true
728
+ */
729
+ deduplicate?: boolean;
730
+ }
695
731
  interface MiokiPlugin {
696
732
  /** 插件 ID,请保持唯一,一般为插件目录名称,框架内部通过这个识别不同的插件 */
697
733
  name: string;
@@ -729,5 +765,5 @@ declare function findLocalPlugins(): Promise<{
729
765
  //#region src/builtins/index.d.ts
730
766
  declare const BUILTIN_PLUGINS: MiokiPlugin[];
731
767
  //#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 };
768
+ 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
769
  //# 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,49 @@ 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 getNoticeGroupKey;
659
+ private getRequestKey;
660
+ /**
661
+ * 生成事件唯一键
653
662
  */
654
663
  private getKey;
664
+ /**
665
+ * 检查事件是否已处理过
666
+ * @param event
667
+ * @param scope
668
+ */
669
+ isProcessed(event: DeduplicableEvent, scope?: string): boolean;
670
+ /**
671
+ * 标记事件为已处理
672
+ * @param event
673
+ * @param scope 需与 isProcessed 一致
674
+ */
675
+ markProcessed(event: DeduplicableEvent, scope?: string): void;
676
+ }
677
+ /**
678
+ * 消息去重器
679
+ * @deprecated 请使用 Deduplicator,它支持更多事件类型
680
+ */
681
+ declare class MessageDeduplicator extends Deduplicator {
655
682
  isProcessed(event: GroupMessageEvent | PrivateMessageEvent): boolean;
656
683
  markProcessed(event: GroupMessageEvent | PrivateMessageEvent): void;
657
- clear(): void;
658
684
  }
659
- declare const deduplicator: MessageDeduplicator;
685
+ declare const deduplicator: Deduplicator;
660
686
  /**
661
687
  * Mioki 上下文对象,包含 Mioki 运行时的信息和方法
662
688
  */
@@ -672,15 +698,15 @@ interface MiokiContext extends Services, Configs, Utils, RemoveBotParam<Actions>
672
698
  /** 通过域名获取 Cookies */
673
699
  getCookie: NapCat['getCookie'];
674
700
  /** 注册事件处理器 */
675
- handle: <EventName extends keyof EventMap>(eventName: EventName, handler: (event: EventMap[EventName]) => any) => void;
701
+ handle: <EventName extends keyof EventMap>(eventName: EventName, handler: (event: EventMap[EventName]) => any, options?: HandleOptions) => () => void;
676
702
  /** 注册定时任务 */
677
703
  cron: (cronExpression: string, handler: (ctx: MiokiContext, task: TaskContext) => any) => ScheduledTask;
678
704
  /** 待清理的函数集合,在插件卸载时会被调用 */
679
705
  clears: Set<(() => any) | null | undefined>;
680
706
  /** 日志器 */
681
707
  logger: Logger;
682
- /** 消息去重器 */
683
- deduplicator: MessageDeduplicator;
708
+ /** 事件去重器 */
709
+ deduplicator: Deduplicator;
684
710
  }
685
711
  declare const runtimePlugins: Map<string, {
686
712
  name: string;
@@ -690,6 +716,16 @@ declare const runtimePlugins: Map<string, {
690
716
  plugin: MiokiPlugin;
691
717
  disable: () => any;
692
718
  }>;
719
+ /**
720
+ * 事件处理器选项
721
+ */
722
+ interface HandleOptions {
723
+ /**
724
+ * 是否启用自动去重
725
+ * @default true
726
+ */
727
+ deduplicate?: boolean;
728
+ }
693
729
  interface MiokiPlugin {
694
730
  /** 插件 ID,请保持唯一,一般为插件目录名称,框架内部通过这个识别不同的插件 */
695
731
  name: string;
@@ -727,5 +763,5 @@ declare function findLocalPlugins(): Promise<{
727
763
  //#region src/builtins/index.d.ts
728
764
  declare const BUILTIN_PLUGINS: MiokiPlugin[];
729
765
  //#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 };
766
+ 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
767
  //# 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-B4h-fhCq.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,92 @@ 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
+ getNoticeGroupKey(e) {
1246
+ 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 ?? "_"}`;
1247
+ }
1248
+ getRequestKey(e) {
1249
+ const typeKey = this.getEventTypeKey(e);
1250
+ const userId = e.user_id ?? "_";
1251
+ const groupId = "group_id" in e ? e.group_id ?? "_" : "_";
1252
+ const time = e.time ?? "_";
1253
+ const comment = e.comment ?? "_";
1254
+ return `${typeKey}:${userId}:${groupId}:${time}:${comment ? crypto.createHash("md5").update(comment).digest("hex") : "_"}`;
1255
+ }
1256
+ /**
1257
+ * 生成事件唯一键
1258
+ */
1259
+ getKey(e) {
1260
+ const typeKey = this.getEventTypeKey(e);
1261
+ if (typeKey === "msg:group") return this.getGroupMessageKey(e);
1262
+ if (typeKey.startsWith("notice:group:")) return this.getNoticeGroupKey(e);
1263
+ if (typeKey.startsWith("req:")) return this.getRequestKey(e);
1264
+ return "";
1265
+ }
1266
+ /**
1267
+ * 检查事件是否已处理过
1268
+ * @param event
1269
+ * @param scope
1270
+ */
1271
+ isProcessed(event, scope) {
1272
+ const key = scope ? `${this.getKey(event)}:${scope}` : this.getKey(event);
1273
+ return this.processedEvents.has(key);
1274
+ }
1275
+ /**
1276
+ * 标记事件为已处理
1277
+ * @param event
1278
+ * @param scope 需与 isProcessed 一致
1279
+ */
1280
+ markProcessed(event, scope) {
1281
+ const key = scope ? `${this.getKey(event)}:${scope}` : this.getKey(event);
1282
+ if (this.processedEvents.size >= this.maxSize) {
1283
+ const first = this.processedEvents.values().next();
1284
+ if (!first.done) this.processedEvents.delete(first.value);
1238
1285
  }
1239
- this.processedMessages.add(this.getKey(event));
1286
+ this.processedEvents.add(key);
1287
+ }
1288
+ };
1289
+ /**
1290
+ * 消息去重器
1291
+ * @deprecated 请使用 Deduplicator,它支持更多事件类型
1292
+ */
1293
+ var MessageDeduplicator = class extends Deduplicator {
1294
+ isProcessed(event) {
1295
+ return super.isProcessed(event);
1240
1296
  }
1241
- clear() {
1242
- this.processedMessages.clear();
1297
+ markProcessed(event) {
1298
+ super.markProcessed(event);
1243
1299
  }
1244
1300
  };
1245
- const deduplicator = new MessageDeduplicator();
1301
+ const deduplicator = new Deduplicator();
1246
1302
  const runtimePlugins = /* @__PURE__ */ new Map();
1247
1303
  const buildRemovedActions = (bot) => Object.fromEntries(Object.entries(actions_exports).map(([k, v]) => [k, bindBot(bot, v)]));
1248
1304
  /**
@@ -1264,6 +1320,24 @@ function isMessageEvent(event) {
1264
1320
  return isGroupMessageEvent(event) || isPrivateMessageEvent(event);
1265
1321
  }
1266
1322
  /**
1323
+ * 检查事件是否是请求事件
1324
+ */
1325
+ function isRequestEvent(event) {
1326
+ return event?.post_type === "request";
1327
+ }
1328
+ /**
1329
+ * 检查事件是否是群通知事件
1330
+ */
1331
+ function isGroupNoticeEvent(event) {
1332
+ return event?.post_type === "notice" && event?.notice_type === "group";
1333
+ }
1334
+ /**
1335
+ * 检查事件是否需要去重
1336
+ */
1337
+ function isDeduplicableEvent(event) {
1338
+ return isMessageEvent(event) || isRequestEvent(event) || isGroupNoticeEvent(event);
1339
+ }
1340
+ /**
1267
1341
  * 定义一个 Mioki 插件
1268
1342
  * @param plugin Mioki 插件对象
1269
1343
  * @returns Mioki 插件对象
@@ -1314,22 +1388,26 @@ async function enablePlugin(bots, plugin, type = "external") {
1314
1388
  clears.add(remove);
1315
1389
  return remove;
1316
1390
  },
1317
- handle: (eventName, handler) => {
1391
+ handle: (eventName, handler, options = {}) => {
1318
1392
  logger$1.debug(`Registering event handler for event: ${String(eventName)}`);
1393
+ const { deduplicate = true } = options;
1394
+ const dedupeScope = `${name}:${String(eventName)}:${crypto.randomUUID()}`;
1319
1395
  const unsubscribes = [];
1320
1396
  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
- }
1397
+ const wrappedHandler = (e) => {
1398
+ if (isPrivateMessageEvent(e)) {
1399
+ if (e.self_id !== bot$1.bot_id) return;
1400
+ }
1401
+ const senderUserId = e.user_id;
1402
+ const senderOperatorId = e.operator_id;
1403
+ const isFromConnectedBot = senderUserId && bots.some((b) => b.bot_id === senderUserId);
1404
+ const isFromConnectedBotOperator = senderOperatorId && bots.some((b) => b.bot_id === senderOperatorId);
1405
+ if (isFromConnectedBot || isFromConnectedBotOperator) return;
1406
+ if (deduplicate && isDeduplicableEvent(e)) {
1407
+ if (deduplicator.isProcessed(e, dedupeScope)) return;
1408
+ deduplicator.markProcessed(e, dedupeScope);
1331
1409
  }
1332
- handler(event);
1410
+ handler(e);
1333
1411
  };
1334
1412
  bot$1.on(eventName, wrappedHandler);
1335
1413
  const unsubscribe = () => {
@@ -2045,5 +2123,5 @@ async function start(options = {}) {
2045
2123
  }
2046
2124
 
2047
2125
  //#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 };
2126
+ 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
2127
  //# sourceMappingURL=index.mjs.map