This commit is contained in:
bipproduction
2025-11-03 21:18:51 +08:00
parent 4da0401247
commit 74c63c3944
6 changed files with 93 additions and 12 deletions

View File

@@ -20,6 +20,7 @@
"@types/js-yaml": "^4.0.9",
"@types/jwt-decode": "^3.1.0",
"@types/lodash": "^4.17.20",
"@types/mime-types": "^3.0.1",
"@types/qrcode-terminal": "^0.12.2",
"@types/sharp": "^0.32.0",
"add": "^2.0.6",
@@ -32,6 +33,7 @@
"lodash": "^4.17.21",
"meta-cloud-api": "^1.3.0",
"mime": "^4.1.0",
"mime-types": "^3.0.1",
"node-fetch": "^3.3.2",
"pino": "^10.1.0",
"pino-pretty": "^13.1.2",
@@ -202,6 +204,8 @@
"@types/mime": ["@types/mime@1.3.5", "", {}, "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="],
"@types/mime-types": ["@types/mime-types@3.0.1", "", {}, "sha512-xRMsfuQbnRq1Ef+C+RKaENOxXX87Ygl38W1vDfPHRku02TgQr+Qd8iivLtAMcR0KF5/29xlnFihkTlbqFrGOVQ=="],
"@types/node": ["@types/node@24.7.0", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw=="],
"@types/qrcode-terminal": ["@types/qrcode-terminal@0.12.2", "", {}, "sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q=="],
@@ -480,9 +484,9 @@
"mime": ["mime@4.1.0", "", { "bin": { "mime": "bin/cli.js" } }, "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw=="],
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
"mime-types": ["mime-types@3.0.1", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA=="],
"minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
@@ -742,6 +746,8 @@
"fluent-ffmpeg/async": ["async@0.2.10", "", {}, "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="],
"form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
"giget/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
"glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
@@ -776,6 +782,8 @@
"duplexer2/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
"form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
"glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],

View File

@@ -26,6 +26,7 @@
"@types/js-yaml": "^4.0.9",
"@types/jwt-decode": "^3.1.0",
"@types/lodash": "^4.17.20",
"@types/mime-types": "^3.0.1",
"@types/qrcode-terminal": "^0.12.2",
"@types/sharp": "^0.32.0",
"add": "^2.0.6",
@@ -38,6 +39,7 @@
"lodash": "^4.17.21",
"meta-cloud-api": "^1.3.0",
"mime": "^4.1.0",
"mime-types": "^3.0.1",
"node-fetch": "^3.3.2",
"pino": "^10.1.0",
"pino-pretty": "^13.1.2",

BIN
qr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -1,6 +1,8 @@
import Elysia, { t } from "elysia";
import Elysia, { t, type Context } from "elysia";
import { startClient, getState } from "../lib/wa/wa_service";
import _ from "lodash";
import mime from "mime-types";
import { MessageMedia } from "whatsapp-web.js";
const WaRoute = new Elysia({
prefix: "/wa",
@@ -80,5 +82,75 @@ const WaRoute = new Elysia({
tags: ["WhatsApp"],
}
})
.post(
"/send-media",
async ({ body }) => {
const state = getState();
if (!state.ready)
return { message: "WhatsApp route not ready" };
const client = state.client;
if (!client)
return { message: "WhatsApp client not ready" };
try {
const { number, caption, media } = body;
const jid = `${number}@c.us`;
// Siapkan data media
const { data, filename, mimetype } = media;
const mimeType = mimetype || mime.lookup(filename) || "application/octet-stream";
const fileName = filename || `file.${mime.extension(mimeType) || "bin"}`;
const waMedia = new MessageMedia(mimeType, data, fileName);
// Tentukan opsi pengiriman otomatis
const sendOptions: any = { caption };
if (mimeType.startsWith("audio/")) {
// kirim voice note jika ogg/opus
sendOptions.sendAudioAsVoice =
mimeType.includes("ogg") || mimeType.includes("opus");
} else if (
!mimeType.startsWith("image/") &&
!mimeType.startsWith("video/")
) {
// selain gambar/video kirim sebagai dokumen
sendOptions.sendMediaAsDocument = true;
}
await client.sendMessage(jid, waMedia, sendOptions);
return {
success: true,
message: `✅ Media sent to ${number}`,
info: { filename: fileName, mimetype: mimeType },
};
} catch (err: any) {
console.error("Send media error:", err);
return {
success: false,
message: "❌ Failed to send media",
error: err.message,
};
}
},
{
body: t.Object({
number: t.String({ minLength: 10, maxLength: 15 }),
caption: t.Optional(t.String({ maxLength: 255 })),
media: t.Object({
data: t.String(), // base64 tanpa prefix
filename: t.String({ minLength: 1, maxLength: 255 }),
mimetype: t.String({ minLength: 1, maxLength: 255 }),
}),
}),
detail: {
description:
"Send media (image, audio, video, PDF, or any file) to WhatsApp",
tags: ["WhatsApp"],
},
}
);
export default WaRoute;

5
x.sh
View File

@@ -1,3 +1,4 @@
curl -X POST https://n8n.wibudev.com/form/82848bc4-5ea2-4e5a-8bb6-3c09b94a8c5d \
curl -X POST "https://n8n.wibudev.com/form/d65f7cda-4fb6-40cc-aaa0-59127e224429" \
-H "accept: */*" \
-H "Content-Type: multipart/form-data" \
-F "file=@/Users/bip/Documents/projects/jenna/wajs-server/xarif.pdf"
-F "data=@//Users/bip/Documents/projects/jenna/wajs-server/xarif.pdf"

4
xx.ts
View File

@@ -1,3 +1 @@
import mime from "mime";
console.log(mime.getAllExtensions("image/png"));
console.log("nama".includes("namxa"))