Discord: bind group DM interactions by channel

This commit is contained in:
huntharo 2026-03-15 17:47:40 -04:00 committed by Vincent Koc
parent fd7c06264b
commit 329d6c8bb6
2 changed files with 41 additions and 3 deletions

View File

@ -804,9 +804,10 @@ async function dispatchPluginDiscordInteractiveEvent(params: {
fields?: Array<{ id: string; name: string; values: string[] }>;
messageId?: string;
}): Promise<"handled" | "unmatched"> {
const normalizedConversationId = params.interactionCtx.rawGuildId
? `channel:${params.interactionCtx.channelId}`
: `user:${params.interactionCtx.userId}`;
const normalizedConversationId =
params.interactionCtx.rawGuildId || params.channelCtx.channelType === ChannelType.GroupDM
? `channel:${params.interactionCtx.channelId}`
: `user:${params.interactionCtx.userId}`;
let responded = false;
const respond = {
acknowledge: async () => {

View File

@ -5,6 +5,7 @@ import type {
StringSelectMenuInteraction,
} from "@buape/carbon";
import type { Client } from "@buape/carbon";
import { ChannelType } from "discord-api-types/v10";
import type { GatewayPresenceUpdate } from "discord-api-types/v10";
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../../../src/config/config.js";
@ -641,6 +642,42 @@ describe("discord component interactions", () => {
expect(dispatchReplyMock).not.toHaveBeenCalled();
});
it("routes plugin Discord interactions in group DMs by channel id instead of sender id", async () => {
registerDiscordComponentEntries({
entries: [createButtonEntry({ callbackData: "codex:approve" })],
modals: [],
});
dispatchPluginInteractiveHandlerMock.mockResolvedValue({
matched: true,
handled: true,
duplicate: false,
});
const button = createDiscordComponentButton(createComponentContext());
const { interaction } = createComponentButtonInteraction({
rawData: {
channel_id: "group-dm-1",
id: "interaction-group-dm-1",
} as unknown as ButtonInteraction["rawData"],
channel: {
id: "group-dm-1",
type: ChannelType.GroupDM,
} as unknown as ButtonInteraction["channel"],
});
await button.run(interaction, { cid: "btn_1" } as ComponentData);
expect(dispatchPluginInteractiveHandlerMock).toHaveBeenCalledWith(
expect.objectContaining({
ctx: expect.objectContaining({
conversationId: "channel:group-dm-1",
senderId: "123456789",
}),
}),
);
expect(dispatchReplyMock).not.toHaveBeenCalled();
});
it("does not fall through to Claw when a plugin Discord interaction already replied", async () => {
registerDiscordComponentEntries({
entries: [createButtonEntry({ callbackData: "codex:approve" })],