UNPKG

@jackiemacklein/nettz-utils

Version:

Serviços de imagem, e-mail, códigos de barras, utilitários numéricos e componentes React para apps Node.js com TypeScript

358 lines (357 loc) 13.6 kB
"use strict"; /** * @author Jackiê Macklein * @company Onside tecnologia/Nettz * @copyright Todos direitos reservados. * @description Cliente HTTP para WhatsApp Cloud API (envio de mensagens via Graph API). */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createWhatsAppCloudClient = createWhatsAppCloudClient; const errors_1 = require("./errors"); const types_1 = require("./types"); async function readResponseBody(res) { try { return await res.text(); } catch { return ""; } } function applyReplyContext(payload, replyToMessageId) { if (replyToMessageId) { payload.context = { message_id: replyToMessageId }; } } function createWhatsAppCloudClient(config) { var _a, _b, _c, _d; const graphBaseUrl = ((_a = config.graphBaseUrl) !== null && _a !== void 0 ? _a : types_1.WHATSAPP_GRAPH_DEFAULT_BASE_URL).replace(/\/$/, ""); const graphApiVersion = (_b = config.graphApiVersion) !== null && _b !== void 0 ? _b : types_1.WHATSAPP_GRAPH_DEFAULT_VERSION; const phoneNumberId = config.phoneNumberId; const accessToken = config.accessToken; const timeoutMs = (_c = config.timeoutMs) !== null && _c !== void 0 ? _c : 30000; const fetchFn = (_d = config.fetchImpl) !== null && _d !== void 0 ? _d : fetch; if (!accessToken || !phoneNumberId) { throw new errors_1.WhatsAppCloudApiError("WhatsApp Cloud: accessToken e phoneNumberId são obrigatórios", 400, ""); } function versionedPath(suffix) { const s = suffix.startsWith("/") ? suffix : `/${suffix}`; return `/${graphApiVersion}/${phoneNumberId}${s}`; } async function graphRequest(path, init) { var _a, _b; const url = `${graphBaseUrl}${path.startsWith("/") ? path : `/${path}`}`; const controller = new AbortController(); const t = setTimeout(() => controller.abort(), (_a = init === null || init === void 0 ? void 0 : init.timeoutMs) !== null && _a !== void 0 ? _a : timeoutMs); try { const res = await fetchFn(url, { ...init, signal: (_b = init === null || init === void 0 ? void 0 : init.signal) !== null && _b !== void 0 ? _b : controller.signal, headers: { Accept: "application/json", ...((init === null || init === void 0 ? void 0 : init.body) ? { "Content-Type": "application/json" } : {}), Authorization: `Bearer ${accessToken}`, ...init === null || init === void 0 ? void 0 : init.headers, }, }); const text = await readResponseBody(res); if (!res.ok) { throw new errors_1.WhatsAppCloudApiError(`WhatsApp Cloud HTTP ${res.status} ${res.statusText}`, res.status, text); } if (!text || text.trim() === "") { return undefined; } try { return JSON.parse(text); } catch { throw new errors_1.WhatsAppCloudApiError("WhatsApp Cloud resposta não é JSON válido", res.status, text); } } finally { clearTimeout(t); } } async function postMessages(body) { return graphRequest(versionedPath("/messages"), { method: "POST", body: JSON.stringify(body), }); } const api = { graphBaseUrl, graphApiVersion, phoneNumberId, async sendMessage(body) { return postMessages(body); }, async sendTextMessage(options) { var _a; const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "text", text: { preview_url: (_a = options.previewUrl) !== null && _a !== void 0 ? _a : false, body: options.body, }, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendTemplateMessage(options) { var _a; const payload = { messaging_product: "whatsapp", to: options.to, type: "template", template: { name: options.templateName, language: { code: options.languageCode }, ...(((_a = options.components) === null || _a === void 0 ? void 0 : _a.length) ? { components: options.components } : {}), }, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendAddressMessage(options) { var _a; const parameters = { country: options.country, ...((_a = options.actionParameters) !== null && _a !== void 0 ? _a : {}), }; const interactive = { type: "address_message", body: { text: options.bodyText }, action: { name: "address_message", parameters, }, }; if (options.headerText) { interactive.header = { type: "text", text: options.headerText }; } if (options.footerText) { interactive.footer = { text: options.footerText }; } const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "interactive", interactive, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendAudioMessage(options) { const audio = {}; if (options.id) audio.id = options.id; if (options.link) audio.link = options.link; if (options.voice === true) audio.voice = true; const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "audio", audio, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendContactsMessage(options) { const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "contacts", contacts: options.contacts, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendDocumentMessage(options) { const document = {}; if (options.id) document.id = options.id; if (options.link) document.link = options.link; if (options.caption) document.caption = options.caption; if (options.filename) document.filename = options.filename; const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "document", document, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendImageMessage(options) { const image = {}; if (options.id) image.id = options.id; if (options.link) image.link = options.link; if (options.caption) image.caption = options.caption; const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "image", image, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendVideoMessage(options) { const video = {}; if (options.id) video.id = options.id; if (options.link) video.link = options.link; if (options.caption) video.caption = options.caption; const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "video", video, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendLocationMessage(options) { const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "location", location: { latitude: String(options.latitude), longitude: String(options.longitude), ...(options.name ? { name: options.name } : {}), ...(options.address ? { address: options.address } : {}), }, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendInteractiveCtaUrlMessage(options) { const interactive = { type: "cta_url", body: { text: options.bodyText }, action: { name: "cta_url", parameters: { display_text: options.buttonDisplayText, url: options.buttonUrl, }, }, }; if (options.header) { interactive.header = options.header; } if (options.footerText) { interactive.footer = { text: options.footerText }; } const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "interactive", interactive, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendInteractiveListMessage(options) { const interactive = { type: "list", body: { text: options.bodyText }, action: { button: options.actionButtonText, sections: options.sections, }, }; if (options.headerText) { interactive.header = { type: "text", text: options.headerText }; } if (options.footerText) { interactive.footer = { text: options.footerText }; } const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "interactive", interactive, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendInteractiveMediaCarouselMessage(options) { const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "interactive", interactive: { type: "carousel", body: { text: options.mainBodyText }, action: { cards: options.cards }, }, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async sendInteractiveReplyButtonsMessage(options) { const interactive = { type: "button", body: { text: options.bodyText }, action: { buttons: options.buttons.map((b) => ({ type: "reply", reply: { id: b.id, title: b.title }, })), }, }; if (options.header) { interactive.header = options.header; } if (options.footerText) { interactive.footer = { text: options.footerText }; } const payload = { messaging_product: "whatsapp", recipient_type: "individual", to: options.to, type: "interactive", interactive, }; applyReplyContext(payload, options.replyToMessageId); return postMessages(payload); }, async getPhoneNumber(fields) { const q = fields ? `?${new URLSearchParams({ fields }).toString()}` : ""; return graphRequest(`/${graphApiVersion}/${encodeURIComponent(phoneNumberId)}${q}`); }, }; return { ...api, sendText: api.sendTextMessage, sendTemplate: api.sendTemplateMessage, }; }