Discord: dedupe listener registration on reload

Closes #744
This commit is contained in:
Shadow
2026-01-12 21:41:47 -06:00
parent cddd836909
commit 9f1f65f0e3
3 changed files with 33 additions and 3 deletions

View File

@@ -7,6 +7,7 @@
- Memory: allow custom OpenAI-compatible embedding endpoints for memory search (remote baseUrl/apiKey/headers). (#819 — thanks @mukhtharcm)
### Fixes
- Discord: avoid duplicate message/reaction listeners on monitor reloads. (#744 — thanks @thewilloftheshadow)
- System events: include local timestamps when events are injected into prompts. (#245 — thanks @thewilloftheshadow)
- Cron: accept `jobId` aliases for cron update/run/remove params in gateway validation. (#252 — thanks @thewilloftheshadow)
- Models/Google: normalize Gemini 3 model ids to preview variants before runtime selection. (#795 — thanks @thewilloftheshadow)

View File

@@ -7,6 +7,7 @@ import {
isDiscordGroupAllowedByPolicy,
normalizeDiscordAllowList,
normalizeDiscordSlug,
registerDiscordListener,
resolveDiscordChannelConfig,
resolveDiscordGuildEntry,
resolveDiscordReplyTarget,
@@ -34,6 +35,18 @@ const makeEntries = (
return out;
};
describe("registerDiscordListener", () => {
class FakeListener {}
it("dedupes listeners by constructor", () => {
const listeners: object[] = [];
expect(registerDiscordListener(listeners, new FakeListener())).toBe(true);
expect(registerDiscordListener(listeners, new FakeListener())).toBe(false);
expect(listeners).toHaveLength(1);
});
});
describe("discord allowlist helpers", () => {
it("normalizes slugs", () => {
expect(normalizeDiscordSlug("Friends of Clawd")).toBe("friends-of-clawd");

View File

@@ -175,6 +175,17 @@ function logSlowDiscordListener(params: {
}
}
export function registerDiscordListener(
listeners: Array<object>,
listener: object,
) {
if (listeners.some((existing) => existing.constructor === listener.constructor)) {
return false;
}
listeners.push(listener);
return true;
}
async function resolveDiscordThreadStarter(params: {
channel: DiscordThreadChannel;
client: Client;
@@ -602,8 +613,12 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
guildEntries,
});
client.listeners.push(new DiscordMessageListener(messageHandler, logger));
client.listeners.push(
registerDiscordListener(
client.listeners,
new DiscordMessageListener(messageHandler, logger),
);
registerDiscordListener(
client.listeners,
new DiscordReactionListener({
cfg,
accountId: account.accountId,
@@ -613,7 +628,8 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
logger,
}),
);
client.listeners.push(
registerDiscordListener(
client.listeners,
new DiscordReactionRemoveListener({
cfg,
accountId: account.accountId,