@warriorteam/zalo-personal
Version:
Unofficial Zalo Personal API for JavaScript - A powerful library for interacting with Zalo personal accounts with URL attachment support, auto-reply, product catalog, and business features
89 lines (88 loc) • 4.25 kB
JavaScript
import sharp from "sharp";
import { ZaloApiError } from "../Errors/ZaloApiError.js";
import { ThreadType } from "../models/index.js";
import { apiFactory, isBun } from "../utils.js";
function inferExtension(contentType, imageUrl) {
const normalizedContentType = contentType === null || contentType === void 0 ? void 0 : contentType.split(";")[0].trim().toLowerCase();
if (normalizedContentType === "image/jpeg")
return "jpg";
if (normalizedContentType === "image/png")
return "png";
if (normalizedContentType === "image/webp")
return "webp";
if (normalizedContentType === "image/gif")
return "gif";
try {
const pathname = new URL(imageUrl).pathname.toLowerCase();
const ext = pathname.split(".").pop();
if (ext && ["jpg", "jpeg", "png", "webp", "gif"].includes(ext))
return ext;
}
catch (_a) {
return "jpg";
}
return "jpg";
}
export const sendImageByUrlFactory = apiFactory()((api, ctx) => {
/**
* Download an image from URL, convert it to Buffer, then send it as an attachment.
*
* @param options Image URL and message options
* @param threadId ID of the user or group to send the image to
* @param type Type of thread, default user
*
* @throws {ZaloApiError}
*/
return async function sendImageByUrl(options, threadId, type = ThreadType.User) {
var _a, _b, _c, _d, _e;
if (!(options === null || options === void 0 ? void 0 : options.imageUrl))
throw new ZaloApiError("Missing imageUrl");
if (!threadId)
throw new ZaloApiError("Missing threadId");
const requestOptions = Object.assign({ method: "GET", headers: options.headers }, (isBun
? {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
proxy: (_b = (_a = ctx.options.agent) === null || _a === void 0 ? void 0 : _a.proxy) === null || _b === void 0 ? void 0 : _b.href,
}
: { agent: ctx.options.agent }));
const response = await ctx.options.polyfill(options.imageUrl, requestOptions).catch((error) => {
throw new ZaloApiError(`Unable to download image: ${error instanceof Error ? error.message : String(error)}`);
});
if (!(response === null || response === void 0 ? void 0 : response.ok)) {
throw new ZaloApiError(`Unable to download image: HTTP ${(_c = response === null || response === void 0 ? void 0 : response.status) !== null && _c !== void 0 ? _c : "unknown"}`);
}
const contentType = response.headers.get("content-type");
if (!(contentType === null || contentType === void 0 ? void 0 : contentType.toLowerCase().startsWith("image/"))) {
throw new ZaloApiError(`URL does not point to an image. Received content-type: ${contentType !== null && contentType !== void 0 ? contentType : "unknown"}`);
}
const buffer = Buffer.from(await response.arrayBuffer());
const metadata = await sharp(buffer).metadata().catch((error) => {
throw new ZaloApiError(`Unable to read image metadata: ${error instanceof Error ? error.message : String(error)}`);
});
if (!metadata.width || !metadata.height) {
throw new ZaloApiError("Unable to determine image dimensions");
}
const extension = inferExtension(contentType, options.imageUrl);
const filename = (_d = options.filename) !== null && _d !== void 0 ? _d : `image.${extension}`;
return await api.sendMessage({
msg: (_e = options.msg) !== null && _e !== void 0 ? _e : "",
ttl: options.ttl,
mentions: options.mentions,
quote: options.quote,
styles: options.styles,
urgency: options.urgency,
attachments: [
{
data: buffer,
filename,
metadata: {
totalSize: buffer.length,
width: metadata.width,
height: metadata.height,
},
},
],
}, threadId, type);
};
});