import { posthogHelper } from '@botpress/common' import { z, IntegrationDefinition } from '@botpress/sdk' import * as sdk from '@botpress/sdk' import proactiveConversation from 'bp_modules/proactive-conversation' import proactiveUser from 'bp_modules/proactive-user' import typingIndicator from 'bp_modules/typing-indicator' import { actions } from './definitions/actions' import { messages } from './definitions/channels/channel/messages' export const INTEGRATION_NAME = 'messenger' export const INTEGRATION_VERSION = '5.1.12' const commonConfigSchema = z.object({ downloadMedia: z .boolean() .default(false) .title('Download Media') .describe( 'Automatically download media files using the Files API for content access. If disabled, Messenger media URLs will be used.' ), downloadedMediaExpiry: z .number() .default(24) .optional() .title('Downloaded Media Expiry') .describe( 'Expiry time in hours for downloaded media files. An expiry time of 0 means the files will never expire.' ), }) const replyToCommentsSchema = z.object({ replyToComments: z .boolean() .default(false) .title('Reply to Comments') .describe('Whether to reply to comments on Facebook posts (limited to 1 reply per top-level comment)'), }) export default new IntegrationDefinition({ name: INTEGRATION_NAME, version: INTEGRATION_VERSION, title: 'Messenger and Facebook', description: 'Give your bot access to one of the world’s largest messaging platforms and manage your Facebook page content in one place.', icon: 'icon.svg', readme: 'hub.md', configuration: { identifier: { linkTemplateScript: 'linkTemplate.vrl', required: true, }, schema: commonConfigSchema.merge(replyToCommentsSchema), }, configurations: { manual: { title: 'Manual Configuration', description: 'Configure by manually supplying the Meta app details', schema: z .object({ clientId: z.string().title('Client ID').min(1).describe('Meta app client id'), clientSecret: z .string() .title('Client Secret') .optional() .describe('Meta App secret used for webhook signature check. Leave empty to disable signature check.'), verifyToken: z .string() .title('Verify Token') .min(1) .describe( 'Token used for verification when subscribing to webhooks on the Meta app (enter a random string of your choice)' ), accessToken: z .string() .title('Access Token') .min(1) .describe('Page access token that with permissions to access the Facebook page'), pageId: z.string().min(1).describe('Id from the Facebook page').title('Page ID'), shouldGetUserProfile: z .boolean() .default(true) .optional() .describe('Whether to get the user profile infos from Messenger when creating a new user') .title('Get User Profile'), }) .merge(commonConfigSchema) .merge(replyToCommentsSchema), }, sandbox: { title: 'Sandbox Configuration', description: 'Sandbox configuration, for testing purposes only', schema: commonConfigSchema, identifier: { linkTemplateScript: 'sandboxLinkTemplate.vrl', }, }, }, identifier: { extractScript: 'extract.vrl', fallbackHandlerScript: 'fallbackHandler.vrl', }, channels: { channel: { title: 'Messenger conversation', description: 'Channel for a Messenger conversation', messages, message: { tags: { id: { title: 'Message ID', description: 'The Messenger ID of the message' }, commentId: { title: 'Comment ID', description: 'The Messenger ID of the comment for which the message is a private-reply to', }, recipientId: { title: 'Recipient ID', description: 'The Messenger ID of the recipient' }, senderId: { title: 'Sender ID', description: 'The Messenger ID of the sender' }, }, }, conversation: { tags: { id: { title: 'Conversation ID', description: 'The Messenger user ID of the user in the conversation' }, commentId: { title: 'Comment ID', description: 'The Messenger ID of the comment from which the private-reply conversation was created', }, lastCommentId: { title: 'Last Comment ID', description: 'The Messenger ID of the comment from which a private-reply message was last sent', }, }, }, }, commentReplies: { title: 'Comment Replies', description: 'Channel for replies to comments on Facebook posts', messages: { text: sdk.messages.defaults.text }, message: { tags: { id: { title: 'Comment ID', description: 'The unique ID of the comment' }, postId: { title: 'Post ID', description: 'The Facebook post ID where the comment was posted' }, }, }, conversation: { tags: { id: { title: 'Comment ID', description: 'The Facebook comment ID under which the reply was posted' }, postId: { title: 'Post ID', description: 'The Facebook post ID where the comment was posted' }, userId: { title: 'User ID', description: 'The Facebook user ID of the user who posted the comment' }, }, }, }, }, actions, events: {}, states: { oauth: { type: 'integration', schema: z.object({ // TODO: Rename to 'userToken' if we bump a major accessToken: z.string().optional().title('Access token').describe('The access token obtained by OAuth'), pageToken: z .string() .optional() .title('Page token') .describe('The token used to authenticate API calls related to the page'), pageId: z.string().optional().title('Page ID').describe('The page ID'), }), }, }, secrets: { ...posthogHelper.COMMON_SECRET_NAMES, CLIENT_ID: { description: 'The client ID of your Meta app', }, CLIENT_SECRET: { description: 'The client secret of your Meta app', }, OAUTH_CONFIG_ID: { description: 'The OAuth configuration ID for the OAuth Meta app', }, VERIFY_TOKEN: { description: 'The verify token for the Meta Webhooks subscription', }, ACCESS_TOKEN: { description: 'Access token for internal Meta App', }, SHOULD_GET_USER_PROFILE: { description: "Whether to get the user profile infos from Messenger when creating a new user ('true' or 'false')", }, SANDBOX_CLIENT_ID: { description: 'The client ID of the Sandbox Meta app', }, SANDBOX_CLIENT_SECRET: { description: 'The client secret of the Sandbox Meta app', }, SANDBOX_VERIFY_TOKEN: { description: 'The verify token for the Sandbox Meta App Webhooks subscription', }, SANDBOX_ACCESS_TOKEN: { description: 'Access token for the Sandbox Meta App', }, SANDBOX_PAGE_ID: { description: 'Page ID for the Sandbox Facebook page', }, SANDBOX_SHOULD_GET_USER_PROFILE: { description: "Whether to get the user profile infos from Messenger when creating a new user ('true' or 'false')", }, }, user: { tags: { id: { title: 'User ID', description: 'The Messenger ID of the user' } }, }, entities: { user: { schema: z .object({ id: z.string().title('User ID').describe('The Messenger ID of the user'), }) .title('User') .describe('The user object fields'), title: 'User', description: 'A Messenger user', }, conversation: { schema: z .object({ userId: z.string().title('User ID').describe('The Messenger user ID of the user in the conversation'), commentId: z .string() .optional() .title('Comment ID') .describe('The Messenger ID of the comment for which the private-reply conversation should be created'), }) .title('Conversation') .describe('The conversation object fields'), title: 'Conversation', description: 'A conversation with a Messenger user', }, }, attributes: { category: 'Communication & Channels', guideSlug: 'messenger', repo: 'botpress', }, }) .extend(typingIndicator, () => ({ entities: {} })) .extend(proactiveUser, ({ entities }) => ({ entities: { user: entities.user, }, })) .extend(proactiveConversation, ({ entities }) => ({ entities: { conversation: entities.conversation, }, }))