Отправка вложений мультимедиа с помощью пакета SDK Bot Framework
Статья
ОБЛАСТЬ ПРИМЕНЕНИЯ: ПАКЕТ SDK версии 4
Обмен сообщениями между пользователем и ботом может включать вложения мультимедиа, такие как изображения, видео, аудио и файлы. Пакет SDK Bot Framework поддерживает задачу отправки пользователю форматированного сообщения. Чтобы определить тип форматированных сообщений, поддерживаемых каналом (Facebook, Slack и т. д.), ознакомьтесь с документацией канала по вопросам ограничений.
Примечание.
Пакеты SDK для JavaScript, C# и Python для Bot Framework по-прежнему будут поддерживаться, однако пакет SDK java отменяется с окончательной долгосрочной поддержкой, заканчивающейся в ноябре 2023 года.
Существующие боты, созданные с помощью пакета SDK для Java, будут продолжать функционировать.
Свойство Attachments объекта Activity содержит массив объектов Attachment, представляющих вложения в виде форматированных карточек и файлов мультимедиа. Чтобы добавить мультимедийное вложение в сообщение, создайте объект Attachment для действия reply и задайте свойства ContentType, ContentUrl и Name.
Чтобы создать ответное сообщение, определите текст и настройте вложения. Присвоение вложений ответному сообщению выполняется одинаково для всех типов вложений, но настройка и определение разных вложений будут отличаться, как показано в следующих фрагментах. Ниже приведен код для настройки ответа со встроенным вложением:
Bots/AttachmentsBot.cs
{
reply = MessageFactory.Text("This is an inline attachment.");
Далее мы рассмотрим разные типы вложений. Во-первых, это встроенные вложения:
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}",
};
}
Во-вторых, отправленные вложения:
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,
};
}
И, в-третьих, вложения из Интернета:
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",
};
}
}
Чтобы создать ответное сообщение, определите текст и настройте вложения. Присвоение вложений ответному сообщению выполняется одинаково для всех типов вложений, но настройка и определение разных вложений будут отличаться, как показано в следующих фрагментах. Ниже приведен код для настройки ответа со встроенным вложением:
bots/attachmentsBot.js
*/
const firstChar = turnContext.activity.text[0];
if (firstChar === '1') {
У вас есть несколько разных методов для отправки пользователю мультимедийного содержимого (например, изображения или видео). Во-первых, это встроенные вложения:
И представленные 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()Activity объекта содержит массив Attachment объектов, представляющих вложения мультимедиа и расширенные карточки, подключенные к сообщению. Чтобы добавить мультимедийное вложение в сообщение, создайте объект Attachment для действия reply и задайте свойства ContentType, ContentUrl и Name.
Чтобы создать ответное сообщение, определите текст и настройте вложения. Присвоение вложений ответному сообщению выполняется одинаково для всех типов вложений, но настройка и определение разных вложений будут отличаться, как показано в следующих фрагментах. Ниже приведен код для настройки ответа со встроенным вложением:
AttachmentsBot.java
result = getInlineAttachment()
.thenApply(attachment -> {
Activity reply = MessageFactory.text("This is an inline attachment.");
reply.setAttachment(attachment);
return reply;
});
Далее мы рассмотрим разные типы вложений. Во-первых, это встроенные вложения:
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;
}
Чтобы создать ответное сообщение, определите текст и настройте вложения. Присвоение вложений ответному сообщению выполняется одинаково для всех типов вложений, но настройка и определение разных вложений будут отличаться, как показано в следующих фрагментах.
Ниже приведен код для настройки ответа со встроенным вложением:
bots/attachments_bot.py
reply.text = "This is an inline attachment."
reply.attachments = [self._get_inline_attachment()]
У вас есть несколько разных методов для отправки пользователю мультимедийного содержимого (например, изображения или видео). Во-первых, это встроенные вложения:
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}",
)
Во-вторых, отправленные вложения:
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,
)
И представленные 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",
)
Если вложение представляет собой изображение, аудиофайл или видео, служба соединителя будет передавать данные вложения каналу так, чтобы позволить каналу обрабатывать это вложение в диалоге. Если вложение представляет собой файл, URL-адрес файла будет отображаться в диалоге как гиперссылка.
Отправка карточки для имиджевого баннера
Помимо изображений или видео, вы можете прикрепить карточку для имиджевого баннера, которая позволяет совмещать изображения и кнопки в один объект и отправлять их в таком виде пользователю. Markdown поддерживается для большинства текстовых полей, но особенности поддержки зависят от канала.
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);
Чтобы создать сообщение с карточкой героя и кнопкой, можно подключить HeroCard объект к сообщению.
* @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];
Чтобы создать сообщение с карточкой героя и кнопкой, можно подключить HeroCard объект к сообщению.
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);
}
Чтобы создать сообщение с карточкой героя и кнопкой, можно подключить HeroCard объект к сообщению.
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"
),
],
)
Обработка событий в форматированных карточках
Чтобы обработать события в богатых карточках, используйте объекты действия карточки, чтобы указать, что должно происходить, когда пользователь выбирает кнопку или касается раздела карточки. Каждое действие карточки имеет свойство типа и значения .
Чтобы правильно функционировать, назначьте тип действия каждому элементу, который можно щелкнуть на карточке героя. В этой таблице перечислены и описаны доступные типы действий и требуемый формат для связанного свойства.
Действие messageBack карточки имеет более обобщенное значение, чем другие действия карты. Дополнительные сведения о messageBack других типах действий карточек см. в разделе "Действие карты".
Тип
Описание
Значение
call
Инициирует телефонный звонок.
Целевое назначение телефонного звонка в следующем формате: tel:123123123123.
downloadFile
Скачивает файл.
URL-адрес для скачивания файла.
imBack
Отправляет боту сообщение и отображает полученный ответ в чате.
Текст отправляемого сообщения.
messageBack
Представляет текстовый ответ, отправляемый через систему чата.
Необязательное программное значение для включения в созданные сообщения.
openUrl
Открывает URL-адрес в окне встроенного браузера.
URL-адрес, который нужно открыть.
playAudio
Воспроизводит звук.
URL-адрес для воспроизведения звука.
playVideo
Воспроизводит видео.
URL-адрес для воспроизведения видео.
postBack
Отправляет боту сообщение, но не всегда отображает полученный ответ в чате.
Текст отправляемого сообщения.
showImage
Отображает изображение.
URL-адрес для отображения изображения.
signin
Инициирует процесс входа OAuth.
URL-адрес потока OAuth, который нужно запустить.
Карточка для имиджевого баннера с различными типами событий
В следующем коде показаны примеры использования различных событий форматированных карточек.
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)
Отправка адаптивной карточки
Хотя можно использовать фабрику сообщений для создания сообщения, содержащего вложение (любого рода), адаптивная карточка — это один из конкретных типов вложений. Не все каналы поддерживают адаптивные карточки, а некоторые каналы могут частично поддерживать адаптивные карточки. Например, при отправке адаптивной карточки в Facebook, кнопки не будут работать, а тексты и изображения будут отображаться. Фабрика сообщений — это вспомогательный класс пакета SDK Bot Framework, используемый для автоматизации действий по созданию.
Адаптивные карточки — это открытый формат обмена карточками, позволяющий разработчикам обмениваться контентом пользовательского интерфейса общим и согласованным способом. Однако не все каналы поддерживают адаптивные карточки.
Конструктор адаптивных карточек предоставляет широкий интерактивный интерфейс разработки адаптивных карточек.
Примечание.
Вы должны протестировать эту функцию, выбрав каналы, которые будут использоваться ботом, чтобы определить, поддерживают ли они адаптивные карточки.
Сначала создайте ответ и определите вложения в виде списка.
// 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);
Затем добавьте вложения и задайте тип макета каруселя.
Здесь мы добавляем их по одному, но вы можете управлять этим списком и добавлять в него карточки любым удобным методом.
// 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());
Завершив добавление вложений, вы можете отправить этот ответ так же, как и любой другой.
// Send the card(s) to the user as an attachment to the activity
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
Сначала создайте ответ и определите вложения в виде списка.
// 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);
Затем добавьте вложения и задайте тип макета каруселя.
Здесь мы добавляем их по одному, но вы можете управлять этим списком и добавлять в него карточки любым удобным методом.
// 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());
Завершив добавление вложений, вы можете отправить этот ответ так же, как и любой другой.
// Send the card(s) to the user as an attachment to the activity
return stepContext.getContext().sendActivity(reply)
Сначала создайте ответ и определите вложения в виде списка.
reply = MessageFactory.list([])
Затем добавьте вложения и задайте тип макета каруселя.
Здесь мы добавляем их по одному, но вы можете управлять этим списком и добавлять в него карточки любым удобным методом.
Завершив добавление вложений, вы можете отправить этот ответ так же, как и любой другой.
# Send the card(s) to the user as an attachment to the activity
await step_context.context.send_activity(reply)
Пример кода для обработки входных данных адаптивной карточки
В следующем примере показан один из способов использования входных данных адаптивной карточки в классе диалоговых окон бота.
Он расширяет образец карточек героев, проверяя входные данные, полученные в текстовом поле от клиента ответа.
Сначала необходимо добавить функции ввода текста и кнопки в существующую адаптивную карточку, добавив следующий код непосредственно перед окончательной скобкой adaptiveCard.json, расположенной в папке ресурсов:
Идентификатор текстового поля ввода имеет значение text. Когда пользователь нажимает кнопку "ОК", сообщение, которое создает адаптивная карточка, будет иметь свойство значения с именем text , которое содержит сведения, введенные пользователем в поле ввода текста карточки.
Наш проверяющий элемент использует Newtonsoft.json , чтобы сначала преобразовать его в JObjectобъект, а затем создать обрезанная текстовая строка для сравнения. Поэтому добавьте:
using System;
using System.Linq;
using Newtonsoft.Json.Linq;
для MainDialog.cs и установки последнего стабильного пакета NuGet Newtonsoft.Json.
В коде проверяющего элемента мы добавили поток логики в комментарии кода.
Этот ChoiceValidator метод помещается в образец "Использование карточек " сразу после закрытой фигурной скобки для объявления 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;
}
Теперь выше в MainDialog изменении объявления:
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
на:
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt), ChoiceValidator));
Это вызовет проверяющий элемент для поиска входных данных адаптивной карточки при каждом создании нового запроса выбора.
Откройте mainDialog.js и найдите метод async run(turnContext, accessor) выполнения, который этот метод обрабатывает входящие действия.
Сразу после вызова dialogSet.add(this); добавьте следующее:
// 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;
}
Если эта проверка находит несуществующие текстовые входные данные от клиента, он проверяет, есть ли входные данные из адаптивной карточки.
Если входные данные адаптивной карточки существуют _activity.value.text, он копирует его в обычное текстовое поле ввода.
Наш проверяющий элемент использует вспомогательный элемент сериализации из com.microsoft.bot.schema, чтобы сначала преобразовать его в JsonNodeобъект, а затем создать усеченную текстовую строку для сравнения. Для выполнения этого также потребуется несколько других импортов, поэтому добавьте:
для MainDialog.java.
В коде проверяющего элемента мы добавили поток логики в комментарии кода.
Это PromptValidator выражение помещается в образец "Использование карточек " сразу после закрытой фигурной скобки для объявления 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());
};
Теперь выше в MainDialog изменении объявления:
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt"));
на:
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt", validator, null));
Это вызовет проверяющий элемент для поиска входных данных адаптивной карточки при каждом создании нового запроса выбора.
Создайте и отправьте действие с предлагаемыми действиями пользователю.
Этот choice_validator метод помещается в пример "Использование карточек " сразу после закрытой фигурной скобки для объявления 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