I try to show the keyboard chatting telegram using botframework, but the keyboard is not displayed. I tried send keybord like this:
Activity reply = activity.CreateReply(message);
var keyboard =new ReplyKeyboardMarkup
{
Keyboard = new[] { new[] { new KeyboardButton("Text1"), new KeyboardButton("text1") } }
};
reply.ChannelData = keyboard;
await connector.Conversations.ReplyToActivityAsync(reply);
And many other ways. But keyboard does not show up.
What could be the reason? How to make it show up?
You don't need to use ChannelData. Just send the buttons on a HeroCard:
var card = new HeroCard("Some Text");
card.Buttons = new List<CardAction>()
{
new CardAction()
{
Title = "button1",
Type=ActionTypes.ImBack,
Value="button1"
},
new CardAction()
{
Title = "button2",
Type=ActionTypes.ImBack,
Value="button2"
}
};
var reply = activity.CreateReply("");
reply.Attachments = new List<Attachment>();
reply.Attachments.Add(new Attachment()
{
ContentType = HeroCard.ContentType,
Content = card
});
return reply;
Related
Hi i tried all these methods of attaching a video to a bot. All of them are working fine in bot emulator. But when i publish it to messenger it is throwing an exception . (I can't see the exception by the way i just know because of the message. Is there a way to see or log exceptions?). Is video card not supported in messenger? Or is youtube not supported as an url link?
Here are the codes:
AddStep(async (stepContext, cancellationToken) =>
{
var reply = stepContext.Context.Activity.CreateReply();
reply.Attachments = new List<Attachment>();
reply.Attachments.Add(GetVideoCard().ToAttachment());
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
return await stepContext.NextAsync();
});
////////////////
private static VideoCard GetVideoCard()
{
var videoCard = new VideoCard
{
Title = "Budgeting Introduction",
Subtitle = "by Finko",
Media = new List<MediaUrl>
{
new MediaUrl()
{
Url = "https://www.youtube.com/watch?v=XLo1geVokhA",
},
},
Buttons = new List<CardAction>
{
new CardAction()
{
Title = "Learn More at Finko.PH",
Type = ActionTypes.OpenUrl,
Value = "https://m-moreno.wixsite.com/finkoph?fbclid=IwAR1NVtlyKfzZ0mYFIWva8L-d8TUv4KFpt_m1i1ij3raT-pbWr2c3-kqzB2Q",
},
},
};
return videoCard;
}
and
AddStep(async (stepContext, cancellationToken) =>
{
var activity = stepContext.Context.Activity;
await stepContext.Context.SendActivityAsync(CreateResponse(activity, CreateVideoCardAttacment()));
return await stepContext.NextAsync();
});
////////////////////////
private Activity CreateResponse(Activity activity, Attachment attachment)
{
var response = activity.CreateReply();
response.Attachments = new List<Attachment>() { attachment };
return response;
}
private Attachment CreateVideoCardAttacment()
{
return new VideoCard()
{
Title = "Are you a Seafarer? OFW? FREE PERSONAL FINANCIAL ADVICE HERE!!",
Media = new List<MediaUrl>()
{
new MediaUrl("https://www.youtube.com/watch?v=XLo1geVokhA")
},
Buttons = new List<CardAction>()
{
new CardAction()
{
Type = ActionTypes.OpenUrl,
Title = "Learn More at Finko.PH",
Value = "https://m-moreno.wixsite.com/finkoph?fbclid=IwAR1NVtlyKfzZ0mYFIWva8L-d8TUv4KFpt_m1i1ij3raT-pbWr2c3-kqzB2Q"
}
},
Subtitle = "by Finko.Ph",
Text = "Are you tired of getting bogus financial advice? Tired of having 'kape' just to find out it was networking, or a pyramid scheme? Tired of scouring the internet for HOURS but not finding what you're looking for? We're here to help! We give financial advice and will educate you on financial literacy topics, ABSOLUTELY FREE!!"
}.ToAttachment();
}
and
Activity reply = stepContext.Context.Activity.CreateReply();
var card = new VideoCard
{
Title = "Finko.ph",
Media = new List<MediaUrl>()
{
new MediaUrl("https://www.youtube.com/watch?v=XLo1geVokhA")
},
Buttons = new List<CardAction>()
{
new CardAction()
{
Type = ActionTypes.OpenUrl,
Title = "Learn More at Finko.PH",
Value = "https://m-moreno.wixsite.com/finkoph?fbclid=IwAR1NVtlyKfzZ0mYFIWva8L-d8TUv4KFpt_m1i1ij3raT-pbWr2c3-kqzB2Q"
}
},
};
reply.Attachments.Add(card.ToAttachment());
await stepContext.Context.SendActivityAsync(reply);
return await stepContext.NextAsync();
and
var reply1 = stepContext.Context.Activity.CreateReply();
var attachment1 = new Attachment
{
ContentUrl = "https://www.youtube.com/watch?v=XLo1geVokhA",
ContentType = "video/mp4",
Name = "imageName1",
};
reply1.Attachments = new List<Attachment>() { attachment1 };
await stepContext.Context.SendActivityAsync(reply1, cancellationToken);
return await stepContext.NextAsync();
All of these codes are working in bot emulator but not in messenger. Any help would be appreciated thank you.
The BotFramework converts Video Cards into Media Templates for Facebook Messenger, and per Facebook's Developer documentation, media templates do not allow any external URLs, only those on Facebook. You must either upload the video to Facebook or provide a URL directly to the mp4 file which, unfortunately, YouTube doesn't make readily available.
For more details, take a look at Facebooks documentation regarding Media Templates.
I'm using an Adaptive Card with a multiselect, in the context of Bot created with BotBuilder (Bot Framework):
var card = new AdaptiveCard();
card.Body.Add(new AdaptiveTextBlock()
{
Text = "Q1:xxxxxxxx?",
Size = AdaptiveTextSize.Default,
Weight = AdaptiveTextWeight.Bolder
});
card.Body.Add(new AdaptiveChoiceSetInput()
{
Id = "choiceset1",
Choices = new List<AdaptiveChoice>()
{
new AdaptiveChoice(){
Title="answer1",
Value="answer1"
},
new AdaptiveChoice(){
Title="answer2",
Value="answer2"
},
new AdaptiveChoice(){
Title="answer3",
Value="answer3"
}
},
Style = AdaptiveChoiceInputStyle.Expanded,
IsMultiSelect = true
});
var message = context.MakeMessage();
message.Attachments.Add(new Attachment() { Content = card, ContentType = "application/vnd.microsoft.card.adaptive"});
await context.PostAsync(message);
Now, I would like to know which elements the user has selected.
I would like to know which elements the user has selected.
You can get user's selections from message Value property, the following code snippets work for me, please refer to it.
if (message.Value != null)
{
var user_selections = Newtonsoft.Json.JsonConvert.DeserializeObject<userselections>(message.Value.ToString());
await context.PostAsync($"You selected {user_selections.choiceset1}!");
context.Wait(MessageReceivedAsync);
}
The definition of userselections class:
public class userselections
{
public string choiceset1 { get; set; }
}
Test result:
Update: Code snippet of adding AdaptiveChoiceSetInput and AdaptiveSubmitAction
card.Body.Add(new AdaptiveChoiceSetInput()
{
Id = "choiceset1",
Choices = new List<AdaptiveChoice>()
{
new AdaptiveChoice(){
Title="answer1",
Value="answer1"
},
new AdaptiveChoice(){
Title="answer2",
Value="answer2"
},
new AdaptiveChoice(){
Title="answer3",
Value="answer3"
}
},
Style = AdaptiveChoiceInputStyle.Expanded,
IsMultiSelect = true
});
card.Actions.Add(new AdaptiveSubmitAction()
{
Title = "submit"
});
I have created a carousel using Hero Cards. It works fine in bot framework emulator but in Facebook messenger it shows only my first reply "Select an option" of the code below? Am I missing something, does messenger supports carousel? Why are the images and buttons missing?
Activity replyToConversation = activity.CreateReply("Select an option");
replyToConversation.AttachmentLayout = AttachmentLayoutTypes.Carousel;
replyToConversation.Attachments = new List<Attachment>();
Dictionary<string, string> cardContentList = new Dictionary<string, string>();
cardContentList.Add("Shirt", System.Web.HttpContext.Current.Server.MapPath(#"~\imgs\shirt.jpg"));
cardContentList.Add("shoes", System.Web.HttpContext.Current.Server.MapPath(#"~\imgs\shoes.jpg"));
foreach (KeyValuePair<string, string> cardContent in cardContentList)
{
List<CardImage> cardImages = new List<CardImage>();
cardImages.Add(new CardImage(url: cardContent.Value));
List<CardAction> cardButtons = new List<CardAction>();
CardAction plButton = new CardAction()
{
Value = "nike",
Type = "postBack",
Title = "shirt"
};
cardButtons.Add(plButton);
HeroCard plCard = new HeroCard()
{
Title = "nike",
Images = cardImages,
Buttons = cardButtons
};
Attachment plAttachment = plCard.ToAttachment();
replyToConversation.Attachments.Add(plAttachment);
}
await context.PostAsync(replyToConversation);
I tried to implement your case on my bot, it's working using images hosted on the web, but not with "local" images from your bot folder.
Using local images I got an Exception on my bot, not just "Select an option".
Code for this test:
[Serializable]
public class Dialog49665918 : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Type anything to get user question or 'debug' to get debug version");
context.Wait(this.MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var activity = await result as Activity;
var replyToConversation = activity.CreateReply("Select an option");
replyToConversation.AttachmentLayout = AttachmentLayoutTypes.Carousel;
replyToConversation.Attachments = new List<Attachment>();
var cardContentList = new Dictionary<string, string>();
if (!"debug".Equals(activity.Text, StringComparison.InvariantCultureIgnoreCase))
{
cardContentList.Add("Shirt", System.Web.HttpContext.Current.Server.MapPath(#"~\imgs\shirt.jpg"));
cardContentList.Add("shoes", System.Web.HttpContext.Current.Server.MapPath(#"~\imgs\shoes.jpg"));
}
else
{
cardContentList.Add("Shirt", "https://media.deparis.me/3257-tm_large_default/tshirt-homme-papa-cool-et-tatoue.jpg");
cardContentList.Add("shoes", "https://assets.adidas.com/images/w_840,h_840,f_auto,q_auto/d4dd2144b22b41bfbbd5a7ff01674bb3_9366/Superstar_Shoes_White_C77153_01_standard.jpg");
}
foreach (var cardContent in cardContentList)
{
var cardImages = new List<CardImage>
{
new CardImage(url: cardContent.Value)
};
var plButton = new CardAction()
{
Value = "nike",
Type = "postBack",
Title = "shirt"
};
var cardButtons = new List<CardAction>
{
plButton
};
var plCard = new HeroCard()
{
Title = "nike",
Images = cardImages,
Buttons = cardButtons
};
var plAttachment = plCard.ToAttachment();
replyToConversation.Attachments.Add(plAttachment);
}
await context.PostAsync(replyToConversation);
}
}
Proof ("debug" case, with internet images):
I have some code for the bot to send a message (string) on start up.
However, instead of sending text like you see in the code below. I am trying to figure out how you would send an Adaptive Card in this case. I have sent a Card from the RootDialog before, but not from the MessageController.cs. Any direction would be great here!
else if (message.Type == ActivityTypes.ConversationUpdate)
{
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
IConversationUpdateActivity iConversationUpdated = message as IConversationUpdateActivity;
if (iConversationUpdated != null)
{
ConnectorClient connector = new ConnectorClient(new System.Uri(message.ServiceUrl));
foreach (var member in iConversationUpdated.MembersAdded ?? System.Array.Empty<ChannelAccount>())
{
// if the bot is added, then
if (member.Id == iConversationUpdated.Recipient.Id)
{
var reply = ((Activity)iConversationUpdated).CreateReply($"WELCOME MESSAGE HERE");
await connector.Conversations.ReplyToActivityAsync(reply);
}
}
}
}
Thanks
Using the code snippet you provided you should be able to copy and paste this to replace it. More information about cards in bot framework can be found in this blog
else if (message.Type == ActivityTypes.ConversationUpdate)
{
IConversationUpdateActivity iConversationUpdated = message as IConversationUpdateActivity;
if (iConversationUpdated != null)
{
ConnectorClient connector = new ConnectorClient(new System.Uri(message.ServiceUrl));
foreach (var member in iConversationUpdated.MembersAdded ?? System.Array.Empty<ChannelAccount>())
{
// if the bot is added, then
if (member.Id == iConversationUpdated.Recipient.Id)
{
Activity replyToConversation = message.CreateReply("Should go to conversation");
replyToConversation.Attachments = new List<Attachment>();
AdaptiveCard card = new AdaptiveCard();
// Specify speech for the card.
card.Speak = "<s>Your meeting about \"Adaptive Card design session\"<break strength='weak'/> is starting at 12:30pm</s><s>Do you want to snooze <break strength='weak'/> or do you want to send a late notification to the attendees?</s>";
// Add text to the card.
card.Body.Add(new TextBlock()
{
Text = "Adaptive Card design session",
Size = TextSize.Large,
Weight = TextWeight.Bolder
});
// Add text to the card.
card.Body.Add(new TextBlock()
{
Text = "Conf Room 112/3377 (10)"
});
// Add text to the card.
card.Body.Add(new TextBlock()
{
Text = "12:30 PM - 1:30 PM"
});
// Add list of choices to the card.
card.Body.Add(new ChoiceSet()
{
Id = "snooze",
Style = ChoiceInputStyle.Compact,
Choices = new List<Choice>()
{
new Choice() { Title = "5 minutes", Value = "5", IsSelected = true },
new Choice() { Title = "15 minutes", Value = "15" },
new Choice() { Title = "30 minutes", Value = "30" }
}
});
// Add buttons to the card.
card.Actions.Add(new HttpAction()
{
Url = "http://foo.com",
Title = "Snooze"
});
card.Actions.Add(new HttpAction()
{
Url = "http://foo.com",
Title = "I'll be late"
});
card.Actions.Add(new HttpAction()
{
Url = "http://foo.com",
Title = "Dismiss"
});
// Create the attachment.
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
replyToConversation.Attachments.Add(attachment);
var reply = await connector.Conversations.SendToConversationAsync(replyToConversation);
}
}
}
}
I'm writing a c# console application that sends toast notifications in VS2017 on a Windows 10 machine. When I run my code and have only defined adaptive text content for my notification it runs correctly and displays the desired text. If I add actions, it no longer displays the adaptive text I defined ("title" and "content" below), nor does it have the option to perform said actions. If I try to add additional visuals such as a logo or picture, they do not appear but the adaptive text is unaffected.
string category = "Notifications";
string title = "New Test Notification!;
string content = "Testing push notifications!";
ToastContent toastContent = new ToastContent()
{
Visual = new ToastVisual()
{
BindingGeneric = new ToastBindingGeneric()
{
Children =
{
new AdaptiveText()
{
Text = title
},
new AdaptiveText()
{
Text = content
}
},
/*AppLogoOverride = new ToastGenericAppLogo()
{
Source = "https://unsplash.it/64?image=883",
HintCrop = ToastGenericAppLogoCrop.Circle
}*/
}
},
/*Actions = new ToastActionsCustom()
{
Buttons =
{
new ToastButton("check", "check")
{
ImageUri = "check.png"
},
new ToastButton("cancel", "cancel")
{
ImageUri = "cancel.png"
}
}
}*/
};
string toastXml = toastContent.GetContent();
XmlDocument doc = new XmlDocument();
doc.LoadXml(toastXml);
var toast = new ToastNotification(doc);
ToastNotificationManager.CreateToastNotifier(category).Show(toast);
Result when above code is run with or without the first block of commented code:
Result when code is run with the second block of commented code: