microsoft/teams.net

Public

mirrored from https://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
feat/a365-mcp

Branches

Tags

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

Clone

HTTPS

Download ZIP

core/src/Microsoft.Teams.Apps/Schema/Entities/ActivityQuotedReplyExtensions.cs

82lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Diagnostics.CodeAnalysis;
5using System.Security;
6
7namespace Microsoft.Teams.Apps.Schema.Entities;
8
9/// <summary>
10/// Extension methods for Activity to handle quoted replies.
11/// </summary>
12[Experimental("ExperimentalTeamsQuotedReplies")]
13public static class ActivityQuotedReplyExtensions
14{
15 /// <summary>
16 /// Builds the inline placeholder element that pairs with a <see cref="QuotedReplyEntity"/>.
17 /// XML-escapes <paramref name="messageId"/> so values containing &quot;, &lt;, &amp; etc. can't break out of the attribute.
18 /// </summary>
19 internal static string QuotedPlaceholder(string messageId)
20 => $"<quoted messageId=\"{SecurityElement.Escape(messageId)}\"/>";
21
22 /// <summary>
23 /// Gets all quoted reply entities from the activity's entity collection.
24 /// </summary>
25 /// <param name="activity">The activity to extract quoted replies from. Cannot be null.</param>
26 /// <returns>An enumerable of QuotedReplyEntity instances found in the activity's entities.</returns>
27 public static IEnumerable<QuotedReplyEntity> GetQuotedMessages(this TeamsActivity activity)
28 {
29 ArgumentNullException.ThrowIfNull(activity);
30 if (activity.Entities == null)
31 {
32 return [];
33 }
34 return activity.Entities.OfType<QuotedReplyEntity>();
35 }
36
37 /// <summary>
38 /// Add a quoted message reference and append a placeholder to the message text.
39 /// Teams renders the quoted message as a preview bubble above the response text.
40 /// If text is provided, it is appended to the quoted message placeholder.
41 /// </summary>
42 /// <param name="activity">The message activity to add the quote to. Cannot be null.</param>
43 /// <param name="messageId">The ID of the message to quote. Cannot be null or whitespace.</param>
44 /// <param name="text">Optional text, appended to the quoted message placeholder.</param>
45 /// <returns>The created QuotedReplyEntity that was added to the activity.</returns>
46 public static QuotedReplyEntity AddQuote(this MessageActivity activity, string messageId, string? text = null)
47 {
48 ArgumentNullException.ThrowIfNull(activity);
49 ArgumentException.ThrowIfNullOrWhiteSpace(messageId);
50
51 QuotedReplyEntity entity = new() { QuotedReply = new QuotedReplyData { MessageId = messageId } };
52 activity.Entities ??= [];
53 activity.Entities.Add(entity);
54
55 activity.Text = (activity.Text ?? "") + QuotedPlaceholder(messageId);
56 if (text != null)
57 {
58 activity.Text += $" {text}";
59 }
60
61 return entity;
62 }
63
64 /// <summary>
65 /// Prepend a QuotedReply entity and placeholder before existing text.
66 /// Used by <see cref="Context{TActivity}.Reply(TeamsActivity, CancellationToken)"/> and
67 /// <see cref="Context{TActivity}.Quote(string, TeamsActivity, CancellationToken)"/> for quote-above-response.
68 /// </summary>
69 /// <param name="activity">The message activity to prepend the quoted reply to.</param>
70 /// <param name="messageId">The ID of the message to quote.</param>
71 public static void PrependQuote(this MessageActivity activity, string messageId)
72 {
73 ArgumentNullException.ThrowIfNull(activity);
74 ArgumentException.ThrowIfNullOrWhiteSpace(messageId);
75
76 activity.Entities ??= [];
77 activity.Entities.Insert(0, new QuotedReplyEntity { QuotedReply = new QuotedReplyData { MessageId = messageId } });
78 var placeholder = QuotedPlaceholder(messageId);
79 var text = activity.Text?.Trim() ?? "";
80 activity.Text = string.IsNullOrEmpty(text) ? placeholder : $"{placeholder} {text}";
81 }
82}
83