mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-13 23:56:07 +00:00
fix(telegram): honor forced document videos
Fixes #80389. Thanks @jbetala7.
This commit is contained in:
@@ -64,6 +64,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Doctor/GitHub CLI: surface a `GH_CONFIG_DIR` hint when the GitHub skill is usable but `gh` auth lives under a different operator HOME than the agent process, without warning for disabled or filtered skills. Fixes #78063. (#78095) Thanks @tmimmanuel.
|
||||
- Gateway: dedupe concurrent `send`, `poll`, and `message.action` requests while delivery is still in flight, preventing duplicate outbound work for the same idempotency key. (#68341) Thanks @thesomewhatyou.
|
||||
- Cron: keep main-session `systemEvent` heartbeat wakes on their bound session route for both direct and queued wake paths by dropping inherited explicit heartbeat destinations when forcing `target: "last"`. Fixes #73900. Thanks @richardmqq.
|
||||
- Telegram: honor forced document delivery for video media so `--force-document` sends MP4s as documents instead of typed videos. Fixes #80389. (#80405) Thanks @jbetala7.
|
||||
- Gateway: clear speculative node wake state when APNs registration is missing, preventing unregistered or mistyped node IDs from retaining wake throttle entries. Fixes #68847. (#68848) Thanks @Feelw00.
|
||||
- Auto-reply: keep late follow-up queue drain finalizers from deleting a replacement queue registered after `/stop`, preventing immediate follow-up messages from being orphaned. Fixes #68838. (#68839) Thanks @Feelw00.
|
||||
- Feishu: make manual App ID/App Secret setup the default channel-binding path while keeping QR scan-to-create as an optional best-effort flow, and document the manual fallback for domestic Feishu mobile clients that do not react to the QR code. Fixes #80591. Thanks @wei-wei-zhao.
|
||||
|
||||
@@ -840,7 +840,7 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \
|
||||
|
||||
- `--presentation` with `buttons` blocks for inline keyboards when `channels.telegram.capabilities.inlineButtons` allows it
|
||||
- `--pin` or `--delivery '{"pin":true}'` to request pinned delivery when the bot can pin in that chat
|
||||
- `--force-document` to send outbound images and GIFs as documents instead of compressed photo or animated-media uploads
|
||||
- `--force-document` to send outbound images, GIFs, and videos as documents instead of compressed photo, animated-media, or video uploads
|
||||
|
||||
Action gating:
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ Name lookup:
|
||||
- Optional: `--media`, `--presentation`, `--delivery`, `--pin`, `--reply-to`, `--thread-id`, `--gif-playback`, `--force-document`, `--silent`
|
||||
- Shared presentation payloads: `--presentation` sends semantic blocks (`text`, `context`, `divider`, `buttons`, `select`) that core renders through the selected channel's declared capabilities. See [Message Presentation](/plugins/message-presentation).
|
||||
- Generic delivery preferences: `--delivery` accepts delivery hints such as `{ "pin": true }`; `--pin` is shorthand for pinned delivery when the channel supports it.
|
||||
- Telegram only: `--force-document` (send images and GIFs as documents to avoid Telegram compression)
|
||||
- Telegram only: `--force-document` (send images, GIFs, and videos as documents to avoid Telegram compression)
|
||||
- Telegram only: `--thread-id` (forum topic id)
|
||||
- Slack only: `--thread-id` (thread timestamp; `--reply-to` uses the same field)
|
||||
- Telegram + Discord: `--silent`
|
||||
|
||||
@@ -1385,6 +1385,13 @@ describe("sendMessageTelegram", () => {
|
||||
fileName: "fun.gif",
|
||||
mediaUrl: "https://example.com/fun.gif",
|
||||
},
|
||||
{
|
||||
name: "videos",
|
||||
buffer: Buffer.from("fake-video"),
|
||||
contentType: "video/mp4",
|
||||
fileName: "clip.mp4",
|
||||
mediaUrl: "https://example.com/clip.mp4",
|
||||
},
|
||||
])("sends $name as documents when forceDocument is true", async (testCase) => {
|
||||
const chatId = "123";
|
||||
const sendAnimation = vi.fn();
|
||||
@@ -1393,10 +1400,12 @@ describe("sendMessageTelegram", () => {
|
||||
chat: { id: chatId },
|
||||
});
|
||||
const sendPhoto = vi.fn();
|
||||
const api = { sendAnimation, sendDocument, sendPhoto } as unknown as {
|
||||
const sendVideo = vi.fn();
|
||||
const api = { sendAnimation, sendDocument, sendPhoto, sendVideo } as unknown as {
|
||||
sendAnimation: typeof sendAnimation;
|
||||
sendDocument: typeof sendDocument;
|
||||
sendPhoto: typeof sendPhoto;
|
||||
sendVideo: typeof sendVideo;
|
||||
};
|
||||
|
||||
mockLoadedMedia({
|
||||
@@ -1420,6 +1429,8 @@ describe("sendMessageTelegram", () => {
|
||||
});
|
||||
expect(sendPhoto, testCase.name).not.toHaveBeenCalled();
|
||||
expect(sendAnimation, testCase.name).not.toHaveBeenCalled();
|
||||
expect(sendVideo, testCase.name).not.toHaveBeenCalled();
|
||||
expect(probeVideoDimensions, testCase.name).not.toHaveBeenCalled();
|
||||
expect(res.messageId).toBe("10");
|
||||
});
|
||||
|
||||
|
||||
@@ -814,12 +814,13 @@ export async function sendMessageTelegram(
|
||||
fileName: media.fileName,
|
||||
});
|
||||
|
||||
// Validate photo dimensions before attempting sendPhoto
|
||||
let sendImageAsPhoto = true;
|
||||
if (kind === "image" && !isGif && !opts.forceDocument) {
|
||||
const deliveryKind =
|
||||
opts.forceDocument === true && (kind === "image" || kind === "video") ? "document" : kind;
|
||||
if (deliveryKind === "image" && !isGif) {
|
||||
sendImageAsPhoto = await shouldSendTelegramImageAsPhoto(media.buffer);
|
||||
}
|
||||
const isVideoNote = kind === "video" && opts.asVideoNote === true;
|
||||
const isVideoNote = deliveryKind === "video" && opts.asVideoNote === true;
|
||||
const fileName =
|
||||
media.fileName ?? (isGif ? "animation.gif" : inferFilename(kind ?? "document")) ?? "file";
|
||||
const file = new InputFileCtor(media.buffer, fileName);
|
||||
@@ -845,7 +846,9 @@ export async function sendMessageTelegram(
|
||||
...(!needsSeparateText && replyMarkup ? { reply_markup: replyMarkup } : {}),
|
||||
};
|
||||
const videoDimensions =
|
||||
kind === "video" && !isVideoNote ? await probeVideoDimensions(media.buffer) : undefined;
|
||||
deliveryKind === "video" && !isVideoNote
|
||||
? await probeVideoDimensions(media.buffer)
|
||||
: undefined;
|
||||
const mediaParams = {
|
||||
...(htmlCaption ? { caption: htmlCaption, parse_mode: "HTML" as const } : {}),
|
||||
...baseMediaParams,
|
||||
@@ -868,7 +871,7 @@ export async function sendMessageTelegram(
|
||||
);
|
||||
|
||||
const mediaSender = (() => {
|
||||
if (isGif && !opts.forceDocument) {
|
||||
if (isGif && deliveryKind !== "document") {
|
||||
return {
|
||||
label: "animation",
|
||||
sender: (effectiveParams: TelegramThreadScopedParams | undefined) =>
|
||||
@@ -879,7 +882,7 @@ export async function sendMessageTelegram(
|
||||
) as Promise<TelegramMessageLike>,
|
||||
};
|
||||
}
|
||||
if (kind === "image" && !opts.forceDocument && sendImageAsPhoto) {
|
||||
if (deliveryKind === "image" && !isGif && sendImageAsPhoto) {
|
||||
return {
|
||||
label: "photo",
|
||||
sender: (effectiveParams: TelegramThreadScopedParams | undefined) =>
|
||||
@@ -890,7 +893,7 @@ export async function sendMessageTelegram(
|
||||
) as Promise<TelegramMessageLike>,
|
||||
};
|
||||
}
|
||||
if (kind === "video") {
|
||||
if (deliveryKind === "video") {
|
||||
if (isVideoNote) {
|
||||
return {
|
||||
label: "video_note",
|
||||
@@ -946,8 +949,6 @@ export async function sendMessageTelegram(
|
||||
api.sendDocument(
|
||||
chatId,
|
||||
file,
|
||||
// Only force Telegram to keep the uploaded media type when callers explicitly
|
||||
// opt into document delivery for image/GIF uploads.
|
||||
(opts.forceDocument
|
||||
? { ...effectiveParams, disable_content_type_detection: true }
|
||||
: effectiveParams) as Parameters<typeof api.sendDocument>[2],
|
||||
|
||||
Reference in New Issue
Block a user