mirror of https://github.com/openclaw/openclaw.git
telegram: add dedicated topic-delete action
This commit is contained in:
parent
6ab5c55716
commit
f70d58cd9d
|
|
@ -428,8 +428,10 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
|||
- `editMessage` (`chatId`, `messageId`, `content`)
|
||||
- `createForumTopic` (`chatId`, `name`, optional `iconColor`, `iconCustomEmojiId`)
|
||||
|
||||
Channel message actions expose ergonomic aliases (`send`, `react`, `delete`, `edit`, `sticker`, `sticker-search`, `topic-create`).
|
||||
For `delete`, pass `messageId` to delete a message (existing behavior), or pass `threadId`/`topicId` to delete a forum topic.
|
||||
Channel message actions expose ergonomic aliases (`send`, `react`, `delete`, `topic-delete`, `edit`, `sticker`, `sticker-search`, `topic-create`).
|
||||
- `delete`: deletes a message and requires `messageId`.
|
||||
- `topic-delete`: deletes a forum topic and requires explicit `threadId`/`topicId`.
|
||||
Backward compatibility: `delete` with explicit `threadId`/`topicId` is still accepted for now.
|
||||
|
||||
Gating controls:
|
||||
|
||||
|
|
@ -971,7 +973,7 @@ Telegram-specific high-signal fields:
|
|||
- formatting/delivery: `textChunkLimit`, `chunkMode`, `linkPreview`, `responsePrefix`
|
||||
- media/network: `mediaMaxMb`, `timeoutSeconds`, `retry`, `network.autoSelectFamily`, `proxy`
|
||||
- webhook: `webhookUrl`, `webhookSecret`, `webhookPath`, `webhookHost`
|
||||
- actions/capabilities: `capabilities.inlineButtons`, `actions.sendMessage|editMessage|deleteMessage|reactions|sticker`
|
||||
- actions/capabilities: `capabilities.inlineButtons`, `actions.sendMessage|editMessage|deleteMessage|reactions|sticker` (both `delete` and `topic-delete` route through `actions.deleteMessage`)
|
||||
- reactions: `reactionNotifications`, `reactionLevel`
|
||||
- writes/history: `configWrites`, `historyLimit`, `dmHistoryLimit`, `dms.*.historyLimit`
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import {
|
|||
resolveTelegramPollActionGateState,
|
||||
} from "./accounts.js";
|
||||
import { isTelegramInlineButtonsEnabled } from "./inline-buttons.js";
|
||||
import { parseTelegramTarget } from "./targets.js";
|
||||
|
||||
const providerId = "telegram";
|
||||
|
||||
|
|
@ -79,17 +78,10 @@ function readTelegramMessageIdParam(
|
|||
}
|
||||
|
||||
function readTelegramTopicIdParam(params: Record<string, unknown>): number | undefined {
|
||||
const explicitTopicId =
|
||||
return (
|
||||
readNumberParam(params, "topicId", { integer: true }) ??
|
||||
readNumberParam(params, "threadId", { integer: true });
|
||||
if (typeof explicitTopicId === "number") {
|
||||
return explicitTopicId;
|
||||
}
|
||||
const targetLike = readStringParam(params, "to") ?? readStringParam(params, "chatId");
|
||||
if (!targetLike) {
|
||||
return undefined;
|
||||
}
|
||||
return parseTelegramTarget(targetLike).messageThreadId;
|
||||
readNumberParam(params, "threadId", { integer: true })
|
||||
);
|
||||
}
|
||||
|
||||
export const telegramMessageActions: ChannelMessageActionAdapter = {
|
||||
|
|
@ -123,6 +115,7 @@ export const telegramMessageActions: ChannelMessageActionAdapter = {
|
|||
}
|
||||
if (isEnabled("deleteMessage")) {
|
||||
actions.add("delete");
|
||||
actions.add("topic-delete");
|
||||
}
|
||||
if (isEnabled("editMessage")) {
|
||||
actions.add("edit");
|
||||
|
|
@ -249,7 +242,25 @@ export const telegramMessageActions: ChannelMessageActionAdapter = {
|
|||
);
|
||||
}
|
||||
|
||||
throw new Error("messageId or threadId/topicId is required.");
|
||||
throw new Error("messageId is required for action=delete.");
|
||||
}
|
||||
|
||||
if (action === "topic-delete") {
|
||||
const chatId = readTelegramChatIdParam(params);
|
||||
const topicId = readTelegramTopicIdParam(params);
|
||||
if (typeof topicId !== "number") {
|
||||
throw new Error("threadId/topicId is required for action=topic-delete.");
|
||||
}
|
||||
return await handleTelegramAction(
|
||||
{
|
||||
action: "deleteForumTopic",
|
||||
chatId,
|
||||
topicId,
|
||||
accountId: accountId ?? undefined,
|
||||
},
|
||||
cfg,
|
||||
{ mediaLocalRoots },
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "edit") {
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ describe("message tool description", () => {
|
|||
label: "Telegram",
|
||||
docsPath: "/channels/telegram",
|
||||
blurb: "Telegram test plugin.",
|
||||
actions: ["send", "react", "delete", "edit", "topic-create"],
|
||||
actions: ["send", "react", "delete", "edit", "topic-create", "topic-delete"],
|
||||
});
|
||||
|
||||
setActivePluginRegistry(
|
||||
|
|
@ -372,7 +372,9 @@ describe("message tool description", () => {
|
|||
expect(tool.description).toContain("Current channel (signal) supports: react, send.");
|
||||
// Other configured channels are also listed
|
||||
expect(tool.description).toContain("Other configured channels:");
|
||||
expect(tool.description).toContain("telegram (delete, edit, react, send, topic-create)");
|
||||
expect(tool.description).toContain(
|
||||
"telegram (delete, edit, react, send, topic-create, topic-delete)",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not include 'Other configured channels' when only one channel is configured", () => {
|
||||
|
|
|
|||
|
|
@ -617,10 +617,10 @@ describe("handleTelegramAction", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("respects createForumTopic gating for deleteForumTopic", async () => {
|
||||
it("respects deleteMessage gating for deleteForumTopic", async () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
telegram: { botToken: "tok", actions: { createForumTopic: false } },
|
||||
telegram: { botToken: "tok", actions: { deleteMessage: false } },
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
await expect(
|
||||
|
|
@ -632,7 +632,7 @@ describe("handleTelegramAction", () => {
|
|||
},
|
||||
cfg,
|
||||
),
|
||||
).rejects.toThrow(/Telegram createForumTopic is disabled/);
|
||||
).rejects.toThrow(/Telegram forum topic deletion is disabled/);
|
||||
});
|
||||
|
||||
it("respects deleteMessage gating", async () => {
|
||||
|
|
|
|||
|
|
@ -343,8 +343,10 @@ export async function handleTelegramAction(
|
|||
}
|
||||
|
||||
if (action === "deleteForumTopic") {
|
||||
if (!isActionEnabled("createForumTopic")) {
|
||||
throw new Error("Telegram createForumTopic is disabled.");
|
||||
if (!isActionEnabled("deleteMessage")) {
|
||||
throw new Error(
|
||||
"Telegram forum topic deletion is disabled. Set channels.telegram.actions.deleteMessage to true.",
|
||||
);
|
||||
}
|
||||
const chatId = readStringOrNumberParam(params, "chatId", {
|
||||
required: true,
|
||||
|
|
|
|||
|
|
@ -792,8 +792,8 @@ describe("telegramMessageActions", () => {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "delete maps to deleteForumTopic when threadId is provided",
|
||||
action: "delete" as const,
|
||||
name: "topic-delete maps to deleteForumTopic when threadId is provided",
|
||||
action: "topic-delete" as const,
|
||||
params: {
|
||||
to: "-1001234567890",
|
||||
threadId: 271,
|
||||
|
|
@ -805,6 +805,20 @@ describe("telegramMessageActions", () => {
|
|||
accountId: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "delete keeps backward compatibility for explicit topic ids",
|
||||
action: "delete" as const,
|
||||
params: {
|
||||
to: "-1001234567890",
|
||||
topicId: 271,
|
||||
},
|
||||
expectedPayload: {
|
||||
action: "deleteForumTopic",
|
||||
chatId: "-1001234567890",
|
||||
topicId: 271,
|
||||
accountId: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "topic-create maps to createForumTopic",
|
||||
action: "topic-create" as const,
|
||||
|
|
@ -834,7 +848,7 @@ describe("telegramMessageActions", () => {
|
|||
}
|
||||
});
|
||||
|
||||
it("rejects delete when neither messageId nor topic/thread id is provided", async () => {
|
||||
it("rejects delete when messageId is not provided", async () => {
|
||||
const cfg = telegramCfg();
|
||||
const handleAction = telegramMessageActions.handleAction;
|
||||
if (!handleAction) {
|
||||
|
|
@ -850,7 +864,28 @@ describe("telegramMessageActions", () => {
|
|||
},
|
||||
cfg,
|
||||
}),
|
||||
).rejects.toThrow(/messageId or threadId\/topicId is required/i);
|
||||
).rejects.toThrow(/messageId is required for action=delete/i);
|
||||
|
||||
expect(handleTelegramAction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects topic-delete when threadId/topicId is missing", async () => {
|
||||
const cfg = telegramCfg();
|
||||
const handleAction = telegramMessageActions.handleAction;
|
||||
if (!handleAction) {
|
||||
throw new Error("telegram handleAction unavailable");
|
||||
}
|
||||
|
||||
await expect(
|
||||
handleAction({
|
||||
channel: "telegram",
|
||||
action: "topic-delete",
|
||||
params: {
|
||||
to: "-1001234567890",
|
||||
},
|
||||
cfg,
|
||||
}),
|
||||
).rejects.toThrow(/threadId\/topicId is required for action=topic-delete/i);
|
||||
|
||||
expect(handleTelegramAction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export const CHANNEL_MESSAGE_ACTION_NAMES = [
|
|||
"category-edit",
|
||||
"category-delete",
|
||||
"topic-create",
|
||||
"topic-delete",
|
||||
"voice-status",
|
||||
"event-list",
|
||||
"event-create",
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ export const MESSAGE_ACTION_TARGET_MODE: Record<ChannelMessageActionName, Messag
|
|||
"category-edit": "none",
|
||||
"category-delete": "none",
|
||||
"topic-create": "to",
|
||||
"topic-delete": "to",
|
||||
"voice-status": "none",
|
||||
"event-list": "none",
|
||||
"event-create": "none",
|
||||
|
|
|
|||
Loading…
Reference in New Issue