diff --git a/src/telegram/bot.media.downloads-media-file-path-no-file-download.test.ts b/src/telegram/bot.media.downloads-media-file-path-no-file-download.test.ts index 8b2089a6984..959b18bb731 100644 --- a/src/telegram/bot.media.downloads-media-file-path-no-file-download.test.ts +++ b/src/telegram/bot.media.downloads-media-file-path-no-file-download.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import * as ssrf from "../infra/net/ssrf.js"; -import { onSpy, sendChatActionSpy } from "./bot.media.e2e-harness.js"; +import { onSpy, saveMediaBufferSpy, sendChatActionSpy } from "./bot.media.e2e-harness.js"; const cacheStickerSpy = vi.fn(); const getCachedStickerSpy = vi.fn(); @@ -184,6 +184,47 @@ describe("telegram inbound media", () => { INBOUND_MEDIA_TEST_TIMEOUT_MS, ); + it( + "keeps Telegram inbound media paths with triple-dash ids", + async () => { + const runtimeError = vi.fn(); + const { handler, replySpy } = await createBotHandlerWithOptions({ runtimeError }); + const fetchSpy = mockTelegramFileDownload({ + contentType: "image/jpeg", + bytes: new Uint8Array([0xff, 0xd8, 0xff, 0x00]), + }); + const inboundPath = "/tmp/media/inbound/file_1095---f00a04a2-99a0-4d98-99b0-dfe61c5a4198.jpg"; + saveMediaBufferSpy.mockResolvedValueOnce({ + id: "media", + path: inboundPath, + size: 4, + contentType: "image/jpeg", + }); + + try { + await handler({ + message: { + message_id: 1001, + chat: { id: 1234, type: "private" }, + photo: [{ file_id: "fid" }], + date: 1736380800, + }, + me: { username: "openclaw_bot" }, + getFile: async () => ({ file_path: "photos/1.jpg" }), + }); + + expect(runtimeError).not.toHaveBeenCalled(); + expect(replySpy).toHaveBeenCalledTimes(1); + const payload = replySpy.mock.calls[0]?.[0] as { Body?: string; MediaPaths?: string[] }; + expect(payload.Body).toContain(""); + expect(payload.MediaPaths).toContain(inboundPath); + } finally { + fetchSpy.mockRestore(); + } + }, + INBOUND_MEDIA_TEST_TIMEOUT_MS, + ); + it("prefers proxyFetch over global fetch", async () => { const runtimeLog = vi.fn(); const runtimeError = vi.fn(); diff --git a/src/telegram/bot.media.e2e-harness.ts b/src/telegram/bot.media.e2e-harness.ts index 7fff9e1e274..191f92744d2 100644 --- a/src/telegram/bot.media.e2e-harness.ts +++ b/src/telegram/bot.media.e2e-harness.ts @@ -6,6 +6,12 @@ export const middlewareUseSpy: Mock = vi.fn(); export const onSpy: Mock = vi.fn(); export const stopSpy: Mock = vi.fn(); export const sendChatActionSpy: Mock = vi.fn(); +export const saveMediaBufferSpy: Mock = vi.fn(async (buffer: Buffer, contentType?: string) => ({ + id: "media", + path: "/tmp/telegram-media", + size: buffer.byteLength, + contentType: contentType ?? "application/octet-stream", +})); type ApiStub = { config: { use: (arg: unknown) => void }; @@ -52,12 +58,8 @@ vi.mock("../media/store.js", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, - saveMediaBuffer: vi.fn(async (buffer: Buffer, contentType?: string) => ({ - id: "media", - path: "/tmp/telegram-media", - size: buffer.byteLength, - contentType: contentType ?? "application/octet-stream", - })), + saveMediaBuffer: (...args: Parameters) => + saveMediaBufferSpy(...args), }; });