microsoft/teams.net
Publicmirrored from https://github.com/microsoft/teams.netAvailable
core/src/Microsoft.Teams.Apps/Schema/Entities/ActivityQuotedReplyExtensions.cs
82lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | using System.Diagnostics.CodeAnalysis; |
| 5 | using System.Security; |
| 6 | |
| 7 | namespace Microsoft.Teams.Apps.Schema.Entities; |
| 8 | |
| 9 | /// <summary> |
| 10 | /// Extension methods for Activity to handle quoted replies. |
| 11 | /// </summary> |
| 12 | [Experimental("ExperimentalTeamsQuotedReplies")] |
| 13 | public 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 ", <, & 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 | |