| import type { ReplyPayload } from "../../../auto-reply/types.js"; |
| import type { OutboundSendDeps } from "../../../infra/outbound/deliver.js"; |
| import type { TelegramInlineButtons } from "../../../telegram/button-types.js"; |
| import { markdownToTelegramHtmlChunks } from "../../../telegram/format.js"; |
| import { |
| parseTelegramReplyToMessageId, |
| parseTelegramThreadId, |
| } from "../../../telegram/outbound-params.js"; |
| import { sendMessageTelegram } from "../../../telegram/send.js"; |
| import type { ChannelOutboundAdapter } from "../types.js"; |
| import { resolvePayloadMediaUrls, sendPayloadMediaSequence } from "./direct-text-media.js"; |
|
|
| type TelegramSendFn = typeof sendMessageTelegram; |
| type TelegramSendOpts = Parameters<TelegramSendFn>[2]; |
|
|
| function resolveTelegramSendContext(params: { |
| cfg: NonNullable<TelegramSendOpts>["cfg"]; |
| deps?: OutboundSendDeps; |
| accountId?: string | null; |
| replyToId?: string | null; |
| threadId?: string | number | null; |
| }): { |
| send: TelegramSendFn; |
| baseOpts: { |
| cfg: NonNullable<TelegramSendOpts>["cfg"]; |
| verbose: false; |
| textMode: "html"; |
| messageThreadId?: number; |
| replyToMessageId?: number; |
| accountId?: string; |
| }; |
| } { |
| const send = params.deps?.sendTelegram ?? sendMessageTelegram; |
| return { |
| send, |
| baseOpts: { |
| verbose: false, |
| textMode: "html", |
| cfg: params.cfg, |
| messageThreadId: parseTelegramThreadId(params.threadId), |
| replyToMessageId: parseTelegramReplyToMessageId(params.replyToId), |
| accountId: params.accountId ?? undefined, |
| }, |
| }; |
| } |
|
|
| export async function sendTelegramPayloadMessages(params: { |
| send: TelegramSendFn; |
| to: string; |
| payload: ReplyPayload; |
| baseOpts: Omit<NonNullable<TelegramSendOpts>, "buttons" | "mediaUrl" | "quoteText">; |
| }): Promise<Awaited<ReturnType<TelegramSendFn>>> { |
| const telegramData = params.payload.channelData?.telegram as |
| | { buttons?: TelegramInlineButtons; quoteText?: string } |
| | undefined; |
| const quoteText = |
| typeof telegramData?.quoteText === "string" ? telegramData.quoteText : undefined; |
| const text = params.payload.text ?? ""; |
| const mediaUrls = resolvePayloadMediaUrls(params.payload); |
| const payloadOpts = { |
| ...params.baseOpts, |
| quoteText, |
| }; |
|
|
| if (mediaUrls.length === 0) { |
| return await params.send(params.to, text, { |
| ...payloadOpts, |
| buttons: telegramData?.buttons, |
| }); |
| } |
|
|
| |
| const finalResult = await sendPayloadMediaSequence({ |
| text, |
| mediaUrls, |
| send: async ({ text, mediaUrl, isFirst }) => |
| await params.send(params.to, text, { |
| ...payloadOpts, |
| mediaUrl, |
| ...(isFirst ? { buttons: telegramData?.buttons } : {}), |
| }), |
| }); |
| return finalResult ?? { messageId: "unknown", chatId: params.to }; |
| } |
|
|
| export const telegramOutbound: ChannelOutboundAdapter = { |
| deliveryMode: "direct", |
| chunker: markdownToTelegramHtmlChunks, |
| chunkerMode: "markdown", |
| textChunkLimit: 4000, |
| sendText: async ({ cfg, to, text, accountId, deps, replyToId, threadId }) => { |
| const { send, baseOpts } = resolveTelegramSendContext({ |
| cfg, |
| deps, |
| accountId, |
| replyToId, |
| threadId, |
| }); |
| const result = await send(to, text, { |
| ...baseOpts, |
| }); |
| return { channel: "telegram", ...result }; |
| }, |
| sendMedia: async ({ |
| cfg, |
| to, |
| text, |
| mediaUrl, |
| mediaLocalRoots, |
| accountId, |
| deps, |
| replyToId, |
| threadId, |
| }) => { |
| const { send, baseOpts } = resolveTelegramSendContext({ |
| cfg, |
| deps, |
| accountId, |
| replyToId, |
| threadId, |
| }); |
| const result = await send(to, text, { |
| ...baseOpts, |
| mediaUrl, |
| mediaLocalRoots, |
| }); |
| return { channel: "telegram", ...result }; |
| }, |
| sendPayload: async ({ |
| cfg, |
| to, |
| payload, |
| mediaLocalRoots, |
| accountId, |
| deps, |
| replyToId, |
| threadId, |
| }) => { |
| const { send, baseOpts } = resolveTelegramSendContext({ |
| cfg, |
| deps, |
| accountId, |
| replyToId, |
| threadId, |
| }); |
| const result = await sendTelegramPayloadMessages({ |
| send, |
| to, |
| payload, |
| baseOpts: { |
| ...baseOpts, |
| mediaLocalRoots, |
| }, |
| }); |
| return { channel: "telegram", ...result }; |
| }, |
| }; |
|
|