Merge a87796d596178b271082c1d8743ef4dfdb95707e into 5e417b44e1540f528d2ae63e3e20229a902d1db2
This commit is contained in:
commit
6a1a273ac2
@ -791,7 +791,7 @@ export async function preflightDiscordMessage(
|
||||
`[discord-preflight] shouldRequireMention=${shouldRequireMention} baseRequireMention=${shouldRequireMentionByConfig} boundThreadSession=${isBoundThreadSession} mentionGate.shouldSkip=${mentionGate.shouldSkip} wasMentioned=${wasMentioned}`,
|
||||
);
|
||||
if (isGuildMessage && shouldRequireMention) {
|
||||
if (botId && mentionGate.shouldSkip) {
|
||||
if (mentionGate.shouldSkip) {
|
||||
logDebug(`[discord-preflight] drop: no-mention`);
|
||||
logVerbose(`discord: drop guild message (mention required, botId=${botId})`);
|
||||
logger.info(
|
||||
|
||||
@ -627,4 +627,36 @@ describe("monitorDiscordProvider", () => {
|
||||
const messages = vi.mocked(runtime.log).mock.calls.map((call) => String(call[0]));
|
||||
expect(messages.some((msg) => msg.includes("discord startup ["))).toBe(false);
|
||||
});
|
||||
|
||||
it("falls back to applicationId when fetchUser('@me') fails (#42219)", async () => {
|
||||
const { monitorDiscordProvider } = await import("./provider.js");
|
||||
const runtime = baseRuntime();
|
||||
|
||||
clientFetchUserMock.mockRejectedValueOnce(new Error("network timeout"));
|
||||
|
||||
// Should NOT throw — the code now falls back to applicationId as botUserId
|
||||
// instead of aborting. We race with a short timeout to confirm no immediate rejection.
|
||||
const result = await Promise.race([
|
||||
monitorDiscordProvider({
|
||||
config: baseConfig(),
|
||||
runtime,
|
||||
}).then(() => "resolved", (err: Error) => `rejected: ${err.message}`),
|
||||
new Promise<string>((r) => setTimeout(() => r("still-running"), 200)),
|
||||
]);
|
||||
expect(result).toBe("still-running");
|
||||
});
|
||||
|
||||
it("throws when fetchUser('@me') returns no user id", async () => {
|
||||
const { monitorDiscordProvider } = await import("./provider.js");
|
||||
const runtime = baseRuntime();
|
||||
|
||||
clientFetchUserMock.mockResolvedValueOnce({ id: undefined as unknown as string, username: "NoId" });
|
||||
|
||||
await expect(
|
||||
monitorDiscordProvider({
|
||||
config: baseConfig(),
|
||||
runtime,
|
||||
}),
|
||||
).rejects.toThrow("discord: fetchUser('@me') returned no user id");
|
||||
});
|
||||
});
|
||||
|
||||
@ -882,6 +882,20 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
|
||||
gateway: lifecycleGateway,
|
||||
details: String(err),
|
||||
});
|
||||
// Transient REST/proxy failures should not take down the whole channel.
|
||||
// applicationId is the same snowflake as the bot user id and was already
|
||||
// resolved above (with a token-decoding fallback), so we can use it for
|
||||
// mention gating and self-message filtering. botUserName is only used for
|
||||
// logging and is non-critical.
|
||||
botUserId = applicationId;
|
||||
runtime.warn?.(
|
||||
`discord: using applicationId as botUserId fallback (fetchUser failed: ${String(err)})`,
|
||||
);
|
||||
}
|
||||
if (!botUserId) {
|
||||
// fetchUser succeeded but returned no id and applicationId is also missing —
|
||||
// this should not happen in practice.
|
||||
throw new Error("discord: fetchUser('@me') returned no user id");
|
||||
}
|
||||
|
||||
if (voiceEnabled) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user