Reputation: 11
So, when a bot sends a message through Bot Connecter, it sends it as a JSON object, that lookks something like:
{
"type": "message",
"timestamp": "2017-07-20T06:35:09.196Z",
"serviceUrl": "http://127.0.0.1:53484",
"channelId": "emulator",
"from": {
"id": "ijfi3f969c6fij756",
"name": "Bot"
},
"conversation": {
"id": "g671h707amhch9326"
},
"recipient": {
"id": "default-user"
},
"membersAdded": [],
"membersRemoved": [],
"text": "Hey there!",
"attachments": [],
"entities": [],
"replyToId": "efincfmnc40la0g7c",
"id": "hi959g2a8ji1fn86",
"localTimestamp": "2017-07-20T08:35:09+02:00"
}
We would like to add a few additional tags, to carry a bit more data about the message being sent. For example, we might want to add a tag that shows we are expecting the user to reply with an email address. Perhaps something like:
{
"type": "message",
"expecting": "email"
"timestamp": "2017-07-20T06:35:09.196Z", "serviceUrl": "http://127.0.0.1:53484", "channelId": "emulator", "from": {
"id": "ijfi3f969c6fij756", "name": "Bot" },
The idea is, that we'd like to use our custom tags to run additional code. Something we might want to do, for example, is:
if(reply.Expecting.Equals("email")
{
//Do something awesome here.
}
But, we haven't been able to find any information on how to customize these JSON messages. Is it possible? And if so, how would we go about it?
Upvotes: 1
Views: 313
Reputation: 128
Assuming that you are using .net Framework.
below is one option i can think of. Introducing custom properties to the Activity
Implement Activity class on your CustomActivity class
public class CustomActivity : Activity
{
[JsonProperty(PropertyName = "cutomprop")]
public string MyCustomProp { get; set; } = "Custom Prop";
}
Then while posting back replies consider creating Activity of type CustomActivity and do copy all props of original Activity to it (use tool Automapper for this purpose)
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var activity = await result as Activity;
ConnectorClient client = new ConnectorClient(new Uri(activity.ServiceUrl));
var reply = new CustomActivity
{
ChannelData = activity.ChannelData,
ChannelId = activity.ChannelId,
ServiceUrl = activity.ServiceUrl,
Name = activity.Name,
Action = activity.Action,
Type = activity.Type,
Conversation = activity.Conversation,
Code = activity.Code,
From = activity.From,
Value = activity.Value,
Text = activity.Text,
InputHint = activity.InputHint,
Attachments = activity.Attachments,
Entities = activity.Entities,
ReplyToId = activity.ReplyToId,
AttachmentLayout = activity.AttachmentLayout,
HistoryDisclosed = activity.HistoryDisclosed,
Id = activity.Id,
LocalTimestamp = activity.LocalTimestamp,
Locale = activity.Locale,
MembersAdded = activity.MembersAdded,
MembersRemoved = activity.MembersRemoved,
Properties = activity.Properties,
Recipient = activity.Recipient,
RelatesTo = activity.RelatesTo,
Speak = activity.Speak,
SuggestedActions = activity.SuggestedActions,
Summary = activity.Summary,
TextFormat = activity.TextFormat,
Timestamp = activity.Timestamp,
TopicName = activity.TopicName
};
reply.Text = "I have colors in mind, but need your help to choose the best one.";
reply.Type = ActivityTypes.Message;
reply.TextFormat = TextFormatTypes.Plain;
//set any other prop you want as per your needs
await client.Conversations.SendToConversationAsync(reply);
context.Wait(MessageReceivedAsync);
}
Below is the output i got
{
"cutomprop": "Custom Prop",
"type": "message",
"id": null,
"timestamp": "2017-07-20T12:44:41.504Z",
"localTimestamp": "2017-07-20T18:14:41+05:30",
"serviceUrl": "http://127.0.0.1:56931",
"channelId": "emulator",
"from": {
"id": "default-user",
"name": "default-user"
},
"conversation": {
"id": "h0j9hn8bicfm8e509"
},
"recipient": {
"id": "mcfimjke5aebemhf",
"name": "Bot"
},
"textFormat": "plain",
Hope that helps... consider validating it for your scenario and look out for any other side effects . **not tested it on all channels, it works on emulator
Upvotes: 1
Reputation:
You can accomplish this with middleware. Here's the C# docs, and the NodeJS docs.
Basically, you set up your middleware off of the bot object:
bot.use({
botbuilder: (sess, next) => {
inbound(sess, next);
}
,send: (evt, next) => {
outbound(evt, next);
}
});
...where botbuilder
captures what the user sends and send
captures what the bot sends.
Then you can define functions to deal with the messages, and alter them if you find that to be appropriate:
function inbound(sess: builder.Session, next: Function): void {
console.log(sess.message);
next();
}
function outbound(evt: builder.IEvent, next: Function): void {
console.log(evt);
next();
}
My recommendation is to not alter the message data structure itself, but to instead do your custom behaviors using the middleware, since altering these messages could have side effects. You can easily capture what you need to in the middleware, and then pass arguments to the next()
function to allow the subsequent dialog to handle expectations.
Also, if all you're doing is trying to capture expected user input, regular expression matches with intent dialogs or trigger actions works quite well.
Upvotes: 1