fix: enforce Telegram 100-command limit with warning (#5787) (#15844)

* fix: enforce Telegram 100-command limit with warning (#5787)

Telegram's setMyCommands API rejects requests with more than 100 commands.
When skills + custom + plugin commands exceed the limit, truncate to 100
and warn the user instead of silently failing on every startup.

* fix: enforce Telegram menu cap + keep hidden commands callable (#15844) (thanks @battman21)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
Owen
2026-02-14 11:51:00 +11:00
committed by GitHub
parent aa6d8b27ac
commit 11ab1c6937
4 changed files with 71 additions and 8 deletions

View File

@@ -366,25 +366,26 @@ export const registerTelegramNativeCommands = ({
...pluginCommands,
...customCommands,
];
// Telegram Bot API limits commands to 100 per scope.
// Truncate with a warning rather than failing with BOT_COMMANDS_TOO_MUCH.
const TELEGRAM_MAX_COMMANDS = 100;
if (allCommandsFull.length > TELEGRAM_MAX_COMMANDS) {
runtime.log?.(
`telegram: truncating ${allCommandsFull.length} commands to ${TELEGRAM_MAX_COMMANDS} (Telegram Bot API limit)`,
`Telegram limits bots to ${TELEGRAM_MAX_COMMANDS} commands. ` +
`${allCommandsFull.length} configured; registering first ${TELEGRAM_MAX_COMMANDS}. ` +
`Use channels.telegram.commands.native: false to disable, or reduce skill/custom commands.`,
);
}
const allCommands = allCommandsFull.slice(0, TELEGRAM_MAX_COMMANDS);
// Telegram only limits the setMyCommands payload (menu entries).
const commandsToRegister = allCommandsFull.slice(0, TELEGRAM_MAX_COMMANDS);
// Clear stale commands before registering new ones to prevent
// leftover commands from deleted skills persisting across restarts (#5717).
// Chain delete → set so a late-resolving delete cannot wipe newly registered commands.
const registerCommands = () => {
if (allCommands.length > 0) {
if (commandsToRegister.length > 0) {
withTelegramApiErrorLogging({
operation: "setMyCommands",
runtime,
fn: () => bot.api.setMyCommands(allCommands),
fn: () => bot.api.setMyCommands(commandsToRegister),
}).catch(() => {});
}
};
@@ -401,7 +402,7 @@ export const registerTelegramNativeCommands = ({
registerCommands();
}
if (allCommands.length > 0) {
if (commandsToRegister.length > 0) {
if (typeof (bot as unknown as { command?: unknown }).command !== "function") {
logVerbose("telegram: bot.command unavailable; skipping native handlers");
} else {