Skip to content
This repository was archived by the owner on Dec 4, 2023. It is now read-only.

Commit 7fbad50

Browse files
committed
Adding models to Adaptive Card deserialize
1 parent 74c84ab commit 7fbad50

7 files changed

Lines changed: 356 additions & 132 deletions

File tree

samples/53.teams-messaging-extensions-action-preview/README.md

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
Bot Framework v4 Conversation Bot sample for Teams.
55

6-
This bot has been created using [Bot Framework](https://dev.botframework.com). This sample shows
7-
how to incorporate basic conversational flow into a Teams application. It also illustrates a few of the Teams specific calls you can make from your bot.
6+
This Messaging Extension has been created using [Bot Framework](https://dev.botframework.com). It shows how to create a simple card based on parameters entered by the user from a Task Module.
87

98
## Prerequisites
109

@@ -50,21 +49,7 @@ the Teams service needs to call into the bot.
5049
5150
You can interact with this bot by sending it a message, or selecting a command from the command list. The bot will respond to the following strings.
5251
53-
1. **Show Welcome**
54-
- **Result:** The bot will send the welcome card for you to interact with
55-
- **Valid Scopes:** personal, group chat, team chat
56-
2. **MentionMe**
57-
- **Result:** The bot will respond to the message and mention the user
58-
- **Valid Scopes:** personal, group chat, team chat
59-
3. **MessageAllMembers**
60-
- **Result:** The bot will send a 1-on-1 message to each member in the current conversation (aka on the conversation's roster).
61-
- **Valid Scopes:** personal, group chat, team chat
62-
63-
You can select an option from the command list by typing ```@TeamsConversationBot``` into the compose message area and ```What can I do?``` text above the compose area.
64-
65-
### Avoiding Permission-Related Errors
66-
67-
You may encounter permission-related errors when sending a proactive message. This can often be mitigated by using `MicrosoftAppCredentials.TrustServiceUrl()`. See [the documentation](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-proactive-message?view=azure-bot-service-4.0&tabs=csharp#avoiding-401-unauthorized-errors) for more information.
52+
Click the Messaging Extension icon in the Compose Box's Messaging Extension menu.
6853
6954
## Deploy the bot to Azure
7055

samples/53.teams-messaging-extensions-action-preview/src/main/java/com/microsoft/bot/sample/teamsactionpreview/Application.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* This class also provides overrides for dependency injections. A class that extends the
1919
* {@link com.microsoft.bot.builder.Bot} interface should be annotated with @Component.
2020
*
21-
* @see TeamsConversationBot
21+
* @see TeamsMessagingExtensionsActionPreviewBot
2222
*/
2323
@SpringBootApplication
2424

samples/53.teams-messaging-extensions-action-preview/src/main/java/com/microsoft/bot/sample/teamsactionpreview/TeamsMessagingExtensionsActionPreviewBot.java

Lines changed: 71 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,37 @@
33

44
package com.microsoft.bot.sample.teamsactionpreview;
55

6-
import com.fasterxml.jackson.databind.JsonNode;
6+
import com.fasterxml.jackson.core.JsonProcessingException;
77
import com.fasterxml.jackson.databind.ObjectMapper;
8-
import com.fasterxml.jackson.databind.node.ObjectNode;
98
import com.microsoft.bot.builder.MessageFactory;
109
import com.microsoft.bot.builder.TurnContext;
1110
import com.microsoft.bot.builder.teams.TeamsActivityHandler;
1211
import com.microsoft.bot.integration.Configuration;
12+
import com.microsoft.bot.sample.teamsactionpreview.models.AdaptiveCard;
13+
import com.microsoft.bot.sample.teamsactionpreview.models.Body;
14+
import com.microsoft.bot.sample.teamsactionpreview.models.Choice;
1315
import com.microsoft.bot.schema.Activity;
1416
import com.microsoft.bot.schema.Attachment;
1517
import com.microsoft.bot.schema.teams.*;
1618
import org.apache.commons.io.IOUtils;
19+
import org.slf4j.LoggerFactory;
1720
import org.springframework.stereotype.Component;
1821

1922
import java.io.IOException;
2023
import java.io.InputStream;
2124
import java.nio.charset.StandardCharsets;
22-
import java.util.ArrayList;
2325
import java.util.LinkedHashMap;
2426
import java.util.List;
2527
import java.util.concurrent.CompletableFuture;
28+
import java.util.stream.Collectors;
2629

2730
/**
2831
* This class implements the functionality of the Bot.
2932
*
3033
* <p>This is where application specific logic for interacting with the users would be
31-
* added. For this sample, the {@link #onMessageActivity(TurnContext)} echos the text
32-
* back to the user. The {@link #onMembersAdded(List, TurnContext)} will send a greeting
33-
* to new conversation participants.</p>
34+
* added. This sample shows how to create a simple card based on
35+
* parameters entered by the user from a Task Module.
36+
* </p>
3437
*/
3538
@Component
3639
public class TeamsMessagingExtensionsActionPreviewBot extends TeamsActivityHandler {
@@ -71,17 +74,18 @@ protected CompletableFuture<MessagingExtensionActionResponse> onTeamsMessagingEx
7174

7275
Attachment adaptiveCardEditor = getAdaptiveCardAttachment("adaptiveCardEditor.json");
7376

74-
return CompletableFuture.completedFuture(new MessagingExtensionActionResponse(){{
75-
setTask(new TaskModuleContinueResponse(){{
76-
setValue(new TaskModuleTaskInfo(){{
77-
setCard(adaptiveCardEditor);
78-
setWidth(500);
79-
setHeight(450);
80-
setTitle("Task Module Fetch Example");
77+
return CompletableFuture.completedFuture(
78+
new MessagingExtensionActionResponse(){{
79+
setTask(new TaskModuleContinueResponse(){{
80+
setValue(new TaskModuleTaskInfo(){{
81+
setCard(adaptiveCardEditor);
82+
setWidth(500);
83+
setHeight(450);
84+
setTitle("Task Module Fetch Example");
85+
}});
86+
setType("continue");
8187
}});
82-
setType("continue");
8388
}});
84-
}});
8589
}
8690

8791
@Override
@@ -150,22 +154,25 @@ protected CompletableFuture<Void> onTeamsMessagingExtensionCardButtonClicked(
150154
Object cardData) {
151155
// If the adaptive card was added to the compose window (by either the OnTeamsMessagingExtensionSubmitActionAsync or
152156
// OnTeamsMessagingExtensionBotMessagePreviewSendAsync handler's return values) the submit values will come in here.
153-
Activity reply = MessageFactory.text("OnTeamsMessagingExtensionCardButtonClickedAsync Value: ");
157+
Activity reply = MessageFactory.text("OnTeamsMessagingExtensionCardButtonClickedAsync");
154158
return turnContext.sendActivity(reply)
155159
.thenApply(resourceResponse -> null);
156160
}
157161

158162
private Attachment getAdaptiveCardAttachment(String fileName) {
159163
try {
160-
InputStream input = getClass().getClassLoader().getResourceAsStream(fileName);
164+
InputStream input = getClass()
165+
.getClassLoader()
166+
.getResourceAsStream(fileName);
161167
String content = IOUtils.toString(input, StandardCharsets.UTF_8);
162168

163169
return new Attachment(){{
164170
setContentType("application/vnd.microsoft.card.adaptive");
165-
setContent(new ObjectMapper().readValue(content, ObjectNode.class));
171+
setContent(new ObjectMapper().readValue(content, AdaptiveCard.class));
166172
}};
167173
} catch (IOException e) {
168-
e.printStackTrace();
174+
LoggerFactory.getLogger(TeamsMessagingExtensionsActionPreviewBot.class)
175+
.error("getAdaptiveCardAttachment", e);
169176
}
170177
return new Attachment();
171178
}
@@ -175,49 +182,63 @@ private void updateAttachmentAdaptiveCard(
175182
MessagingExtensionAction action
176183
){
177184
LinkedHashMap data = (LinkedHashMap) action.getData();
178-
ObjectNode content = (ObjectNode) attachment.getContent();
179-
JsonNode body = content.get("body");
180-
for (JsonNode arrayItem : body) {
181-
if (arrayItem.has("choices")){
182-
JsonNode choices = arrayItem.get("choices");
185+
AdaptiveCard card = (AdaptiveCard) attachment.getContent();
186+
for (Body item : card.getBody() ) {
187+
if (item.getChoices() != null) {
183188
for (int index = 0 ; index < 3 ; index++) {
184-
ObjectNode choice = (ObjectNode) choices.get(index);
185-
choice.put("title", (String) data.get("Option" + (index + 1)));
186-
choice.put("value", (String) data.get("Option" + (index + 1)));
189+
item.getChoices().get(index).setTitle((String) data.get("Option" + (index + 1)));
190+
item.getChoices().get(index).setValue((String) data.get("Option" + (index + 1)));
187191
}
188192
}
189193

190-
if(arrayItem.has("id") && arrayItem.get("id").asText().equals("Question")){
191-
ObjectNode question = (ObjectNode) arrayItem;
192-
question.put("text", (String) data.get("Question"));
194+
if (item.getId() != null && item.getId().equals("Question")) {
195+
item.setText((String) data.get("Question"));
193196
}
194197
}
195198
}
196199

197200
private void updateAttachmentAdaptiveCardEdit(
198201
Attachment attachment,
199202
Attachment preview
200-
){
201-
LinkedHashMap data = (LinkedHashMap)preview.getContent();
202-
List bodyPreview = (ArrayList<LinkedHashMap>) data.get("body");
203-
ObjectNode content = (ObjectNode) attachment.getContent();
204-
JsonNode body = content.get("body");
205-
for (JsonNode arrayItem : body) {
206-
207-
if(arrayItem.has("id") && arrayItem.get("id").asText().equals("Question")){
208-
ObjectNode question = (ObjectNode) arrayItem;
209-
LinkedHashMap previewQuestion = (LinkedHashMap) bodyPreview.get(1);
210-
question.put("value", (String) previewQuestion.get("text"));
211-
}
203+
) {
204+
AdaptiveCard prv = null;
205+
try {
206+
String cardAsString = new ObjectMapper().writeValueAsString(preview.getContent());
207+
prv = new ObjectMapper().readValue(cardAsString, AdaptiveCard.class);
208+
} catch (JsonProcessingException e) {
209+
LoggerFactory.getLogger(TeamsMessagingExtensionsActionPreviewBot.class)
210+
.error("updateAttachmentAdaptiveCardEdit", e);
211+
} catch (IOException e) {
212+
LoggerFactory.getLogger(TeamsMessagingExtensionsActionPreviewBot.class)
213+
.error("updateAttachmentAdaptiveCardEdit", e);
214+
}
212215

213-
if(arrayItem.has("id") && arrayItem.get("id").asText().startsWith("Option")){
214-
ObjectNode option = (ObjectNode) arrayItem;
215-
int responseIndex = Integer.parseInt(arrayItem.get("id").asText().charAt(6) + "");
216-
LinkedHashMap previewOptions = (LinkedHashMap) bodyPreview.get(3);
217-
List choices = (ArrayList) previewOptions.get("choices");
218-
LinkedHashMap previewOption = (LinkedHashMap) choices.get(responseIndex - 1);
219-
option.put("value", (String) previewOption.get("value"));
220-
}
216+
AdaptiveCard atc = (AdaptiveCard) attachment.getContent();
217+
218+
Body question = atc.getBody().stream()
219+
.filter(i -> "Question".equals(i.getId()))
220+
.findAny()
221+
.orElse(null);
222+
223+
question.setValue(prv.getBody().stream()
224+
.filter(i -> "Question".equals(i.getId()))
225+
.findAny()
226+
.orElse(null).getText());
227+
228+
List<Body> options = atc.getBody().stream()
229+
.filter(i -> i.getId()!= null && i.getId().startsWith("Option"))
230+
.collect(Collectors.toList());
231+
232+
for (Body item: options) {
233+
int responseIndex = Integer.parseInt(item.getId().charAt(6) + "");
234+
Choice choice = prv.getBody().stream()
235+
.filter(i -> i.getId() != null && i.getId().equals("Choices"))
236+
.findFirst()
237+
.orElse(null)
238+
.getChoices()
239+
.get(responseIndex - 1);
240+
241+
item.setValue(choice.getValue());
221242
}
222243
}
223244
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.microsoft.bot.sample.teamsactionpreview.models;
2+
3+
import com.fasterxml.jackson.annotation.JsonAnyGetter;
4+
import com.fasterxml.jackson.annotation.JsonAnySetter;
5+
import com.fasterxml.jackson.annotation.JsonIgnore;
6+
import com.fasterxml.jackson.annotation.JsonProperty;
7+
8+
import java.util.HashMap;
9+
import java.util.List;
10+
import java.util.Map;
11+
12+
public class AdaptiveCard {
13+
@JsonProperty("body")
14+
private List<Body> body = null;
15+
@JsonIgnore
16+
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
17+
18+
@JsonProperty("body")
19+
public List<Body> getBody() {
20+
return body;
21+
}
22+
23+
@JsonProperty("body")
24+
public void setBody(List<Body> body) {
25+
this.body = body;
26+
}
27+
28+
@JsonAnyGetter
29+
public Map<String, Object> getAdditionalProperties() {
30+
return this.additionalProperties;
31+
}
32+
33+
@JsonAnySetter
34+
public void setAdditionalProperty(String name, Object value) {
35+
this.additionalProperties.put(name, value);
36+
}
37+
}

0 commit comments

Comments
 (0)