Skip to content

Commit 591270b

Browse files
Nic-vdwaltclaude
andcommitted
fix: append file extension from MIME type in WhatsApp document fallback
When sending documents without an explicit filename, the recipient received files named "file" with no extension. Use extensionForMime() to derive the correct extension from the MIME type in both the auto-reply and outbound send paths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a50638e commit 591270b

3 files changed

Lines changed: 22 additions & 4 deletions

File tree

src/web/auto-reply/deliver-reply.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { logVerbose, shouldLogVerbose } from "../../globals.js";
66
import { convertMarkdownTables } from "../../markdown/tables.js";
77
import { markdownToWhatsApp } from "../../markdown/whatsapp.js";
88
import { sleep } from "../../utils.js";
9+
import path from "node:path";
10+
import { extensionForMime } from "../../media/mime.js";
911
import { loadWebMedia } from "../media.js";
1012
import { newConnectionId } from "../reconnect.js";
1113
import { formatError } from "../session.js";
@@ -138,8 +140,9 @@ export async function deliverWebReply(params: {
138140
"media:video",
139141
);
140142
} else {
141-
const fileName = media.fileName ?? mediaUrl.split("/").pop() ?? "file";
142143
const mimetype = media.contentType ?? "application/octet-stream";
144+
const rawName = media.fileName ?? mediaUrl.split("/").pop() ?? "file";
145+
const fileName = path.extname(rawName) ? rawName : `${rawName}${extensionForMime(mimetype) ?? ""}`;
143146
await sendWithRetry(
144147
() =>
145148
msg.sendMedia({

src/web/inbound/send-api.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,31 @@ describe("createWebSendApi", () => {
3838
});
3939
});
4040

41-
it("falls back to default document filename when fileName is absent", async () => {
41+
it("falls back to default document filename with extension when fileName is absent", async () => {
4242
const payload = Buffer.from("pdf");
4343
await api.sendMessage("+1555", "doc", payload, "application/pdf");
4444
expect(sendMessage).toHaveBeenCalledWith(
4545
"1555@s.whatsapp.net",
4646
expect.objectContaining({
4747
document: payload,
48-
fileName: "file",
48+
fileName: "file.pdf",
4949
caption: "doc",
5050
mimetype: "application/pdf",
5151
}),
5252
);
5353
});
54+
55+
it("derives extension from MIME type dynamically (text/csv)", async () => {
56+
const payload = Buffer.from("a,b,c");
57+
await api.sendMessage("+1555", "csv data", payload, "text/csv");
58+
expect(sendMessage).toHaveBeenCalledWith(
59+
"1555@s.whatsapp.net",
60+
expect.objectContaining({
61+
document: payload,
62+
fileName: "file.csv",
63+
caption: "csv data",
64+
mimetype: "text/csv",
65+
}),
66+
);
67+
});
5468
});

src/web/inbound/send-api.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { AnyMessageContent, WAPresence } from "@whiskeysockets/baileys";
22
import type { ActiveWebSendOptions } from "../active-listener.js";
33
import { recordChannelActivity } from "../../infra/channel-activity.js";
4+
import { extensionForMime } from "../../media/mime.js";
45
import { toWhatsappJid } from "../../utils.js";
56

67
export function createWebSendApi(params: {
@@ -38,7 +39,7 @@ export function createWebSendApi(params: {
3839
...(gifPlayback ? { gifPlayback: true } : {}),
3940
};
4041
} else {
41-
const fileName = sendOptions?.fileName?.trim() || "file";
42+
const fileName = sendOptions?.fileName?.trim() || `file${extensionForMime(mediaType) ?? ""}`;
4243
payload = {
4344
document: mediaBuffer,
4445
fileName,

0 commit comments

Comments
 (0)