mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 12:56:01 -06:00
fix: preserve data URL attachment filename extensions (#130625)
Carry the normalized MIME into the existing attachment filename inference. Cover PNG/CSV metadata across actions and the real action-to-plugin dispatch boundary. Explicit filenames and MIME overrides remain unchanged. Closes #130618.
This commit is contained in:
committed by
GitHub
parent
6e3df0d70b
commit
47fe3cc8fc
@@ -29,6 +29,7 @@ const onePixelPng = Buffer.from(
|
||||
const onePixelPngBase64 = onePixelPng.toString("base64");
|
||||
const wrappedOnePixelPngBase64 = onePixelPngBase64.match(/.{1,24}/g)?.join("\r\n") ?? "";
|
||||
const parameterizedPngDataUrl = `data:image/png;charset=utf-8;name=../../ignored.svg;base64,${wrappedOnePixelPngBase64}`;
|
||||
const csvBase64 = Buffer.from("name,value\nexample,1\n").toString("base64");
|
||||
|
||||
function firstMockArg(
|
||||
mock: { mock: { calls: readonly unknown[][] } },
|
||||
@@ -106,10 +107,29 @@ describe("runMessageAction media behavior", () => {
|
||||
await resetMessageActionMediaMocks();
|
||||
});
|
||||
|
||||
it.each(["send", "sendAttachment", "reply", "upload-file", "setGroupIcon"] as const)(
|
||||
"normalizes parameterized, line-wrapped image data URLs for %s",
|
||||
async (action) => {
|
||||
const args: Record<string, unknown> = { buffer: parameterizedPngDataUrl };
|
||||
it.each(
|
||||
(["send", "sendAttachment", "reply", "upload-file", "setGroupIcon"] as const).flatMap(
|
||||
(action) => [
|
||||
{
|
||||
action,
|
||||
buffer: parameterizedPngDataUrl,
|
||||
base64: onePixelPngBase64,
|
||||
contentType: "image/png",
|
||||
filename: "attachment.png",
|
||||
},
|
||||
{
|
||||
action,
|
||||
buffer: `data:text/csv;base64,${csvBase64}`,
|
||||
base64: csvBase64,
|
||||
contentType: "text/csv",
|
||||
filename: "attachment.csv",
|
||||
},
|
||||
],
|
||||
),
|
||||
)(
|
||||
"normalizes $contentType data URLs and infers filenames for $action",
|
||||
async ({ action, buffer, base64, contentType, filename }) => {
|
||||
const args: Record<string, unknown> = { buffer };
|
||||
|
||||
await hydrateAttachmentParamsForAction({
|
||||
cfg: {},
|
||||
@@ -120,14 +140,13 @@ describe("runMessageAction media behavior", () => {
|
||||
mediaPolicy: { mode: "host" },
|
||||
});
|
||||
|
||||
expect(args.contentType).toBe("image/png");
|
||||
expect(args.contentType).toBe(contentType);
|
||||
expect(args.filename).toBe(filename);
|
||||
if (action === "send") {
|
||||
expect(args.media).toBe("buffer://message-send/attachment");
|
||||
expect(args.filename).toBe("attachment.png");
|
||||
} else {
|
||||
expect(canonicalizeBase64(String(args.buffer))).toBe(onePixelPngBase64);
|
||||
expect(canonicalizeBase64(String(args.buffer))).toBe(base64);
|
||||
}
|
||||
expect(args.filename).not.toBe("../../ignored.svg");
|
||||
},
|
||||
);
|
||||
|
||||
@@ -329,6 +348,7 @@ describe("runMessageAction media behavior", () => {
|
||||
|
||||
const payload = requireActionPayload(result);
|
||||
expect(payload.contentType).toBe("image/png");
|
||||
expect(payload.filename).toBe("attachment.png");
|
||||
expect(canonicalizeBase64(String(payload.buffer))).toBe(onePixelPngBase64);
|
||||
},
|
||||
);
|
||||
@@ -617,6 +637,7 @@ describe("runMessageAction media behavior", () => {
|
||||
|
||||
const handlerParams = firstMockArg(handleActionMock, "handleAction");
|
||||
expect(handlerParams.contentType).toBe("image/png");
|
||||
expect(handlerParams.filename).toBe("attachment.png");
|
||||
expect(canonicalizeBase64(String(handlerParams.buffer))).toBe(onePixelPngBase64);
|
||||
});
|
||||
|
||||
|
||||
@@ -538,7 +538,7 @@ async function hydrateAttachmentPayload(params: {
|
||||
} else if (!filename) {
|
||||
params.args.filename = inferAttachmentFilename({
|
||||
mediaHint: mediaSource,
|
||||
contentType: contentTypeParam ?? undefined,
|
||||
contentType: normalized.contentType,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user