mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 11:04:59 +00:00
fix(telegram): preserve inbound quote context and avoid QUOTE_TEXT_INVALID
This commit is contained in:
committed by
Ayaan Zaidi
parent
727a390d13
commit
a4b38ce886
@@ -967,6 +967,42 @@ describe("createTelegramBot", () => {
|
|||||||
expect(payload.ReplyToSender).toBe("unknown sender");
|
expect(payload.ReplyToSender).toBe("unknown sender");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses external_reply quote text for partial replies", async () => {
|
||||||
|
onSpy.mockReset();
|
||||||
|
sendMessageSpy.mockReset();
|
||||||
|
const replySpy = replyModule.__replySpy as unknown as ReturnType<typeof vi.fn>;
|
||||||
|
replySpy.mockReset();
|
||||||
|
|
||||||
|
createTelegramBot({ token: "tok" });
|
||||||
|
const handler = getOnHandler("message") as (ctx: Record<string, unknown>) => Promise<void>;
|
||||||
|
|
||||||
|
await handler({
|
||||||
|
message: {
|
||||||
|
chat: { id: 7, type: "private" },
|
||||||
|
text: "Sure, see below",
|
||||||
|
date: 1736380800,
|
||||||
|
external_reply: {
|
||||||
|
message_id: 9002,
|
||||||
|
text: "Can you summarize this?",
|
||||||
|
from: { first_name: "Ada" },
|
||||||
|
quote: {
|
||||||
|
text: "summarize this",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
me: { username: "openclaw_bot" },
|
||||||
|
getFile: async () => ({ download: async () => new Uint8Array() }),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(replySpy).toHaveBeenCalledTimes(1);
|
||||||
|
const payload = replySpy.mock.calls[0][0];
|
||||||
|
expect(payload.Body).toContain("[Quoting Ada id:9002]");
|
||||||
|
expect(payload.Body).toContain('"summarize this"');
|
||||||
|
expect(payload.ReplyToId).toBe("9002");
|
||||||
|
expect(payload.ReplyToBody).toBe("summarize this");
|
||||||
|
expect(payload.ReplyToSender).toBe("Ada");
|
||||||
|
});
|
||||||
|
|
||||||
it("sends replies without native reply threading", async () => {
|
it("sends replies without native reply threading", async () => {
|
||||||
onSpy.mockReset();
|
onSpy.mockReset();
|
||||||
sendMessageSpy.mockReset();
|
sendMessageSpy.mockReset();
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ describe("deliverReplies", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses reply_parameters when quote text is provided", async () => {
|
it("uses reply_to_message_id when quote text is provided", async () => {
|
||||||
const runtime = { error: vi.fn(), log: vi.fn() };
|
const runtime = { error: vi.fn(), log: vi.fn() };
|
||||||
const sendMessage = vi.fn().mockResolvedValue({
|
const sendMessage = vi.fn().mockResolvedValue({
|
||||||
message_id: 10,
|
message_id: 10,
|
||||||
@@ -217,10 +217,14 @@ describe("deliverReplies", () => {
|
|||||||
"123",
|
"123",
|
||||||
expect.any(String),
|
expect.any(String),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
reply_parameters: {
|
reply_to_message_id: 500,
|
||||||
message_id: 500,
|
}),
|
||||||
quote: "quoted text",
|
);
|
||||||
},
|
expect(sendMessage).toHaveBeenCalledWith(
|
||||||
|
"123",
|
||||||
|
expect.any(String),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
reply_parameters: expect.anything(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -484,16 +484,8 @@ function buildTelegramSendParams(opts?: {
|
|||||||
}): Record<string, unknown> {
|
}): Record<string, unknown> {
|
||||||
const threadParams = buildTelegramThreadParams(opts?.thread);
|
const threadParams = buildTelegramThreadParams(opts?.thread);
|
||||||
const params: Record<string, unknown> = {};
|
const params: Record<string, unknown> = {};
|
||||||
const quoteText = opts?.replyQuoteText?.trim();
|
|
||||||
if (opts?.replyToMessageId) {
|
if (opts?.replyToMessageId) {
|
||||||
if (quoteText) {
|
params.reply_to_message_id = opts.replyToMessageId;
|
||||||
params.reply_parameters = {
|
|
||||||
message_id: Math.trunc(opts.replyToMessageId),
|
|
||||||
quote: quoteText,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
params.reply_to_message_id = opts.replyToMessageId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (threadParams) {
|
if (threadParams) {
|
||||||
params.message_thread_id = threadParams.message_thread_id;
|
params.message_thread_id = threadParams.message_thread_id;
|
||||||
|
|||||||
@@ -226,31 +226,33 @@ export type TelegramReplyTarget = {
|
|||||||
|
|
||||||
export function describeReplyTarget(msg: Message): TelegramReplyTarget | null {
|
export function describeReplyTarget(msg: Message): TelegramReplyTarget | null {
|
||||||
const reply = msg.reply_to_message;
|
const reply = msg.reply_to_message;
|
||||||
const quote = msg.quote;
|
const externalReply = msg.external_reply;
|
||||||
|
const quoteText = msg.quote?.text ?? reply?.quote?.text ?? externalReply?.quote?.text;
|
||||||
let body = "";
|
let body = "";
|
||||||
let kind: TelegramReplyTarget["kind"] = "reply";
|
let kind: TelegramReplyTarget["kind"] = "reply";
|
||||||
|
|
||||||
if (quote?.text) {
|
if (typeof quoteText === "string") {
|
||||||
body = quote.text.trim();
|
body = quoteText.trim();
|
||||||
if (body) {
|
if (body) {
|
||||||
kind = "quote";
|
kind = "quote";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!body && reply) {
|
const replyLike = reply ?? externalReply;
|
||||||
const replyBody = (reply.text ?? reply.caption ?? "").trim();
|
if (!body && replyLike) {
|
||||||
|
const replyBody = (replyLike.text ?? replyLike.caption ?? "").trim();
|
||||||
body = replyBody;
|
body = replyBody;
|
||||||
if (!body) {
|
if (!body) {
|
||||||
if (reply.photo) {
|
if (replyLike.photo) {
|
||||||
body = "<media:image>";
|
body = "<media:image>";
|
||||||
} else if (reply.video) {
|
} else if (replyLike.video) {
|
||||||
body = "<media:video>";
|
body = "<media:video>";
|
||||||
} else if (reply.audio || reply.voice) {
|
} else if (replyLike.audio || replyLike.voice) {
|
||||||
body = "<media:audio>";
|
body = "<media:audio>";
|
||||||
} else if (reply.document) {
|
} else if (replyLike.document) {
|
||||||
body = "<media:document>";
|
body = "<media:document>";
|
||||||
} else {
|
} else {
|
||||||
const locationData = extractTelegramLocation(reply);
|
const locationData = extractTelegramLocation(replyLike);
|
||||||
if (locationData) {
|
if (locationData) {
|
||||||
body = formatLocationText(locationData);
|
body = formatLocationText(locationData);
|
||||||
}
|
}
|
||||||
@@ -260,11 +262,11 @@ export function describeReplyTarget(msg: Message): TelegramReplyTarget | null {
|
|||||||
if (!body) {
|
if (!body) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const sender = reply ? buildSenderName(reply) : undefined;
|
const sender = replyLike ? buildSenderName(replyLike) : undefined;
|
||||||
const senderLabel = sender ?? "unknown sender";
|
const senderLabel = sender ?? "unknown sender";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: reply?.message_id ? String(reply.message_id) : undefined,
|
id: replyLike?.message_id ? String(replyLike.message_id) : undefined,
|
||||||
sender: senderLabel,
|
sender: senderLabel,
|
||||||
body,
|
body,
|
||||||
kind,
|
kind,
|
||||||
|
|||||||
Reference in New Issue
Block a user