Files
botpress--botpress/integrations/messenger/src/webhook/handlers/feed.ts
T
2026-07-13 13:34:48 +08:00

130 lines
3.5 KiB
TypeScript

import { getMetaClientCredentials } from '../../misc/auth'
import { FeedChanges, FeedChange, CommentChangeValue } from '../../misc/types'
import { getErrorFromUnknown } from '../../misc/utils'
import * as bp from '.botpress'
export const handler = async (changes: FeedChanges, props: bp.HandlerProps) => {
if (props.ctx.configurationType === 'sandbox') {
props.logger.error(
'Feed changes are not supported in sandbox mode, turn off webhook subscriptions in the Sandbox Meta App'
)
return
}
for (const change of changes) {
await _handleFeedChange(change, props)
}
}
const _handleFeedChange = async (change: FeedChange, props: bp.HandlerProps) => {
const { logger } = props
const { value } = change
try {
switch (value.item) {
case 'comment':
await _handleCommentEvent(value, props)
break
default:
logger.forBot().warn(`Unhandled event item: ${value.item}`)
}
} catch (error) {
const errorMsg = getErrorFromUnknown(error)
logger.forBot().error(`Error processing feed change: ${errorMsg.message}`)
}
}
const _handleCommentEvent = async (value: CommentChangeValue, props: bp.HandlerProps) => {
const { logger, ctx, client } = props
const { from, verb } = value
const { pageId } = await getMetaClientCredentials({ client, ctx })
if (!pageId) {
logger.forBot().error('Page ID is not set, cannot process comment event. Please configure or reauthorize')
return
}
if (from?.id === pageId) {
logger.forBot().debug('Comment is from our page, ignoring')
return
}
logger.forBot().debug(`Processing comment event: verb=${verb} `)
switch (verb) {
case 'add':
await _handleCommentCreated(value, props)
break
case 'remove': // For removed comments
break
case 'edited': // For edited comments
break
default:
}
}
const _handleCommentCreated = async (value: CommentChangeValue, props: bp.HandlerProps) => {
const { client, logger, ctx } = props
if (ctx.configurationType === 'sandbox') {
logger.forBot().error('Comment replies are not supported in sandbox mode')
return
}
if (!ctx.configuration.replyToComments) {
logger.forBot().info('Comment replies are disabled in the configuration')
return
}
const { comment_id: commentId, post_id: postId, message, from, parent_id: parentId } = value
if (!message) {
logger
.forBot()
.warn(
'Incoming comment has no message, will not reply. Make sure that your app has been granted the necessary permissions to access user data.'
)
return
}
if (postId !== parentId) {
logger.forBot().debug('Incoming comment is not a root comment, will not reply')
return
}
if (!from) {
logger.forBot().error("Incoming comment doesn't contain 'from' information, will not reply")
return
}
// Use the thread resolver to create conversation based on root thread ID
const userId = from.id
const { conversation } = await client.getOrCreateConversation({
channel: 'commentReplies',
tags: { id: commentId, postId, userId },
discriminateByTags: ['id'],
})
const { user } = await client.getOrCreateUser({
tags: { id: userId },
})
if (!user.name) {
await client.updateUser({
id: user.id,
name: from.name,
})
}
await client.getOrCreateMessage({
tags: {
id: commentId,
postId,
},
discriminateByTags: ['id'],
type: 'text',
payload: { text: message, commentId },
userId: user.id,
conversationId: conversation.id,
})
}