Getting Started
In this section, we'll create a simple integration that can send text messages to Telegram and a bot to try it out. This tutorial make use of both the Botpress CLI and the Botpress SDK.
Setup
Installing the Botpress CLI globally.
npm install -g @botpress/cli
Initialize the project
Create a new integration project using the init command. This will create a new folder with the name you specified and generate a basic project structure.
bp init --name <UNIQUE_INTEGRATION_NAME> --type integration
cd <UNIQUE_INTEGRATION_NAME>
pnpm install
Define the integration and generate typings
Inside the file called integration.definition.ts
add the following code:
import { IntegrationDefinition, messages } from '@botpress/sdk'
import { z } from 'zod'
export default new IntegrationDefinition({
name: '<UNIQUE_INTEGRATION_NAME>',
version: '0.0.1',
configuration: {
schema: z.object({
botToken: z.string(),
}),
},
channels: {
group: {
messages: {
text: messages.defaults.text,
},
message: {
tags: {
id: {},
},
},
conversation: {
tags: {
id: {},
},
},
},
},
user: {
tags: {
id: {},
},
},
})
There is a lot going on there, so let's break it down.
Name and version
The name and version are used to identify the integration. The name is used to generate the integration ID, which is a unique identifier for the integration. The version is used to identify the version of the integration. For now, only one version of an integration can be deployed at a time and 0.0.1
is enforced.
Integration Names
The integration names are unique. If you try to create an integration with the same name as an existing one, the CLI will
throw an error.
Configuration
The configuration is used to define the configuration schema of the integration. The schema is used to validate the configuration of the integration. The configuration is used to store sensitive information such as API keys and tokens. This configuration will be provided by the user when added the integration to his bot.
Channels
The channels are used to define which channels the integration supports. In this case, we defined a channel named group
, this will be used to send messages to a specific group channel in telegram. The messages
property is used to define the message types that the integration supports. For now, we will only implement the text
message. The defaults
object that comes from the SDK
is used to define the default messages that the integration supports. We highly recommend implementing all message types provided by the SDK.
Tags
The tags are used to define the tags that the integration supports. In this case, we added a tag named id
to the users
, conversations
and messages
. Those tags will be used to identify the users, conversations and messages in the telegram
system.
Generate typings
The integration definition is used to generate typings for the integration. This will allow us to use the integration in our code without having to worry about the types.
bp build
Implement the integration
Inside the folder src
, there is a file called index.ts
add the following code to it:
import { Telegraf } from 'telegraf'
import { Integration } from '.botpress'
export default new Integration({
register: async ({ webhookUrl, ctx }) => {
const telegraf = new Telegraf(ctx.configuration.botToken)
await telegraf.telegram.setWebhook(webhookUrl)
},
unregister: async ({ ctx }) => {
const telegraf = new Telegraf(ctx.configuration.botToken)
await telegraf.telegram.deleteWebhook({ drop_pending_updates: true })
},
handler: async ({ req, client }) => {
const data = JSON.parse(req.body)
const conversationId = data?.message?.chat?.id
const userId = data?.message?.from?.id
const messageId = data?.message?.message_id
if (!conversationId || !userId || !messageId) {
throw new Error("Handler didn't receive a valid message")
}
const { conversation } = await client.getOrCreateConversation({
channel: 'group',
tags: { 'telegram:id': `${conversationId}` },
})
const { user } = await client.getOrCreateUser({
tags: { 'telegram:id': `${userId}` },
})
await client.createMessage({
tags: { 'telegram:id': `${messageId}` },
type: 'text',
userId: user.id,
conversationId: conversation.id,
payload: { text: data.message.text },
})
},
channels: {
group: {
messages: {
text: async ({ payload, ctx, conversation, ack }) => {
const client = new Telegraf(ctx.configuration.botToken)
const message = await client.telegram.sendMessage(conversation.tags['telegram:id']!, payload.text)
await ack({ tags: { 'telegram:id': `${message.message_id}` } })
},
},
},
},
})
Once again, there is a lot going on there, so let's break it down.
Register and unregister
The register and unregister functions are used to to manage the lifecycle of an integration. The register function is called when the integration is added to a bot and the unregister function is called when the integration is removed from a bot. The register function is used to setup the integration, in this case, we are setting up the webhook for telegram. The unregister function is used to clean up the integration, in this case, we are removing the webhook for telegram. Those functions should also be used to validate the configuration of the integration.
Handler
The handler function is used to handle the incoming requests from the integration. Which means that this function will be called every time the telegram integration sends a request to the webhook url set in the register function.
In this case, we are parsing the incoming request from telegram and extracting the conversation id, user id and message id. Then, we are using those ids to create or retrieve the conversation, user and message from the botpress client. Finally, we are creating a message in the conversation. This message will be sent to the bot as an incoming message from telegram.
Channels
The channels object is used to implement the channels that the integration defined previously. In this case, we defined a channel named group
, this will be used to send messages to a specific group channel in telegram. The text
message type that we defined is implemented in the messages
object. This function will be called every time the bot sends a text
message to the group
channel.
Develop the Bot
Create a new project for the bot
bp init --name tuto-bot --type bot
cd tuto-bot
pnpm install
Add the integration to your bot
Now that we have a bot, we need to add the integration to it. To do so, we need to run the following command:
bp add <integration-id> # replace <integration-id> with the integration ID that was logged when you started the integration
This command will add the integration to the bot. Once the integration is added, we need to configure it. Add the following code to the index.ts
file in the src
folder:
import { <UNIQUE_INTEGRATION_NAME> } from '.botpress'
const bot = new Bot({
integrations: [
new UNIQUE_INTEGRATION_NAME({
enabled: true,
config: {
botToken: '<TELEGRAM_BOT_TOKEN>',
},
})
],
})
Now that the integration is configured, we can add a little bit of code to the index.ts
file to send a message to the group
channel every time the bot receives a message from the user.
bot.message('', async ({ message, client, ctx }) => {
await client.createMessage({
conversationId: message.conversationId,
userId: ctx.botId,
tags: {},
type: 'text',
payload: {
text: `Hello. You said: "${message.payload.text}"`,
},
})
})
We have a parrot bot! Now, let's test it.
Deploy the Integration
Now that we're happy with our integration, we can deploy it to the cloud. To do so, all we need to do is run the following command:
bp deploy
This command will deploy the integration to the cloud. Once the deployment is done, the integration will be available in the Integrations
section of your workspace settings of the Botpress Cloud. You will also see this integration available in the Integrations
tab of your bot.
Congratulations! You've just created your first integration and deployed it to the cloud. Now, you can use this integration in any bot that you create in this workspace.
For in depth documentation about the SDK, CLI and concepts continue to the next section