Files
openclaw/extensions/telegram/src/inline-buttons.test.ts
Shubhankar Tripathy 90f30075aa fix(channels): preserve Telegram SecretRef prompt config
Use read-only Telegram account inspection for prompt-time channel actions, inline buttons, and reaction guidance so unresolved SecretRef tokens retain configured non-secret behavior before runtime snapshot hydration.

Match runtime Telegram account lookup for normalized config keys and multi-account fallback guards, while keeping sends/actions on the existing strict credential resolution path.

Fixes #75433.

Co-authored-by: Shubhankar Tripathy <reach2shubhankar@gmail.com>
2026-05-27 20:25:41 +01:00

143 lines
5.0 KiB
TypeScript

import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import { describe, expect, it } from "vitest";
import { buildTelegramInteractiveButtons } from "./button-types.js";
import { describeTelegramInteractiveButtonBehavior } from "./button-types.test-helpers.js";
import {
isTelegramInlineButtonsEnabled,
resolveTelegramInlineButtonsScope,
resolveTelegramTargetChatType,
} from "./inline-buttons.js";
describe("resolveTelegramTargetChatType", () => {
it("returns 'direct' for positive numeric IDs", () => {
expect(resolveTelegramTargetChatType("5232990709")).toBe("direct");
expect(resolveTelegramTargetChatType("123456789")).toBe("direct");
});
it("returns 'group' for negative numeric IDs", () => {
expect(resolveTelegramTargetChatType("-123456789")).toBe("group");
expect(resolveTelegramTargetChatType("-1001234567890")).toBe("group");
});
it("handles telegram: prefix from normalizeTelegramMessagingTarget", () => {
expect(resolveTelegramTargetChatType("telegram:5232990709")).toBe("direct");
expect(resolveTelegramTargetChatType("telegram:-123456789")).toBe("group");
expect(resolveTelegramTargetChatType("TELEGRAM:5232990709")).toBe("direct");
});
it("handles tg/group prefixes and topic suffixes", () => {
expect(resolveTelegramTargetChatType("tg:5232990709")).toBe("direct");
expect(resolveTelegramTargetChatType("telegram:group:-1001234567890")).toBe("group");
expect(resolveTelegramTargetChatType("telegram:group:-1001234567890:topic:456")).toBe("group");
expect(resolveTelegramTargetChatType("-1001234567890:456")).toBe("group");
});
it("returns 'unknown' for usernames", () => {
expect(resolveTelegramTargetChatType("@username")).toBe("unknown");
expect(resolveTelegramTargetChatType("telegram:@username")).toBe("unknown");
});
it("returns 'unknown' for empty strings", () => {
expect(resolveTelegramTargetChatType("")).toBe("unknown");
expect(resolveTelegramTargetChatType(" ")).toBe("unknown");
});
});
describeTelegramInteractiveButtonBehavior();
describe("buildTelegramInteractiveButtons callback rewrites", () => {
it("drops shared buttons whose callback data exceeds Telegram's limit", () => {
expect(
buildTelegramInteractiveButtons({
blocks: [
{
type: "buttons",
buttons: [
{ label: "Keep", value: "keep" },
{ label: "Too long", value: `a${"b".repeat(64)}` },
],
},
],
}),
).toEqual([[{ text: "Keep", callback_data: "keep", style: undefined }]]);
});
it("rewrites /approve allow-always callbacks to always so plugin IDs fit Telegram limits", () => {
const pluginApprovalId = `plugin:${"a".repeat(36)}`;
expect(
buildTelegramInteractiveButtons({
blocks: [
{
type: "buttons",
buttons: [
{
label: "Allow Always",
value: `/approve ${pluginApprovalId} allow-always`,
style: "primary",
},
],
},
],
}),
).toEqual([
[
{
text: "Allow Always",
callback_data: `/approve ${pluginApprovalId} always`,
style: "primary",
},
],
]);
});
});
describe("resolveTelegramInlineButtonsScope (#75433 SecretRef tolerance)", () => {
// Embedded prompt prep calls this from raw config before the active runtime
// snapshot has resolved channel credentials. Read-only account inspection
// keeps SecretRef-backed config readable without resolving the token.
it("preserves the default inline-buttons scope when botToken is an unresolved SecretRef", () => {
const cfg = {
channels: {
telegram: {
botToken: { source: "exec", provider: "default", id: "telegram-token" },
},
},
} as unknown as OpenClawConfig;
expect(resolveTelegramInlineButtonsScope({ cfg })).toBe("allowlist");
expect(isTelegramInlineButtonsEnabled({ cfg })).toBe(true);
});
it('preserves configured "off" when botToken is an unresolved SecretRef', () => {
const cfg = {
channels: {
telegram: {
botToken: { source: "exec", provider: "default", id: "telegram-token" },
capabilities: { inlineButtons: "off" },
},
},
} as unknown as OpenClawConfig;
expect(resolveTelegramInlineButtonsScope({ cfg })).toBe("off");
expect(isTelegramInlineButtonsEnabled({ cfg })).toBe(false);
});
it("preserves scoped account inline-buttons config when the token is an unresolved SecretRef", () => {
const cfg = {
channels: {
telegram: {
accounts: {
ops: {
botToken: { source: "exec", provider: "default", id: "telegram-ops" },
capabilities: { inlineButtons: "all" },
},
},
},
},
} as unknown as OpenClawConfig;
expect(resolveTelegramInlineButtonsScope({ cfg, accountId: "ops" })).toBe("all");
expect(isTelegramInlineButtonsEnabled({ cfg, accountId: "ops" })).toBe(true);
});
});