diff --git a/extensions/matrix/src/matrix/monitor/handler.media-failure.test.ts b/extensions/matrix/src/matrix/monitor/handler.media-failure.test.ts index 5555ecb703f..f9d844e5149 100644 --- a/extensions/matrix/src/matrix/monitor/handler.media-failure.test.ts +++ b/extensions/matrix/src/matrix/monitor/handler.media-failure.test.ts @@ -74,6 +74,57 @@ describe("createMatrixRoomMessageHandler media failures", () => { installMatrixMonitorTestRuntime(); }); + it("forwards the Matrix event body as originalFilename for media downloads", async () => { + downloadMatrixMediaMock.mockResolvedValue({ + path: "/tmp/inbound/Screenshot-2026-03-27---uuid.png", + contentType: "image/png", + placeholder: "[matrix media]", + }); + const { handler } = createMediaFailureHarness(); + + await handler( + "!room:example.org", + createImageEvent({ + msgtype: "m.image", + body: " Screenshot 2026-03-27.png ", + url: "mxc://example/image", + }), + ); + + expect(downloadMatrixMediaMock).toHaveBeenCalledWith( + expect.objectContaining({ + mxcUrl: "mxc://example/image", + maxBytes: 5 * 1024 * 1024, + originalFilename: "Screenshot 2026-03-27.png", + }), + ); + }); + + it("prefers content.filename over body text when deriving originalFilename", async () => { + downloadMatrixMediaMock.mockResolvedValue({ + path: "/tmp/inbound/Screenshot-2026-03-27---uuid.png", + contentType: "image/png", + placeholder: "[matrix media]", + }); + const { handler } = createMediaFailureHarness(); + + await handler( + "!room:example.org", + createImageEvent({ + msgtype: "m.image", + body: "can you review this screenshot?", + filename: "Screenshot 2026-03-27.png", + url: "mxc://example/image", + }), + ); + + expect(downloadMatrixMediaMock).toHaveBeenCalledWith( + expect.objectContaining({ + originalFilename: "Screenshot 2026-03-27.png", + }), + ); + }); + it("replaces bare image filenames with an unavailable marker when unencrypted download fails", async () => { downloadMatrixMediaMock.mockRejectedValue(new Error("download failed")); const { handler, recordInboundSession, logger, runtime } = createMediaFailureHarness(); diff --git a/extensions/matrix/src/matrix/monitor/handler.ts b/extensions/matrix/src/matrix/monitor/handler.ts index 9647990dd43..3df9f90c859 100644 --- a/extensions/matrix/src/matrix/monitor/handler.ts +++ b/extensions/matrix/src/matrix/monitor/handler.ts @@ -643,6 +643,9 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam ? content.file : undefined; const finalMediaUrl = finalContentUrl ?? finalContentFile?.url; + const contentBody = typeof content.body === "string" ? content.body.trim() : ""; + const contentFilename = typeof content.filename === "string" ? content.filename.trim() : ""; + const originalFilename = contentFilename || contentBody || undefined; const contentInfo = "info" in content && content.info && typeof content.info === "object" ? (content.info as { mimetype?: string; size?: number }) @@ -658,7 +661,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam sizeBytes: contentSize, maxBytes: mediaMaxBytes, file: finalContentFile, - originalFilename: typeof content.body === "string" ? content.body.trim() : undefined, + originalFilename, }); } catch (err) { mediaDownloadFailed = true; @@ -676,8 +679,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam } } - const rawBody = - locationPayload?.text ?? (typeof content.body === "string" ? content.body.trim() : ""); + const rawBody = locationPayload?.text ?? contentBody; const bodyText = resolveMatrixInboundBodyText({ rawBody, filename: typeof content.filename === "string" ? content.filename : undefined,