const { Contacts } = require('./types/contacts');
const { Interactive } = require("./types/interactive");
const { Audio, Document, Image, Sticker, Video } = require('./types/media');
const Location = require('./types/location');
const { Template } = require('./types/template');
const Text = require('./types/text');
const req = require('./fetch-picker').pick();
/**
* Request API object
*
* @property {String} messaging_product The messaging product (always "whatsapp")
* @property {String} type The type of message
* @property {String} to The user's phone number
* @property {Object} [context] The message to reply to
* @property {String} context.message_id The message id to reply to
* @property {String} [text] The text object stringified to send
* @property {String} [audio] The audio object stringified to send
* @property {String} [document] The document object stringified to send
* @property {String} [image] The image object stringified to send
* @property {String} [sticker] The sticker object stringified to send
* @property {String} [video] The video object stringified to send
* @property {String} [location] The location object stringified to send
* @property {String} [contacts] The contacts object stringified to send
* @property {String} [interactive] The interactive object stringified to send
* @property {String} [template] The template object stringified to send
*/
class Request {
/**
* Create a Request object for the API
*
* @param {(Text|Audio|Document|Image|Sticker|Video|Location|Contacts|Interactive|Template)} object The object to send
* @param {String} to The user's phone number
* @param {String} context The message_id to reply to
*/
constructor(object, to, context) {
let message = { ...object };
this.messaging_product = "whatsapp";
this.type = message._;
delete message._;
this.to = to;
if (context) this.context = { message_id: context };
// If the object contains its name as a property, it means it's an array, use it, else use the class
// This horrible thing comes from Contacts, the only API element which must be an array instead of an object...
this[this.type] = JSON.stringify(message[this.type] ?? message);
}
}
/**
* The sendMessage response object
*
* @package
* @ignore
* @typedef {Object} SendMessageResponse
* @property {Promise} promise The fetch promise
* @property {Request} request The request sent to the server
*/
/**
* Make a message post request to the API
*
* @package
* @ignore
* @param {String} token The API token
* @param {String} v The API version
* @param {String} phoneID The bot's phone id
* @param {String} to The user's phone number
* @param {(Text|Audio|Document|Image|Sticker|Video|Location|Contacts|Interactive|Template)} object Each type of message requires a specific type of object, for example, the "image" type requires an url and optionally captions. Use the constructors for each specific type of message (contacts, interactive, location, media, template, text)
* @param {String} context The message id to reply to
* @returns {SendMessageResponse} An object with the sent request and the fetch promise
*/
function sendMessage(token, v, phoneID, to, object, context) {
const request = new Request(object, to, context);
// Make the post request
const promise = req(`https://graph.facebook.com/${v}/${phoneID}/messages`, {
method: "POST",
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});
return { promise, request };
}
/**
* Mark a message as read
*
* @package
* @ignore
* @param {String} token The API token
* @param {String} v The API version
* @param {String} phoneID The bot's phone id
* @param {String} message_id The message id
* @returns {Promise} The fetch promise
*/
function readMessage(token, v, phoneID, message_id) {
return req(`https://graph.facebook.com/${v}/${phoneID}/messages`, {
method: "POST",
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messaging_product: "whatsapp",
status: "read",
message_id,
}),
});
}
/**
* Generate a QR code for the bot
*
* @package
* @ignore
* @param {String} token The API token
* @param {String} v The API version
* @param {String} phoneID The bot's phone id
* @param {String} message The default message in the QR code
* @param {String} format The image format of the QR code (png or svg)
* @returns {Promise} The fetch promise
*/
function makeQR(token, v, phoneID, message, format) {
const params = {
generate_qr_image: format,
prefilled_message: message,
};
return req(`https://graph.facebook.com/${v}/${phoneID}/message_qrdls?${new URLSearchParams(params)}`, {
method: "POST",
headers: {
'Authorization': `Bearer ${token}`,
},
});
}
/**
* Get one or all the QR codes for the bot
*
* @package
* @ignore
* @param {String} token The API token
* @param {String} v The API version
* @param {String} phoneID The bot's phone id
* @param {String} [id] The QR's id to get. If not specified, all the QR codes will be returned
* @returns {Promise} The fetch promise
*/
function getQR(token, v, phoneID, id) {
return req(`https://graph.facebook.com/${v}/${phoneID}/message_qrdls/${id ?? ""}`, {
headers: {
'Authorization': `Bearer ${token}`,
},
});
}
/**
* Update a QR code for the bot
*
* @package
* @ignore
* @param {String} token The API token
* @param {String} v The API version
* @param {String} phoneID The bot's phone id
* @param {String} id The QR's id to edit
* @param {String} message The new message for the QR code
* @returns {Promise} The fetch promise
*/
function updateQR(token, v, phoneID, id, message) {
const params = {
prefilled_message: message,
};
return req(`https://graph.facebook.com/${v}/${phoneID}/message_qrdls/${id}?${new URLSearchParams(params)}`, {
method: "POST",
headers: {
'Authorization': `Bearer ${token}`,
},
});
}
/**
* Delete a QR code
*
* @package
* @ignore
* @param {String} token The API token
* @param {String} v The API version
* @param {String} phoneID The bot's phone id
* @param {String} id The QR's id to delete
* @returns {Promise} The fetch promise
*/
function deleteQR(token, v, phoneID, id) {
return req(`https://graph.facebook.com/${v}/${phoneID}/message_qrdls/${id}`, {
method: "DELETE",
headers: {
'Authorization': `Bearer ${token}`,
},
});
}
module.exports = { sendMessage, readMessage, makeQR, getQR, updateQR, deleteQR, Request };