telegram: tighten topic alias validation and pass cfg

This commit is contained in:
OpenClaw Agent 2026-03-11 17:46:06 +01:00
parent c065d432f0
commit d8fae6c4d7
5 changed files with 76 additions and 6 deletions

View File

@ -80,10 +80,31 @@ function readTelegramMessageIdParam(
}
function readTelegramTopicIdParam(params: Record<string, unknown>): number | undefined {
return (
readNumberParam(params, "topicId", { integer: true, strict: true }) ??
readNumberParam(params, "threadId", { integer: true, strict: true })
);
const hasTopicIdParam = Object.hasOwn(params, "topicId") || Object.hasOwn(params, "topic_id");
const topicId = readNumberParam(params, "topicId", {
integer: true,
strict: true,
strictInteger: true,
});
if (hasTopicIdParam && typeof topicId !== "number") {
throw new Error("topicId must be a valid integer when provided.");
}
if (typeof topicId === "number") {
return topicId;
}
const hasThreadIdParam =
Object.hasOwn(params, "threadId") || Object.hasOwn(params, "thread_id");
const threadId = readNumberParam(params, "threadId", {
integer: true,
strict: true,
strictInteger: true,
});
if (hasThreadIdParam && typeof threadId !== "number") {
throw new Error("threadId must be a valid integer when provided.");
}
return threadId;
}
export const telegramMessageActions: ChannelMessageActionAdapter = {

View File

@ -1443,6 +1443,7 @@ export async function sendPollTelegram(
// ---------------------------------------------------------------------------
type TelegramDeleteForumTopicOpts = {
cfg?: ReturnType<typeof loadConfig>;
token?: string;
accountId?: string;
verbose?: boolean;

View File

@ -629,7 +629,7 @@ describe("handleTelegramAction", () => {
expect(deleteForumTopicTelegram).toHaveBeenCalledWith(
"-100123",
271,
expect.objectContaining({ token: "tok" }),
expect.objectContaining({ cfg, token: "tok" }),
);
});

View File

@ -359,6 +359,7 @@ export async function handleTelegramAction(
required: true,
integer: true,
strict: true,
strictInteger: true,
});
const token = resolveTelegramToken(cfg, { accountId }).token;
if (!token) {
@ -367,6 +368,7 @@ export async function handleTelegramAction(
);
}
await deleteForumTopicTelegram(chatId ?? "", topicId ?? 0, {
cfg,
token,
accountId: accountId ?? undefined,
});

View File

@ -953,7 +953,53 @@ describe("telegramMessageActions", () => {
},
cfg,
}),
).rejects.toThrow(/threadId\/topicId is required for action=topic-delete/i);
).rejects.toThrow(/topicId must be a valid integer when provided/i);
expect(handleTelegramAction).not.toHaveBeenCalled();
});
it("rejects malformed topicId even when threadId alias is valid", 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",
topicId: "oops",
threadId: 271,
},
cfg,
}),
).rejects.toThrow(/topicId must be a valid integer when provided/i);
expect(handleTelegramAction).not.toHaveBeenCalled();
});
it("rejects malformed delete topicId even when threadId alias is valid", async () => {
const cfg = telegramCfg();
const handleAction = telegramMessageActions.handleAction;
if (!handleAction) {
throw new Error("telegram handleAction unavailable");
}
await expect(
handleAction({
channel: "telegram",
action: "delete",
params: {
to: "-1001234567890",
topicId: "oops",
threadId: 271,
},
cfg,
}),
).rejects.toThrow(/topicId must be a valid integer when provided/i);
expect(handleTelegramAction).not.toHaveBeenCalled();
});