Merge 1d6780f5f4 into 4583f88626
This commit is contained in:
commit
db612e920c
@ -5,10 +5,12 @@ import { resolveSlackAccount } from "../../slack/accounts.js";
|
|||||||
import {
|
import {
|
||||||
deleteSlackMessage,
|
deleteSlackMessage,
|
||||||
editSlackMessage,
|
editSlackMessage,
|
||||||
|
getSlackChannelInfo,
|
||||||
getSlackMemberInfo,
|
getSlackMemberInfo,
|
||||||
listSlackEmojis,
|
listSlackEmojis,
|
||||||
listSlackPins,
|
listSlackPins,
|
||||||
listSlackReactions,
|
listSlackReactions,
|
||||||
|
markSlackChannelRead,
|
||||||
pinSlackMessage,
|
pinSlackMessage,
|
||||||
reactSlackMessage,
|
reactSlackMessage,
|
||||||
readSlackMessages,
|
readSlackMessages,
|
||||||
@ -296,5 +298,30 @@ export async function handleSlackAction(
|
|||||||
return jsonResult({ ok: true, emojis });
|
return jsonResult({ ok: true, emojis });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action === "channelInfo") {
|
||||||
|
if (!isActionEnabled("channelInfo")) {
|
||||||
|
throw new Error("Slack channel info is disabled.");
|
||||||
|
}
|
||||||
|
const channelId = resolveChannelId();
|
||||||
|
const info = readOpts
|
||||||
|
? await getSlackChannelInfo(channelId, readOpts)
|
||||||
|
: await getSlackChannelInfo(channelId);
|
||||||
|
return jsonResult({ ok: true, ...info });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === "markRead") {
|
||||||
|
if (!isActionEnabled("channelInfo")) {
|
||||||
|
throw new Error("Slack channel info is disabled.");
|
||||||
|
}
|
||||||
|
const channelId = resolveChannelId();
|
||||||
|
const timestamp = readStringParam(params, "timestamp", { required: true });
|
||||||
|
if (writeOpts) {
|
||||||
|
await markSlackChannelRead(channelId, timestamp, writeOpts);
|
||||||
|
} else {
|
||||||
|
await markSlackChannelRead(channelId, timestamp);
|
||||||
|
}
|
||||||
|
return jsonResult({ ok: true, markedAt: timestamp });
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(`Unknown action: ${action}`);
|
throw new Error(`Unknown action: ${action}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ export const CHANNEL_MESSAGE_ACTION_NAMES = [
|
|||||||
"role-add",
|
"role-add",
|
||||||
"role-remove",
|
"role-remove",
|
||||||
"channel-info",
|
"channel-info",
|
||||||
|
"mark-read",
|
||||||
"channel-list",
|
"channel-list",
|
||||||
"channel-create",
|
"channel-create",
|
||||||
"channel-edit",
|
"channel-edit",
|
||||||
|
|||||||
@ -46,6 +46,10 @@ export function createSlackActions(providerId: string): ChannelMessageActionAdap
|
|||||||
}
|
}
|
||||||
if (isActionEnabled("memberInfo")) actions.add("member-info");
|
if (isActionEnabled("memberInfo")) actions.add("member-info");
|
||||||
if (isActionEnabled("emojiList")) actions.add("emoji-list");
|
if (isActionEnabled("emojiList")) actions.add("emoji-list");
|
||||||
|
if (isActionEnabled("channelInfo")) {
|
||||||
|
actions.add("channel-info");
|
||||||
|
actions.add("mark-read");
|
||||||
|
}
|
||||||
return Array.from(actions);
|
return Array.from(actions);
|
||||||
},
|
},
|
||||||
extractToolSend: ({ args }): ChannelToolSend | null => {
|
extractToolSend: ({ args }): ChannelToolSend | null => {
|
||||||
@ -204,6 +208,30 @@ export function createSlackActions(providerId: string): ChannelMessageActionAdap
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action === "channel-info") {
|
||||||
|
return await handleSlackAction(
|
||||||
|
{
|
||||||
|
action: "channelInfo",
|
||||||
|
channelId: resolveChannelId(),
|
||||||
|
accountId: accountId ?? undefined,
|
||||||
|
},
|
||||||
|
cfg,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === "mark-read") {
|
||||||
|
const timestamp = readStringParam(params, "timestamp", { required: true });
|
||||||
|
return await handleSlackAction(
|
||||||
|
{
|
||||||
|
action: "markRead",
|
||||||
|
channelId: resolveChannelId(),
|
||||||
|
timestamp,
|
||||||
|
accountId: accountId ?? undefined,
|
||||||
|
},
|
||||||
|
cfg,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
|
throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -39,6 +39,7 @@ export const MESSAGE_ACTION_TARGET_MODE: Record<ChannelMessageActionName, Messag
|
|||||||
"role-add": "none",
|
"role-add": "none",
|
||||||
"role-remove": "none",
|
"role-remove": "none",
|
||||||
"channel-info": "channelId",
|
"channel-info": "channelId",
|
||||||
|
"mark-read": "channelId",
|
||||||
"channel-list": "none",
|
"channel-list": "none",
|
||||||
"channel-create": "none",
|
"channel-create": "none",
|
||||||
"channel-edit": "channelId",
|
"channel-edit": "channelId",
|
||||||
|
|||||||
@ -258,3 +258,46 @@ export async function listSlackPins(
|
|||||||
const result = await client.pins.list({ channel: channelId });
|
const result = await client.pins.list({ channel: channelId });
|
||||||
return (result.items ?? []) as SlackPin[];
|
return (result.items ?? []) as SlackPin[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SlackChannelInfo = {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
lastRead?: string;
|
||||||
|
unreadCount?: number;
|
||||||
|
unreadCountDisplay?: number;
|
||||||
|
latest?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get channel info including unread state (last_read, unread_count).
|
||||||
|
* Useful for tracking what messages the bot hasn't processed yet.
|
||||||
|
*/
|
||||||
|
export async function getSlackChannelInfo(
|
||||||
|
channelId: string,
|
||||||
|
opts: SlackActionClientOpts = {},
|
||||||
|
): Promise<SlackChannelInfo> {
|
||||||
|
const client = await getClient(opts);
|
||||||
|
const result = await client.conversations.info({ channel: channelId });
|
||||||
|
const channel = result.channel as Record<string, unknown> | undefined;
|
||||||
|
return {
|
||||||
|
id: channel?.id as string | undefined,
|
||||||
|
name: channel?.name as string | undefined,
|
||||||
|
lastRead: channel?.last_read as string | undefined,
|
||||||
|
unreadCount: channel?.unread_count as number | undefined,
|
||||||
|
unreadCountDisplay: channel?.unread_count_display as number | undefined,
|
||||||
|
latest: (channel?.latest as Record<string, unknown> | undefined)?.ts as string | undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a channel as read up to a specific timestamp.
|
||||||
|
* Updates the bot's read cursor for the channel.
|
||||||
|
*/
|
||||||
|
export async function markSlackChannelRead(
|
||||||
|
channelId: string,
|
||||||
|
timestamp: string,
|
||||||
|
opts: SlackActionClientOpts = {},
|
||||||
|
): Promise<void> {
|
||||||
|
const client = await getClient(opts);
|
||||||
|
await client.conversations.mark({ channel: channelId, ts: timestamp });
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user