Meddelanden som utbyts mellan användare och robot kan innehålla mediebilagor, till exempel bilder, video, ljud och filer. Bot Framework SDK stöder uppgiften att skicka omfattande meddelanden till användaren. Information om begränsningar finns i kanalens dokumentation för att fastställa vilken typ av omfattande meddelanden en kanal (Facebook, Slack och så vidare) stöder.
Om du vill skicka användarinnehåll som en bild eller en video kan du lägga till en bifogad fil eller lista med bifogade filer i ett meddelande.
All källkod som visas i det här avsnittet baseras på exemplet Hantera bifogade filer .
Egenskapen Attachments
för Activity
objektet innehåller en matris med Attachment
objekt som representerar mediebilagor och rtF-kort som är kopplade till meddelandet. Om du vill lägga till en mediebilaga i ett meddelande skapar du ett Attachment
objekt för reply
aktiviteten och anger ContentType
egenskaperna , ContentUrl
och Name
.
Om du vill skapa svarsmeddelandet definierar du texten och konfigurerar sedan de bifogade filerna. Att tilldela bifogade filer till svaret är detsamma för varje typ av bifogad fil, men de olika bilagorna konfigureras och definieras på olika sätt, enligt följande kodfragment. Koden nedan konfigurerar svaret för en infogad bifogad fil:
Robotar/AttachmentsBot.cs
{
reply = MessageFactory.Text("This is an inline attachment.");
Därefter tittar vi på typerna av bifogade filer. Först är en infogad bifogad fil:
Robotar/AttachmentsBot.cs
{
var imagePath = Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png");
var imageData = Convert.ToBase64String(File.ReadAllBytes(imagePath));
return new Attachment
{
Name = @"Resources\architecture-resize.png",
ContentType = "image/png",
ContentUrl = $"data:image/png;base64,{imageData}",
};
}
Sedan en uppladdad bifogad fil:
Robotar/AttachmentsBot.cs
{
if (string.IsNullOrWhiteSpace(serviceUrl))
{
throw new ArgumentNullException(nameof(serviceUrl));
}
if (string.IsNullOrWhiteSpace(conversationId))
{
throw new ArgumentNullException(nameof(conversationId));
}
var imagePath = Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png");
var connector = turnContext.TurnState.Get<IConnectorClient>() as ConnectorClient;
var attachments = new Attachments(connector);
var response = await attachments.Client.Conversations.UploadAttachmentAsync(
conversationId,
new AttachmentData
{
Name = @"Resources\architecture-resize.png",
OriginalBase64 = File.ReadAllBytes(imagePath),
Type = "image/png",
},
cancellationToken);
var attachmentUri = attachments.GetAttachmentUri(response.Id);
return new Attachment
{
Name = @"Resources\architecture-resize.png",
ContentType = "image/png",
ContentUrl = attachmentUri,
};
}
Slutligen en bifogad internetbilaga:
Robotar/AttachmentsBot.cs
{
// ContentUrl must be HTTPS.
return new Attachment
{
Name = @"Resources\architecture-resize.png",
ContentType = "image/png",
ContentUrl = "https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png",
};
}
}
Följande källkod kommer från exemplet Hantera bifogade filer .
Om du vill använda bifogade filer inkluderar du följande bibliotek i roboten:
robotar/attachmentsBot.js
const { ActivityHandler, ActionTypes, ActivityTypes, CardFactory } = require('botbuilder');
Om du vill skapa svarsmeddelandet definierar du texten och konfigurerar sedan de bifogade filerna. Att tilldela bifogade filer till svaret är detsamma för varje typ av bifogad fil, men de olika bilagorna konfigureras och definieras på olika sätt, enligt följande kodfragment. Koden nedan konfigurerar svaret för en infogad bifogad fil:
robotar/attachmentsBot.js
*/
const firstChar = turnContext.activity.text[0];
if (firstChar === '1') {
Om du vill skicka ett enda innehåll till användaren, till exempel en bild eller en video, kan du skicka media på några olika sätt. Först som en infogad bifogad fil:
robotar/attachmentsBot.js
* Returns an inline attachment.
*/
getInlineAttachment() {
const imageData = fs.readFileSync(path.join(__dirname, '../resources/architecture-resize.png'));
const base64Image = Buffer.from(imageData).toString('base64');
return {
name: 'architecture-resize.png',
contentType: 'image/png',
contentUrl: `data:image/png;base64,${ base64Image }`
Sedan en uppladdad bifogad fil:
robotar/attachmentsBot.js
* @param {Object} turnContext
*/
async getUploadedAttachment(turnContext) {
const imageData = fs.readFileSync(path.join(__dirname, '../resources/architecture-resize.png'));
const connectorFactory = turnContext.turnState.get(turnContext.adapter.ConnectorFactoryKey);
const connector = await connectorFactory.create(turnContext.activity.serviceUrl);
const conversationId = turnContext.activity.conversation.id;
const response = await connector.conversations.uploadAttachment(conversationId, {
name: 'architecture-resize.png',
originalBase64: imageData,
type: 'image/png'
});
// Retrieve baseUri from ConnectorClient for... something.
const baseUri = connector.baseUri;
const attachmentUri = baseUri + (baseUri.endsWith('/') ? '' : '/') + `v3/attachments/${ encodeURI(response.id) }/views/original`;
return {
name: 'architecture-resize.png',
contentType: 'image/png',
Slutligen finns en bifogad internetbilaga i en URL:
robotar/attachmentsBot.js
* Returns an attachment to be sent to the user from a HTTPS URL.
*/
getInternetAttachment() {
// NOTE: The contentUrl must be HTTPS.
return {
name: 'architecture-resize.png',
contentType: 'image/png',
contentUrl: 'https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png'
Källkoden som visas i det här avsnittet baseras på exemplet Hantera bifogade filer .
- getAttachments()
metoden för Activity
objektet innehåller en matris med Attachment
objekt som representerar mediebilagor och rtF-kort som är kopplade till meddelandet. Om du vill lägga till en mediebilaga i ett meddelande skapar du ett Attachment
objekt för reply
aktiviteten och anger ContentType
egenskaperna , ContentUrl
och Name
.
Om du vill skapa svarsmeddelandet definierar du texten och konfigurerar sedan de bifogade filerna. Att tilldela bifogade filer till svaret är detsamma för varje typ av bifogad fil, men de olika bilagorna konfigureras och definieras på olika sätt, enligt följande kodfragment. Koden nedan konfigurerar svaret för en infogad bifogad fil:
AttachmentsBot.java
result = getInlineAttachment()
.thenApply(attachment -> {
Activity reply = MessageFactory.text("This is an inline attachment.");
reply.setAttachment(attachment);
return reply;
});
Därefter tittar vi på typerna av bifogade filer. Först är en infogad bifogad fil:
AttachmentsBot.java
// Creates an inline attachment sent from the bot to the user using a base64 string.
// Using a base64 string to send an attachment will not work on all channels.
// Additionally, some channels will only allow certain file types to be sent this way.
// For example a .png file may work but a .pdf file may not on some channels.
// Please consult the channel documentation for specifics.
private CompletableFuture<Attachment> getInlineAttachment() {
return getEncodedFileData("architecture-resize.png")
.thenApply(encodedFileData -> {
Attachment attachment = new Attachment();
attachment.setName("architecture-resize.png");
attachment.setContentType("image/png");
attachment.setContentUrl("data:image/png;base64," + encodedFileData);
return attachment;
});
}
Sedan en uppladdad bifogad fil:
AttachmentsBot.java
private CompletableFuture<Attachment> getUploadedAttachment(TurnContext turnContext, String serviceUrl, String conversationId) {
if (StringUtils.isEmpty(serviceUrl)) {
return Async.completeExceptionally(new IllegalArgumentException("serviceUrl"));
}
if (StringUtils.isEmpty(conversationId)) {
return Async.completeExceptionally(new IllegalArgumentException("conversationId"));
}
ConnectorClient connector = turnContext.getTurnState()
.get(BotFrameworkAdapter.CONNECTOR_CLIENT_KEY);
Attachments attachments = connector.getAttachments();
return getFileData("architecture-resize.png")
.thenCompose(fileData -> {
AttachmentData attachmentData = new AttachmentData();
attachmentData.setName("architecture-resize.png");
attachmentData.setType("image/png");
attachmentData.setOriginalBase64(fileData);
return connector.getConversations().uploadAttachment(conversationId, attachmentData)
.thenApply(response -> {
String attachmentUri = attachments.getAttachmentUri(response.getId());
Attachment attachment = new Attachment();
attachment.setName("architecture-resize.png");
attachment.setContentType("image/png");
attachment.setContentUrl(attachmentUri);
return attachment;
});
});
}
Slutligen en bifogad internetbilaga:
AttachmentsBot.java
// Creates an Attachment to be sent from the bot to the user from a HTTP URL.
private static Attachment getInternetAttachment() {
// ContentUrl must be HTTPS.
Attachment attachment = new Attachment();
attachment.setName("architecture-resize.png");
attachment.setContentType("image/png");
attachment.setContentUrl("https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png");
return attachment;
}
Följande källkod kommer från exemplet Hantera bifogade filer .
Om du vill skapa svarsmeddelandet definierar du texten och konfigurerar sedan de bifogade filerna. Att tilldela bifogade filer till svaret är detsamma för varje typ av bifogad fil, men de olika bilagorna konfigureras och definieras på olika sätt, enligt följande kodfragment.
Koden nedan konfigurerar svaret för en infogad bifogad fil:
robotar/attachments_bot.py
reply.text = "This is an inline attachment."
reply.attachments = [self._get_inline_attachment()]
Om du vill skicka ett enda innehåll till användaren, till exempel en bild eller en video, kan du skicka media på några olika sätt. Först som en infogad bifogad fil:
robotar/attachments_bot.py
def _get_inline_attachment(self) -> Attachment:
"""
Creates an inline attachment sent from the bot to the user using a base64 string.
Using a base64 string to send an attachment will not work on all channels.
Additionally, some channels will only allow certain file types to be sent this way.
For example a .png file may work but a .pdf file may not on some channels.
Please consult the channel documentation for specifics.
:return: Attachment
"""
file_path = os.path.join(os.getcwd(), "resources/architecture-resize.png")
with open(file_path, "rb") as in_file:
base64_image = base64.b64encode(in_file.read()).decode()
return Attachment(
name="architecture-resize.png",
content_type="image/png",
content_url=f"data:image/png;base64,{base64_image}",
)
Sedan en uppladdad bifogad fil:
robotar/attachments_bot.py
async def _get_upload_attachment(self, turn_context: TurnContext) -> Attachment:
"""
Creates an "Attachment" to be sent from the bot to the user from an uploaded file.
:param turn_context:
:return: Attachment
"""
with open(
os.path.join(os.getcwd(), "resources/architecture-resize.png"), "rb"
) as in_file:
image_data = in_file.read()
connector = await turn_context.adapter.create_connector_client(
turn_context.activity.service_url
)
conversation_id = turn_context.activity.conversation.id
response = await connector.conversations.upload_attachment(
conversation_id,
AttachmentData(
name="architecture-resize.png",
original_base64=image_data,
type="image/png",
),
)
base_uri: str = connector.config.base_url
attachment_uri = (
base_uri
+ ("" if base_uri.endswith("/") else "/")
+ f"v3/attachments/{response.id}/views/original"
)
return Attachment(
name="architecture-resize.png",
content_type="image/png",
content_url=attachment_uri,
)
Slutligen finns en bifogad internetbilaga i en URL:
robotar/attachments_bot.py
def _get_internet_attachment(self) -> Attachment:
"""
Creates an Attachment to be sent from the bot to the user from a HTTP URL.
:return: Attachment
"""
return Attachment(
name="architecture-resize.png",
content_type="image/png",
content_url="https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png",
)
Om en bifogad fil är en bild, ett ljud eller en video kommunicerar Anslutningstjänsten bifogade data till kanalen på ett sätt som gör att kanalen kan återge den bifogade filen i konversationen. Om den bifogade filen är en fil återges fil-URL:en som en hyperlänk i konversationen.
Om du vill skapa ett meddelande med ett hero-kort och en knapp kan du koppla ett HeroCard
objekt till ett meddelande.
Följande källkod kommer från exemplet Hantera bifogade filer .
Robotar/AttachmentsBot.cs
private static async Task DisplayOptionsAsync(ITurnContext turnContext, CancellationToken cancellationToken)
{
// Create a HeroCard with options for the user to interact with the bot.
var card = new HeroCard
{
Text = "You can upload an image or select one of the following choices",
Buttons = new List<CardAction>
{
// Note that some channels require different values to be used in order to get buttons to display text.
// In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
// need to provide a value for other parameters like 'text' or 'displayText'.
new CardAction(ActionTypes.ImBack, title: "1. Inline Attachment", value: "1"),
new CardAction(ActionTypes.ImBack, title: "2. Internet Attachment", value: "2"),
new CardAction(ActionTypes.ImBack, title: "3. Uploaded Attachment", value: "3"),
},
};
var reply = MessageFactory.Attachment(card.ToAttachment());
await turnContext.SendActivityAsync(reply, cancellationToken);
Om du vill skapa ett meddelande med ett hero-kort och en knapp kan du koppla ett HeroCard
objekt till ett meddelande.
Följande källkod kommer från exemplet Hantera bifogade filer .
robotar/attachmentsBot.js
* @param {Object} turnContext
*/
async displayOptions(turnContext) {
const reply = { type: ActivityTypes.Message };
// Note that some channels require different values to be used in order to get buttons to display text.
// In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
// need to provide a value for other parameters like 'text' or 'displayText'.
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.' });
reply.attachments = [card];
Om du vill skapa ett meddelande med ett hero-kort och en knapp kan du koppla ett HeroCard
objekt till ett meddelande.
Följande källkod kommer från exemplet Hantera bifogade filer .
AttachmentsBot.java
private static CompletableFuture<Void> displayOptions(TurnContext turnContext) {
// Create a HeroCard with options for the user to interact with the bot.
HeroCard card = new HeroCard();
card.setText("You can upload an image or select one of the following choices");
// Note that some channels require different values to be used in order to get buttons to display text.
// In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
// need to provide a value for other parameters like 'text' or 'displayText'.
card.setButtons(
new CardAction(ActionTypes.IM_BACK, "1. Inline Attachment", "1"),
new CardAction(ActionTypes.IM_BACK, "2. Internet Attachment", "2"),
new CardAction(ActionTypes.IM_BACK, "3. Uploaded Attachment", "3")
);
Activity reply = MessageFactory.attachment(card.toAttachment());
return turnContext.sendActivity(reply).thenApply(resourceResponse -> null);
}
Om du vill skapa ett meddelande med ett hero-kort och en knapp kan du koppla ett HeroCard
objekt till ett meddelande.
Följande källkod kommer från exemplet Hantera bifogade filer .
robotar/attachments_bot.py
async def _display_options(self, turn_context: TurnContext):
"""
Create a HeroCard with options for the user to interact with the bot.
:param turn_context:
:return:
"""
# Note that some channels require different values to be used in order to get buttons to display text.
# In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
# need to provide a value for other parameters like 'text' or 'displayText'.
card = HeroCard(
text="You can upload an image or select one of the following choices",
buttons=[
CardAction(
type=ActionTypes.im_back, title="1. Inline Attachment", value="1"
),
CardAction(
type=ActionTypes.im_back, title="2. Internet Attachment", value="2"
),
CardAction(
type=ActionTypes.im_back, title="3. Uploaded Attachment", value="3"
),
],
)
Om du vill fungera korrekt tilldelar du en åtgärdstyp till varje klickbart objekt på ett hero-kort. Den här tabellen visar och beskriver tillgängliga åtgärdstyper och vad som ska finnas i den associerade värdeegenskapen.
Följande kod visar exempel med olika rich card-händelser.
Exempel på alla tillgängliga kort finns i exemplet Använda kort .
Cards.cs
public static HeroCard GetHeroCard()
{
var heroCard = new HeroCard
{
Title = "BotFramework Hero Card",
Subtitle = "Microsoft Bot Framework",
Text = "Build and connect intelligent bots to interact with your users naturally wherever they are," +
" from text/sms to Skype, Slack, Office 365 mail and other popular services.",
Images = new List<CardImage> { new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg") },
Buttons = new List<CardAction> { new CardAction(ActionTypes.OpenUrl, "Get Started", value: "https://docs.microsoft.com/bot-framework") },
};
return heroCard;
}
Cards.cs
public static SigninCard GetSigninCard()
{
var signinCard = new SigninCard
{
Text = "BotFramework Sign-in Card",
Buttons = new List<CardAction> { new CardAction(ActionTypes.Signin, "Sign-in", value: "https://login.microsoftonline.com/") },
};
return signinCard;
}
Exempel på alla tillgängliga kort finns i exemplet Använda kort .
dialogrutor/mainDialog.js
createHeroCard() {
return CardFactory.heroCard(
'BotFramework Hero Card',
CardFactory.images(['https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg']),
CardFactory.actions([
{
type: 'openUrl',
title: 'Get started',
value: 'https://docs.microsoft.com/en-us/azure/bot-service/'
}
])
);
}
dialogrutor/mainDialog.js
createOAuthCard() {
return CardFactory.oauthCard(
'OAuth connection', // Replace with the name of your Azure AD connection
'Sign In',
'BotFramework OAuth Card'
);
}
Exempel på alla tillgängliga kort finns i exemplet Använda kort .
Cards.java
public static HeroCard getHeroCard() {
HeroCard heroCard = new HeroCard();
heroCard.setTitle("BotFramework Hero Card");
heroCard.setSubtitle("Microsoft Bot Framework");
heroCard.setText("Build and connect intelligent bots to interact with your users naturally wherever they are," +
" from text/sms to Skype, Slack, Office 365 mail and other popular services.");
heroCard.setImages(new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg"));
heroCard.setButtons(new CardAction(ActionTypes.OPEN_URL, "Get Started", "https://docs.microsoft.com/bot-framework"));
return heroCard;
}
Cards.java
public static SigninCard getSigninCard() {
SigninCard signinCard = new SigninCard();
signinCard.setText("BotFramework Sign-in Card");
signinCard.setButtons(new CardAction(ActionTypes.SIGNIN, "Sign-in", "https://login.microsoftonline.com/"));
return signinCard;
}
Exempel på alla tillgängliga kort finns i exemplet Använda kort .
dialogrutor/main_dialog.py
def create_hero_card(self) -> Attachment:
card = HeroCard(
title="",
images=[
CardImage(
url="https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg"
)
],
buttons=[
CardAction(
type=ActionTypes.open_url,
title="Get Started",
value="https://docs.microsoft.com/en-us/azure/bot-service/",
)
],
)
return CardFactory.hero_card(card)
dialogrutor/main_dialog.py
def create_oauth_card(self) -> Attachment:
card = OAuthCard(
text="BotFramework OAuth Card",
connection_name="OAuth connection", # Replace it with the name of your Azure AD connection.
buttons=[
CardAction(
type=ActionTypes.signin,
title="Sign in",
value="https://example.org/signin",
)
],
)
return CardFactory.oauth_card(card)
Adaptiva kort är ett öppet kortutbytesformat som gör det möjligt för utvecklare att utbyta UI-innehåll på ett gemensamt och konsekvent sätt. Alla kanaler stöder dock inte adaptiva kort.
Om du vill använda adaptiva kort måste du lägga AdaptiveCards
till NuGet-paketet.
Följande källkod kommer från exemplet Använda kort .
Cards.cs
Det här exemplet läser JSON för adaptivt kort från en fil och lägger till den som en bifogad fil.
public static Attachment CreateAdaptiveCardAttachment()
{
// combine path for cross platform support
var paths = new[] { ".", "Resources", "adaptiveCard.json" };
var adaptiveCardJson = File.ReadAllText(Path.Combine(paths));
var adaptiveCardAttachment = new Attachment()
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = JsonConvert.DeserializeObject(adaptiveCardJson),
};
return adaptiveCardAttachment;
}
Om du vill använda adaptiva kort måste du lägga adaptivecards
till npm-paketet.
Följande källkod kommer från exemplet Använda kort .
dialogrutor/mainDialog.js
I det här exemplet läss JSON för adaptivt kort från en fil och en meddelandeaktivitet skapas med kortet bifogat.
const AdaptiveCard = require('../resources/adaptiveCard.json');
createAdaptiveCard() {
return CardFactory.adaptiveCard(AdaptiveCard);
}
Följande källkod kommer från exemplet Använda kort .
Cards.java
Det här exemplet läser JSON för adaptivt kort från en fil och lägger till den som en bifogad fil.
public static Attachment createAdaptiveCardAttachment() {
Attachment adaptiveCardAttachment = new Attachment();
try (
InputStream inputStream = adaptiveCardAttachment.getClass().getClassLoader()
.getResourceAsStream("adaptiveCard.json")
) {
String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
adaptiveCardAttachment.setContentType("application/vnd.microsoft.card.adaptive");
adaptiveCardAttachment.setContent(new ObjectMapper().readValue(result, ObjectNode.class));
return adaptiveCardAttachment;
} catch (Throwable t) {
throw new CompletionException(t);
}
}
Följande källkod kommer från exemplet Använda kort .
robotar/main_dialog.py
I det här exemplet läss JSON för adaptivt kort från en fil och en meddelandeaktivitet skapas med kortet bifogat.
from .resources.adaptive_card_example import ADAPTIVE_CARD_CONTENT
def create_adaptive_card(self) -> Attachment:
return CardFactory.adaptive_card(ADAPTIVE_CARD_CONTENT)
Meddelanden kan också innehålla flera bifogade filer i en karuselllayout, vilket placerar bilagorna sida vid sida och gör att användaren kan rulla över.
Följande källkod kommer från exemplet Använda kort .
Dialogrutor/MainDialog.cs
Skapa först svaret och definiera de bifogade filerna som en lista.
// Cards are sent as Attachments in the Bot Framework.
// So we need to create a list of attachments for the reply activity.
var attachments = new List<Attachment>();
// Reply to the activity we received with an activity.
var reply = MessageFactory.Attachment(attachments);
Lägg sedan till de bifogade filerna och ange layouttypen till karusell.
Här lägger vi till dem en i taget, men du kan ändra listan för att lägga till korten hur du vill.
// Display a carousel of all the rich card types.
reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment());
reply.Attachments.Add(Cards.GetAnimationCard().ToAttachment());
reply.Attachments.Add(Cards.GetAudioCard().ToAttachment());
reply.Attachments.Add(Cards.GetHeroCard().ToAttachment());
reply.Attachments.Add(Cards.GetOAuthCard().ToAttachment());
reply.Attachments.Add(Cards.GetReceiptCard().ToAttachment());
reply.Attachments.Add(Cards.GetSigninCard().ToAttachment());
reply.Attachments.Add(Cards.GetThumbnailCard().ToAttachment());
reply.Attachments.Add(Cards.GetVideoCard().ToAttachment());
När de bifogade filerna har lagts till kan du skicka svaret precis som andra.
// Send the card(s) to the user as an attachment to the activity
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
Följande källkod kommer från exemplet Använda kort .
dialogrutor/mainDialog.js
Lägg till bifogade filer och ange layouttypen till karusell.
När de bifogade filerna har lagts till kan du skicka svaret precis som andra.
await stepContext.context.sendActivity({
attachments: [
this.createAdaptiveCard(),
this.createAnimationCard(),
this.createAudioCard(),
this.createHeroCard(),
this.createOAuthCard(),
this.createReceiptCard(),
this.createSignInCard(),
this.createThumbnailCard(),
this.createVideoCard()
],
attachmentLayout: AttachmentLayoutTypes.Carousel
});
Följande källkod kommer från exemplet Använda kort .
MainDialog.java
Skapa först svaret och definiera de bifogade filerna som en lista.
// Cards are sent as Attachments in the Bot Framework.
// So we need to create a list of attachments for the reply activity.
List<Attachment> attachments = new ArrayList<>();
// Reply to the activity we received with an activity.
Activity reply = MessageFactory.attachment(attachments);
Lägg sedan till de bifogade filerna och ange layouttypen till karusell.
Här lägger vi till dem en i taget, men du kan ändra listan för att lägga till korten hur du vill.
// Display a carousel of all the rich card types.
reply.setAttachmentLayout(AttachmentLayoutTypes.CAROUSEL);
reply.getAttachments().add(Cards.createAdaptiveCardAttachment());
reply.getAttachments().add(Cards.getAnimationCard().toAttachment());
reply.getAttachments().add(Cards.getAudioCard().toAttachment());
reply.getAttachments().add(Cards.getHeroCard().toAttachment());
reply.getAttachments().add(Cards.getOAuthCard().toAttachment());
reply.getAttachments().add(Cards.getReceiptCard().toAttachment());
reply.getAttachments().add(Cards.getSigninCard().toAttachment());
reply.getAttachments().add(Cards.getThumbnailCard().toAttachment());
reply.getAttachments().add(Cards.getVideoCard().toAttachment());
När de bifogade filerna har lagts till kan du skicka svaret precis som andra.
// Send the card(s) to the user as an attachment to the activity
return stepContext.getContext().sendActivity(reply)
Källkoden som visas här baseras på exemplet Använda kort .
dialogrutor/main_dialog.py
Skapa först svaret och definiera de bifogade filerna som en lista.
reply = MessageFactory.list([])
Lägg sedan till de bifogade filerna och ange layouttypen till karusell.
Här lägger vi till dem en i taget, men du kan ändra listan för att lägga till korten hur du vill.
reply.attachment_layout = AttachmentLayoutTypes.carousel
reply.attachments.append(self.create_adaptive_card())
reply.attachments.append(self.create_animation_card())
reply.attachments.append(self.create_audio_card())
reply.attachments.append(self.create_hero_card())
reply.attachments.append(self.create_oauth_card())
reply.attachments.append(self.create_receipt_card())
reply.attachments.append(self.create_signin_card())
reply.attachments.append(self.create_thumbnail_card())
reply.attachments.append(self.create_video_card())
När de bifogade filerna har lagts till kan du skicka svaret precis som andra.
# Send the card(s) to the user as an attachment to the activity
await step_context.context.send_activity(reply)
Följande exempel visar ett sätt att använda adaptiva kortindata i en robotdialogruta.
Det utökar hero-kortexemplet genom att validera indata som tas emot i textfältet från den svarande klienten.
Du måste först lägga till textinmatnings- och knappfunktionen i det befintliga adaptiva kortet genom att lägga till följande kod precis innan den sista hakparentesen för adaptiveCard.json, som finns i resursmappen:
ID:t för textinmatningsfältet är inställt på "text". När användaren väljer OK kommer meddelandet som det adaptiva kortet genererar att ha en värdeegenskap som har en egenskap med namnet text
som innehåller den information som användaren angav i kortets textinmatningsfält.
Vår validerare använder Newtonsoft.json för att först konvertera detta till en JObject
, och sedan skapa en trimmad textsträng för jämförelse. Lägg till:
using System;
using System.Linq;
using Newtonsoft.Json.Linq;
för att MainDialog.cs och installera det senaste stabila NuGet-paketet newtonsoft.Json.
I valideringskoden lade vi till logikflödet i kodkommentarna.
Den här ChoiceValidator
metoden placeras i exemplet Using cards (Använda kort ) strax efter den stängda klammerparentesen för deklaration av MainDialog:
private async Task ChoiceValidator(
PromptValidatorContext promptContext,
CancellationToken cancellationToken)
{
// Retrieves Adaptive Card comment text as JObject.
// looks for JObject field "text" and converts that input into a trimmed text string.
var jobject = promptContext.Context.Activity.Value as JObject;
var jtoken = jobject?["text"];
var text = jtoken?.Value().Trim();
// Logic: 1. if succeeded = true, just return promptContext
// 2. if false, see if JObject contained Adaptive Card input.
// No = (bad input) return promptContext
// Yes = update Value field with JObject text string, return "true".
if (!promptContext.Recognized.Succeeded && text != null)
{
var choice = promptContext.Options.Choices.FirstOrDefault(
c => c.Value.Equals(text, StringComparison.InvariantCultureIgnoreCase));
if (choice != null)
{
promptContext.Recognized.Value = new FoundChoice
{
Value = choice.Value,
};
return true;
}
}
return promptContext.Recognized.Succeeded;
}
Nu ovan i deklarationsändringen MainDialog
:
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
till:
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt), ChoiceValidator));
Detta anropar validatorn för att söka efter adaptiva kortindata varje gång en ny alternativprompt skapas.
Öppna mainDialog.js och leta upp körningsmetoden async run(turnContext, accessor)
Den här metoden hanterar inkommande aktivitet.
Precis efter anropet dialogSet.add(this);
lägger du till följande:
// The following check looks for a non-existent text input
// plus Adaptive Card input in _activity.value.text
// If both conditions exist, the Activity Card text
// is copied into the text input field.
if(turnContext._activity.text == null
&& turnContext._activity.value.text != null) {
this.logger.log('replacing null text with Activity Card text input');
turnContext._activity.text = turnContext._activity.value.text;
}
Om den här kontrollen hittar en obefintlig textinmatning från klienten ser den ut att se om det finns indata från ett adaptivt kort.
Om det finns en adaptiv kortinmatning på _activity.value.text
kopieras den till det normala textinmatningsfältet.
Vår validerare använder serialiseringshjälpen från com.microsoft.bot.schema för att först konvertera detta till en JsonNode
och sedan skapa en trimmad textsträng för jämförelse. Vi behöver också några andra importer för att slutföra detta, så lägg till:
import com.fasterxml.jackson.databind.JsonNode;
import com.microsoft.bot.dialogs.prompts.PromptValidator;
import com.microsoft.bot.schema.Serialization;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
till MainDialog.java.
I valideringskoden lade vi till logikflödet i kodkommentarna.
Det här PromptValidator
uttrycket placeras i exemplet Using cards (Använda kort ) strax efter den stängda klammerparentesen för deklaration av MainDialog:
PromptValidator<FoundChoice> validator = (promptContext) -> {
// Retrieves Adaptive Card comment text as JObject.
// looks for JObject field "text" and converts that input into a trimmed text
// string.
JsonNode jsonNode = Serialization.getAs(promptContext.getContext().getActivity().getValue(), JsonNode.class);
JsonNode textNode = jsonNode != null ? jsonNode.get("text") : null;
String text = textNode != null ? textNode.textValue() : "";
// Logic: 1. if succeeded = true, just return promptContext
// 2. if false, see if JObject contained Adaptive Card input.
// No = (bad input) return promptContext
// Yes = update Value field with JObject text string, return "true".
if (!promptContext.getRecognized().getSucceeded() && text != null) {
Optional<Choice> choice = promptContext.getOptions()
.getChoices()
.stream()
.filter(c -> StringUtils.compareIgnoreCase(c.getValue(), text) == 0)
.findFirst();
if (choice.isPresent()) {
promptContext.getRecognized().setValue(new FoundChoice() {
{
setValue(choice.get().getValue());
}
});
return CompletableFuture.completedFuture(true);
}
}
return CompletableFuture.completedFuture(promptContext.getRecognized().getSucceeded());
};
Nu ovan i deklarationsändringen MainDialog
:
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt"));
till:
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt", validator, null));
Detta anropar validatorn för att söka efter adaptiva kortindata varje gång en ny alternativprompt skapas.
Skapa och skicka en aktivitet med föreslagna åtgärder till användaren.
Den här choice_validator
metoden placeras i exemplet Using cards (Använd kort ) strax efter den stängda klammerparentesen för deklaration av MainDialog
:
@staticmethod
async def choice_validator(prompt_context: PromptValidatorContext) -> bool:
if prompt_context.context.activity.value:
text = prompt_context.context.activity.value["text"].lower()
if not prompt_context.recognized.succeeded and text:
matching_choices = [choice for choice in prompt_context.options.choices if choice.value.lower() == text]
if matching_choices:
choice = matching_choices[0]
prompt_context.recognized.value = FoundChoice(
value=choice.value,
index=0,
score=1.0
)
return True
return prompt_context.recognized.succeeded
Nu ovan i deklarationsändringen MainDialog
:
self.add_dialog(ChoicePrompt(CARD_PROMPT))
till:
self.add_dialog(ChoicePrompt(CARD_PROMPT, MainDialog.choice_validator))
Detta anropar validatorn för att söka efter adaptiva kortindata varje gång en ny alternativprompt skapas.