Inviare allegati multimediali con Bot Framework SDK
Articolo
SI APPLICA A: SDK v4
I messaggi scambiati tra utente e bot possono contenere allegati multimediali come immagini, video, audio e file. Bot Framework SDK supporta l'attività di invio di messaggi avanzati all'utente. Per determinare il tipo di messaggi avanzati supportati da un canale (Facebook, Slack e così via), consultare la documentazione del canale per informazioni sulle limitazioni.
Nota
Gli SDK JavaScript, C# e Python di Bot Framework continueranno a essere supportati, ma Java SDK verrà ritirato con il supporto finale a lungo termine che termina a novembre 2023.
I bot esistenti creati con Java SDK continueranno a funzionare.
Tutto il codice sorgente illustrato in questa sezione si basa sull'esempio Di gestione degli allegati.
La proprietà Attachments dell'oggetto Activity contiene una matrice degli oggetti Attachment che rappresentano gli allegati multimediali e le schede avanzate allegate al messaggio. Per aggiungere un allegato multimediale a un messaggio, creare un oggetto Attachment per l'attività reply e impostare le proprietà ContentType, ContentUrl, e Name.
Per creare il messaggio di risposta, definire il testo e quindi configurare gli allegati. La procedura di assegnazione degli allegati alla risposta è la stessa per ogni tipo di allegato, ma i vari allegati vengono configurati e definiti in modo diverso, come si nota nei frammenti seguenti. Il codice seguente consente di configurare la risposta per un allegato inline:
Bots/AttachmentsBot.cs
{
reply = MessageFactory.Text("This is an inline attachment.");
Verranno ora esaminati i tipi di allegati. Il primo è un allegato inline:
Bots/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}",
};
}
Quindi, come allegato caricato:
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,
};
}
Ed infine, ecco un allegato Internet:
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",
};
}
}
Il codice sorgente seguente proviene dall'esempio Di gestione degli allegati.
Per usare gli allegati, includere le librerie seguenti nel bot:
Per creare il messaggio di risposta, definire il testo e quindi configurare gli allegati. La procedura di assegnazione degli allegati alla risposta è la stessa per ogni tipo di allegato, ma i vari allegati vengono configurati e definiti in modo diverso, come si nota nei frammenti seguenti. Il codice seguente consente di configurare la risposta per un allegato inline:
bots/attachmentsBot.js
*/
const firstChar = turnContext.activity.text[0];
if (firstChar === '1') {
Per inviare all'utente una singola parte di contenuto, ad esempio un'immagine o un video, è possibile inviare file multimediali in diversi modi. In primo luogo, come allegato inline:
Infine, come allegato Internet contenuto in un 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'
Il codice sorgente illustrato in questa sezione si basa sull'esempio Gestione degli allegati.
Il getAttachments() metodo dell'oggetto Activity contiene una matrice di Attachment oggetti che rappresentano gli allegati multimediali e le schede avanzate associate al messaggio. Per aggiungere un allegato multimediale a un messaggio, creare un oggetto Attachment per l'attività reply e impostare le proprietà ContentType, ContentUrl, e Name.
Per creare il messaggio di risposta, definire il testo e quindi configurare gli allegati. La procedura di assegnazione degli allegati alla risposta è la stessa per ogni tipo di allegato, ma i vari allegati vengono configurati e definiti in modo diverso, come si nota nei frammenti seguenti. Il codice seguente consente di configurare la risposta per un allegato inline:
AttachmentsBot.java
result = getInlineAttachment()
.thenApply(attachment -> {
Activity reply = MessageFactory.text("This is an inline attachment.");
reply.setAttachment(attachment);
return reply;
});
Verranno ora esaminati i tipi di allegati. Il primo è un allegato inline:
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;
});
}
// 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;
}
Il codice sorgente seguente proviene dall'esempio Di gestione degli allegati.
Per creare il messaggio di risposta, definire il testo e quindi configurare gli allegati. La procedura di assegnazione degli allegati alla risposta è la stessa per ogni tipo di allegato, ma i vari allegati vengono configurati e definiti in modo diverso, come si nota nei frammenti seguenti.
Il codice seguente consente di configurare la risposta per un allegato inline:
bots/attachments_bot.py
reply.text = "This is an inline attachment."
reply.attachments = [self._get_inline_attachment()]
Per inviare all'utente una singola parte di contenuto, ad esempio un'immagine o un video, è possibile inviare file multimediali in diversi modi. In primo luogo, come allegato inline:
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}",
)
Quindi, come allegato caricato:
bots/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,
)
Infine, come allegato Internet contenuto in un 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",
)
Se l'allegato è un'immagine, un audio o un video, il servizio del connettore comunicherà i dati allegati al canale in modo da permettere al canale di eseguire il rendering di tale allegato all'interno della conversazione. Se l'allegato è un file, l'URL del file verrà reso come collegamento ipertestuale all'interno della conversazione.
Inviare una scheda banner
Oltre alla semplice immagine o agli allegati video, è possibile allegare una scheda banner, che consente di combinare le immagini e i pulsanti in un oggetto e li inviano all'utente. La sintassi markdown è supportata per la maggior parte dei campi di testo, ma il supporto può variare a seconda del canale.
Per comporre un messaggio con una scheda hero e un pulsante, è possibile allegare un HeroCard oggetto a un messaggio.
Il codice sorgente seguente proviene dall'esempio Di gestione degli allegati.
Bots/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);
Per comporre un messaggio con una scheda hero e un pulsante, è possibile allegare un HeroCard oggetto a un messaggio.
Il codice sorgente seguente proviene dall'esempio Di gestione degli allegati.
bots/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];
Per comporre un messaggio con una scheda hero e un pulsante, è possibile allegare un HeroCard oggetto a un messaggio.
Il codice sorgente seguente proviene dall'esempio Di gestione degli allegati.
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);
}
Per comporre un messaggio con una scheda hero e un pulsante, è possibile allegare un HeroCard oggetto a un messaggio.
Il codice sorgente seguente proviene dall'esempio Di gestione degli allegati.
bots/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"
),
],
)
Elaborare gli eventi nelle schede avanzate
Per elaborare gli eventi all'interno di schede avanzate, utilizzare oggetti azione scheda per specificare cosa deve accadere quando l'utente seleziona un pulsante o tocca una sezione della scheda. Ogni azione della scheda ha una proprietà di tipo e valore .
Per funzionare correttamente, assegnare un tipo di azione a ogni elemento selezionabile su una scheda hero. Questa tabella elenca e descrive i tipi di azioni disponibili e il valore da inserire nella proprietà valore associata.
L'azione messageBack della scheda ha un significato più generalizzato rispetto alle altre azioni della scheda. Vedere la sezione Azione scheda dello schema Attività per altre informazioni sui messageBack tipi di azione e altri tipi di azione scheda.
Tipo
Descrizione
valore
call
Avvia una chiamata telefonica.
Destinazione della chiamata telefonica in questo formato: tel:123123123123.
downloadFile
Scarica un file.
URL del file da scaricare.
ImBack
Invia un messaggio al bot e pubblica una risposta visibile nella chat.
Testo del messaggio da inviare.
messageBack
Rappresenta una risposta di testo da inviare tramite il sistema di chat.
Valore programmatico facoltativo da includere nei messaggi generati.
openUrl
Apre un URL nel browser predefinito.
URL da aprire.
PlayAudio
Riproduce un contenuto audio.
URL dell'audio da riprodurre.
PlayVideo
Riproduce un contenuto video.
URL del video da riprodurre.
PostBack
Invia un messaggio al bot e potrebbe non pubblicare una risposta visibile nella chat.
Testo del messaggio da inviare.
showImage
Visualizza un'immagine.
URL dell'immagine da visualizzare.
signin
Avvia un processo di accesso OAuth.
URL del flusso OAuth da iniziare.
Scheda banner usando vari tipi di evento
Il codice seguente illustra gli esempi relativi a vari eventi di schede avanzate.
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'
);
}
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;
}
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)
Invio di una scheda adattiva
Anche se è possibile usare la factory dei messaggi per creare un messaggio contenente un allegato (di qualsiasi tipo), una scheda adattiva è un tipo specifico di allegato. Non tutti i canali supportano schede adattive e alcuni canali possono supportare solo parzialmente le schede adattive. Se ad esempio se si invia una scheda adattiva in Facebook, testi e immagini funzionano correttamente, mentre i pulsanti non funzionano. La factory dei messaggi è una classe helper di Bot Framework SDK usata per automatizzare i passaggi di creazione.
Le schede adattive sono un formato di scambio di schede aperto che consente agli sviluppatori di scambiare il contenuto dell'interfaccia utente in modo comune e coerente. Tuttavia, non tutti i canali supportano le schede adattive.
Progettazione schede adattive offre un'esperienza di progettazione interattiva avanzata per la creazione di schede adattive.
Nota
È consigliabile testare questa funzionalità con i canali che verranno usati dal bot per determinare se tali canali supportano le schede adattive.
Il codice sorgente seguente proviene dall'esempio Using cards .The following source code is from the Using cards sample .
Dialogs/MainDialog.cs
Creare la risposta e definire gli allegati sotto forma di elenco.
// 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);
Aggiungere quindi gli allegati e impostare il tipo di layout su carousel.
In questo caso gli allegati vengono aggiunti uno alla volta, ma è possibile modificare l'elenco per aggiungere le schede nel modo che si preferisce.
// 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());
Dopo aver aggiunto gli allegati, è possibile inviare la risposta come qualsiasi altra.
// Send the card(s) to the user as an attachment to the activity
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
Il codice sorgente seguente proviene dall'esempio Using cards .The following source code is from the Using cards sample .
dialogs/mainDialog.js
Aggiungere gli allegati e impostare il tipo di layout su carousel.
Dopo aver aggiunto gli allegati, è possibile inviare la risposta come qualsiasi altra.
Il codice sorgente seguente proviene dall'esempio Using cards .The following source code is from the Using cards sample .
MainDialog.java
Creare la risposta e definire gli allegati sotto forma di elenco.
// 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);
Aggiungere quindi gli allegati e impostare il tipo di layout su carousel.
In questo caso gli allegati vengono aggiunti uno alla volta, ma è possibile modificare l'elenco per aggiungere le schede nel modo che si preferisce.
// 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());
Dopo aver aggiunto gli allegati, è possibile inviare la risposta come qualsiasi altra.
// Send the card(s) to the user as an attachment to the activity
return stepContext.getContext().sendActivity(reply)
Il codice sorgente illustrato di seguito è basato sull'uso di schede di esempio.
dialogs/main_dialog.py
Creare la risposta e definire gli allegati sotto forma di elenco.
reply = MessageFactory.list([])
Aggiungere quindi gli allegati e impostare il tipo di layout su carousel.
In questo caso gli allegati vengono aggiunti uno alla volta, ma è possibile modificare l'elenco per aggiungere le schede nel modo che si preferisce.
Dopo aver aggiunto gli allegati, è possibile inviare la risposta come qualsiasi altra.
# Send the card(s) to the user as an attachment to the activity
await step_context.context.send_activity(reply)
Esempio di codice per l'elaborazione dell'input di schede adattive
L'esempio seguente illustra un modo per usare gli input della scheda adattiva all'interno di una classe di dialogo del bot.
Estende l'esempio di schede hero convalidando l'input ricevuto nel campo di testo dal client che risponde.
È prima necessario aggiungere la funzionalità di input di testo e pulsante alla scheda adattiva esistente aggiungendo il codice seguente subito prima della parentesi finale di adaptiveCard.json, che si trova nella cartella resources:
L'ID del campo di input di testo è impostato su "text". Quando l'utente seleziona OK, il messaggio generato dalla scheda adattiva avrà una proprietà valore con una proprietà denominata text che contiene le informazioni immesse dall'utente nel campo di input di testo della scheda.
Il validator usa Newtonsoft.json per convertirlo in un JObjectoggetto e quindi creare una stringa di testo tagliata per il confronto. Aggiungere:
using System;
using System.Linq;
using Newtonsoft.Json.Linq;
per MainDialog.cs e installare il pacchetto NuGet stabile più recente di Newtonsoft.Json.
Nel codice del validator è stato aggiunto il flusso logico nei commenti del codice.
Questo ChoiceValidator metodo viene inserito nell'esempio Using cards subito dopo la parentesi graffa chiusa per la dichiarazione di 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;
}
A questo ora sopra nella modifica della MainDialog dichiarazione:
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
in:
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt), ChoiceValidator));
Verrà richiamato il validator per cercare l'input della scheda adattiva ogni volta che viene creata una nuova richiesta di scelta.
Aprire mainDialog.js e trovare il metodo async run(turnContext, accessor) run Questo metodo gestisce l'attività in ingresso.
Subito dopo la chiamata dialogSet.add(this); aggiungere quanto segue:
// 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;
}
Se questo controllo trova un input di testo non esistente dal client, cerca di verificare se è presente un input da una scheda adattiva.
Se esiste un input scheda adattiva in _activity.value.text, lo copia nel normale campo di input di testo.
Il validator usa l'helper di serializzazione da com.microsoft.bot.schema per convertirlo prima in un JsonNodeoggetto e quindi creare una stringa di testo tagliata per il confronto. Per completare questa operazione sono necessarie anche altre importazioni, quindi aggiungere:
per MainDialog.java.
Nel codice del validator è stato aggiunto il flusso logico nei commenti del codice.
Questa PromptValidator espressione viene inserita nell'esempio Using cards subito dopo la parentesi graffa chiusa per la dichiarazione di 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());
};
A questo ora sopra nella modifica della MainDialog dichiarazione:
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt"));
in:
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt", validator, null));
Verrà richiamato il validator per cercare l'input della scheda adattiva ogni volta che viene creata una nuova richiesta di scelta.
Creare e inviare un'attività con azioni suggerite all'utente.
Questo choice_validator metodo viene inserito nell'esempio Using cards subito dopo la parentesi graffa chiusa per la dichiarazione di 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
A questo ora sopra nella modifica della MainDialog dichiarazione: