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.
Anteckning
Bot Framework JavaScript-, C#- och Python-SDK:erna fortsätter att stödjas, men Java SDK dras tillbaka med slutligt långsiktigt stöd som slutar i november 2023.
Befintliga robotar som skapats med Java SDK fortsätter att fungera.
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 ContentTypeegenskaperna , ContentUrloch 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:
Bots/AttachmentsBot.cs
{
reply = MessageFactory.Text("This is an inline attachment.");
Därefter tittar vi på typerna av bifogade filer. Först är en 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}",
};
}
Därefter, en uppladdad bifogad fil:
Bots/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:
Bots/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",
};
}
}
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:
Slutligen finns en bifogad internetbilaga i en URL:
bots/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'
getAttachments() metoden för Activity objektet innehåller en array med Attachment objekt som representerar mediebilagor och rika 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 ContentTypeegenskaperna , ContentUrloch 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
Varning
Det verkar som om exemplet du letar efter har flyttats! Var säker på att vi arbetar med att lösa detta.
Därefter tittar vi på typerna av bifogade filer. Först är en infogad bilaga:
AttachmentsBot.java
Varning
Det verkar som om exemplet du letar efter har flyttats! Var säker på att vi arbetar med att lösa detta.
Sedan en uppladdad bifogad fil:
AttachmentsBot.java
Varning
Det verkar som om exemplet du letar efter har flyttats! Var säker på att vi arbetar med att lösa detta.
Slutligen en bifogad internetbilaga:
AttachmentsBot.java
Varning
Det verkar som om exemplet du letar efter har flyttats! Var säker på att vi arbetar med att lösa detta.
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:
bots/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 bilaga:
bots/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}",
)
Därefter laddades bilagan upp:
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:
bots/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.
Skicka ett hero-kort
Förutom enkla bild- eller videobilagor kan du bifoga ett hero-kort, som gör att du kan kombinera bilder och knappar i ett objekt och skicka dem till användaren. Markdown stöds för de flesta textfält, men stödet kan variera beroende på kanal.
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.
* @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.
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"
),
],
)
Bearbeta händelser inom rika kort
Om du vill bearbeta händelser inom rich cards använder du kortåtgärdsobjekt för att ange vad som ska hända när användaren väljer en knapp eller trycker på en del av kortet. Varje kortåtgärd har en typ och värdeegenskap.
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.
Kortåtgärden messageBack har en mer generaliserad betydelse än de andra kortåtgärderna. Mer information om och andra kortåtgärdstyper finns i avsnittet Kortåtgärd i messageBack.
Typ
Beskrivning
Värde
call
Initierar ett telefonsamtal.
Målet för telefonsamtalet i det här formatet: tel:123123123123.
HämtaFil
Laddar ned en fil.
URL:en för filen som ska laddas ned.
imBack
Skickar ett meddelande till roboten och publicerar ett synligt svar i chatten.
Text på meddelandet som ska skickas.
skicka svar
Representerar ett textsvar som ska skickas via chattsystemet.
Ett valfritt programmatiskt värde som ska inkluderas i genererade meddelanden.
openUrl
Öppnar en URL i den inbyggda webbläsaren.
Url:en som ska öppnas.
playAudio
Spelar upp ljud.
URL:en för det ljud som ska spelas upp.
spelaVideo
Spelar upp en video.
URL:en för videon som ska spelas upp.
postBack
Skickar ett meddelande till roboten och kanske inte publicerar ett synligt svar i chatten.
Text på meddelandet som ska skickas.
visaBild
Visar en bild.
URL:en för den bild som ska visas.
logga in
Initierar en OAuth-inloggningsprocess.
URL:en för OAuth-flödet som ska initieras.
Hero-kort med olika händelsetyper
Följande kod visar exempel med olika rich card-händelser.
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;
}
createOAuthCard() {
return CardFactory.oauthCard(
'OAuth connection', // Replace with the name of your Azure AD connection
'Sign In',
'BotFramework OAuth Card'
);
}
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)
Skicka ett adaptivt kort
Du kan använda meddelandefabriken för att skapa ett meddelande som innehåller en bifogad fil (av alla slag), men ett adaptivt kort är en specifik typ av bifogad fil. Alla kanaler stöder inte adaptiva kort, och vissa kanaler kanske bara delvis stöder adaptiva kort. Om du till exempel skickar ett adaptivt kort på Facebook fungerar inte knapparna medan texter och bilder fungerar bra. Meddelandefabriken är en Bot Framework SDK-hjälpklass som används för att automatisera skapandesteg åt dig.
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.
Designern för adaptiva kort ger en omfattande, interaktiv designtidsupplevelse för redigering av adaptiva kort.
Kommentar
Du bör testa den här funktionen med de kanaler som roboten använder för att avgöra om dessa kanaler stöder adaptiva kort.
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.
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);
Skapa först svaret och definiera de bifogade filerna som en lista.
Varning
Det verkar som om exemplet du letar efter har flyttats! Var säker på att vi arbetar med att lösa detta.
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.
Varning
Det verkar som om exemplet du letar efter har flyttats! Var säker på att vi arbetar med att lösa detta.
När de bifogade filerna har lagts till kan du skicka svaret precis som andra.
Varning
Det verkar som om exemplet du letar efter har flyttats! Var säker på att vi arbetar med att lösa detta.
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.
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)
Kodexempel för bearbetning av adaptiva kortindata
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;
till MainDialog.cs och installera det senaste stabila NuGet-paketet av 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 MainDialog deklarationen, ändra:
// 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.textkopieras 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 JsonNodeoch 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:
till MainDialog.java.
I valideringskoden lade vi till logikflödet i kodkommentarna.
Det här PromptValidator uttrycket placeras i exemplet 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 Använda kort strax efter den stängda klammerparentesen för deklarationen 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