






















@@ -67,12 +67,24 @@ vi.mock("./gateway-supervisor.js", () => ({
6767}));
68686969vi.mock("./listeners.js", () => ({
70-DiscordMessageListener: function DiscordMessageListener() {},
71-DiscordInteractionListener: function DiscordInteractionListener() {},
72-DiscordPresenceListener: function DiscordPresenceListener() {},
73-DiscordReactionListener: function DiscordReactionListener() {},
74-DiscordReactionRemoveListener: function DiscordReactionRemoveListener() {},
75-DiscordThreadUpdateListener: function DiscordThreadUpdateListener() {},
70+DiscordMessageListener: function DiscordMessageListener() {
71+return { type: "message" };
72+},
73+DiscordInteractionListener: function DiscordInteractionListener() {
74+return { type: "interaction" };
75+},
76+DiscordPresenceListener: function DiscordPresenceListener() {
77+return { type: "presence" };
78+},
79+DiscordReactionListener: function DiscordReactionListener() {
80+return { type: "reaction-add" };
81+},
82+DiscordReactionRemoveListener: function DiscordReactionRemoveListener() {
83+return { type: "reaction-remove" };
84+},
85+DiscordThreadUpdateListener: function DiscordThreadUpdateListener() {
86+return { type: "thread-update" };
87+},
7688registerDiscordListener: vi.fn(),
7789}));
7890@@ -81,13 +93,19 @@ vi.mock("./presence.js", () => ({
8193}));
82948395import { createDiscordRequestClient, DISCORD_REST_TIMEOUT_MS } from "../proxy-request-client.js";
84-import { createDiscordMonitorClient, fetchDiscordBotIdentity } from "./provider.startup.js";
96+import { registerDiscordListener } from "./listeners.js";
97+import {
98+createDiscordMonitorClient,
99+fetchDiscordBotIdentity,
100+registerDiscordMonitorListeners,
101+} from "./provider.startup.js";
8510286103describe("createDiscordMonitorClient", () => {
87104beforeEach(() => {
88105registerVoiceClientSpy.mockReset();
89106waitForDiscordGatewayPluginRegistrationMock.mockReset().mockReturnValue(undefined);
90107vi.mocked(createDiscordRequestClient).mockClear();
108+vi.mocked(registerDiscordListener).mockClear();
91109});
9211093111function createRuntime() {
@@ -296,6 +314,92 @@ describe("createDiscordMonitorClient", () => {
296314});
297315});
298316317+describe("registerDiscordMonitorListeners", () => {
318+beforeEach(() => {
319+vi.mocked(registerDiscordListener).mockClear();
320+});
321+322+function createRuntime() {
323+return {
324+log: vi.fn(),
325+error: vi.fn(),
326+exit: vi.fn(),
327+};
328+}
329+330+function createListenerParams(
331+overrides: Partial<Parameters<typeof registerDiscordMonitorListeners>[0]> = {},
332+): Parameters<typeof registerDiscordMonitorListeners>[0] {
333+return {
334+cfg: {},
335+client: { listeners: [] },
336+accountId: "default",
337+discordConfig: {},
338+runtime: createRuntime(),
339+botUserId: "bot-1",
340+dmEnabled: false,
341+groupDmEnabled: false,
342+groupDmChannels: [],
343+dmPolicy: "disabled",
344+allowFrom: [],
345+groupPolicy: "allowlist",
346+guildEntries: {
347+"guild-1": {
348+id: "guild-1",
349+reactionNotifications: "off",
350+},
351+},
352+logger: {},
353+messageHandler: {},
354+ ...overrides,
355+} as Parameters<typeof registerDiscordMonitorListeners>[0];
356+}
357+358+function registeredListenerTypes() {
359+return vi.mocked(registerDiscordListener).mock.calls.map((call) => {
360+const listener = call[1] as { type?: string };
361+return listener.type;
362+});
363+}
364+365+it("skips reaction listeners when every configured guild disables reactions and DMs are off", () => {
366+registerDiscordMonitorListeners(createListenerParams());
367+368+expect(registeredListenerTypes()).toEqual(["interaction", "message", "thread-update"]);
369+});
370+371+it("keeps reaction listeners when direct messages can emit reaction notifications", () => {
372+registerDiscordMonitorListeners(
373+createListenerParams({
374+dmEnabled: true,
375+}),
376+);
377+378+expect(registeredListenerTypes()).toContain("reaction-add");
379+expect(registeredListenerTypes()).toContain("reaction-remove");
380+});
381+382+it("keeps reaction listeners when a configured guild enables reaction notifications", () => {
383+registerDiscordMonitorListeners(
384+createListenerParams({
385+guildEntries: {
386+"guild-1": {
387+id: "guild-1",
388+reactionNotifications: "off",
389+},
390+"guild-2": {
391+id: "guild-2",
392+reactionNotifications: "own",
393+},
394+},
395+}),
396+);
397+398+expect(registeredListenerTypes()).toContain("reaction-add");
399+expect(registeredListenerTypes()).toContain("reaction-remove");
400+});
401+});
402+299403describe("fetchDiscordBotIdentity", () => {
300404it("derives the bot id from a Discord bot token without calling /users/@me", async () => {
301405const fetchUser = vi.fn(async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。