Skip to content

Commit ac2ede5

Browse files
committed
fix(telegram): treat no-op editMessage as success
1 parent 7089885 commit ac2ede5

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

src/telegram/send.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,22 @@ describe("editMessageTelegram", () => {
13211321
);
13221322
});
13231323

1324+
it("treats 'message is not modified' as success", async () => {
1325+
botApi.editMessageText.mockRejectedValueOnce(
1326+
new Error(
1327+
"400: Bad Request: message is not modified: specified new message content and reply markup are exactly the same as a current content and reply markup of the message",
1328+
),
1329+
);
1330+
1331+
await expect(
1332+
editMessageTelegram("123", 1, "hi", {
1333+
token: "tok",
1334+
cfg: {},
1335+
}),
1336+
).resolves.toEqual({ ok: true, messageId: "1", chatId: "123" });
1337+
expect(botApi.editMessageText).toHaveBeenCalledTimes(1);
1338+
});
1339+
13241340
it("disables link previews when linkPreview is false", async () => {
13251341
botApi.editMessageText.mockResolvedValue({ message_id: 1, chat: { id: "123" } });
13261342

src/telegram/send.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ type TelegramReactionOpts = {
7474

7575
const PARSE_ERR_RE = /can't parse entities|parse entities|find end of the entity/i;
7676
const THREAD_NOT_FOUND_RE = /400:\s*Bad Request:\s*message thread not found/i;
77+
const MESSAGE_NOT_MODIFIED_RE =
78+
/400:\s*Bad Request:\s*message is not modified|MESSAGE_NOT_MODIFIED/i;
7779
const diagLogger = createSubsystemLogger("telegram/diagnostic");
7880

7981
function createTelegramHttpLogger(cfg: ReturnType<typeof loadConfig>) {
@@ -182,6 +184,10 @@ function isTelegramThreadNotFoundError(err: unknown): boolean {
182184
return THREAD_NOT_FOUND_RE.test(formatErrorMessage(err));
183185
}
184186

187+
function isTelegramMessageNotModifiedError(err: unknown): boolean {
188+
return MESSAGE_NOT_MODIFIED_RE.test(formatErrorMessage(err));
189+
}
190+
185191
function hasMessageThreadIdParam(params?: Record<string, unknown>): boolean {
186192
if (!params) {
187193
return false;
@@ -730,10 +736,15 @@ export async function editMessageTelegram(
730736
verbose: opts.verbose,
731737
});
732738
const logHttpError = createTelegramHttpLogger(cfg);
733-
const requestWithDiag = <T>(fn: () => Promise<T>, label?: string) =>
739+
const requestWithDiag = <T>(
740+
fn: () => Promise<T>,
741+
label?: string,
742+
shouldLog?: (err: unknown) => boolean,
743+
) =>
734744
withTelegramApiErrorLogging({
735745
operation: label ?? "request",
736746
fn: () => request(fn, label),
747+
shouldLog,
737748
}).catch((err) => {
738749
logHttpError(label ?? "request", err);
739750
throw err;
@@ -768,7 +779,12 @@ export async function editMessageTelegram(
768779
await requestWithDiag(
769780
() => api.editMessageText(chatId, messageId, htmlText, editParams),
770781
"editMessage",
782+
(err) => !isTelegramMessageNotModifiedError(err),
771783
).catch(async (err) => {
784+
if (isTelegramMessageNotModifiedError(err)) {
785+
return;
786+
}
787+
772788
// Telegram rejects malformed HTML. Fall back to plain text.
773789
const errText = formatErrorMessage(err);
774790
if (PARSE_ERR_RE.test(errText)) {
@@ -788,7 +804,13 @@ export async function editMessageTelegram(
788804
? api.editMessageText(chatId, messageId, text, plainParams)
789805
: api.editMessageText(chatId, messageId, text),
790806
"editMessage-plain",
791-
);
807+
(plainErr) => !isTelegramMessageNotModifiedError(plainErr),
808+
).catch((plainErr) => {
809+
if (isTelegramMessageNotModifiedError(plainErr)) {
810+
return;
811+
}
812+
throw plainErr;
813+
});
792814
}
793815
throw err;
794816
});

0 commit comments

Comments
 (0)