Telegram Integration with Twilio Flex via Corezoid

March 15, 2022
Written by
Reviewed by

Corezoid Telegram

Recently, one of our customers asked us to check on the feasibility of integrating Telegram messenger with Twilio Flex. These were their requirements:

  • Due to the urgent nature of the situation, the solution should be quick to stand-up and deploy.
  • The solution should be scalable as this would be a critical mode of communication for the end-users.
  • The messages being exchanged should be persistent for a specific user irrespective of which agent they first engage. In short – maintain conversation history across interactions.

Prerequisites

To build this solution, you will need:

Let’s get started!

Start with Flex

If you’ve already set up your Flex instance, you can skip ahead to the next step.

If you’re new to Flex, create a new Flex account. Follow the prompts to kick off the Flex setup. During this process, several Twilio services will be created and provisioned for you.

Launch the Flex UI in your browser, and you should see something like this.

Twilio Flex without CRM configured

Create API Keys for Corezoid

Twilio recommends you issue an API token for Corezoid and don't use your Twilio Account SID and Secret directly. Twilio API Keys can be provisioned and revoked through the REST API or the Twilio Console. This provides a powerful and flexible primitive for managing access to the Twilio API.

Creating API Keys in Twilio

For example, you might issue separate API Keys for different developers or different subsystems within your application.

Since API Keys can be independently revoked, you have complete control of the lifecycle of your API credentials. You can create a key here.

Set up a Telegram Task Channel in Task Router

Task Channels provide a mechanism to separate tasks of different types.

Execute the below command using twilio-cli

curl -X POST https://taskrouter.twilio.com/v1/Workspaces/WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/TaskChannels \
--data-urlencode "FriendlyName=Telegram" \
--data-urlencode "UniqueName=telegram" \
-u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN

Response:

{
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "workspace_sid": "WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "sid": "TCXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "friendly_name": "Telegram",
  "unique_name": "telegram",
  "date_created": "2016-04-14T17:35:54Z",
  "date_updated": "2016-04-14T17:35:54Z",
  "channel_optimized_routing": true,
  "url": "https://taskrouter.twilio.com/v1/Workspaces/WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/TaskChannels/TCXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "links": {
    "workspace": "https://taskrouter.twilio.com/v1/Workspaces/WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  }
} 

Set up a Studio Flow for Telegram

Twilio Studio is a visual tool that you can use to build communication applications with little or no code. In this section, you will import and publish one Studio flow.

Import the Telegram Flow

Navigate to the Twilio Studio Dashboard. Click "+" to create a new Studio Flow, then name the flow Telegram Flow (or whatever name you prefer), and click "Next".

Naming a Twilio Studio Flow

Scroll to the bottom of the next pop-up and select Import from JSON template, then click Next.

{
        "description": "Telegram Flow",
        "states": [
                {
                        "name": "Trigger",
                        "type": "trigger",
                        "transitions": [
                                {
                                        "next": "send_to_flex_1",
                                        "event": "incomingMessage"
                                },
                                {
                                        "event": "incomingCall"
                                },
                                {
                                        "event": "incomingRequest"
                                },
                                {
                                        "event": "incomingParent"
                                }
                        ],
                        "properties": {
                                "offset": {
                                        "x": 0,
                                        "y": 0
                                }
                        }
                },
                {
                        "name": "send_to_flex_1",
                        "type": "send-to-flex",
                        "transitions": [
                                {
                                        "event": "callComplete"
                                },
                                {
                                        "event": "failedToEnqueue"
                                },
                                {
                                        "event": "callFailure"
                                }
                        ],
                        "properties": {
                                "offset": {
                                        "x": 40,
                                        "y": 300
                                },
                                "workflow": "WorkflowSID",
                                "channel": "telegramTaskChannelUniqueSID",
                                "attributes": "{}"
                        }
                }
        ],
        "initial_state": "Trigger",
        "flags": {
                "allow_concurrent_calls": true
        }
}

Update the workflow and the channel to the Telegram Task Channel in the placeholders in “send_to_flex_1” with the actual values from the TaskRouter deployed as part of the Flex instance.

Save the send_to_flex_1 widget after making the changes and Publish the Studio flow.

