使用者與 Bot 之間交換的訊息可以包含媒體附件,例如影像、視訊、音訊和檔案。 Bot Framework SDK 支援將豐富訊息傳送給使用者的工作。 若要判斷通道支援的豐富訊息類型(Facebook、Slack 等等),請參閱通道的檔以取得限制的相關信息。
本節中顯示的所有原始程式碼都是以處理附件範例為基礎。
對象的 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",
};
}
}
下列原始碼來自 處理附件 範例。
若要使用附件,請在 Bot 中包含下列連結庫:
bots/attachmentsBot.js
const { ActivityHandler, ActionTypes, ActivityTypes, CardFactory } = require('botbuilder');
若要建立回復訊息,請定義文字,然後設定附件。 將附件指派給回復的每個附件類型都相同,不過會以不同的方式設定和定義各種附件,如下列代碼段所示。 下列程式代碼會設定內嵌附件的回復:
bots/attachmentsBot.js
const reply = { type: ActivityTypes.Message };
reply.text = 'This is an inline attachment.';
reply.attachments = [this.getInlineAttachment()];
若要傳送單一內容,例如影像或視訊,您可以透過幾種不同的方式傳送媒體。 首先,作為內嵌附件:
bots/attachmentsBot.js
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 }`
};
}
然後,上傳的附件:
bots/attachmentsBot.js
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',
contentUrl: attachmentUri
};
最後,URL 中包含的因特網附件:
bots/attachmentsBot.js
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;
});
}
然後,上傳的附件:
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;
});
});
}
最後,因特網附件:
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;
}
下列原始碼來自 處理附件 範例。
若要建立回復訊息,請定義文字,然後設定附件。 將附件指派給回復的每個附件類型都相同,不過會以不同的方式設定和定義各種附件,如下列代碼段所示。
下列程式代碼會設定內嵌附件的回復:
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",
)
若要使用主圖卡片和按鈕撰寫訊息,您可以將物件附加 HeroCard
至訊息。
下列原始碼來自 處理附件 範例。
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);
若要使用主圖卡片和按鈕撰寫訊息,您可以將物件附加 HeroCard
至訊息。
下列原始碼來自 處理附件 範例。
bots/attachmentsBot.js
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];
await turnContext.sendActivity(reply);
}
若要使用主圖卡片和按鈕撰寫訊息,您可以將物件附加 HeroCard
至訊息。
下列原始碼來自 處理附件 範例。
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);
}
若要使用主圖卡片和按鈕撰寫訊息,您可以將物件附加 HeroCard
至訊息。
下列原始碼來自 處理附件 範例。
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"
),
],
)
如需所有可用卡片的範例,請參閱 使用卡片 範例。
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;
}
如需所有可用卡片的範例,請參閱 使用卡片 範例。
dialogs/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/'
}
])
);
}
dialogs/mainDialog.js
createOAuthCard() {
return CardFactory.oauthCard(
'OAuth connection', // Replace with the name of your Azure AD connection
'Sign In',
'BotFramework OAuth Card'
);
}
如需所有可用卡片的範例,請參閱 使用卡片 範例。
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;
}
如需所有可用卡片的範例,請參閱 使用卡片 範例。
dialogs/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)
dialogs/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)
若要使用調適型卡片,請務必新增 AdaptiveCards
NuGet 套件。
下列原始碼來自 使用卡片 範例。
Cards.cs
此範例會從檔案讀取調適型卡片 JSON,並將其新增為附件。
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;
}
若要使用調適型卡片,請務必新增 adaptivecards
npm 套件。
下列原始碼來自 使用卡片 範例。
dialogs/mainDialog.js
此範例會從檔案讀取調適型卡片 JSON,並建立連結卡片的訊息活動。
const AdaptiveCard = require('../resources/adaptiveCard.json');
createAdaptiveCard() {
return CardFactory.adaptiveCard(AdaptiveCard);
}
下列原始碼來自 使用卡片 範例。
Cards.java
此範例會從檔案讀取調適型卡片 JSON,並將其新增為附件。
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);
}
}
下列原始碼來自 使用卡片 範例。
bots/main_dialog.py
此範例會從檔案讀取調適型卡片 JSON,並建立連結卡片的訊息活動。
from .resources.adaptive_card_example import ADAPTIVE_CARD_CONTENT
def create_adaptive_card(self) -> Attachment:
return CardFactory.adaptive_card(ADAPTIVE_CARD_CONTENT)
下列原始碼來自 使用卡片 範例。
Dialogs/MainDialog.cs
首先,建立回復,並將附件定義為清單。
// 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);
下列原始碼來自 使用卡片 範例。
dialogs/mainDialog.js
新增附件,並將版面配置類型設定為 浮動切換。
新增附件之後,您可以像任何其他一樣傳送回復。
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
});
下列原始碼來自 使用卡片 範例。
MainDialog.java
首先,建立回復,並將附件定義為清單。
// 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)
此處顯示的原始程式碼是以使用卡片範例為基礎。
dialogs/main_dialog.py
首先,建立回復,並將附件定義為清單。
reply = MessageFactory.list([])
然後新增附件,並將版面配置類型設定為 浮動切換。
在這裡,我們會一次新增一個卡片,但您可以隨意操作清單,以視您偏好新增卡片。
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())
新增附件之後,您可以像任何其他一樣傳送回復。
# Send the card(s) to the user as an attachment to the activity
await step_context.context.send_activity(reply)
下列範例示範在 Bot 對話類別中使用調適型卡片輸入的其中一種方式。
它會驗證回應用戶端在文字欄位中收到的輸入,藉此擴充主圖卡片範例。
您必須先將文字輸入和按鈕功能新增至現有的調適型卡片,方法是將下列程式代碼新增至位於 resources 資料夾中adaptiveCard.json的最後括弧之前:
驗證程式會使用 Newtonsoft.json 先將此轉換成 JObject
,然後建立修剪后的文字字串進行比較。 因此,請新增:
using System;
using System.Linq;
using Newtonsoft.Json.Linq;
以MainDialog.cs並安裝Newtonsoft.Json的最新穩定 NuGet 套件。
在驗證程式程式代碼中,我們已將邏輯流程新增至程式代碼批注。
這個 ChoiceValidator
方法會放在 MainDialog 宣告的封閉大括弧公開之後的 Using card 範例中:
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 並尋找 run 方法 這個方法 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
,然後建立修剪后的文字字串進行比較。 我們還需要一些其他匯入才能完成這項作業,因此請新增:
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;
以 MainDialog.java。
在驗證程式程式代碼中,我們已將邏輯流程新增至程式代碼批注。
此 PromptValidator
表達式會放在 MainDialog 宣告的封閉大括弧公開之後的 Using card 範例中:
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
方法會放在 公開的封閉大括弧公開之後的 Using card 範例中,以宣告 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
現在,宣告中的 MainDialog
上方變更:
self.add_dialog(ChoicePrompt(CARD_PROMPT))
變更為:
self.add_dialog(ChoicePrompt(CARD_PROMPT, MainDialog.choice_validator))
這將會叫用驗證程式,以在每次建立新的選擇提示時尋找調適型卡片輸入。