Discord: honor accountId across channel actions (refs #1489)
This commit is contained in:
@@ -3,6 +3,7 @@ import { describe, expect, it, vi } from "vitest";
|
||||
import type { ClawdbotConfig } from "../../../config/config.js";
|
||||
type SendMessageDiscord = typeof import("../../../discord/send.js").sendMessageDiscord;
|
||||
type SendPollDiscord = typeof import("../../../discord/send.js").sendPollDiscord;
|
||||
type ReactMessageDiscord = typeof import("../../../discord/send.js").reactMessageDiscord;
|
||||
|
||||
const sendMessageDiscord = vi.fn<Parameters<SendMessageDiscord>, ReturnType<SendMessageDiscord>>(
|
||||
async () => ({ ok: true }) as Awaited<ReturnType<SendMessageDiscord>>,
|
||||
@@ -10,6 +11,9 @@ const sendMessageDiscord = vi.fn<Parameters<SendMessageDiscord>, ReturnType<Send
|
||||
const sendPollDiscord = vi.fn<Parameters<SendPollDiscord>, ReturnType<SendPollDiscord>>(
|
||||
async () => ({ ok: true }) as Awaited<ReturnType<SendPollDiscord>>,
|
||||
);
|
||||
const reactMessageDiscord = vi.fn<Parameters<ReactMessageDiscord>, ReturnType<ReactMessageDiscord>>(
|
||||
async () => ({ ok: true }) as Awaited<ReturnType<ReactMessageDiscord>>,
|
||||
);
|
||||
|
||||
vi.mock("../../../discord/send.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("../../../discord/send.js")>(
|
||||
@@ -19,6 +23,7 @@ vi.mock("../../../discord/send.js", async () => {
|
||||
...actual,
|
||||
sendMessageDiscord: (...args: Parameters<SendMessageDiscord>) => sendMessageDiscord(...args),
|
||||
sendPollDiscord: (...args: Parameters<SendPollDiscord>) => sendPollDiscord(...args),
|
||||
reactMessageDiscord: (...args: Parameters<ReactMessageDiscord>) => reactMessageDiscord(...args),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -104,4 +109,29 @@ describe("handleDiscordMessageAction", () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("forwards accountId for reaction actions", async () => {
|
||||
reactMessageDiscord.mockClear();
|
||||
const handleDiscordMessageAction = await loadHandleDiscordMessageAction();
|
||||
|
||||
await handleDiscordMessageAction({
|
||||
action: "react",
|
||||
params: {
|
||||
channelId: "123",
|
||||
messageId: "m1",
|
||||
emoji: "👍",
|
||||
},
|
||||
cfg: {} as ClawdbotConfig,
|
||||
accountId: "ops",
|
||||
});
|
||||
|
||||
expect(reactMessageDiscord).toHaveBeenCalledWith(
|
||||
"123",
|
||||
"m1",
|
||||
"👍",
|
||||
expect.objectContaining({
|
||||
accountId: "ops",
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
import { handleDiscordAction } from "../../../../agents/tools/discord-actions.js";
|
||||
import type { ChannelMessageActionContext } from "../../types.js";
|
||||
|
||||
type Ctx = Pick<ChannelMessageActionContext, "action" | "params" | "cfg">;
|
||||
type Ctx = Pick<ChannelMessageActionContext, "action" | "params" | "cfg" | "accountId">;
|
||||
|
||||
export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
ctx: Ctx;
|
||||
@@ -16,27 +16,38 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
}): Promise<AgentToolResult<unknown> | undefined> {
|
||||
const { ctx, resolveChannelId, readParentIdParam } = params;
|
||||
const { action, params: actionParams, cfg } = ctx;
|
||||
const accountId = ctx.accountId ?? readStringParam(actionParams, "accountId");
|
||||
const accountIdParam = accountId ?? undefined;
|
||||
|
||||
if (action === "member-info") {
|
||||
const userId = readStringParam(actionParams, "userId", { required: true });
|
||||
const guildId = readStringParam(actionParams, "guildId", {
|
||||
required: true,
|
||||
});
|
||||
return await handleDiscordAction({ action: "memberInfo", guildId, userId }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "memberInfo", accountId: accountIdParam, guildId, userId },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "role-info") {
|
||||
const guildId = readStringParam(actionParams, "guildId", {
|
||||
required: true,
|
||||
});
|
||||
return await handleDiscordAction({ action: "roleInfo", guildId }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "roleInfo", accountId: accountIdParam, guildId },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "emoji-list") {
|
||||
const guildId = readStringParam(actionParams, "guildId", {
|
||||
required: true,
|
||||
});
|
||||
return await handleDiscordAction({ action: "emojiList", guildId }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "emojiList", accountId: accountIdParam, guildId },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "emoji-upload") {
|
||||
@@ -50,7 +61,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
});
|
||||
const roleIds = readStringArrayParam(actionParams, "roleIds");
|
||||
return await handleDiscordAction(
|
||||
{ action: "emojiUpload", guildId, name, mediaUrl, roleIds },
|
||||
{ action: "emojiUpload", accountId: accountIdParam, guildId, name, mediaUrl, roleIds },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
@@ -73,7 +84,15 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
trim: false,
|
||||
});
|
||||
return await handleDiscordAction(
|
||||
{ action: "stickerUpload", guildId, name, description, tags, mediaUrl },
|
||||
{
|
||||
action: "stickerUpload",
|
||||
accountId: accountIdParam,
|
||||
guildId,
|
||||
name,
|
||||
description,
|
||||
tags,
|
||||
mediaUrl,
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
@@ -87,6 +106,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: action === "role-add" ? "roleAdd" : "roleRemove",
|
||||
accountId: accountIdParam,
|
||||
guildId,
|
||||
userId,
|
||||
roleId,
|
||||
@@ -99,14 +119,20 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
const channelId = readStringParam(actionParams, "channelId", {
|
||||
required: true,
|
||||
});
|
||||
return await handleDiscordAction({ action: "channelInfo", channelId }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "channelInfo", accountId: accountIdParam, channelId },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "channel-list") {
|
||||
const guildId = readStringParam(actionParams, "guildId", {
|
||||
required: true,
|
||||
});
|
||||
return await handleDiscordAction({ action: "channelList", guildId }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "channelList", accountId: accountIdParam, guildId },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "channel-create") {
|
||||
@@ -124,6 +150,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "channelCreate",
|
||||
accountId: accountIdParam,
|
||||
guildId,
|
||||
name,
|
||||
type: type ?? undefined,
|
||||
@@ -153,6 +180,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "channelEdit",
|
||||
accountId: accountIdParam,
|
||||
channelId,
|
||||
name: name ?? undefined,
|
||||
topic: topic ?? undefined,
|
||||
@@ -169,7 +197,10 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
const channelId = readStringParam(actionParams, "channelId", {
|
||||
required: true,
|
||||
});
|
||||
return await handleDiscordAction({ action: "channelDelete", channelId }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "channelDelete", accountId: accountIdParam, channelId },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "channel-move") {
|
||||
@@ -186,6 +217,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "channelMove",
|
||||
accountId: accountIdParam,
|
||||
guildId,
|
||||
channelId,
|
||||
parentId: parentId === undefined ? undefined : parentId,
|
||||
@@ -206,6 +238,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "categoryCreate",
|
||||
accountId: accountIdParam,
|
||||
guildId,
|
||||
name,
|
||||
position: position ?? undefined,
|
||||
@@ -225,6 +258,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "categoryEdit",
|
||||
accountId: accountIdParam,
|
||||
categoryId,
|
||||
name: name ?? undefined,
|
||||
position: position ?? undefined,
|
||||
@@ -237,7 +271,10 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
const categoryId = readStringParam(actionParams, "categoryId", {
|
||||
required: true,
|
||||
});
|
||||
return await handleDiscordAction({ action: "categoryDelete", categoryId }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "categoryDelete", accountId: accountIdParam, categoryId },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "voice-status") {
|
||||
@@ -245,14 +282,20 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
required: true,
|
||||
});
|
||||
const userId = readStringParam(actionParams, "userId", { required: true });
|
||||
return await handleDiscordAction({ action: "voiceStatus", guildId, userId }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "voiceStatus", accountId: accountIdParam, guildId, userId },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "event-list") {
|
||||
const guildId = readStringParam(actionParams, "guildId", {
|
||||
required: true,
|
||||
});
|
||||
return await handleDiscordAction({ action: "eventList", guildId }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "eventList", accountId: accountIdParam, guildId },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "event-create") {
|
||||
@@ -271,6 +314,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "eventCreate",
|
||||
accountId: accountIdParam,
|
||||
guildId,
|
||||
name,
|
||||
startTime,
|
||||
@@ -301,6 +345,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: discordAction,
|
||||
accountId: accountIdParam,
|
||||
guildId,
|
||||
userId,
|
||||
durationMinutes,
|
||||
@@ -325,6 +370,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "threadList",
|
||||
accountId: accountIdParam,
|
||||
guildId,
|
||||
channelId,
|
||||
includeArchived,
|
||||
@@ -344,6 +390,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "threadReply",
|
||||
accountId: accountIdParam,
|
||||
channelId: resolveChannelId(),
|
||||
content,
|
||||
mediaUrl: mediaUrl ?? undefined,
|
||||
@@ -361,6 +408,7 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: {
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "searchMessages",
|
||||
accountId: accountIdParam,
|
||||
guildId,
|
||||
content: query,
|
||||
channelId: readStringParam(actionParams, "channelId"),
|
||||
|
||||
@@ -22,6 +22,7 @@ export async function handleDiscordMessageAction(
|
||||
): Promise<AgentToolResult<unknown>> {
|
||||
const { action, params, cfg } = ctx;
|
||||
const accountId = ctx.accountId ?? readStringParam(params, "accountId");
|
||||
const accountIdParam = accountId ?? undefined;
|
||||
|
||||
const resolveChannelId = () =>
|
||||
resolveDiscordChannelId(
|
||||
@@ -40,7 +41,7 @@ export async function handleDiscordMessageAction(
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "sendMessage",
|
||||
accountId: accountId ?? undefined,
|
||||
accountId: accountIdParam,
|
||||
to,
|
||||
content,
|
||||
mediaUrl: mediaUrl ?? undefined,
|
||||
@@ -64,7 +65,7 @@ export async function handleDiscordMessageAction(
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "poll",
|
||||
accountId: accountId ?? undefined,
|
||||
accountId: accountIdParam,
|
||||
to,
|
||||
question,
|
||||
answers,
|
||||
@@ -83,6 +84,7 @@ export async function handleDiscordMessageAction(
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "react",
|
||||
accountId: accountIdParam,
|
||||
channelId: resolveChannelId(),
|
||||
messageId,
|
||||
emoji,
|
||||
@@ -96,7 +98,13 @@ export async function handleDiscordMessageAction(
|
||||
const messageId = readStringParam(params, "messageId", { required: true });
|
||||
const limit = readNumberParam(params, "limit", { integer: true });
|
||||
return await handleDiscordAction(
|
||||
{ action: "reactions", channelId: resolveChannelId(), messageId, limit },
|
||||
{
|
||||
action: "reactions",
|
||||
accountId: accountIdParam,
|
||||
channelId: resolveChannelId(),
|
||||
messageId,
|
||||
limit,
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
@@ -106,6 +114,7 @@ export async function handleDiscordMessageAction(
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "readMessages",
|
||||
accountId: accountIdParam,
|
||||
channelId: resolveChannelId(),
|
||||
limit,
|
||||
before: readStringParam(params, "before"),
|
||||
@@ -122,6 +131,7 @@ export async function handleDiscordMessageAction(
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "editMessage",
|
||||
accountId: accountIdParam,
|
||||
channelId: resolveChannelId(),
|
||||
messageId,
|
||||
content,
|
||||
@@ -133,7 +143,12 @@ export async function handleDiscordMessageAction(
|
||||
if (action === "delete") {
|
||||
const messageId = readStringParam(params, "messageId", { required: true });
|
||||
return await handleDiscordAction(
|
||||
{ action: "deleteMessage", channelId: resolveChannelId(), messageId },
|
||||
{
|
||||
action: "deleteMessage",
|
||||
accountId: accountIdParam,
|
||||
channelId: resolveChannelId(),
|
||||
messageId,
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
@@ -144,6 +159,7 @@ export async function handleDiscordMessageAction(
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: action === "pin" ? "pinMessage" : action === "unpin" ? "unpinMessage" : "listPins",
|
||||
accountId: accountIdParam,
|
||||
channelId: resolveChannelId(),
|
||||
messageId,
|
||||
},
|
||||
@@ -152,7 +168,10 @@ export async function handleDiscordMessageAction(
|
||||
}
|
||||
|
||||
if (action === "permissions") {
|
||||
return await handleDiscordAction({ action: "permissions", channelId: resolveChannelId() }, cfg);
|
||||
return await handleDiscordAction(
|
||||
{ action: "permissions", accountId: accountIdParam, channelId: resolveChannelId() },
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "thread-create") {
|
||||
@@ -164,6 +183,7 @@ export async function handleDiscordMessageAction(
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "threadCreate",
|
||||
accountId: accountIdParam,
|
||||
channelId: resolveChannelId(),
|
||||
name,
|
||||
messageId,
|
||||
@@ -182,6 +202,7 @@ export async function handleDiscordMessageAction(
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
action: "sticker",
|
||||
accountId: accountIdParam,
|
||||
to: readStringParam(params, "to", { required: true }),
|
||||
stickerIds,
|
||||
content: readStringParam(params, "message"),
|
||||
|
||||
Reference in New Issue
Block a user