Make a note of the flowSid for the Studio flow. You will need it soon.

Set up a Flex Flow

A Flex Flow is the logic linking a contact identity (e.g., SMS-enabled phone number or WhatsApp number) to Flex.

This page details the Flex Flow API Resource. Check out the additional documentation to learn more about working with Flex Flows.

Execute the below command using twilio-cli:

curl -X POST https://flex-api.twilio.com/v1/FlexFlows \
--data-urlencode "IntegrationType=studio" \
--data-urlencode "Enabled=True" \
--data-urlencode "Integration.FlowSid=FWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
--data-urlencode "ContactIdentity=telegram" \
--data-urlencode "FriendlyName=Telegram Flex Flow" \
--data-urlencode "ChannelType=custom" \
--data-urlencode "ChatServiceSid=ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
--data-urlencode "longLived=true" \
--data-urlencode "janitorEnabled=true" \
-u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN

Response:

{
    "integration": {
        "retry_count": 3,
        "flow_sid": "FWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    },
    "janitor_enabled": true,
    "integration_type": "studio",
    "date_updated": "2022-03-11T11:12:05Z",
    "enabled": true,
    "friendly_name": "Telegram Flex Flow",
    "contact_identity": "telegram",
    "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "channel_type": "custom",
    "url": "https://flex-api.twilio.com/v1/FlexFlows/FOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "sid": "FOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "date_created": "2022-03-11T11:12:05Z",
    "long_lived": true,
    "chat_service_sid": "ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}

Make a note of the flexFlowSid for the Flex flow.

async init(flex, manager) {
   //Create Telegram Task Channel
   const telegramTaskChannel = flex.DefaultTaskChannels.createChatTaskChannel(
     "telegram",
     (task) => task.taskChannelUniqueName === "telegram"
   );}

Set up a Twilio Serverless Service

Let's create a new service called "telegram" and two functions:

  1. Check if webhook already exists, and if not, create one
  2. Webhook itself that is responsible for sending messages back to Telegram

Serverless Telegram service

create_webhook Function

This function is public because it’s being called from Corezoid (step 12 in the previous section). Please note that this is just a functional example that does not cover authentication and proper logging.

exports.handler = function (context, event, callback) {

    let client = context.getTwilioClient();
    const channelSid = event.channelSid;
    const telegramId = event.telegramId

    client.chat.services(<ISxxxx>)
        .channels(channelSid)
        .webhooks
        .list({ limit: 20 })
        .then(webhooks => {

            if (webhooks.filter(hook => { return (hook.configuration && hook.configuration.url && hook.configuration.url.includes("telegram")) }).length > 0) {
                console.log("telegram")
                const res = { 'nok': 'nok' }
                return callback(null, res);
            } else {
                client.chat.services(<ISxxxx>)
                    .channels(channelSid)
                    .webhooks
                    .create({
                        type: 'webhook',
                        configuration: {
                            filters: ['onMessageSent', 'onChannelUpdated'],
                            url: `https://<FUNCTION_URL>/webhook?teleId=${telegramId}`
                        }
                    })
                    .then(webhook => {
                        console.log(webhook.sid)
                        const res = { 'ok': 'ok' }
                        return callback(null, res);
                    });
            }
        })
};

webhook Function

This function can be protected as it is being called from within Twilio any time a message is being added to the channel. If the message is from the agent, then we pass it to the Telegram user.

const axios = require('axios');

exports.handler = function (context, event, callback) {

    const telegramId = event.teleId
    const sendBy = event.From
    const message = event.Body

    if (sendBy != telegramId) {
        const url = "https://api.telegram.org/bot<TELEGRAM_TOKEN>/sendMessage"

        axios.post(url, {
            chat_id: telegramId,
            text: message
        })
            .then(function (response) {
                console.log(response);
                return callback(null, response);

            })
            .catch(function (error) {
                console.log(error);
                return callback(null, error);

            });
    } else {
        console.log("Messages from Customer")
        return callback(null, null);
    }
};

Set up a Telegram Account

  1. Install Telegram Messenger on your iOS/Android device.
  2. Register (Create) an account on Telegram App.
  3. Find ‘@botfather’ in the Telegram Messenger App.
  4. Use the ‘/newbot’ command to create a new bot. The BotFather will ask you for a name and username, then generate an authentication token for your new bot.
  5. The name of your bot is displayed in contact details and elsewhere.
  6. The Username is a short name, to be used in mentions and t.me links. Usernames are 5-32 characters long and are case insensitive, but may only include Latin characters, numbers, and underscores. Your bot's username must end in 'bot', e.g. 'tetris_bot' or 'TetrisBot'.
  7. The token is a string that is required to authorize the bot and send requests to the Bot API.
  1. Keep your token secure and store it safely, it can be used by anyone to control your bot.

Creating a new telegram bot with BotFather

Create a Corezoid Trial Account

1. Create an account on Corezoid if you haven't yet. If you have already created an account click here to sign in.

2. Once signed in, you will be greeted with the Corezoid home screen.

Corezoid home screen

3. Click on the “Create” button on the top left corner to create a new process.

Create a new process in Corezoid

4. Create a new process called “Telegram”.

Create a "Telegram" process in Corezoid

5. This will open a blank canvas to build the process flow.

Blank Corezoid process and flow

6. Select the “Start” widget, this opens a side panel with multiple options. Click on the “Connect to Messenger” button on the side panel.

Corezoid connect to Telegram

Hit the Corezoid "Connect to Messenger" button

7. Enter the Telegram Bot API Token which you created and saved earlier. Then click on “OK” button.

Enter your BotFather bot API Key from Telegram in Corezoid

This will connect the Telegram Bot with Corezoid.

8. Let’s add additional api call widgets to the Corezoid process as described in the create customer channel blog post.

Adding API call widgets in Corezoid

9. Create channel API call:

URL = https://{{account_sid}}:{{twilio_token}}@flex-api.twilio.com/v1/Channels

Parameters:

  • FlexFlowSid = FOxxx
  • LongLived = True
  • Identity = {{message.chat.id}}
  • ChatFriendlyName = Telegram
  • ChatUserFriendlyName = {{message.from.first_name}}
  • Target = {{message.chat.id}}

ViberCorezoid2

 

10. Add “Reply to Process” widget to get Channel SID created

Adding Key Value reply to process params in Corezoid

11. Call Function that adds webhook to the Channel (more about the function in the next chapter):
URL = https://<function_url>/create_webhook

Parameters:

  • channelSid = {{sid}}
  • telegramId = {{message.chat.id}}

Entering an API request URL in Corezoid

12. Send Message to Channel Widget:
URL = https://{{account_sid}}:{{twilio_token}}@chat.twilio.com/v2/Services/{{service_sid}}/Channels/{{sid}}/Messages

Parameters:

  • Body = {{message.text}}
  • From = {{message.chat.id}}


Headers:

  • X-Twilio-Webhook-Enabled = True

Entering more params and request headers in Corezoid

And that’s it! You've now built a straightforward example of a process used as middleware between Telegram and Twilio, using Corezoid.

Great Job!

That’s it! You can start testing your solution:

  1. Send a message to your Telegram Bot
  2. This triggers the process in Corezoid
  3. Corezoid API calls creates a new channel, adds webhook & adds a new message into the channel
  4. Flex Flow triggers the Studio as soon as the message is in the channel
  5. Studio creates a new task in Flex
  6. Reply in Flex that triggers webhook sending agent’s message back to the Telegram

Testing a message from Telergam in Flex

Example Telegram, Flex, and Corezoid message log


More from the Twilio.org product team coming soon

This is just one of the many ways that the fast-growing Twilio.org product team is building software to help social impact organizations advance their missions with Twilio. Stay tuned for future product releases from Twilio.org that focus on the unique needs of the social sector including tools for beneficiary, volunteer, and donor engagement.

Vinit Dave is a Senior Solutions Architect at Twilio Professional Services, primarily functioning to innovate, design and build complete e2e solutions for variety to customer problems and industry verticals. He can be reached at vdave [at] twilio [dot] com.

Miroslav Botur is a Senior Solution Architect at Twilio Professional Services. He is focused mainly on Flex Insights and enhancing analytics data by using Flex plugins, Functions and advanced Studio flows. He can be reached at mbotur [at] twilio [dot] com