ws-cloud-api
Version:
WhatsApp Cloud API for NodeJS
360 lines (355 loc) • 7.64 kB
JavaScript
;
const media = require('../media.cjs');
const index = require('../index.cjs');
async function sendRequest({
id,
body,
path,
query,
method,
config
}) {
const apiVersion = typeof process !== "undefined" ? process.env.WS_CA_VERSION ?? config?.apiVersion ?? "20.0" : config?.apiVersion ?? "20.0";
const phoneNumberId = typeof process !== "undefined" ? process.env.WS_PHONE_NUMBER_ID ?? config?.phoneNumberId : config?.phoneNumberId;
const businessId = typeof process !== "undefined" ? process.env.WS_BUSINESS_ID ?? config?.businessId : config?.businessId;
const token = typeof process !== "undefined" ? process.env.WS_TOKEN ?? config?.token : config?.token;
const requestId = id === "phoneNumberId" ? phoneNumberId : businessId;
if (requestId === void 0) {
return {
success: false,
error: "Missing request ID"
};
}
if (token === void 0) {
return {
success: false,
error: "Missing token"
};
}
try {
const response = await fetch(
`https://graph.facebook.com/v${apiVersion}/${requestId}/${path}${query !== void 0 ? `?${query}` : ""}`,
{
method,
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body
}
);
if (!response.ok) {
return {
success: false,
error: response
};
}
return {
success: true,
response: await response.json()
};
} catch (error) {
console.error("Fetch failed:", error);
return {
success: false,
error
};
}
}
async function sendMessageRequest({
to,
body,
config
}) {
const postBody = JSON.stringify({
messaging_product: "whatsapp",
to,
...body
});
const requestResponse = await sendRequest({
id: "phoneNumberId",
body: postBody,
path: "messages",
method: "POST",
config
});
if (!requestResponse.success) {
console.error(`Failed to send ${body.type} message`);
console.error(JSON.stringify(await requestResponse.error, null, 2));
}
return requestResponse;
}
async function sendText({
to,
message,
previewUrl,
config
}) {
return await sendMessageRequest({
to,
body: {
type: index.MessageTypes.Text,
[index.MessageTypes.Text]: {
preview_url: previewUrl,
body: message
}
},
config
});
}
async function sendSimpleMedia({
to,
type,
link,
filename,
caption,
config
}) {
return await sendMessageRequest({
to,
// FIXME: Typescript not identifying the type
// @ts-expect-error Typescript not identifying the type
body: {
type,
[type]: {
link,
filename,
caption
}
},
config
});
}
async function sendImage({
to,
link,
config
}) {
return await sendSimpleMedia({ to, type: index.MessageTypes.Image, link, config });
}
async function sendVideo({
to,
link,
config
}) {
return await sendSimpleMedia({ to, type: index.MessageTypes.Video, link, config });
}
async function sendDocument({
to,
link,
filename,
caption,
config
}) {
return await sendSimpleMedia({
to,
type: index.MessageTypes.Document,
link,
filename,
caption,
config
});
}
async function sendAudio({
to,
link,
config
}) {
return await sendSimpleMedia({ to, type: index.MessageTypes.Audio, link, config });
}
async function sendFile({
to,
file,
config
}) {
try {
const mediaId = await media.uploadMedia({ media: file, config });
const mimeType = file.type.split("/")[0];
const type = mimeType === "text" || mimeType === "application" ? index.MessageTypes.Document : mimeType;
return await sendMessageRequest({
to,
// FIXME: Typescript not identifying the type
// @ts-expect-error Typescript not identifying the type
body: {
type,
[type]: {
id: mediaId
}
},
config
});
} catch (error) {
console.error("Failed to send file");
console.error(error);
return {
success: false,
error
};
}
}
function generateInteractiveBody(input) {
return {
type: index.MessageTypes.Interactive,
interactive: input
};
}
async function sendButtonMessage({
to,
message,
config
}) {
const body = {
type: index.InteractiveTypes.Button,
body: {
text: message.text
},
action: {
buttons: []
}
};
for (let i = 0; i < message.buttons.length; i++) {
body.action.buttons.push({
type: "reply",
reply: message.buttons[i]
});
}
return await sendMessageRequest({
to,
body: generateInteractiveBody(body),
config
});
}
async function sendCTAButtonMessage({
to,
message,
config
}) {
const body = {
type: index.InteractiveTypes.CTAButton,
body: {
text: message.text
},
action: {
name: index.InteractiveTypes.CTAButton,
parameters: {
display_text: message.buttonText,
url: message.url
}
}
};
return await sendMessageRequest({
to,
body: generateInteractiveBody(body),
config
});
}
async function sendInteractiveListMessage({
to,
list,
config
}) {
const body = {
type: index.InteractiveTypes.List,
body: {
text: list.text
},
action: {
button: list.buttonText,
sections: [
{
title: list.buttonText,
rows: []
}
]
}
};
for (let i = 0; i < list.list.length; i++) {
body.action.sections[0].rows.push({
id: list.list[i].description,
...list.list[i]
});
}
return await sendMessageRequest({
to,
body: generateInteractiveBody(body),
config
});
}
async function sendInteractiveSectionListMessage({
to,
list,
config
}) {
const body = {
type: index.InteractiveTypes.List,
body: {
text: list.text
},
action: {
button: list.buttonText,
sections: []
}
};
for (let i = 0; i < list.sections.length; i++) {
body.action.sections.push({
title: list.sections[i].sectionTitle,
rows: []
});
for (let j = 0; j < list.sections[i].list.length; j++) {
body.action.sections[i].rows.push({
id: list.sections[i].list[j].description,
...list.sections[i].list[j]
});
}
}
return await sendMessageRequest({
to,
body: generateInteractiveBody(body),
config
});
}
async function sendFlowMessage({
to,
flow,
draft,
config
}) {
const body = {
type: index.InteractiveTypes.Flow,
body: {
text: flow.text
},
action: {
name: "flow",
parameters: {
mode: draft === true ? "draft" : "published",
flow_message_version: "3",
flow_action: "navigate",
flow_token: flow.token,
flow_id: flow.id,
flow_cta: flow.ctaText,
flow_action_payload: {
screen: flow.defaultScreen
}
}
}
};
return await sendMessageRequest({
to,
body: generateInteractiveBody(body),
config
});
}
exports.sendAudio = sendAudio;
exports.sendButtonMessage = sendButtonMessage;
exports.sendCTAButtonMessage = sendCTAButtonMessage;
exports.sendDocument = sendDocument;
exports.sendFile = sendFile;
exports.sendFlowMessage = sendFlowMessage;
exports.sendImage = sendImage;
exports.sendInteractiveListMessage = sendInteractiveListMessage;
exports.sendInteractiveSectionListMessage = sendInteractiveSectionListMessage;
exports.sendMessageRequest = sendMessageRequest;
exports.sendRequest = sendRequest;
exports.sendText = sendText;
exports.sendVideo = sendVideo;