170 lines
5.4 KiB
TypeScript
170 lines
5.4 KiB
TypeScript
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
|
|
|
|
import type { ClawdbotConfig } from "../../config/config.js";
|
|
import {
|
|
deleteSlackMessage,
|
|
editSlackMessage,
|
|
getSlackMemberInfo,
|
|
listSlackEmojis,
|
|
listSlackPins,
|
|
listSlackReactions,
|
|
pinSlackMessage,
|
|
reactSlackMessage,
|
|
readSlackMessages,
|
|
removeOwnSlackReactions,
|
|
removeSlackReaction,
|
|
sendSlackMessage,
|
|
unpinSlackMessage,
|
|
} from "../../slack/actions.js";
|
|
import {
|
|
createActionGate,
|
|
jsonResult,
|
|
readReactionParams,
|
|
readStringParam,
|
|
} from "./common.js";
|
|
|
|
const messagingActions = new Set([
|
|
"sendMessage",
|
|
"editMessage",
|
|
"deleteMessage",
|
|
"readMessages",
|
|
]);
|
|
|
|
const reactionsActions = new Set(["react", "reactions"]);
|
|
const pinActions = new Set(["pinMessage", "unpinMessage", "listPins"]);
|
|
|
|
export async function handleSlackAction(
|
|
params: Record<string, unknown>,
|
|
cfg: ClawdbotConfig,
|
|
): Promise<AgentToolResult<unknown>> {
|
|
const action = readStringParam(params, "action", { required: true });
|
|
const isActionEnabled = createActionGate(cfg.slack?.actions);
|
|
|
|
if (reactionsActions.has(action)) {
|
|
if (!isActionEnabled("reactions")) {
|
|
throw new Error("Slack reactions are disabled.");
|
|
}
|
|
const channelId = readStringParam(params, "channelId", { required: true });
|
|
const messageId = readStringParam(params, "messageId", { required: true });
|
|
if (action === "react") {
|
|
const { emoji, remove, isEmpty } = readReactionParams(params, {
|
|
removeErrorMessage: "Emoji is required to remove a Slack reaction.",
|
|
});
|
|
if (remove) {
|
|
await removeSlackReaction(channelId, messageId, emoji);
|
|
return jsonResult({ ok: true, removed: emoji });
|
|
}
|
|
if (isEmpty) {
|
|
const removed = await removeOwnSlackReactions(channelId, messageId);
|
|
return jsonResult({ ok: true, removed });
|
|
}
|
|
await reactSlackMessage(channelId, messageId, emoji);
|
|
return jsonResult({ ok: true, added: emoji });
|
|
}
|
|
const reactions = await listSlackReactions(channelId, messageId);
|
|
return jsonResult({ ok: true, reactions });
|
|
}
|
|
|
|
if (messagingActions.has(action)) {
|
|
if (!isActionEnabled("messages")) {
|
|
throw new Error("Slack messages are disabled.");
|
|
}
|
|
switch (action) {
|
|
case "sendMessage": {
|
|
const to = readStringParam(params, "to", { required: true });
|
|
const content = readStringParam(params, "content", { required: true });
|
|
const mediaUrl = readStringParam(params, "mediaUrl");
|
|
const result = await sendSlackMessage(to, content, {
|
|
mediaUrl: mediaUrl ?? undefined,
|
|
});
|
|
return jsonResult({ ok: true, result });
|
|
}
|
|
case "editMessage": {
|
|
const channelId = readStringParam(params, "channelId", {
|
|
required: true,
|
|
});
|
|
const messageId = readStringParam(params, "messageId", {
|
|
required: true,
|
|
});
|
|
const content = readStringParam(params, "content", {
|
|
required: true,
|
|
});
|
|
await editSlackMessage(channelId, messageId, content);
|
|
return jsonResult({ ok: true });
|
|
}
|
|
case "deleteMessage": {
|
|
const channelId = readStringParam(params, "channelId", {
|
|
required: true,
|
|
});
|
|
const messageId = readStringParam(params, "messageId", {
|
|
required: true,
|
|
});
|
|
await deleteSlackMessage(channelId, messageId);
|
|
return jsonResult({ ok: true });
|
|
}
|
|
case "readMessages": {
|
|
const channelId = readStringParam(params, "channelId", {
|
|
required: true,
|
|
});
|
|
const limitRaw = params.limit;
|
|
const limit =
|
|
typeof limitRaw === "number" && Number.isFinite(limitRaw)
|
|
? limitRaw
|
|
: undefined;
|
|
const before = readStringParam(params, "before");
|
|
const after = readStringParam(params, "after");
|
|
const result = await readSlackMessages(channelId, {
|
|
limit,
|
|
before: before ?? undefined,
|
|
after: after ?? undefined,
|
|
});
|
|
return jsonResult({ ok: true, ...result });
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pinActions.has(action)) {
|
|
if (!isActionEnabled("pins")) {
|
|
throw new Error("Slack pins are disabled.");
|
|
}
|
|
const channelId = readStringParam(params, "channelId", { required: true });
|
|
if (action === "pinMessage") {
|
|
const messageId = readStringParam(params, "messageId", {
|
|
required: true,
|
|
});
|
|
await pinSlackMessage(channelId, messageId);
|
|
return jsonResult({ ok: true });
|
|
}
|
|
if (action === "unpinMessage") {
|
|
const messageId = readStringParam(params, "messageId", {
|
|
required: true,
|
|
});
|
|
await unpinSlackMessage(channelId, messageId);
|
|
return jsonResult({ ok: true });
|
|
}
|
|
const pins = await listSlackPins(channelId);
|
|
return jsonResult({ ok: true, pins });
|
|
}
|
|
|
|
if (action === "memberInfo") {
|
|
if (!isActionEnabled("memberInfo")) {
|
|
throw new Error("Slack member info is disabled.");
|
|
}
|
|
const userId = readStringParam(params, "userId", { required: true });
|
|
const info = await getSlackMemberInfo(userId);
|
|
return jsonResult({ ok: true, info });
|
|
}
|
|
|
|
if (action === "emojiList") {
|
|
if (!isActionEnabled("emojiList")) {
|
|
throw new Error("Slack emoji list is disabled.");
|
|
}
|
|
const emojis = await listSlackEmojis();
|
|
return jsonResult({ ok: true, emojis });
|
|
}
|
|
|
|
throw new Error(`Unknown action: ${action}`);
|
|
}
|