UNPKG

messaging-api-messenger

Version:
1,299 lines 109 kB
"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}&params=[%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