UNPKG

@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
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); }; });