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 .github/workflows/deploy-integrations-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
uses: ./.github/actions/deploy-integrations
with:
environment: 'production'
extra_filter: "-F '!docusign' -F '!whatsapp'"
extra_filter: "-F '!docusign'"
force: ${{ github.event.inputs.force == 'true' }}
sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }}
token_cloud_ops_account: ${{ secrets.PRODUCTION_TOKEN_CLOUD_OPS_ACCOUNT }}
Expand Down
6 changes: 1 addition & 5 deletions integrations/anthropic/integration.definition.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* bplint-disable */
import { z, IntegrationDefinition } from '@botpress/sdk'
import { ModelId } from 'src/schemas'
import llm from './bp_modules/llm'
Expand All @@ -7,7 +6,7 @@ export default new IntegrationDefinition({
name: 'anthropic',
title: 'Anthropic',
description: 'Access a curated list of Claude models to set as your chosen LLM.',
version: '12.0.0',
version: '12.0.1',
readme: 'hub.md',
icon: 'icon.svg',
entities: {
Expand All @@ -22,9 +21,6 @@ export default new IntegrationDefinition({
description: 'Anthropic API key',
},
},
__advanced: {
useLegacyZuiTransformer: true,
},
}).extend(llm, ({ entities }) => ({
entities: { modelRef: entities.modelRef },
}))
5 changes: 4 additions & 1 deletion integrations/instagram/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const commonConfigSchema = z.object({

export default new IntegrationDefinition({
name: INTEGRATION_NAME,
version: '4.1.0',
version: '4.1.1',
title: 'Instagram',
description: 'Automate interactions, manage comments, and send/receive messages all in real-time.',
icon: 'icon.svg',
Expand Down Expand Up @@ -187,6 +187,9 @@ export default new IntegrationDefinition({
SANDBOX_INSTAGRAM_ID: {
description: 'Instagram ID for the Sandbox Instagram profile',
},
POSTHOG_KEY: {
description: 'The PostHog key for the Instagram integration',
},
},
user: {
tags: {
Expand Down
3 changes: 2 additions & 1 deletion integrations/instagram/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"@botpress/client": "workspace:*",
"@botpress/sdk": "workspace:*",
"@botpress/sdk-addons": "workspace:*",
"axios": "^1.6.2"
"axios": "^1.6.2",
"posthog-node": "^5.10.4"
},
"devDependencies": {
"@botpress/cli": "workspace:*",
Expand Down
49 changes: 49 additions & 0 deletions integrations/instagram/src/misc/posthog-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { EventMessage, PostHog } from 'posthog-node'
import * as bp from '.botpress'

type BotpressEventMessage = Omit<EventMessage, 'event'> & {
event: BotpressEvent
}

type PostHogErrorOptions = {
from: string
integrationName: string
errorType?: BotpressEvent
}

export const botpressEvents = {
UNHANDLED_ERROR: 'unhandled_error',
UNHANDLED_MESSAGE: 'unhandled_message',
INVALID_MESSAGE_FORMAT: 'invalid_message_format',
} as const
type BotpressEvent = (typeof botpressEvents)[keyof typeof botpressEvents]

const sendPosthogEvent = async (props: BotpressEventMessage): Promise<void> => {
const client = new PostHog(bp.secrets.POSTHOG_KEY, {
host: 'https://us.i.posthog.com',
})
try {
await client.captureImmediate(props)
await client.shutdown()
console.info('PostHog event sent')
} catch (thrown: any) {
const errMsg = thrown instanceof Error ? thrown.message : String(thrown)
console.error(`The server for posthog could not be reached - Error: ${errMsg}`)
}
}

export const sendPosthogError = async (
distinctId: string,
errorMessage: string,
{ from, integrationName, errorType = botpressEvents.UNHANDLED_ERROR }: PostHogErrorOptions
): Promise<void> => {
await sendPosthogEvent({
distinctId,
event: errorType,
properties: {
from,
integrationName,
message: errorMessage,
},
})
}
29 changes: 21 additions & 8 deletions integrations/instagram/src/webhook/handler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { isSandboxCommand } from '@botpress/common'
import { Request } from '@botpress/sdk'
import * as crypto from 'crypto'
import { INTEGRATION_NAME } from 'integration.definition'
import { getClientSecret } from 'src/misc/client'
import { sendPosthogError } from 'src/misc/posthog-client'
import {
instagramPayloadSchema,
InstagramLegacyCommentEntry,
Expand Down Expand Up @@ -48,13 +50,15 @@ const _handler: bp.IntegrationProps['handler'] = async (props: bp.HandlerProps)
}
const { data, success } = safeJsonParse(req.body)
if (!success) {
return { status: 400, body: 'Invalid payload body' }
const errorMsg = 'Unable to parse request payload as JSON'
return { status: 400, body: errorMsg }
}

// Parse payload once with entry-level union schema
const payloadResult = instagramPayloadSchema.safeParse(data)
if (!payloadResult.success) {
props.logger.warn('Received invalid Instagram payload:', payloadResult.error.message)
const errorMsg = `Received invalid Instagram payload: ${payloadResult.error.message}`
props.logger.warn(errorMsg)
return { status: 400, body: 'Invalid payload' }
}

Expand Down Expand Up @@ -113,14 +117,23 @@ const _handlerWrapper: typeof _handler = async (props: bp.HandlerProps) => {
try {
const response = await _handler(props)
if (response && response.status !== 200) {
props.logger.error(`Instagram handler failed with status ${response.status}: ${response.body}`)
const errorMessage = `Instagram handler failed with status ${response.status}: ${response.body}`
props.logger.error(errorMessage)
await sendPosthogError(props.ctx.integrationId, errorMessage, {
from: `${INTEGRATION_NAME}:handler`,
integrationName: INTEGRATION_NAME,
})
}
return response
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error)
const logMessage = `Instagram handler failed with error: ${errorMessage ?? 'Unknown error thrown'}`
props.logger.error(logMessage)
return { status: 500, body: logMessage }
} catch (thrown: unknown) {
const errorMsg = thrown instanceof Error ? thrown.message : String(thrown)
const errorMessage = `Instagram handler failed with error: ${errorMsg}`
await sendPosthogError(props.ctx.integrationId, errorMessage, {
from: `${INTEGRATION_NAME}:handler`,
integrationName: INTEGRATION_NAME,
})
props.logger.error(errorMessage)
return { status: 500, body: errorMessage }
}
}

Expand Down
4 changes: 1 addition & 3 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.0',
version: '2.0.2',
title: 'Line',
description: 'Interact with customers using a rich set of features.',
icon: 'icon.svg',
Expand Down Expand Up @@ -49,7 +49,6 @@ export default new IntegrationDefinition({
description: 'Line user ID of the bot',
},
},
creation: { enabled: true, requiredTags: ['usrId', 'destId'] },
},
},
},
Expand Down Expand Up @@ -84,7 +83,6 @@ export default new IntegrationDefinition({
description: 'Line user ID',
},
},
creation: { enabled: true, requiredTags: ['usrId'] },
},
entities: {
user: {
Expand Down
10 changes: 5 additions & 5 deletions integrations/line/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { RuntimeError } from '@botpress/client'
import { transformMarkdown } from '@botpress/common'
import { sentry as sentryHelpers } from '@botpress/sdk-addons'
import { messagingApi as lineMessagingApi } from '@line/bot-sdk'
import crypto from 'crypto'
import { parseMarkdown } from './markdown-parser'
import getOrCreateConversation from './proactive-conversation'
import getOrCreateUser from './proactive-user'
import * as bp from '.botpress'
Expand Down Expand Up @@ -61,11 +61,11 @@ const replyOrSendLineMessage = async (props: SendOrReplyLineProps, message: line
}
}

const tryParseMarkdown = (text: string) => {
const tryTransformMarkdown = (text: string) => {
try {
return parseMarkdown(text)
return transformMarkdown(text)
} catch {
console.error('Failed to parse the markdown. The message will be sent as text without parsing markdown.')
console.error('Failed to transform the markdown. The message will be sent as text without transfoming markdown.')
return text
}
}
Expand Down Expand Up @@ -108,7 +108,7 @@ const integration = new bp.Integration({
{ ctx, conversation, client, ack },
{
type: 'text',
text: tryParseMarkdown(payload.text),
text: tryTransformMarkdown(payload.text),
}
)
},
Expand Down
155 changes: 0 additions & 155 deletions integrations/line/src/markdown-parser.ts

This file was deleted.

Loading
Loading