fix(telegram): send interactive fallback replies

This commit is contained in:
Vincent Koc
2026-05-03 19:17:14 -07:00
parent be438cf887
commit b0b5983ce3
3 changed files with 43 additions and 2 deletions

View File

@@ -36,6 +36,7 @@ import {
renderTelegramHtmlText,
wrapFileReferencesInHtml,
} from "../format.js";
import { resolveTelegramInteractiveTextFallback } from "../interactive-fallback.js";
import { buildInlineKeyboard } from "../send.js";
import { resolveTelegramVoiceSend } from "../voice.js";
import {
@@ -751,7 +752,17 @@ export async function deliverReplies(params: {
? [reply.mediaUrl]
: [];
const hasMedia = mediaList.length > 0;
if (!reply?.text && !hasMedia) {
const resolvedReplyText =
resolveTelegramInteractiveTextFallback({
text: reply?.text,
interactive: reply?.interactive,
}) ??
reply?.text ??
"";
if (reply && resolvedReplyText !== (reply.text ?? "")) {
reply = { ...reply, text: resolvedReplyText };
}
if (!resolvedReplyText && !hasMedia) {
if (reply?.audioAsVoice) {
logVerbose("telegram reply has audioAsVoice without media/text; skipping");
continue;
@@ -760,7 +771,7 @@ export async function deliverReplies(params: {
continue;
}
const rawContent = reply.text || "";
const rawContent = resolvedReplyText;
const replyToId =
params.replyToMode === "off" ? undefined : resolveTelegramReplyId(reply.replyToId);
const replyQuote = resolveReplyQuoteForSend({

View File

@@ -257,6 +257,35 @@ describe("deliverReplies", () => {
);
});
it("uses interactive button labels as fallback text for button-only replies", async () => {
const runtime = createRuntime(false);
const sendMessage = vi.fn().mockResolvedValue({ message_id: 3, chat: { id: "123" } });
const bot = createBot({ sendMessage });
await deliverWith({
replies: [
{
interactive: {
blocks: [{ type: "buttons", buttons: [{ label: "Retry", value: "cmd:retry" }] }],
},
},
],
runtime,
bot,
});
expect(runtime.error).not.toHaveBeenCalled();
expect(sendMessage).toHaveBeenCalledWith(
"123",
expect.stringContaining("Retry"),
expect.objectContaining({
reply_markup: {
inline_keyboard: [[{ text: "Retry", callback_data: "cmd:retry" }]],
},
}),
);
});
it("reports message_sent success=false when hooks blank out a text-only reply", async () => {
messageHookRunner.hasHooks.mockImplementation(
(name: string) => name === "message_sending" || name === "message_sent",