mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-11 09:51:41 +00:00
fix(telegram): guard malformed native menu specs
This commit is contained in:
committed by
Peter Steinberger
parent
ed55b63684
commit
0958d11478
@@ -51,6 +51,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
- Mentions/Slack formatting hardening: add null-safe guards for runtime text normalization paths so malformed/undefined text payloads do not crash mention stripping or mrkdwn conversion. (#31865) Thanks @stone-jin.
|
- Mentions/Slack formatting hardening: add null-safe guards for runtime text normalization paths so malformed/undefined text payloads do not crash mention stripping or mrkdwn conversion. (#31865) Thanks @stone-jin.
|
||||||
- Failover/error classification: treat HTTP `529` (provider overloaded, common with Anthropic-compatible APIs) as `rate_limit` so model failover can engage instead of misclassifying the error path. (#31854) Thanks @bugkill3r.
|
- Failover/error classification: treat HTTP `529` (provider overloaded, common with Anthropic-compatible APIs) as `rate_limit` so model failover can engage instead of misclassifying the error path. (#31854) Thanks @bugkill3r.
|
||||||
- Voice-call/webhook routing: require exact webhook path matches (instead of prefix matches) so lookalike paths cannot reach provider verification/dispatch logic. (#31930) Thanks @afurm.
|
- Voice-call/webhook routing: require exact webhook path matches (instead of prefix matches) so lookalike paths cannot reach provider verification/dispatch logic. (#31930) Thanks @afurm.
|
||||||
|
- Telegram/native command menu hardening: guard plugin command name/description normalization so malformed plugin command specs cannot crash Telegram startup command registration (`trim` on undefined). (#31997) Fixes #31944. Thanks @liuxiaopai-ai.
|
||||||
- Web UI/config form: support SecretInput string-or-secret-ref unions in map `additionalProperties`, so provider API key fields stay editable instead of being marked unsupported. (#31866) Thanks @ningding97.
|
- Web UI/config form: support SecretInput string-or-secret-ref unions in map `additionalProperties`, so provider API key fields stay editable instead of being marked unsupported. (#31866) Thanks @ningding97.
|
||||||
- Slack/Bolt startup compatibility: remove invalid `message.channels` and `message.groups` event registrations so Slack providers no longer crash on startup with Bolt 4.6+; channel/group traffic continues through the unified `message` handler (`channel_type`). (#32033) Thanks @mahopan.
|
- Slack/Bolt startup compatibility: remove invalid `message.channels` and `message.groups` event registrations so Slack providers no longer crash on startup with Bolt 4.6+; channel/group traffic continues through the unified `message` handler (`channel_type`). (#32033) Thanks @mahopan.
|
||||||
- Telegram: guard duplicate-token checks and gateway startup token normalization when account tokens are missing, preventing `token.trim()` crashes during status/start flows. (#31973) Thanks @ningding97.
|
- Telegram: guard duplicate-token checks and gateway startup token normalization when account tokens are missing, preventing `token.trim()` crashes during status/start flows. (#31973) Thanks @ningding97.
|
||||||
|
|||||||
@@ -60,6 +60,27 @@ describe("bot-native-command-menu", () => {
|
|||||||
expect(result.issues).toEqual([]);
|
expect(result.issues).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("ignores malformed plugin specs without crashing", () => {
|
||||||
|
const malformedSpecs = [
|
||||||
|
{ name: "valid", description: " Works " },
|
||||||
|
{ name: "missing-description", description: undefined },
|
||||||
|
{ name: undefined, description: "Missing name" },
|
||||||
|
] as unknown as Parameters<typeof buildPluginTelegramMenuCommands>[0]["specs"];
|
||||||
|
|
||||||
|
const result = buildPluginTelegramMenuCommands({
|
||||||
|
specs: malformedSpecs,
|
||||||
|
existingCommands: new Set<string>(),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.commands).toEqual([{ command: "valid", description: "Works" }]);
|
||||||
|
expect(result.issues).toContain(
|
||||||
|
'Plugin command "/missing_description" is missing a description.',
|
||||||
|
);
|
||||||
|
expect(result.issues).toContain(
|
||||||
|
'Plugin command "/<unknown>" is invalid for Telegram (use a-z, 0-9, underscore; max 32 chars).',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("deletes stale commands before setting new menu", async () => {
|
it("deletes stale commands before setting new menu", async () => {
|
||||||
const callOrder: string[] = [];
|
const callOrder: string[] = [];
|
||||||
const deleteMyCommands = vi.fn(async () => {
|
const deleteMyCommands = vi.fn(async () => {
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ export type TelegramMenuCommand = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type TelegramPluginCommandSpec = {
|
type TelegramPluginCommandSpec = {
|
||||||
name: string;
|
name: unknown;
|
||||||
description: string;
|
description: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
function isBotCommandsTooMuchError(err: unknown): boolean {
|
function isBotCommandsTooMuchError(err: unknown): boolean {
|
||||||
@@ -54,14 +54,16 @@ export function buildPluginTelegramMenuCommands(params: {
|
|||||||
const pluginCommandNames = new Set<string>();
|
const pluginCommandNames = new Set<string>();
|
||||||
|
|
||||||
for (const spec of specs) {
|
for (const spec of specs) {
|
||||||
const normalized = normalizeTelegramCommandName(spec.name);
|
const rawName = typeof spec.name === "string" ? spec.name : "";
|
||||||
|
const normalized = normalizeTelegramCommandName(rawName);
|
||||||
if (!normalized || !TELEGRAM_COMMAND_NAME_PATTERN.test(normalized)) {
|
if (!normalized || !TELEGRAM_COMMAND_NAME_PATTERN.test(normalized)) {
|
||||||
|
const invalidName = rawName.trim() ? rawName : "<unknown>";
|
||||||
issues.push(
|
issues.push(
|
||||||
`Plugin command "/${spec.name}" is invalid for Telegram (use a-z, 0-9, underscore; max 32 chars).`,
|
`Plugin command "/${invalidName}" is invalid for Telegram (use a-z, 0-9, underscore; max 32 chars).`,
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const description = spec.description.trim();
|
const description = typeof spec.description === "string" ? spec.description.trim() : "";
|
||||||
if (!description) {
|
if (!description) {
|
||||||
issues.push(`Plugin command "/${normalized}" is missing a description.`);
|
issues.push(`Plugin command "/${normalized}" is missing a description.`);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user