messaging-api-messenger
Version:
Messaging API client for Messenger
1,299 lines • 109 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = __importDefault(require("crypto"));
const fs_1 = __importDefault(require("fs"));
const querystring_1 = __importDefault(require("querystring"));
const url_1 = __importDefault(require("url"));
const axios_error_1 = __importDefault(require("axios-error"));
const form_data_1 = __importDefault(require("form-data"));
const append_query_1 = __importDefault(require("append-query"));
const axios_1 = __importDefault(require("axios"));
const get_1 = __importDefault(require("lodash/get"));
const ts_invariant_1 = __importDefault(require("ts-invariant"));
const isPlainObject_1 = __importDefault(require("lodash/isPlainObject"));
const omit_1 = __importDefault(require("lodash/omit"));
const warning_1 = __importDefault(require("warning"));
const messaging_api_common_1 = require("messaging-api-common");
const Messenger_1 = __importDefault(require("./Messenger"));
function extractVersion(version) {
if (version.startsWith('v')) {
return version.slice(1);
}
return version;
}
function handleError(err) {
if (err.response && err.response.data) {
const error = (0, get_1.default)(err, 'response.data.error');
if (error) {
const msg = `Messenger API - ${error.code} ${error.type} ${error.message}`;
throw new axios_error_1.default(msg, err);
}
}
throw new axios_error_1.default(err.message, err);
}
class MessengerClient {
constructor(config) {
(0, ts_invariant_1.default)(typeof config !== 'string', `MessengerClient: do not allow constructing client with ${config} string. Use object instead.`);
this.accessToken = config.accessToken;
(0, ts_invariant_1.default)(!config.version || typeof config.version === 'string', 'Type of `version` must be string.');
this.appId = config.appId;
this.appSecret = config.appSecret;
this.version = extractVersion(config.version || '6.0');
this.onRequest = config.onRequest;
const { origin } = config;
let skipAppSecretProof;
if (typeof config.skipAppSecretProof === 'boolean') {
skipAppSecretProof = config.skipAppSecretProof;
}
else {
skipAppSecretProof = this.appSecret == null;
}
this.axios = axios_1.default.create({
baseURL: `${origin || 'https://graph.facebook.com'}/v${this.version}/`,
headers: { 'Content-Type': 'application/json' },
transformRequest: [
// axios use any as type of the data in AxiosTransformer
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(data) => data && (0, isPlainObject_1.default)(data) ? (0, messaging_api_common_1.snakecaseKeysDeep)(data) : data,
...axios_1.default.defaults.transformRequest,
],
// `transformResponse` allows changes to the response data to be made before
// it is passed to then/catch
transformResponse: [
...axios_1.default.defaults.transformResponse,
// axios use any as type of the data in AxiosTransformer
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(data) => data && (0, isPlainObject_1.default)(data) ? (0, messaging_api_common_1.camelcaseKeysDeep)(data) : data,
],
});
this.axios.interceptors.request.use((0, messaging_api_common_1.createRequestInterceptor)({ onRequest: this.onRequest }));
// add appsecret_proof to request
if (!skipAppSecretProof) {
(0, ts_invariant_1.default)(this.appSecret, 'Must provide appSecret when skipAppSecretProof is false');
const appSecret = this.appSecret;
this.axios.interceptors.request.use((requestConfig) => {
const isBatch = requestConfig.url === '/' && Array.isArray(requestConfig.data.batch);
if (isBatch) {
// eslint-disable-next-line no-param-reassign
requestConfig.data.batch = requestConfig.data.batch.map((item) => {
const urlParts = url_1.default.parse(item.relativeUrl, true);
let accessToken = (0, get_1.default)(urlParts, 'query.access_token');
if (!accessToken && item.body) {
const entries = decodeURIComponent(item.body)
.split('&')
.map((pair) => pair.split('='));
const accessTokenEntry = entries.find(([key]) => key === 'access_token');
if (accessTokenEntry) {
accessToken = accessTokenEntry[1];
}
}
if (accessToken) {
const appSecretProof = crypto_1.default
.createHmac('sha256', appSecret)
.update(accessToken, 'utf8')
.digest('hex');
return Object.assign(Object.assign({}, item), { relativeUrl: (0, append_query_1.default)(item.relativeUrl, {
appsecret_proof: appSecretProof,
}) });
}
return item;
});
}
const urlParts = url_1.default.parse(requestConfig.url || '', true);
const accessToken = (0, get_1.default)(urlParts, 'query.access_token', this.accessToken);
const appSecretProof = crypto_1.default
.createHmac('sha256', appSecret)
.update(accessToken, 'utf8')
.digest('hex');
// eslint-disable-next-line no-param-reassign
requestConfig.url = (0, append_query_1.default)(requestConfig.url || '', {
appsecret_proof: appSecretProof,
});
return requestConfig;
});
}
}
/**
* @deprecated Use `new MessengerClient(...)` instead.
*/
static connect(config) {
(0, warning_1.default)(false, '`MessengerClient.connect(...)` is deprecated. Use `new MessengerClient(...)` instead.');
return new MessengerClient(config);
}
/**
* Gets page info using Graph API.
*
* @returns Page info
*
* @see https://developers.facebook.com/docs/graph-api/reference/page/
*
* @example
*
* ```js
* await client.getPageInfo();
* // {
* // name: 'Bot Demo',
* // id: '1895382890692546',
* // }
* ```
*/
getPageInfo({ fields, } = {}) {
return this.axios
.get('/me', {
params: {
access_token: this.accessToken,
fields: fields ? fields.join(',') : undefined,
},
})
.then((res) => res.data, handleError);
}
/**
* Gets token information.
*
* @returns Token information
*
* @see https://developers.facebook.com/docs/facebook-login/access-tokens/debugging-and-error-handling
*
* @example
*
* ```js
* await client.debugToken();
* // {
* // appId: '000000000000000',
* // application: 'Social Cafe',
* // expiresAt: 1352419328,
* // isValid: true,
* // issuedAt: 1347235328,
* // scopes: ['email', 'user_location'],
* // userId: 1207059,
* // }
* ```
*/
debugToken() {
(0, ts_invariant_1.default)(this.appId, 'App ID is required to debug token');
(0, ts_invariant_1.default)(this.appSecret, 'App Secret is required to debug token');
const accessToken = `${this.appId}|${this.appSecret}`;
return this.axios
.get(`/debug_token`, {
params: {
input_token: this.accessToken,
access_token: accessToken,
},
})
.then((res) => res.data.data, handleError);
}
/**
* Create new Webhooks subscriptions.
*
* @param subscription - Subscription parameters.
* @param subscription.accessToken - App access token.
* @param subscription.callbackUrl - The URL to receive the POST request when an update is triggered, and a GET request when attempting this publish operation.
* @param subscription.verifyToken - An arbitrary string that can be used to confirm to your server that the request is valid.
* @param subscription.fields - One or more of the set of valid fields in this object to subscribe to. Default Fields: `messages`, `messaging_postbacks`, `messaging_optins`, `messaging_referrals`, `messaging_handovers` and `messaging_policy_enforcement`.
* @param subscription.object - Indicates the object type that this subscription applies to. Defaults to `page`.
* @param subscription.includeValues - Indicates if change notifications should include the new values.
* @returns Success status
*
* @see https://developers.facebook.com/docs/graph-api/reference/app/subscriptions
*
* @example
*
* ```js
* await client.createSubscription({
* accessToken: APP_ACCESS_TOKEN,
* callbackUrl: 'https://mycallback.com',
* fields: ['messages', 'messaging_postbacks', 'messaging_referrals'],
* verifyToken: VERIFY_TOKEN,
* });
*
* // Or provide app id and app secret instead of app access token:
* client.createSubscription({
* accessToken: `${APP_ID}|${APP_SECRET}`,
* callbackUrl: 'https://mycallback.com',
* fields: ['messages', 'messaging_postbacks', 'messaging_referrals'],
* verifyToken: VERIFY_TOKEN,
* });
* ```
*/
createSubscription({ object = 'page', callbackUrl, fields = [
'messages',
'messaging_postbacks',
'messaging_optins',
'messaging_referrals',
'messaging_handovers',
'messaging_policy_enforcement',
], includeValues, verifyToken, accessToken: appAccessToken, }) {
const { appId } = this;
(0, ts_invariant_1.default)(appId, 'App ID is required to create subscription');
(0, ts_invariant_1.default)(this.appSecret || appAccessToken, 'App Secret or App Token is required to create subscription');
const accessToken = appAccessToken || `${appId}|${this.appSecret}`;
return this.axios
.post(`/${appId}/subscriptions?access_token=${accessToken}`, {
object,
callbackUrl,
fields: fields.join(','),
includeValues,
verifyToken,
})
.then((res) => res.data, handleError);
}
/**
* Gets the current Webhook subscriptions set up on your app.
*
* @param options - The other parameters.
* @param options.accessToken - App access token.
* @returns An array of subscriptions.
*
* @see https://developers.facebook.com/docs/graph-api/reference/app/subscriptions
*
* @example
*
* ```js
* await client.getSubscriptions({
* accessToken: APP_ACCESS_TOKEN,
* });
* // [{
* // object: 'page',
* // callbackUrl: 'https://www.example.com/callback'
* // fields: ['messages', 'messaging_postbacks', 'messaging_optins'],
* // active: true,
* // }]
*
* // Or provide app id and app secret instead of app access token:
* await client.getSubscriptions({
* accessToken: `${APP_ID}|${APP_SECRET}`,
* });
* ```
*/
getSubscriptions({ accessToken: appAccessToken, } = {}) {
const { appId } = this;
(0, ts_invariant_1.default)(appId, 'App ID is required to get subscriptions');
(0, ts_invariant_1.default)(this.appSecret || appAccessToken, 'App Secret or App Token is required to get subscriptions');
const accessToken = appAccessToken || `${appId}|${this.appSecret}`;
return this.axios
.get(`/${appId}/subscriptions?access_token=${accessToken}`)
.then((res) => res.data.data, handleError);
}
/**
* Get the current page subscription set up on your app.
*
* @param options - The other parameters.
* @param options.accessToken - App access token.
* @returns The current page subscription
*
* @see https://developers.facebook.com/docs/graph-api/reference/app/subscriptions
*
* @example
*
* ```js
* await client.getPageSubscription({
* accessToken: APP_ACCESS_TOKEN,
* });
*
* // Or provide app id and app secret instead of app access token:
* await client.getPageSubscription({
* accessToken: `${APP_ID}|${APP_SECRET}`,
* });
* ```
*/
getPageSubscription({ accessToken: appAccessToken, } = {}) {
const { appId } = this;
(0, ts_invariant_1.default)(appId, 'App ID is required to get subscription');
(0, ts_invariant_1.default)(this.appSecret || appAccessToken, 'App Secret or App Token is required to get subscription');
const accessToken = appAccessToken || `${appId}|${this.appSecret}`;
return this.getSubscriptions({
accessToken,
}).then((subscriptions) => subscriptions.filter((subscription) => subscription.object === 'page')[0] || null);
}
/**
* Programmatically check the feature submission status of page-level platform features
*
* @returns An array of all submitted feature submission requests. If no request has been submitted, the array will be empty.
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messaging-feature-review-api
*
* @example
*
* ```js
* await client.getMessagingFeatureReview();
* // [{
* // "feature": "subscription_messaging",
* // "status": "<pending|rejected|approved|limited>"
* // }]
*/
getMessagingFeatureReview() {
return this.axios
.get(`/me/messaging_feature_review?access_token=${this.accessToken}`)
.then((res) => res.data.data, handleError);
}
/**
* Retrieves a person's profile.
*
* @param userId - Facebook page-scoped user ID.
* @param options - Other optional parameters.
* @param options.fields - Value must be among `id`, `name`, `first_name`, `last_name`, `profile_pic`, `locale`, `timezone` and `gender`, default with `id`, `name`, `first_name`, `last_name` and `profile_pic`.
* @returns Profile of the user.
*
* @see https://www.quora.com/How-connect-Facebook-user-id-to-sender-id-in-the-Facebook-messenger-platform
*
* @example
*
* ```js
* await client.getUserProfile(USER_ID);
* // {
* // id: '5566'
* // firstName: 'Johnathan',
* // lastName: 'Jackson',
* // profilePic: 'https://example.com/pic.png',
* // }
* ```
*/
getUserProfile(userId, { fields = ['id', 'name', 'first_name', 'last_name', 'profile_pic'], } = {}) {
return this.axios
.get(`/${userId}?fields=${fields.join(',')}&access_token=${this.accessToken}`)
.then((res) => res.data, handleError);
}
/**
* Retrieves the current value of one or more Messenger Profile properties by name.
*
* @param fields - An array of Messenger profile properties to retrieve. Value must be among `account_linking_url`, `persistent_menu`, `get_started`, `greeting`, `ice_breakers` and `whitelisted_domains`.
* @returns The current value of the requested properties
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api
*
* @example
*
* ```js
* await client.getMessengerProfile(['get_started', 'persistent_menu']);
* // [
* // {
* // getStarted: {
* // payload: 'GET_STARTED',
* // },
* // },
* // {
* // persistentMenu: [
* // {
* // locale: 'default',
* // composerInputDisabled: true,
* // callToActions: [
* // {
* // type: 'postback',
* // title: 'Restart Conversation',
* // payload: 'RESTART',
* // },
* // ],
* // },
* // ],
* // },
* // ]
* ```
*/
getMessengerProfile(fields) {
return this.axios
.get(`/me/messenger_profile?fields=${fields.join(',')}&access_token=${this.accessToken}`)
.then((res) => res.data.data, handleError);
}
/**
* Sets the values of one or more Messenger Profile properties. Only properties set in the request body will be overwritten.
*
* @param profile - [Profile](https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api#profile_properties) object.
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api#post
*
* @example
*
* ```js
* await client.setMessengerProfile({
* getStarted: {
* payload: 'GET_STARTED',
* },
* persistentMenu: [
* {
* locale: 'default',
* composerInputDisabled: true,
* callToActions: [
* {
* type: 'postback',
* title: 'Restart Conversation',
* payload: 'RESTART',
* },
* ],
* },
* ],
* });
* ```
*/
setMessengerProfile(profile) {
return this.axios
.post(`/me/messenger_profile?access_token=${this.accessToken}`, profile)
.then((res) => res.data, handleError);
}
/**
* Deletes one or more Messenger Profile properties. Only properties specified in the fields array will be deleted.
*
* @param fields - An array of Messenger profile properties to delete. Value must be among `account_linking_url`, `persistent_menu`, `get_started`, `greeting`, `ice_breakers` and `whitelisted_domains`.
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api#delete
*
* @example
*
* ```js
* await client.deleteMessengerProfile(['get_started', 'persistent_menu']);
* ```
*/
deleteMessengerProfile(fields) {
return this.axios
.delete(`/me/messenger_profile?access_token=${this.accessToken}`, {
data: {
fields,
},
})
.then((res) => res.data, handleError);
}
/**
* Retrieves the current value of get started button.
*
* @returns Config of get started button
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/get-started-button
*
* @example
*
* ```js
* await client.getGetStarted();
* // {
* // payload: 'GET_STARTED',
* // }
* ```
*/
getGetStarted() {
return this.getMessengerProfile(['get_started']).then((res) => res[0]
? res[0].getStarted
: null);
}
/**
* Sets the values of get started button.
*
* @param payload - Payload sent back to your webhook in a `messaging_postbacks` event when the 'Get Started' button is tapped.
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/get-started-button
*
* @example
* *
* ```js
* await client.setGetStarted('GET_STARTED');
* ```
*/
setGetStarted(payload) {
return this.setMessengerProfile({
getStarted: {
payload,
},
});
}
/**
* Deletes get started button.
*
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/get-started-button
*
* @example
*
* ```js
* await client.deleteGetStarted();
* ```
*/
deleteGetStarted() {
return this.deleteMessengerProfile(['get_started']);
}
/**
* Retrieves the current value of persistent menu.
*
* @returns Array of persistent menus.
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/persistent-menu
*
* @example
*
* ```js
* await client.getPersistentMenu();
* // [
* // {
* // locale: 'default',
* // composerInputDisabled: true,
* // callToActions: [
* // {
* // type: 'postback',
* // title: 'Restart Conversation',
* // payload: 'RESTART',
* // },
* // {
* // type: 'web_url',
* // title: 'Powered by ALOHA.AI, Yoctol',
* // url: 'https://www.yoctol.com/',
* // },
* // ],
* // },
* // ]
* ```
*/
getPersistentMenu() {
return this.getMessengerProfile(['persistent_menu']).then((res) => res[0] ? res[0].persistentMenu : null);
}
/**
* Sets the values of persistent menu.
*
* @param menu - Array of [menu](https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/persistent-menu#properties).
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/persistent-menu
*
* @example
*
* ```js
* await client.setPersistentMenu([
* {
* locale: 'default',
* callToActions: [
* {
* title: 'Play Again',
* type: 'postback',
* payload: 'RESTART',
* },
* {
* title: 'Explore',
* type: 'web_url',
* url: 'https://www.youtube.com/watch?v=v',
* webviewHeightRatio: 'tall',
* },
* {
* title: 'Powered by YOCTOL',
* type: 'web_url',
* url: 'https://www.yoctol.com/',
* webviewHeightRatio: 'tall',
* },
* ],
* },
* ]);
* ```
*
* @note You must set a get started button to use the persistent menu.
*/
setPersistentMenu(menuItems, { composerInputDisabled = false, } = {}) {
// locale is in type PersistentMenuItem
if (menuItems.some((item) => 'locale' in item && item.locale === 'default')) {
return this.setMessengerProfile({
persistentMenu: menuItems,
});
}
// menuItems is in type MenuItem[]
return this.setMessengerProfile({
persistentMenu: [
{
locale: 'default',
composerInputDisabled,
callToActions: menuItems,
},
],
});
}
/**
* Deletes persistent menu.
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/persistent-menu
*
* @example
*
* ```js
* await client.deletePersistentMenu();
* ```
*/
deletePersistentMenu() {
return this.deleteMessengerProfile(['persistent_menu']);
}
/**
* User Level Persistent Menu
*
* @see https://developers.facebook.com/docs/messenger-platform/send-messages/persistent-menu#user_level_menu
*
* @example
*
* ```js
* ```
*/
getUserPersistentMenu(userId) {
return this.axios
.get(`/me/custom_user_settings?psid=${userId}&access_token=${this.accessToken}`)
.then((res) => res.data.data[0]
? res.data.data[0]
.userLevelPersistentMenu
: null, handleError);
}
/**
*
* @example
*
* ```js
* ```
*/
setUserPersistentMenu(userId, menuItems, { composerInputDisabled = false, } = {}) {
// locale is in type PersistentMenuItem
if (menuItems.some((item) => 'locale' in item && item.locale === 'default')) {
return this.axios
.post(`/me/custom_user_settings?access_token=${this.accessToken}`, {
psid: userId,
persistentMenu: menuItems,
})
.then((res) => res.data, handleError);
}
// menuItems is in type MenuItem[]
return this.axios
.post(`/me/custom_user_settings?access_token=${this.accessToken}`, {
psid: userId,
persistentMenu: [
{
locale: 'default',
composerInputDisabled,
callToActions: menuItems,
},
],
})
.then((res) => res.data, handleError);
}
/**
*
* @example
*
* ```js
* ```
*/
deleteUserPersistentMenu(userId) {
return this.axios
.delete(`/me/custom_user_settings?psid=${userId}¶ms=[%22persistent_menu%22]&access_token=${this.accessToken}`)
.then((res) => res.data, handleError);
}
/**
* Retrieves the current value of greeting text.
*
* @returns Array of greeting configs
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/greeting
*
* @example
*
* ```js
* await client.getGreeting();
* // [
* // {
* // locale: 'default',
* // text: 'Hello!',
* // },
* // ]
* ```
*/
getGreeting() {
return this.getMessengerProfile(['greeting']).then((res) => res[0] ? res[0].greeting : null);
}
/**
* Sets the values of greeting text.
*
* @param greeting - Array of [greeting](https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/greeting#properties).
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/greeting
*
* @example
*
* ```js
* await client.setGreeting([
* {
* locale: 'default',
* text: 'Hello!',
* },
* ]);
* ```
*/
setGreeting(greeting) {
if (typeof greeting === 'string') {
return this.setMessengerProfile({
greeting: [
{
locale: 'default',
text: greeting,
},
],
});
}
return this.setMessengerProfile({
greeting,
});
}
/**
* Deletes greeting text.
*
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/greeting
*
* @example
*
* ```js
* await client.deleteGreeting();
* ```
*/
deleteGreeting() {
return this.deleteMessengerProfile(['greeting']);
}
/**
* Retrieves the current value of ice breakers.
*
* @returns Array of ice breakers.
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/ice-breakers
*
* @example
*
* ```js
* await client.getIceBreakers()
* // [
* // {
* // "question": "<QUESTION>",
* // "payload": "<PAYLOAD>",
* // },
* // {
* // "question": "<QUESTION>",
* // "payload": "<PAYLOAD>",
* // }
* // ]
* ```
*/
getIceBreakers() {
return this.getMessengerProfile(['ice_breakers']).then((res) => res[0] ? res[0].iceBreakers : null);
}
/**
* Sets the values of ice breakers.
*
* @param iceBreakers - Array of ice breakers.
* @returns Success status
*
* @example
*
* ```js
* await client.setIceBreakers([
* {
* question: '<QUESTION>',
* payload: '<PAYLOAD>',
* },
* {
* question: '<QUESTION>',
* payload: '<PAYLOAD>',
* }
* ]);
* ```
*/
setIceBreakers(iceBreakers) {
return this.setMessengerProfile({
iceBreakers,
});
}
/**
* Deletes ice breakers.
*
* @returns Success status
*
* @example
*
* ```js
* await client.deleteIceBreakers();
* ```
*/
deleteIceBreakers() {
return this.deleteMessengerProfile(['ice_breakers']);
}
/**
* Retrieves the current value of whitelisted domains.
*
* @returns Array of whitelisted domains.
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/domain-whitelisting
*
* @example
*
* ```js
* await client.getWhitelistedDomains();
* // ['http://www.example.com/']
* ```
*/
getWhitelistedDomains() {
return this.getMessengerProfile(['whitelisted_domains']).then((res) => res[0] ? res[0].whitelistedDomains : null);
}
/**
* Sets the values of whitelisted domains.
*
* @param whitelistedDomains - Array of [whitelisted_domain](https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/domain-whitelisting#properties).
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/domain-whitelisting
*
* @example
*
* ```js
* await client.setWhitelistedDomains(['www.example.com']);
* ```
*/
setWhitelistedDomains(whitelistedDomains) {
return this.setMessengerProfile({
whitelistedDomains,
});
}
/**
* Deletes whitelisted domains.
*
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/domain-whitelisting
*
* @example
*
* ```js
* await client.deleteWhitelistedDomains();
* ```
*/
deleteWhitelistedDomains() {
return this.deleteMessengerProfile(['whitelisted_domains']);
}
/**
* Retrieves the current value of account linking URL.
*
* @returns Account linking URL
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/account-linking-url
*
* @example
*
* ```js
* await client.getAccountLinkingURL();
* // 'https://www.example.com/oauth?response_type=code&client_id=1234567890&scope=basic'
* ```
*/
getAccountLinkingURL() {
return this.getMessengerProfile(['account_linking_url']).then((res) => res[0] ? res[0].accountLinkingUrl : null);
}
/**
* Sets the values of account linking URL.
*
* @param url - Account linking URL.
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/account-linking-url
*
* @example
*
* ```js
* await client.setAccountLinkingURL(
* 'https://www.example.com/oauth?response_type=code&client_id=1234567890&scope=basic'
* );
* ```
*/
setAccountLinkingURL(accountLinkingUrl) {
return this.setMessengerProfile({
accountLinkingUrl,
});
}
/**
* Deletes account linking URL.
*
* @returns Success status
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/account-linking-url
*
* @example
*
* ```js
* await client.deleteAccountLinkingURL();
* ```
*/
deleteAccountLinkingURL() {
return this.deleteMessengerProfile(['account_linking_url']);
}
/**
* Sends request raw body using the Send API.
*
* @param body - The raw body to be sent.
* @returns An object includes recipientId and messageId.
*
* @see https://developers.facebook.com/docs/messenger-platform/reference/send-api#request
*
* @example
*
* ```js
* await client.sendRawBody({
* recipient: {
* id: USER_ID,
* },
* message: {
* text: 'Hello!',
* },
* });
* // {
* // recipientId: '1254477777772919',
* // messageId: 'AG5Hz2Uq7tuwNEhXfYYKj8mJEM_QPpz5jdCK48PnKAjSdjfipqxqMvK8ma6AC8fplwlqLP_5cgXIbu7I3rBN0P'
* // }
* ```
*/
sendRawBody(body) {
return this.axios
.post(`/me/messages?access_token=${this.accessToken}`, body)
.then((res) => res.data, handleError);
}
/**
* Sends messages to the specified user using the Send API.
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param message - A [message](https://developers.facebook.com/docs/messenger-platform/reference/send-api#message) object.
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @returns An object includes recipientId and messageId.
*
* @example
*
* ```js
* await client.sendMessage(USER_ID, {
* text: 'Hello!',
* });
* ```
*
* You can specify [messaging type](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) using options. If `messagingType` and `tag` is not provided, `UPDATE` will be used as default messaging type.
*
* ```js
* await client.sendMessage(
* USER_ID,
* { text: 'Hello!' },
* { messagingType: 'RESPONSE' }
* );
* ```
*
* Available messaging types:
* - `UPDATE` as default
* - `RESPONSE` using `{ messagingType: 'RESPONSE' }` options
* - `MESSAGE_TAG` using `{ tag: 'ANY_TAG' }` options
*/
sendMessage(psidOrRecipient, message, options = {}) {
const recipient = typeof psidOrRecipient === 'string'
? {
id: psidOrRecipient,
}
: psidOrRecipient;
let messagingType = 'UPDATE';
if (options.messagingType) {
messagingType = options.messagingType;
}
else if (options.tag) {
messagingType = 'MESSAGE_TAG';
}
return this.sendRawBody(Object.assign({ messagingType,
recipient, message: Messenger_1.default.createMessage(message, options) }, (0, omit_1.default)(options, 'quickReplies')));
}
/**
* Sends messages to the specified user using the Send API with form-data format.
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param formdata - A FromData object
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @returns An object includes recipientId and messageId.
*
* @example
*/
sendMessageFormData(psidOrRecipient, formdata, options = {}) {
const recipient = typeof psidOrRecipient === 'string'
? {
id: psidOrRecipient,
}
: psidOrRecipient;
let messagingType = 'UPDATE';
if (options.messagingType) {
messagingType = options.messagingType;
}
else if (options.tag) {
messagingType = 'MESSAGE_TAG';
}
formdata.append('messaging_type', messagingType);
formdata.append('recipient', JSON.stringify((0, messaging_api_common_1.snakecaseKeysDeep)(recipient)));
return this.axios
.post(`/me/messages?access_token=${this.accessToken}`, formdata, {
headers: formdata.getHeaders(),
})
.then((res) => res.data, handleError);
}
/**
* Sends attachment messages to the specified user using the Send API.
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param attachment - The attachment of media or template to be sent.
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @returns An object includes recipientId and messageId.
*
* @see https://developers.facebook.com/docs/messenger-platform/send-messages#sending_attachments
*
* @example
*
* ```js
* await client.sendAttachment(USER_ID, {
* type: 'image',
* payload: {
* url: 'https://example.com/pic.png',
* },
* });
* ```
*/
sendAttachment(psidOrRecipient, attachment, options) {
return this.sendMessage(psidOrRecipient, Messenger_1.default.createAttachment(attachment, options), options);
}
/**
* Sends plain text messages to the specified user using the Send API.
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param text - The text to be sent.
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @returns An object includes recipientId and messageId.
*
* @see https://developers.facebook.com/docs/messenger-platform/send-messages#sending_text
*
* @example
*
* ```js
* await client.sendText(USER_ID, 'Hello!', { tag: 'CONFIRMED_EVENT_UPDATE' });
* ```
*/
sendText(psidOrRecipient, text, options) {
return this.sendMessage(psidOrRecipient, Messenger_1.default.createText(text, options), options);
}
/**
* Sends sounds to the specified user by uploading them or sharing a URL using the Send API.
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param audio - The audio to be sent.
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @param options.filename - Required when upload from a buffer.
* @returns An object includes recipientId and messageId.
*
* @see https://developers.facebook.com/docs/messenger-platform/send-messages#types
*
* @example
*
* ```js
* // Send audio using url string:
* await client.sendAudio(USER_ID, 'https://example.com/audio.mp3');
*
* // Use `AttachmentPayload` to send cached attachment:
* await client.sendAudio(USER_ID, { attachmentId: '55688' });
*
* // Use `ReadStream` created from the local file:
* const fs = require('fs');
* await client.sendAudio(USER_ID, fs.createReadStream('audio.mp3'));
*
* // Use `Buffer` to send attachment:
* await client.sendAudio(USER_ID, buffer, { filename: 'audio.mp3' });
* ```
*/
sendAudio(psidOrRecipient, audio, options) {
if (Buffer.isBuffer(audio) || audio instanceof fs_1.default.ReadStream) {
const message = Messenger_1.default.createAudioFormData(audio, options);
return this.sendMessageFormData(psidOrRecipient, message, options);
}
const message = Messenger_1.default.createAudio(audio, options);
return this.sendMessage(psidOrRecipient, message, options);
}
/**
* Sends images to the specified user by uploading them or sharing a URL using the Send API. Supported formats are jpg, png and gif.
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param image - The image to be sent.
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @param options.filename - Required when upload from a buffer.
* @returns An object includes recipientId and messageId.
*
* @see https://developers.facebook.com/docs/messenger-platform/send-messages#types
*
* @example
*
* ```js
* // Send image using url string:
* await client.sendImage(USER_ID, 'https://example.com/image.jpg');
*
* // Use `AttachmentPayload` to send cached attachment:
* await client.sendImage(USER_ID, { attachmentId: '55688' });
*
* // Use `ReadStream` created from the local file:
* const fs = require('fs');
* await client.sendImage(USER_ID, fs.createReadStream('image.jpg'));
*
* // Use `Buffer` to send attachment:
* await client.sendImage(USER_ID, buffer, { filename: 'image.jpg' });
* ```
*/
sendImage(psidOrRecipient, image, options) {
if (Buffer.isBuffer(image) || image instanceof fs_1.default.ReadStream) {
const message = Messenger_1.default.createImageFormData(image, options);
return this.sendMessageFormData(psidOrRecipient, message, options);
}
const message = Messenger_1.default.createImage(image, options);
return this.sendMessage(psidOrRecipient, message, options);
}
/**
* Sends videos to the specified user by uploading them or sharing a URL using the Send API.
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param video - The video to be sent.
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @param options.filename - Required when upload from a buffer.
* @returns An object includes recipientId and messageId.
*
* @see https://developers.facebook.com/docs/messenger-platform/send-messages#types
*
* @example
*
* ```js
* // Send video using url string:
* await client.sendVideo(USER_ID, 'https://example.com/video.mp4');
*
* // Use `AttachmentPayload` to send cached attachment:
* await client.sendVideo(USER_ID, { attachmentId: '55688' });
*
* // Use `ReadStream` created from the local file:
* const fs = require('fs');
* await client.sendVideo(USER_ID, fs.createReadStream('video.mp4'));
*
* // Use `Buffer` to send attachment:
* await client.sendVideo(USER_ID, buffer, { filename: 'video.mp4' });
* ```
*/
sendVideo(psidOrRecipient, video, options) {
if (Buffer.isBuffer(video) || video instanceof fs_1.default.ReadStream) {
const message = Messenger_1.default.createVideoFormData(video, options);
return this.sendMessageFormData(psidOrRecipient, message, options);
}
const message = Messenger_1.default.createVideo(video, options);
return this.sendMessage(psidOrRecipient, message, options);
}
/**
* Sends files to the specified user by uploading them or sharing a URL using the Send API.
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param file - The file to be sent.
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @param options.filename - Required when upload from a buffer.
* @returns An object includes recipientId and messageId.
*
* @see https://developers.facebook.com/docs/messenger-platform/send-messages#types
*
* @example
*
* ```js
* // Send file using url string:
* await client.sendFile(USER_ID, 'https://example.com/file.pdf');
*
* // Use `AttachmentPayload` to send cached attachment:
* await client.sendFile(USER_ID, { attachmentId: '55688' });
*
* // Use `ReadStream` created from the local file:
* const fs = require('fs');
* await client.sendFile(USER_ID, fs.createReadStream('file.pdf'));
*
* // Use `Buffer` to send attachment:
* await client.sendFile(USER_ID, buffer, { filename: 'file.pdf' });
* ```
*/
sendFile(psidOrRecipient, file, options) {
if (Buffer.isBuffer(file) || file instanceof fs_1.default.ReadStream) {
const message = Messenger_1.default.createFileFormData(file, options);
return this.sendMessageFormData(psidOrRecipient, message, options);
}
const message = Messenger_1.default.createFile(file, options);
return this.sendMessage(psidOrRecipient, message, options);
}
/**
* Sends structured template messages to the specified user using the Send API.
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param payload - The template object.
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @returns An object includes recipientId and messageId.
*
* @see https://developers.facebook.com/docs/messenger-platform/send-messages/templates
*
* @example
*
* ```js
* await client.sendTemplate(USER_ID, {
* templateType: 'button',
* text: 'title',
* buttons: [
* {
* type: 'postback',
* title: 'Start Chatting',
* payload: 'USER_DEFINED_PAYLOAD',
* },
* ],
* });
* ```
*/
sendTemplate(psidOrRecipient, payload, options) {
return this.sendMessage(psidOrRecipient, Messenger_1.default.createTemplate(payload, options), options);
}
/**
* Sends button template messages to the specified user using the Send API.
*
* <img src="https://user-images.githubusercontent.com/3382565/37410664-0b80b080-27dc-11e8-8854-4408d6f32fdf.png" alt="sendButtonTemplate" width="250" />
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param title - Text that appears above the buttons.
* @param buttons - Array of [button](https://developers.facebook.com/docs/messenger-platform/send-messages/template/button#button). Set of 1-3 buttons that appear as call-to-actions.
* @param options - Other optional parameters. For example, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types) or [tags](https://developers.facebook.com/docs/messenger-platform/message-tags).
* @returns An object includes recipientId and messageId.
*
* @see https://developers.facebook.com/docs/messenger-platform/send-messages/template/button
*
* @example
*
* ```js
* await client.sendButtonTemplate(USER_ID, 'What do you want to do next?', [
* {
* type: 'web_url',
* url: 'https://petersapparel.parseapp.com',
* title: 'Show Website',
* },
* {
* type: 'postback',
* title: 'Start Chatting',
* payload: 'USER_DEFINED_PAYLOAD',
* },
* ]);
* ```
*/
sendButtonTemplate(psidOrRecipient, text, buttons, options) {
return this.sendMessage(psidOrRecipient, Messenger_1.default.createButtonTemplate(text, buttons, options), options);
}
/**
* Sends generic template messages to the specified user using the Send API.
*
* <img src="https://user-images.githubusercontent.com/3382565/37410502-bf948426-27db-11e8-8c9d-7fd6158d0cc2.png" alt="sendGenericTemplate" width="750" />
*
* @param psidOrRecipient - A facebook page-scoped ID of the recipient or a recipient object
* @param elements - Array of [element](https://developers.facebook.com/docs/messenger-platform/send-messages/template/generic#element). Data for each bubble in message.
* @param options - Other optional parameters, such as `image_aspect_ratio`, [messaging types](https://developers.facebook.com/docs/messenger-platform/send-messages#messaging_types