fix(telegram): retry failed commands pagination callbacks

This commit is contained in:
Vincent Koc
2026-04-13 17:26:48 +01:00
parent b42c999633
commit 0c5471ef8e
2 changed files with 53 additions and 1 deletions

View File

@@ -1434,7 +1434,7 @@ export const registerTelegramHandlers = ({
} catch (editErr) {
const errStr = String(editErr);
if (!errStr.includes("message is not modified")) {
throw editErr;
throw new TelegramRetryableCallbackError(editErr);
}
}
return;

View File

@@ -2932,4 +2932,56 @@ describe("createTelegramBot", () => {
expect(editMessageTextSpy).toHaveBeenCalledTimes(1);
expect(editMessageTextSpy.mock.calls[0]?.[2]).toContain("Select a provider:");
});
it("retries command pagination callbacks after a bubbled edit failure", async () => {
createTelegramBot({ token: "tok" });
const callbackHandler = getOnHandler("callback_query");
const middlewares = middlewareUseSpy.mock.calls
.map((call) => call[0])
.filter(
(fn): fn is (ctx: Record<string, unknown>, next: () => Promise<void>) => Promise<void> =>
typeof fn === "function",
);
const runMiddlewareChain = async (ctx: Record<string, unknown>) => {
let idx = -1;
const dispatch = async (i: number): Promise<void> => {
if (i <= idx) {
throw new Error("middleware dispatch called multiple times");
}
idx = i;
const fn = middlewares[i];
if (!fn) {
await callbackHandler(ctx);
return;
}
await fn(ctx, async () => dispatch(i + 1));
};
await dispatch(0);
};
const ctx = {
update: { update_id: 777 },
callbackQuery: {
id: "cbq-commands-retry-1",
data: "commands_page_2:main",
from: { id: 9, first_name: "Ada", username: "ada_bot" },
message: {
chat: { id: 1234, type: "private" },
date: 1736380800,
message_id: 19,
},
},
me: { username: "openclaw_bot" },
getFile: async () => ({ download: async () => new Uint8Array() }),
};
editMessageTextSpy.mockImplementationOnce(async () => {
throw new Error("edit boom");
});
await expect(runMiddlewareChain(ctx)).rejects.toThrow("edit boom");
await runMiddlewareChain(ctx);
expect(editMessageTextSpy).toHaveBeenCalledTimes(2);
expect(editMessageTextSpy.mock.calls.at(-1)?.[2]).toContain("Commands (2/");
});
});