Files
botpress--botpress/integrations/intercom/src/channels.ts
T
2026-07-13 13:34:48 +08:00

186 lines
5.1 KiB
TypeScript

import { RuntimeError } from '@botpress/client'
import { ReplyToConversationMessageType } from 'intercom-client'
import { getAuthenticatedIntercomClient } from './auth'
import * as html from './html.utils'
import * as types from './types'
import * as bp from '.botpress'
type Card = bp.channels.channel.card.Card
type Location = bp.channels.channel.location.Location
export const channels: bp.IntegrationProps['channels'] = {
channel: {
messages: {
text: async ({ payload, conversation, ack, client, ctx }) => {
await sendMessage({
body: payload.text,
conversation,
client,
ctx,
ack,
})
},
image: async ({ payload, client, ctx, conversation, ack }) => {
await sendMessage({
body: '',
conversation,
client,
ctx,
ack,
attachmentUrls: [payload.imageUrl],
})
},
audio: async ({ client, ctx, conversation, ack, payload }) => {
await sendMessage({
body: '',
conversation,
client,
ctx,
ack,
attachmentUrls: [payload.audioUrl],
})
},
video: async ({ client, ctx, conversation, ack, payload }) => {
await sendMessage({
body: '',
conversation,
client,
ctx,
ack,
attachmentUrls: [payload.videoUrl],
})
},
file: async ({ client, ctx, conversation, ack, payload }) => {
await sendMessage({
body: '',
conversation,
client,
ctx,
ack,
attachmentUrls: [payload.fileUrl],
})
},
location: async ({ client, ctx, conversation, ack, payload }) => {
await sendMessage({
body: formatGoogleMapLink(payload),
conversation,
client,
ctx,
ack,
})
},
carousel: async ({ client, ctx, conversation, ack, payload }) => {
const carousel = payload.items.map((card) => createCard(card)).join('')
await sendMessage({
body: carousel,
conversation,
client,
ctx,
ack,
})
},
card: async ({ client, ctx, conversation, ack, payload }) => {
await sendMessage({
body: createCard(payload),
conversation,
client,
ctx,
ack,
})
},
dropdown: async ({ client, ctx, conversation, ack, payload }) => {
const choices = payload.options.map((choice) => html.li(choice.value))
const message = composeMessage(
html.p(payload.text),
html.p('Type one of the following options:'),
choices.length > 0 ? html.ol(choices.join('')) : ''
)
await sendMessage({
body: message,
conversation,
client,
ctx,
ack,
})
},
choice: async ({ client, ctx, conversation, ack, payload }) => {
const choices = payload.options.map((choice) => html.li(choice.value))
const message = composeMessage(
html.p(payload.text),
html.p('Type one of the following options:'),
choices.length > 0 ? html.ol(choices.join('')) : ''
)
await sendMessage({
body: message,
conversation,
client,
ctx,
ack,
})
},
bloc: () => {
throw new RuntimeError('Not implemented')
},
},
},
}
async function sendMessage(
props: Pick<types.MessageHandlerProps, 'conversation' | 'client' | 'ctx' | 'ack'> & {
body: string
attachmentUrls?: string[]
}
) {
const { body, attachmentUrls, client, ctx, conversation, ack } = props
const { state } = await client.getState({ type: 'integration', name: 'credentials', id: ctx.integrationId })
const { adminId } = state.payload
const intercomClient = await getAuthenticatedIntercomClient(client, ctx)
const {
conversation_parts: { conversation_parts: conversationParts },
} = await intercomClient.conversations.replyByIdAsAdmin({
id: conversation.tags.id ?? '',
adminId,
messageType: ReplyToConversationMessageType.COMMENT,
body,
attachmentUrls,
})
const lastMessageId = conversationParts.at(-1)?.id
await ack({ tags: { id: lastMessageId } })
}
function composeMessage(...parts: string[]) {
return parts.join('')
}
function createCard({ title, subtitle, imageUrl, actions }: Card) {
const image = imageUrl ? html.img(imageUrl) : ''
const text = html.b(title) + html.p(subtitle ? subtitle : '')
const links = actions.filter((item) => item.action === 'url').map((item) => html.li(html.a(item.value, item.label)))
const choices = actions
.filter((item) => item.action !== 'url')
.map((item) => html.li(item.value))
.join('')
return composeMessage(
image,
text,
links.length > 0 ? html.ul(links.join('')) : '',
html.p('Type one of the following options:'),
html.ol(choices)
)
}
function formatGoogleMapLink(payload: Location) {
return `https://www.google.com/maps/search/?api=1&query=${payload.latitude},${payload.longitude}`
}