From 984f5a51ca84ed074d56e5b007abbfb97d79a4da Mon Sep 17 00:00:00 2001 From: Masato Hoshino Date: Wed, 1 Jul 2026 02:27:53 +0900 Subject: [PATCH] fix(discord): expose sender bot status in context (#97824) * fix(discord): expose sender bot status in context * fix(discord): expose sender bot status in context --------- Co-authored-by: Vincent Koc --- .../monitor/message-handler.context.test.ts | 44 +++++++++++++++++++ .../src/monitor/message-handler.context.ts | 4 ++ 2 files changed, 48 insertions(+) create mode 100644 extensions/discord/src/monitor/message-handler.context.test.ts diff --git a/extensions/discord/src/monitor/message-handler.context.test.ts b/extensions/discord/src/monitor/message-handler.context.test.ts new file mode 100644 index 00000000000..cea8f3ea5f5 --- /dev/null +++ b/extensions/discord/src/monitor/message-handler.context.test.ts @@ -0,0 +1,44 @@ +// Discord tests cover sender bot-status forwarding into the inbound context payload. +import { describe, expect, it } from "vitest"; +import { buildDiscordMessageProcessContext } from "./message-handler.context.js"; +import { createBaseDiscordMessageContext } from "./message-handler.test-harness.js"; + +describe("discord buildDiscordMessageProcessContext sender bot status", () => { + it("forwards bot author status to ctxPayload.SenderIsBot", async () => { + const ctx = await createBaseDiscordMessageContext({ + author: { id: "U1", username: "alice", discriminator: "0", globalName: "Alice", bot: true }, + }); + + const result = await buildDiscordMessageProcessContext({ ctx, text: "hi", mediaList: [] }); + if (!result) { + throw new Error("expected a built Discord message context"); + } + + expect(result.ctxPayload.SenderIsBot).toBe(true); + }); + + it("omits SenderIsBot for human authors", async () => { + const ctx = await createBaseDiscordMessageContext(); + + const result = await buildDiscordMessageProcessContext({ ctx, text: "hi", mediaList: [] }); + if (!result) { + throw new Error("expected a built Discord message context"); + } + + expect(result.ctxPayload.SenderIsBot).toBeUndefined(); + }); + + it("omits SenderIsBot for PluralKit proxy senders despite the bot author", async () => { + const ctx = await createBaseDiscordMessageContext({ + author: { id: "U1", username: "pk", discriminator: "0", globalName: "PK", bot: true }, + sender: { label: "user", name: "Member", tag: "member", isPluralKit: true }, + }); + + const result = await buildDiscordMessageProcessContext({ ctx, text: "hi", mediaList: [] }); + if (!result) { + throw new Error("expected a built Discord message context"); + } + + expect(result.ctxPayload.SenderIsBot).toBeUndefined(); + }); +}); diff --git a/extensions/discord/src/monitor/message-handler.context.ts b/extensions/discord/src/monitor/message-handler.context.ts index e7cac9a9276..5366034ad86 100644 --- a/extensions/discord/src/monitor/message-handler.context.ts +++ b/extensions/discord/src/monitor/message-handler.context.ts @@ -335,6 +335,10 @@ export async function buildDiscordMessageProcessContext(params: { tag: sender.tag, roles: memberRoleIds, displayLabel: senderLabel, + // PluralKit proxies post under a bot author but represent a human member, + // whose identity already replaced the sender fields here; only mark + // genuine (non-PluralKit) bot authors as bots. + isBot: author.bot && !sender.isPluralKit ? true : undefined, }, conversation: { kind: isDirectMessage ? "direct" : "channel",