mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 10:51:23 +00:00
fix: telegram sendPayload and plugin auth (#1917) (thanks @JoshuaLelon)
This commit is contained in:
81
src/channels/plugins/outbound/telegram.test.ts
Normal file
81
src/channels/plugins/outbound/telegram.test.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import type { ClawdbotConfig } from "../../../config/config.js";
|
||||
import { telegramOutbound } from "./telegram.js";
|
||||
|
||||
describe("telegramOutbound.sendPayload", () => {
|
||||
it("sends text payload with buttons", async () => {
|
||||
const sendTelegram = vi.fn(async () => ({ messageId: "m1", chatId: "c1" }));
|
||||
|
||||
const result = await telegramOutbound.sendPayload?.({
|
||||
cfg: {} as ClawdbotConfig,
|
||||
to: "telegram:123",
|
||||
text: "ignored",
|
||||
payload: {
|
||||
text: "Hello",
|
||||
channelData: {
|
||||
telegram: {
|
||||
buttons: [[{ text: "Option", callback_data: "/option" }]],
|
||||
},
|
||||
},
|
||||
},
|
||||
deps: { sendTelegram },
|
||||
});
|
||||
|
||||
expect(sendTelegram).toHaveBeenCalledTimes(1);
|
||||
expect(sendTelegram).toHaveBeenCalledWith(
|
||||
"telegram:123",
|
||||
"Hello",
|
||||
expect.objectContaining({
|
||||
buttons: [[{ text: "Option", callback_data: "/option" }]],
|
||||
textMode: "html",
|
||||
}),
|
||||
);
|
||||
expect(result).toEqual({ channel: "telegram", messageId: "m1", chatId: "c1" });
|
||||
});
|
||||
|
||||
it("sends media payloads and attaches buttons only to first", async () => {
|
||||
const sendTelegram = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({ messageId: "m1", chatId: "c1" })
|
||||
.mockResolvedValueOnce({ messageId: "m2", chatId: "c1" });
|
||||
|
||||
const result = await telegramOutbound.sendPayload?.({
|
||||
cfg: {} as ClawdbotConfig,
|
||||
to: "telegram:123",
|
||||
text: "ignored",
|
||||
payload: {
|
||||
text: "Caption",
|
||||
mediaUrls: ["https://example.com/a.png", "https://example.com/b.png"],
|
||||
channelData: {
|
||||
telegram: {
|
||||
buttons: [[{ text: "Go", callback_data: "/go" }]],
|
||||
},
|
||||
},
|
||||
},
|
||||
deps: { sendTelegram },
|
||||
});
|
||||
|
||||
expect(sendTelegram).toHaveBeenCalledTimes(2);
|
||||
expect(sendTelegram).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
"telegram:123",
|
||||
"Caption",
|
||||
expect.objectContaining({
|
||||
mediaUrl: "https://example.com/a.png",
|
||||
buttons: [[{ text: "Go", callback_data: "/go" }]],
|
||||
}),
|
||||
);
|
||||
const secondOpts = sendTelegram.mock.calls[1]?.[2] as { buttons?: unknown } | undefined;
|
||||
expect(sendTelegram).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
"telegram:123",
|
||||
"",
|
||||
expect.objectContaining({
|
||||
mediaUrl: "https://example.com/b.png",
|
||||
}),
|
||||
);
|
||||
expect(secondOpts?.buttons).toBeUndefined();
|
||||
expect(result).toEqual({ channel: "telegram", messageId: "m2", chatId: "c1" });
|
||||
});
|
||||
});
|
||||
@@ -18,6 +18,7 @@ function parseThreadId(threadId?: string | number | null) {
|
||||
const parsed = Number.parseInt(trimmed, 10);
|
||||
return Number.isFinite(parsed) ? parsed : undefined;
|
||||
}
|
||||
|
||||
export const telegramOutbound: ChannelOutboundAdapter = {
|
||||
deliveryMode: "direct",
|
||||
chunker: markdownToTelegramHtmlChunks,
|
||||
@@ -54,20 +55,42 @@ export const telegramOutbound: ChannelOutboundAdapter = {
|
||||
const send = deps?.sendTelegram ?? sendMessageTelegram;
|
||||
const replyToMessageId = parseReplyToMessageId(replyToId);
|
||||
const messageThreadId = parseThreadId(threadId);
|
||||
|
||||
// Extract Telegram-specific data from channelData
|
||||
const telegramData = payload.channelData?.telegram as
|
||||
| { buttons?: Array<Array<{ text: string; callback_data: string }>> }
|
||||
| undefined;
|
||||
|
||||
const result = await send(to, payload.text ?? "", {
|
||||
const text = payload.text ?? "";
|
||||
const mediaUrls = payload.mediaUrls?.length
|
||||
? payload.mediaUrls
|
||||
: payload.mediaUrl
|
||||
? [payload.mediaUrl]
|
||||
: [];
|
||||
const baseOpts = {
|
||||
verbose: false,
|
||||
textMode: "html",
|
||||
textMode: "html" as const,
|
||||
messageThreadId,
|
||||
replyToMessageId,
|
||||
accountId: accountId ?? undefined,
|
||||
buttons: telegramData?.buttons,
|
||||
});
|
||||
return { channel: "telegram", ...result };
|
||||
};
|
||||
|
||||
if (mediaUrls.length === 0) {
|
||||
const result = await send(to, text, {
|
||||
...baseOpts,
|
||||
buttons: telegramData?.buttons,
|
||||
});
|
||||
return { channel: "telegram", ...result };
|
||||
}
|
||||
|
||||
// Telegram allows reply_markup on media; attach buttons only to first send.
|
||||
let finalResult: Awaited<ReturnType<typeof send>> | undefined;
|
||||
for (let i = 0; i < mediaUrls.length; i += 1) {
|
||||
const mediaUrl = mediaUrls[i];
|
||||
const isFirst = i === 0;
|
||||
finalResult = await send(to, isFirst ? text : "", {
|
||||
...baseOpts,
|
||||
mediaUrl,
|
||||
...(isFirst ? { buttons: telegramData?.buttons } : {}),
|
||||
});
|
||||
}
|
||||
return { channel: "telegram", ...(finalResult ?? { messageId: "unknown", chatId: to }) };
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user