microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
samples/migration-bot

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

core/src/Microsoft.Teams.Bot.Apps/Schema/TeamsActivityBuilder.cs

230lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using Microsoft.Teams.Bot.Apps.Schema.Entities;
5using Microsoft.Teams.Bot.Core.Schema;
6
7namespace Microsoft.Teams.Bot.Apps.Schema;
8
9/// <summary>
10/// Provides a fluent API for building TeamsActivity instances.
11/// </summary>
12public class TeamsActivityBuilder : CoreActivityBuilder<TeamsActivity, TeamsActivityBuilder>
13{
14 /// <summary>
15 /// Initializes a new instance of the TeamsActivityBuilder class.
16 /// </summary>
17 internal TeamsActivityBuilder() : base(new TeamsActivity())
18 {
19 }
20
21 /// <summary>
22 /// Initializes a new instance of the TeamsActivityBuilder class with an existing activity.
23 /// </summary>
24 /// <param name="activity">The activity to build upon.</param>
25 internal TeamsActivityBuilder(TeamsActivity activity) : base(activity)
26 {
27 }
28
29 /// <summary>
30 /// Sets the conversation (override for Teams-specific type).
31 /// </summary>
32 protected override void SetConversation(Conversation? conversation)
33 {
34 _activity.Conversation = conversation is TeamsConversation teamsConv
35 ? teamsConv
36 : TeamsConversation.FromConversation(conversation);
37 }
38
39 /// <summary>
40 /// Sets the From account (override for Teams-specific type).
41 /// </summary>
42 protected override void SetFrom(ConversationAccount? from)
43 {
44 _activity.From = from is TeamsConversationAccount teamsAccount
45 ? teamsAccount
46 : TeamsConversationAccount.FromConversationAccount(from);
47 }
48
49 /// <summary>
50 /// Sets the Recipient account (override for Teams-specific type).
51 /// </summary>
52 protected override void SetRecipient(ConversationAccount? recipient)
53 {
54 _activity.Recipient = recipient is TeamsConversationAccount teamsAccount
55 ? teamsAccount
56 : TeamsConversationAccount.FromConversationAccount(recipient);
57 }
58
59 /// <summary>
60 /// Sets the Teams-specific channel data.
61 /// </summary>
62 /// <param name="channelData">The channel data.</param>
63 /// <returns>The builder instance for chaining.</returns>
64 public TeamsActivityBuilder WithChannelData(TeamsChannelData? channelData)
65 {
66 _activity.ChannelData = channelData;
67 return this;
68 }
69
70 /// <summary>
71 /// Sets the entities collection.
72 /// </summary>
73 /// <param name="entities">The entities collection.</param>
74 /// <returns>The builder instance for chaining.</returns>
75 public TeamsActivityBuilder WithEntities(EntityList entities)
76 {
77 _activity.Entities = entities;
78 return this;
79 }
80
81 /// <summary>
82 /// Sets the attachments collection.
83 /// </summary>
84 /// <param name="attachments">The attachments collection.</param>
85 /// <returns>The builder instance for chaining.</returns>
86 public TeamsActivityBuilder WithAttachments(IList<TeamsAttachment> attachments)
87 {
88 _activity.Attachments = attachments;
89 return this;
90 }
91
92 // TODO: Builders should only have "With" methods, not "Add" methods.
93 /// <summary>
94 /// Replaces the attachments collection with a single attachment.
95 /// </summary>
96 /// <param name="attachment">The attachment to set. Passing null clears the attachments.</param>
97 /// <returns>The builder instance for chaining.</returns>
98 public TeamsActivityBuilder WithAttachment(TeamsAttachment? attachment)
99 {
100 _activity.Attachments = attachment is null
101 ? null
102 : [attachment];
103
104 return this;
105 }
106
107 /// <summary>
108 /// Adds an entity to the activity's Entities collection.
109 /// </summary>
110 /// <param name="entity">The entity to add.</param>
111 /// <returns>The builder instance for chaining.</returns>
112 public TeamsActivityBuilder AddEntity(Entity entity)
113 {
114 _activity.Entities ??= [];
115 _activity.Entities.Add(entity);
116 return this;
117 }
118
119 /// <summary>
120 /// Adds an attachment to the activity's Attachments collection.
121 /// </summary>
122 /// <param name="attachment">The attachment to add.</param>
123 /// <returns>The builder instance for chaining.</returns>
124 public TeamsActivityBuilder AddAttachment(TeamsAttachment attachment)
125 {
126 _activity.Attachments ??= [];
127 _activity.Attachments.Add(attachment);
128 return this;
129 }
130
131 /// <summary>
132 /// Adds an Adaptive Card attachment to the activity.
133 /// </summary>
134 /// <param name="adaptiveCard">The Adaptive Card payload.</param>
135 /// <param name="configure">Optional callback to further configure the attachment before it is added.</param>
136 /// <returns>The builder instance for chaining.</returns>
137 public TeamsActivityBuilder AddAdaptiveCardAttachment(object adaptiveCard, Action<TeamsAttachmentBuilder>? configure = null)
138 {
139 TeamsAttachment attachment = BuildAdaptiveCardAttachment(adaptiveCard, configure);
140 return AddAttachment(attachment);
141 }
142
143 /// <summary>
144 /// Sets the activity attachments collection to a single Adaptive Card attachment.
145 /// </summary>
146 /// <param name="adaptiveCard">The Adaptive Card payload.</param>
147 /// <param name="configure">Optional callback to further configure the attachment.</param>
148 /// <returns>The builder instance for chaining.</returns>
149 public TeamsActivityBuilder WithAdaptiveCardAttachment(object adaptiveCard, Action<TeamsAttachmentBuilder>? configure = null)
150 {
151 TeamsAttachment attachment = BuildAdaptiveCardAttachment(adaptiveCard, configure);
152 return WithAttachment(attachment);
153 }
154
155 /// <summary>
156 /// Adds or sets the text content of the activity.
157 /// </summary>
158 /// <param name="text"></param>
159 /// <param name="textFormat"></param>
160 /// <returns></returns>
161 public TeamsActivityBuilder WithText(string text, string textFormat = "plain")
162 {
163 WithProperty("text", text);
164 WithProperty("textFormat", textFormat);
165 return this;
166 }
167
168 /// <summary>
169 /// With Suggested Actions
170 /// </summary>
171 /// <param name="suggestedActions"></param>
172 /// <returns></returns>
173 public TeamsActivityBuilder WithSuggestedActions(SuggestedActions suggestedActions)
174 {
175 ArgumentNullException.ThrowIfNull(_activity);
176 _activity.SuggestedActions = suggestedActions;
177 return this;
178 }
179
180 /// <summary>
181 /// Adds a mention to the activity.
182 /// </summary>
183 /// <param name="account">The account to mention.</param>
184 /// <param name="text">Optional custom text for the mention. If null, uses the account name.</param>
185 /// <param name="addText">Whether to prepend the mention text to the activity's text content.</param>
186 /// <returns>The builder instance for chaining.</returns>
187 public TeamsActivityBuilder AddMention(ConversationAccount account, string? text = null, bool addText = true)
188 {
189 ArgumentNullException.ThrowIfNull(account);
190 string? mentionText = text ?? account.Name;
191
192 if (addText)
193 {
194 string? currentText = _activity.Properties.TryGetValue("text", out object? value) ? value?.ToString() : null;
195 WithProperty("text", $"<at>{mentionText}</at> {currentText}");
196 }
197
198 _activity.Entities ??= [];
199 _activity.Entities.Add(new MentionEntity(account, $"<at>{mentionText}</at>"));
200
201 CoreActivity baseActivity = _activity;
202 baseActivity.Entities = _activity.Entities.ToJsonArray();
203
204 return this;
205 }
206
207 /// <summary>
208 /// Builds and returns the configured TeamsActivity instance.
209 /// </summary>
210 /// <returns>The configured TeamsActivity.</returns>
211 public override TeamsActivity Build()
212 {
213 _activity.Rebase();
214
215 return _activity;
216 }
217
218 private static TeamsAttachment BuildAdaptiveCardAttachment(object adaptiveCard, Action<TeamsAttachmentBuilder>? configure)
219 {
220 ArgumentNullException.ThrowIfNull(adaptiveCard);
221
222 TeamsAttachmentBuilder attachmentBuilder = TeamsAttachment
223 .CreateBuilder()
224 .WithAdaptiveCard(adaptiveCard);
225
226 configure?.Invoke(attachmentBuilder);
227
228 return attachmentBuilder.Build();
229 }
230}
231