Bot generate multiple questions using backdoor events from webchat in sequence
without getting answer from user. Below example for two questions :
//Question 1
var reply = ((Activity)activity).CreateReply("Question 1");
reply.Type = ActivityTypes.Message;
reply.TextFormat = TextFormatTypes.Plain;
reply.SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() {Title = "Ans 1", Type = ActionTypes.ImBack, Value = "Ans 1"},
new CardAction() {Title = "Ans 2", Type = ActionTypes.ImBack, Value = "Ans 2"}
}
};
await connectorClient.Conversations.ReplyToActivityAsync(reply);
//Question 2 after 10 sec
var reply = ((Activity)activity).CreateReply("Question 2");
reply.Type = ActivityTypes.Message;
reply.TextFormat = TextFormatTypes.Plain;
reply.SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() {Title = "Ans 1", Type = ActionTypes.ImBack, Value = "Ans 1"},
new CardAction() {Title = "Ans 2", Type = ActionTypes.ImBack, Value = "Ans 2"}
}
};
await connectorClient.Conversations.ReplyToActivityAsync(reply);
How to recognize in receiving Activity activity on what question user answered- on Question 1 or Question 2?
The solution to this is very simple, all you need to do Is make the Value parameter unique. In code, it would look like the snippet below. You may also want to consider using ActionTypes.PostBack rather than ActionTypes.ImBack that way the user does not actually see the Value
var connectorClient = new ConnectorClient(new Uri(activity.ServiceUrl));
var reply = ((Activity)activity).CreateReply("Question 1");
reply.Type = ActivityTypes.Message;
reply.TextFormat = TextFormatTypes.Plain;
reply.SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() {Title = "Ans 1", Type = ActionTypes.PostBack, Value = "question 1 Ans 1"},
new CardAction() {Title = "Ans 2", Type = ActionTypes.PostBack, Value = "question 1 Ans 2"}
}
};
await connectorClient.Conversations.ReplyToActivityAsync(reply);
//Question 2 after 10 sec
reply = ((Activity)activity).CreateReply("Question 2");
reply.Type = ActivityTypes.Message;
reply.TextFormat = TextFormatTypes.Plain;
reply.SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() {Title = "Ans 1", Type = ActionTypes.PostBack, Value = "question 2 Ans 1"},
new CardAction() {Title = "Ans 2", Type = ActionTypes.PostBack, Value = "question 2 Ans 2"}
}
};
await connectorClient.Conversations.ReplyToActivityAsync(reply);
Related
I have to create a adaptive card which have city of name and each city have different holiday list.
I have to show city name in dropdown list and on selection of each city i have to show child card which contains Holiday list.
I have develop below code:
private async Task<DialogTurnResult> ShowCard(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
List<string> city = new List<string>() { "Delhi", "Bangalore", "Mumbai" };
List<string> date = new List<string>() { "1-Jan", "26-Jan", "15-Aug" };
List<string> des = new List<string>() { "New Year", "Republic Day", "Independence Day" };
List<string> date1 = new List<string>() { "1-Jan", "26-Jan", "15-Aug", "25-Dec" };
List<string> des1 = new List<string>() { "New Year", "Republic Day", "Independence Day", "Christmas Day" };
List<string> date2 = new List<string>() { "1-Jan", "25-Dec" };
List<string> des2 = new List<string>() { "New Year", "Christmas Day" };
List<AdaptiveCard> cards = new List<AdaptiveCard>();
cards.Add(HolidayListAdaptiveCard(date, des));
cards.Add(HolidayListAdaptiveCard(date1, des1));
cards.Add(HolidayListAdaptiveCard(date2, des2));
var mainCard = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0));
var column3 = new AdaptiveColumn();
column3.Items.Add(new AdaptiveTextBlock() { Text = "Holiday City", Weight = AdaptiveTextWeight.Bolder });
var columnSet1 = new AdaptiveColumnSet();
columnSet1.Columns.Add(column3);
var container1 = new AdaptiveContainer();
container1.Style = AdaptiveContainerStyle.Emphasis;
container1.Items.Add(columnSet1);
mainCard.Body.Add(container1);
List<AdaptiveShowCardAction> adaptiveShowCardActions = new List<AdaptiveShowCardAction>();
for (int i = 0; i < city.Count; i++)
{
mainCard.Actions.Add(new AdaptiveShowCardAction() { Title = city[i], Card = cards[i] });
}
var attachment = new Attachment
{
ContentType = AdaptiveCard.ContentType,
Content = mainCard
};
var reply = MessageFactory.Attachment(attachment);
await stepContext.Context.SendActivityAsync(reply);
return new DialogTurnResult(DialogTurnStatus.Waiting);
}
private AdaptiveCard HolidayListAdaptiveCard(List<string> date, List<string> description)
{
var card = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0));
List<AdaptiveColumn> columns = new List<AdaptiveColumn>();
var column = new AdaptiveColumn();
var column1 = new AdaptiveColumn();
var column2 = new AdaptiveColumn();
var textBlock = new AdaptiveTextBlock();
textBlock.Text = "Sr. No";
textBlock.Weight = AdaptiveTextWeight.Bolder;
textBlock.Size = AdaptiveTextSize.Large;
textBlock.Color = AdaptiveTextColor.Accent;
column.Items.Add(textBlock);
var textBlock1 = new AdaptiveTextBlock();
textBlock1.Text = "Date";
textBlock1.Weight = AdaptiveTextWeight.Bolder;
textBlock1.Size = AdaptiveTextSize.Large;
textBlock1.Color = AdaptiveTextColor.Good;
column1.Items.Add(textBlock1);
var textBlock2 = new AdaptiveTextBlock();
textBlock2.Text = "Description";
textBlock2.Weight = AdaptiveTextWeight.Bolder;
textBlock2.Size = AdaptiveTextSize.Large;
textBlock2.Color = AdaptiveTextColor.Dark;
column2.Items.Add(textBlock2);
for (int i = 0; i < date.Count; i++)
{
column.Items.Add(new AdaptiveTextBlock() { Text = (i + 1).ToString() });
column1.Items.Add(new AdaptiveTextBlock() { Text = date[i] });
column2.Items.Add(new AdaptiveTextBlock() { Text = description[i] });
}
var columnSet = new AdaptiveColumnSet();
columnSet.Columns.Add(column);
columnSet.Columns.Add(column1);
columnSet.Columns.Add(column2);
var container = new AdaptiveContainer();
container.Style = AdaptiveContainerStyle.Emphasis;
container.Items.Add(columnSet);
card.Body.Add(container);
return card;
}
O/P:
Issue: City name coming as separate button but i need city name in dropdown list.
You can create a dropdown menu in an Adaptive Card by using an Input.ChoiceSet element and setting style to "compact". Note that the compact style is the default in Teams.
You can only extend Adaptive Card functionality if you're using Web Chat so you won't be able to respond to events from this dropdown and you won't be able to modify the card as the user is filling it out. You'll need to have the user select a city and then click the submit button. While Teams does allow message updates and so you could update the card in response to the submit action, it's probably better and easier just to send a whole new card with the holiday list.
I want to use facebook's quick replies -
at first I tried to use IMessageActivity's SuggestedActions property
IMessageActivity result = Activity.CreateMessageActivity();
result.Type = ActivityTypes.Message;
result.TextFormat = TextFormatTypes.Plain;
result.SuggestedActions = suggestedActions.Select(x => new CardAction()
{
Title = x,
Type = ActionTypes.ImBack,
Value = x
}).ToList()
but, as it didn't work for facebook, I found another solution based on ChanelData
result.ChannelData = JObject.FromObject(new {
quick_replies = suggestedActions.Actions.Select(x => new
{
content_type = "text",
title = x.Title,
payload = x.Value is null ? x.Title : x.Value
}).ToArray()
});
sadly it still doesn't work. Is there anything else to do?
I beleive you can use HeroCards and attach them to an activity and send that via SendActivityAsync.
Activity activity = _context.Context.Activity.CreateReply();
var buttonList = new List<CardAction>();
foreach (var prompt in Prompts)
{
buttonList.Add(
new CardAction { Value = prompt.DisplayText, Type = "imBack", Title = prompt.DisplayText, });
}
var heroCard = new HeroCard { Text = "message text", Subtitle = string.Empty, Buttons = buttonList };
activity.Attachments.Add(heroCard.ToAttachment());
await stepContext.Context.SendActivityAsync(activity).ConfigureAwait(false);
Try using a TextPrompt with the PromptOptions like this:
await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{
Prompt = new Activity
{
Type = ActivityTypes.Message,
Text = "¡Bien! Ahora te envié un código de acceso a tu teléfono. Por favor ingrésalo aquí cuando lo recibas.",
SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() { Title = "Reenviar token", Type = ActionTypes.ImBack, Value = "Reenviar token" }
},
},
}
});
Result:
Edit:
If you dont want to use prompts, try this:
Activity activity = stepContext.Context.Activity.CreateReply();
activity.Type = ActivityTypes.Message;
activity.Text = "This is an example of SuggestedAction";
activity.SuggestedActions = new SuggestedActions()
{
Actions = new List<CardAction>()
{
new CardAction() { Title = "Action", Type = ActionTypes.ImBack, Value = "Action" }
}
};
await stepContext.Context.SendActivityAsync(activity);
return await stepContext.EndDialogAsync();
Result:
Is it possible to include HeroCard attachment in WaterfallStepContext, i am able to call ITurnContext but not from WaterfallStepContext
Trying using C# code however .Activity is part of waterfallstep contenxt
var getFeedback = turnContext.Activity.CreateReply();
var feedbackChoices = new HeroCard
{
Text = "Our conversation was helpful?",
Buttons = new List<CardAction>
{
new CardAction() { Title = Constants.userResponseThumbsUp, Type = ActionTypes.ImBack, Value = Constants.userResponseYes},
new CardAction() { Title = Constants.userResponseThumbsDown, Type = ActionTypes.ImBack, Value = Constants.userResponseNo},
},
};
// Add the card to our reply to user.
getFeedback.Attachments = new List<Attachment>() { feedbackChoices.ToAttachment() };
await turnContext.SendActivityAsync(getFeedback, cancellationToken);
Yes, it is possible to include a HeroCard attachment in WaterfallStepContext. Here is the implementation below:
private static async Task<DialogTurnResult> ShowCardStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var getFeedback = stepContext.Context.Activity.CreateReply();
var feedbackChoices = new HeroCard
{
Text = "Our conversation was helpful?",
Buttons = new List<CardAction>
{
new CardAction() { Title = Constants.userResponseThumbsUp, Type = ActionTypes.ImBack, Value = Constants.userResponseYes},
new CardAction() { Title = Constants.userResponseThumbsDown, Type = ActionTypes.ImBack, Value = Constants.userResponseNo},
},
};
// Add the card to our reply to user.
getFeedback.Attachments = new List<Attachment>() { feedbackChoices.ToAttachment() };
await stepContext.Context.SendActivityAsync(getFeedback, cancellationToken);
}
Hope this helps.
I'm developing a bot with Microsoft Bot Framework, on Facebook Messenger the carousel shows as it should, but in Telegram it shows as 2 different cards on two different messages.
Doesn't Telegram support carousels or is it my fault?
Code:
public async Task Carousel(IDialogContext context, IAwaitable<IMessageActivity> activity)
{
var act = await activity;
//carousel
var replyToConversation = context.MakeMessage();
replyToConversation.Text = "2+ Cards are a Carousel";
replyToConversation.Recipient = message.From;
replyToConversation.Type = "message";
replyToConversation.Attachments = new List<Attachment>();
//1
List<CardImage> cardImages = new List<CardImage>();
cardImages.Add(new CardImage(url: "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/Asimo_look_new_design.jpg/330px-Asimo_look_new_design.jpg"));
List<CardAction> cardButtons = new List<CardAction>();
CardAction plButton = new CardAction()
{
Value = "https://en.wikipedia.org/wiki/Robot",
Type = "openUrl",
Title = "WikiPedia Page"
};
cardButtons.Add(plButton);
HeroCard plCard = new HeroCard()
{
Title = "I'm a hero card",
Subtitle = "Robot Wikipedia Page",
Images = cardImages,
Buttons = cardButtons
};
Attachment plAttachment = plCard.ToAttachment();
replyToConversation.Attachments.Add(plAttachment);
//2
List<CardImage> cardImages2 = new List<CardImage>();
cardImages2.Add(new CardImage(url: "https://upload.wikimedia.org/wikipedia/en/thumb/9/9b/FANUC_6-axis_welding_robots.jpg/330px-FANUC_6-axis_welding_robots.jpg"));
List<CardAction> cardButtons2 = new List<CardAction>();
CardAction plButton2 = new CardAction()
{
Value = "https://en.wikipedia.org/wiki/Robot",
Type = "openUrl",
Title = "WikiPedia Page"
};
cardButtons2.Add(plButton);
HeroCard plCard2 = new HeroCard()
{
Title = "I'm a hero card",
Subtitle = "Robot Wikipedia Page",
Images = cardImages2,
Buttons = cardButtons2
};
Attachment plAttachment2 = plCard2.ToAttachment();
replyToConversation.AttachmentLayout = AttachmentLayoutTypes.Carousel;
replyToConversation.Attachments.Add(plAttachment2);
await context.PostAsync(replyToConversation);
}
It's not your fault. Per the Channel Inspector, the carousel in Telegram has a down-rendered appearance.
I have an object created by - new {name1 = "string1"}
I have to add additional members to it eg {name2 = "string2"} so that the final result is
{
name1 = "string1",
name2 = "string2"
}
You can either instantiate it all at once:
var someObj = new {name1 = "name 1", name2 = "name 2"};
Or you can do it in steps.
var someObj1 = new {name1 = "name 1"};
var someObj2 = new {name1 = someObj1.name1, name2 = "name 2"};
But no, you can't add properties/field to anonymous types at run-time or after it's been instantiated.
You have to create a new object, of a new anonymous type:
var obj1 = new {name1 = "string1"};
var obj2 = new {name1 = obj1.name1, name2 = "string2" };