In this article we are going to have a look at the data we receive on the server (where our bot runs) when the user sends a message, how we can access that data and also how to send back data in different ways. We only focus on how to deal with this server-side, not on the user’s front end.
How can my bot access info coming from a user?
Via an object called TurnContext. It provides information to process an incoming activity during the length of the turn. What is a turn? A turn starts when the user sends an activity and ends after the server sends an activity back.
// src/bot.ts import {TurnContext} from 'botbuilder'; export class MyBot { public onTurn = async (turnContext: TurnContext) => { // process the activity }; }
What info does TurnContext contain?
As we can see above we get plenty of info:
- ID of the channel the message was sent in (“emulator”)
- Name of the user that send the message (“User”)
- Name of the recipient (“Bot”)
- type of this activity (“ConversationUpdate”)
- timestamp when this message was sent
- and more
In the example above the Bot Framework Service sends an activity of type ConversationUpdate. It does that when a party joins the conversation. For example, on starting a conversation with the Bot Framework Emulator we see two conversation update activities: one for the user joining the conversation and one for the bot joining. To distinguish these conversation update activities, check whether the members added property includes a member other than the bot.
Receiving a user message and sending text back
public onTurn = async (turnContext: TurnContext) => { // without the following check the bot would immediately react on intialisation if (turnContext.activity.type === ActivityTypes.Message) { // receiving let text = turnContext.activity.text; // sending await turnContext.sendActivity("Welcome!"); } }
Sending files
The following example will send an image, but the same applies for audio, video or other files.
public onTurn = async (turnContext: TurnContext) => { if (turnContext.activity.type === ActivityTypes.Message) { const reply = { type: ActivityTypes.Message, attachments: [this.getInternetAttachment()], text: 'This is an internet attachment.' }; await turnContext.sendActivity(reply); } }; private getInternetAttachment() { return { name: 'imageName.png', contentType: 'image/png', contentUrl: 'http://bothe.at/img/whatever.png' } }
Sending a hero card
A hero card allows you to combine several elements together, such as images, text and action buttons.
import {ActionTypes, ActivityTypes, TurnContext, CardFactory} from 'botbuilder'; public onTurn = async (turnContext: TurnContext) => { if (turnContext.activity.type === ActivityTypes.Message) { const buttons = [ {type: ActionTypes.ImBack, title: '1. Inline Attachment', value: '1'}, {type: ActionTypes.ImBack, title: '2. Internet Attachment', value: '2'}, {type: ActionTypes.ImBack, title: '3. Uploaded Attachment', value: '3'} ]; const card = CardFactory.heroCard('', undefined, buttons, {text: 'You can upload an image or select one of the following choices.'}); const reply = {type: ActivityTypes.Message, attachments: [card]}; await turnContext.sendActivity(reply); } };
Implementing click behavior for hero card buttons
There are many types of actions, such as opening a URL, calling a phone number, playing audio or video, showing an image, downloading a file or signing in using OAuth described on the Microsoft Doc page.
We use MessageFactory here which is just a helper class within the Bot Framework SDK to automate creation steps for you, and it is supported by most channels.
public onTurn = async (turnContext: TurnContext) => { if (turnContext.activity.type === ActivityTypes.Message) { const hero = MessageFactory.attachment( CardFactory.heroCard( 'Holler Back Buttons', ['https://example.com/whiteShirt.jpg'], [{ type: ActionTypes.ImBack, title: 'ImBack', value: 'You can ALL hear me! Shout Out Loud' }, { type: ActionTypes.PostBack, title: 'PostBack', value: 'Shh! My Bot friend hears me. Much Quieter' }, { type: ActionTypes.OpenUrl, title: 'OpenUrl', value: 'https://en.wikipedia.org/wiki/{cardContent.Key}' }] ) ); await turnContext.sendActivity(hero); } };
Sending an Adaptive Card
Adaptive Card is another way to send rich messages in card format, but it is not supported by all channels.
The AdaptiveCard type of FlightIternary was picked from BotBuilder Sample on Github.
import {ActivityTypes, TurnContext, CardFactory} from 'botbuilder'; import * as FlightItineraryCard from './resources/FlightItineraryCard'; export class MyBot { public onTurn = async (turnContext: TurnContext) => { if (turnContext.activity.type === ActivityTypes.Message) { await turnContext.sendActivity({ text: 'Here is an Adaptive Card:', attachments: [CardFactory.adaptiveCard(FlightItineraryCard.default)] }); } }; }
Sending a Carousel of Cards
import {ActivityTypes, TurnContext, CardFactory, MessageFactory} from 'botbuilder'; export class MyBot { public onTurn = async (turnContext: TurnContext) => { if (turnContext.activity.type === ActivityTypes.Message) { let messageWithCarouselOfCards = MessageFactory.carousel([ CardFactory.heroCard('title1', ['imageUrl1'], ['button1']), CardFactory.heroCard('title2', ['imageUrl2'], ['button2']), CardFactory.heroCard('title3', ['imageUrl3'], ['button3']) ]); await turnContext.sendActivity(messageWithCarouselOfCards); } }; }
Sending action buttons
We are sending buttons that will disappear once the user tapped on them.
import {ActivityTypes, TurnContext, MessageFactory} from 'botbuilder'; export class MyBot { public onTurn = async (turnContext: TurnContext) => { if (turnContext.activity.type === ActivityTypes.Message) { const reply = MessageFactory.suggestedActions(['Red', 'Yellow', 'Blue'], 'What is the best color?'); await turnContext.sendActivity(reply); } }; }
No comments yet.