Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion integrations/asana/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { configuration, states, user, channels, actions } from './src/definition

export default new IntegrationDefinition({
name: INTEGRATION_NAME,
version: '0.3.8',
version: '0.3.9',
title: 'Asana',
readme: 'hub.md',
description: 'Connect your bot to your Asana inbox, create and update tasks, add comments, and locate users.',
Expand Down
1 change: 1 addition & 0 deletions integrations/asana/src/definitions/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const channels = {
messages: {
...messages.defaults,
markdown: messages.markdown,
bloc: messages.markdownBloc,
},
},
} satisfies IntegrationDefinitionProps['channels']
4 changes: 3 additions & 1 deletion integrations/chat/definitions/channels/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as sdk from '@botpress/sdk'
import { z } from '@botpress/sdk'

const metadata = z.record(z.any()).optional()

const text = { schema: sdk.messages.defaults.text.schema.extend({ metadata }) }
const image = { schema: sdk.messages.defaults.image.schema.extend({ metadata }) }
const audio = { schema: sdk.messages.defaults.audio.schema.extend({ metadata }) }
Expand All @@ -12,7 +13,8 @@ const carousel = { schema: sdk.messages.defaults.carousel.schema.extend({ metada
const card = { schema: sdk.messages.defaults.card.schema.extend({ metadata }) }
const dropdown = { schema: sdk.messages.defaults.dropdown.schema.extend({ metadata }) }
const choice = { schema: sdk.messages.defaults.choice.schema.extend({ metadata }) }
const bloc = { schema: sdk.messages.defaults.bloc.schema.extend({ metadata }) }

const bloc = { schema: sdk.messages.markdownBloc.schema.extend({ metadata }) }
const markdown = { schema: sdk.messages.markdown.schema.extend({ metadata }) }

export const messages = {
Expand Down
2 changes: 1 addition & 1 deletion integrations/freshchat/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { events, configuration, channels, states, user } from './src/definitions
export default new sdk.IntegrationDefinition({
name: INTEGRATION_NAME,
title: 'Freshchat',
version: '1.5.2',
version: '1.5.3',
icon: 'icon.svg',
description: 'This integration allows your bot to use Freshchat as a HITL Provider',
readme: 'hub.md',
Expand Down
3 changes: 3 additions & 0 deletions integrations/gmail/definitions/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export const channels = {
title: sdk.z.string().optional().title('Title').describe('Title for the file'),
}),
},
bloc: {
schema: sdk.messages.markdownBloc.schema,
},
},
message: {
tags: {
Expand Down
2 changes: 1 addition & 1 deletion integrations/gmail/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

export default new sdk.IntegrationDefinition({
name: 'gmail',
version: '0.6.4',
version: '0.6.5',
title: 'Gmail',
description: "Send, receive, and manage emails directly within your bot's workflow.",
icon: 'icon.svg',
Expand Down
5 changes: 3 additions & 2 deletions integrations/googlecalendar/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import * as sdk from '@botpress/sdk'
import { actions, entities, configuration, configurations, identifier, events, secrets, states } from './definitions'

export const INTEGRATION_NAME = 'googlecalendar'
export const INTEGRATION_VERSION = '2.0.3'

export default new sdk.IntegrationDefinition({
name: 'googlecalendar',
version: '2.0.2',
name: INTEGRATION_NAME,
version: INTEGRATION_VERSION,
description: 'Sync with your calendar to manage events, appointments, and schedules directly within the chatbot.',
title: 'Google Calendar',
readme: 'hub.md',
Expand Down
8 changes: 6 additions & 2 deletions integrations/googlecalendar/src/google-api/error-handling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { isApiError } from '@botpress/client'
import { createAsyncFnWrapperWithErrorRedaction, createErrorHandlingDecorator, posthogHelper } from '@botpress/common'
import * as sdk from '@botpress/sdk'
import { Common as GoogleApisCommon } from 'googleapis'
import { INTEGRATION_NAME } from 'integration.definition'
import { INTEGRATION_NAME, INTEGRATION_VERSION } from 'integration.definition'
import * as bp from '.botpress'

export const wrapAsyncFnWithTryCatch = createAsyncFnWrapperWithErrorRedaction((error: Error, customMessage: string) => {
Expand Down Expand Up @@ -31,7 +31,11 @@ export const wrapAsyncFnWithTryCatch = createAsyncFnWrapperWithErrorRedaction((e
errorReason: errorReason?.substring(0, 100),
},
},
{ integrationName: INTEGRATION_NAME, key: (bp.secrets as any).POSTHOG_KEY as string }
{
integrationName: INTEGRATION_NAME,
integrationVersion: INTEGRATION_VERSION,
key: (bp.secrets as any).POSTHOG_KEY as string,
}
)
.catch(() => {
// Silently fail if PostHog is unavailable
Expand Down
3 changes: 2 additions & 1 deletion integrations/googlecalendar/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { posthogHelper } from '@botpress/common'
import { sentry as sentryHelpers } from '@botpress/sdk-addons'
import { INTEGRATION_NAME } from 'integration.definition'
import { INTEGRATION_NAME, INTEGRATION_VERSION } from 'integration.definition'
import { actions } from './actions'
import { register, unregister } from './setup'
import { handler } from './webhook-events'
import * as bp from '.botpress'

@posthogHelper.wrapIntegration({
integrationName: INTEGRATION_NAME,
integrationVersion: INTEGRATION_VERSION,
key: (bp.secrets as any).POSTHOG_KEY as string,
})
class GoogleCalendarIntegration extends bp.Integration {
Expand Down
4 changes: 2 additions & 2 deletions integrations/instagram/definitions/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ const channelMessages = {
card: { schema: sdk.messages.defaults.card.schema.merge(commentIdSchema) },
dropdown: { schema: sdk.messages.defaults.dropdown.schema.merge(commentIdSchema) },
choice: { schema: sdk.messages.defaults.choice.schema.merge(commentIdSchema) },
bloc: { schema: sdk.messages.defaults.bloc.schema.merge(commentIdSchema) },
} as const satisfies typeof sdk.messages.defaults
bloc: { schema: sdk.messages.markdownBloc.schema.merge(commentIdSchema) },
} as const satisfies Record<string, { schema: z.ZodTypeAny }>

type ValueOf<T> = T[keyof T]
type ChannelMessageDefinition = ValueOf<typeof channelMessages>
Expand Down
3 changes: 2 additions & 1 deletion integrations/instagram/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import proactiveUser from 'bp_modules/proactive-user'
import { dmChannelMessages } from './definitions/channel'

export const INTEGRATION_NAME = 'instagram'
export const INTEGRATION_VERSION = '4.1.4'

const commonConfigSchema = z.object({
replyToComments: z
Expand All @@ -16,7 +17,7 @@ const commonConfigSchema = z.object({

export default new IntegrationDefinition({
name: INTEGRATION_NAME,
version: '4.1.2',
version: INTEGRATION_VERSION,
title: 'Instagram',
description: 'Automate interactions, manage comments, and send/receive messages all in real-time.',
icon: 'icon.svg',
Expand Down
3 changes: 2 additions & 1 deletion integrations/instagram/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { posthogHelper } from '@botpress/common'
import { INTEGRATION_NAME } from 'integration.definition'
import { INTEGRATION_NAME, INTEGRATION_VERSION } from 'integration.definition'
import actions from './actions'
import channels from './channels'
import { register, unregister } from './setup'
Expand All @@ -8,6 +8,7 @@ import * as bp from '.botpress'

@posthogHelper.wrapIntegration({
integrationName: INTEGRATION_NAME,
integrationVersion: INTEGRATION_VERSION,
key: bp.secrets.POSTHOG_KEY,
})
class InstagramIntegration extends bp.Integration {
Expand Down
4 changes: 2 additions & 2 deletions integrations/intercom/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import proactiveUser from 'bp_modules/proactive-user'

export default new IntegrationDefinition({
name: 'intercom',
version: '2.0.0',
version: '2.0.1',
title: 'Intercom',
description: 'Engage with customers in realtime with personalized messaging.',
icon: 'icon.svg',
Expand Down Expand Up @@ -53,7 +53,7 @@ export default new IntegrationDefinition({
channel: {
title: 'Intercom conversation',
description: 'Channel for a Intercom conversation',
messages: messages.defaults,
messages: { ...messages.defaults, bloc: messages.markdownBloc },
message: {
tags: {
id: {
Expand Down
4 changes: 2 additions & 2 deletions integrations/line/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import typingIndicator from 'bp_modules/typing-indicator'

export default new IntegrationDefinition({
name: 'line',
version: '2.0.2',
version: '2.0.3',
title: 'Line',
description: 'Interact with customers using a rich set of features.',
icon: 'icon.svg',
Expand All @@ -29,7 +29,7 @@ export default new IntegrationDefinition({
channel: {
title: 'Line conversation',
description: 'Channel for a Line conversation',
messages: { ...messages.defaults },
messages: { ...messages.defaults, bloc: messages.markdownBloc },
message: {
tags: {
msgId: {
Expand Down
2 changes: 1 addition & 1 deletion integrations/linear/definitions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const channels = {
issue: {
title: 'Issue',
description: 'A linear issue',
messages: { ...messages.defaults, markdown: messages.markdown },
messages: { ...messages.defaults, markdown: messages.markdown, bloc: messages.markdownBloc },
message: {
tags: {
id: {
Expand Down
2 changes: 1 addition & 1 deletion integrations/linear/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { actions, channels, events, configuration, configurations, user, states,

export default new IntegrationDefinition({
name: 'linear',
version: '1.1.4',
version: '1.1.5',
title: 'Linear',
description:
'Manage your projects autonomously. Have your bot participate in discussions, manage issues and teams, and track progress.',
Expand Down
34 changes: 22 additions & 12 deletions integrations/linear/src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { fireIssueCreated } from './events/issueCreated'
import { fireIssueDeleted } from './events/issueDeleted'
import { fireIssueUpdated } from './events/issueUpdated'
import { LinearEvent, handleOauth } from './misc/linear'
import { Result } from './misc/types'
import { getLinearClient, getUserAndConversation } from './misc/utils'
import * as bp from '.botpress'

Expand All @@ -23,13 +24,11 @@ export const handler: bp.IntegrationProps['handler'] = async ({ req, ctx, client
const linearEvent: LinearEvent = JSON.parse(req.body)
linearEvent.type = linearEvent.type.toLowerCase() as LinearEvent['type']

if (!_isWebhookProperlyAuthenticated({ req, linearEvent, ctx })) {
logger
.forBot()
.error(
'Received a webhook event that is not properly authenticated. Please ensure the webhook signing secret is correct.'
)
throw new Error('Webhook event is not properly authenticated: the signing secret is invalid.')
const result = _safeCheckWebhookSignature({ req, linearEvent, ctx })
if (!result.success) {
const message = `Error while verifying webhook signature: ${result.message}`
logger.forBot().error(message)
throw new Error(message)
}

const linearBotId = await _getLinearBotId({ client, ctx })
Expand Down Expand Up @@ -91,26 +90,37 @@ export const handler: bp.IntegrationProps['handler'] = async ({ req, ctx, client
}
}

const _isWebhookProperlyAuthenticated = ({
const _safeCheckWebhookSignature = ({
req,
linearEvent,
ctx,
}: {
req: Request
linearEvent: LinearEvent
ctx: bp.Context
}) => {
}): Result<undefined> => {
const webhookSignatureHeader = req.headers[LINEAR_WEBHOOK_SIGNATURE_HEADER]

if (!webhookSignatureHeader || !req.body) {
return
return { success: false, message: 'missing signature header or request body' }
}

const webhookHandler = new LinearWebhooks(_getWebhookSigningSecret({ ctx }))
const bodyBuffer = Buffer.from(req.body)
const timeStampHeader = linearEvent[LINEAR_WEBHOOK_TS_FIELD]

return webhookHandler.verify(bodyBuffer, webhookSignatureHeader, timeStampHeader)
try {
const result = webhookHandler.verify(bodyBuffer, webhookSignatureHeader, timeStampHeader)
if (result) {
return { success: true, result: undefined }
}
return { success: false, message: 'webhook signature verification failed' }
} catch (thrown) {
const errorMessage = thrown instanceof Error ? thrown.message : String(thrown)
return {
success: false,
message: `Webhook signature verification failed: ${errorMessage}`,
}
}
}

const _getWebhookSigningSecret = ({ ctx }: { ctx: bp.Context }) =>
Expand Down
10 changes: 10 additions & 0 deletions integrations/linear/src/misc/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,13 @@ export type MessageDefinition = sdk.MessageDefinition
export type ActionProps = bp.AnyActionProps
export type MessageHandlerProps = bp.AnyMessageProps
export type AckFunction = bp.AnyAckFunction

export type Result<T> =
| {
success: true
result: T
}
| {
success: false
message: string
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export const messages = {
card: { schema: sdk.messages.defaults.card.schema.merge(commentIdSchema) },
dropdown: { schema: sdk.messages.defaults.dropdown.schema.merge(commentIdSchema) },
choice: { schema: sdk.messages.defaults.choice.schema.merge(commentIdSchema) },
bloc: { schema: sdk.messages.defaults.bloc.schema.merge(commentIdSchema) },
} as const satisfies typeof sdk.messages.defaults
bloc: { schema: sdk.messages.markdownBloc.schema.merge(commentIdSchema) },
} as const satisfies Record<string, { schema: z.ZodTypeAny }>

type ValueOf<T> = T[keyof T]
type ChannelMessageDefinition = ValueOf<typeof messages>
Expand Down
3 changes: 2 additions & 1 deletion integrations/messenger/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import typingIndicator from 'bp_modules/typing-indicator'
import { messages } from './definitions/channels/channel/messages'

export const INTEGRATION_NAME = 'messenger'
export const INTEGRATION_VERSION = '5.0.4'

const commonConfigSchema = z.object({
downloadMedia: z
Expand Down Expand Up @@ -36,7 +37,7 @@ const replyToCommentsSchema = z.object({

export default new IntegrationDefinition({
name: INTEGRATION_NAME,
version: '5.0.2',
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.',
Expand Down
13 changes: 10 additions & 3 deletions integrations/messenger/src/channels/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,16 @@ async function _sendMessage(
.debug(
`Sending ${type} message ${commentId ? 'as private reply ' : ''}from bot to Messenger: ${_formatPayloadToStr(payload)}`
)
const messengerClient = await createAuthenticatedMessengerClient(client, ctx)
const { messageId } = await send(messengerClient, recipient)
await ack({ tags: { id: messageId, commentId } })

try {
const messengerClient = await createAuthenticatedMessengerClient(client, ctx)
const { messageId } = await send(messengerClient, recipient)
await ack({ tags: { id: messageId, commentId } })
} catch (thrown) {
const error = thrown instanceof Error ? thrown : new Error(String(thrown))
const errorMessage = `Failed to send ${type} message to Messenger: ${error.message}`
logger.forBot().error(errorMessage)
}

if (commentId && conversation.tags.lastCommentId !== commentId) {
await client.updateConversation({
Expand Down
3 changes: 2 additions & 1 deletion integrations/messenger/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { posthogHelper } from '@botpress/common'
import { INTEGRATION_NAME } from 'integration.definition'
import { INTEGRATION_NAME, INTEGRATION_VERSION } from 'integration.definition'
import actions from './actions'
import channels from './channels'
import { register, unregister } from './setup'
Expand All @@ -8,6 +8,7 @@ import * as bp from '.botpress'

@posthogHelper.wrapIntegration({
integrationName: INTEGRATION_NAME,
integrationVersion: INTEGRATION_VERSION,
key: bp.secrets.POSTHOG_KEY,
})
class MessengerIntegration extends bp.Integration {
Expand Down
9 changes: 5 additions & 4 deletions integrations/messenger/src/webhook/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ const _handler: bp.IntegrationProps['handler'] = async (props) => {
const _handlerWrapper: typeof _handler = async (props: bp.HandlerProps) => {
try {
const response = await _handler(props)

if (response?.status && response.status >= 400) {
const errorMessage = `Messenger handler failed with status ${response.status}: ${response.body}`
props.logger.error(errorMessage)
throw new Error(`${response.status}: ${response.body}`)
}

return response
} catch (thrown: unknown) {
const errorMsg = thrown instanceof Error ? thrown.message : String(thrown)
const errorMessage = `Messenger handler failed with error: ${errorMsg}`
const error = thrown instanceof Error ? thrown.message : String(thrown)
const errorMessage = `Messenger handler failed with error: ${error}`
props.logger.error(errorMessage)
return { status: 500, body: errorMessage }
}
Expand Down
1 change: 1 addition & 0 deletions integrations/slack/definitions/channels/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const messages = {
text: {
schema: textSchema,
},
bloc: sdk.messages.markdownBloc,
} as const satisfies sdk.ChannelDefinition['messages']

const conversationTags = {
Expand Down
2 changes: 1 addition & 1 deletion integrations/slack/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default new IntegrationDefinition({
name: 'slack',
title: 'Slack',
description: 'Automate interactions with your team.',
version: '3.1.1',
version: '3.1.2',
icon: 'icon.svg',
readme: 'hub.md',
configuration,
Expand Down
Loading
Loading