// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using Microsoft.Teams.Api.Entities; using Microsoft.Teams.Common; namespace Microsoft.Teams.Api.Activities; public partial class ActivityType : StringEnum { public static readonly ActivityType Message = new("message"); public bool IsMessage => Message.Equals(Value); } public class MessageActivity : Activity { [JsonPropertyName("text")] [JsonPropertyOrder(31)] public string Text { get; set; } [JsonPropertyName("speak")] [JsonPropertyOrder(32)] [Obsolete("This will be removed by end of summer 2026.")] public string? Speak { get; set; } [JsonPropertyName("inputHint")] [JsonPropertyOrder(33)] [Obsolete("This will be removed by end of summer 2026.")] public InputHint? InputHint { get; set; } [JsonPropertyName("summary")] [JsonPropertyOrder(34)] public string? Summary { get; set; } [JsonPropertyName("textFormat")] [JsonPropertyOrder(35)] public TextFormat? TextFormat { get; set; } [JsonPropertyName("attachmentLayout")] [JsonPropertyOrder(121)] public Attachment.Layout? AttachmentLayout { get; set; } [JsonPropertyName("attachments")] [JsonPropertyOrder(122)] public IList? Attachments { get; set; } [JsonPropertyName("suggestedActions")] [JsonPropertyOrder(123)] public SuggestedActions? SuggestedActions { get; set; } [JsonPropertyName("importance")] [JsonPropertyOrder(39)] [Obsolete("This will be removed by end of summer 2026.")] public Importance? Importance { get; set; } [JsonPropertyName("deliveryMode")] [JsonPropertyOrder(41)] public DeliveryMode? DeliveryMode { get; set; } [JsonPropertyName("expiration")] [JsonPropertyOrder(42)] [Obsolete("This will be removed by end of summer 2026.")] public DateTime? Expiration { get; set; } [JsonPropertyName("value")] [JsonPropertyOrder(43)] public object? Value { get; set; } [JsonIgnore] public bool IsRecipientMentioned { get => (Entities ?? []).Any(e => e is MentionEntity mention && mention.Mentioned.Id == Recipient.Id); } /// /// Get all quoted reply entities from this message. /// public IReadOnlyList GetQuotedMessages() { return Entities?.OfType().ToList() ?? new List(); } public MessageActivity() : base(ActivityType.Message) { Text ??= string.Empty; } public MessageActivity(string text) : base(ActivityType.Message) { Text = text; } public MessageActivity WithText(string text) { Text = text; return this; } [Obsolete("This will be removed by end of summer 2026.")] public MessageActivity WithSpeak(string speak) { #pragma warning disable CS0618 Speak = speak; #pragma warning restore CS0618 return this; } [Obsolete("This will be removed by end of summer 2026.")] public MessageActivity WithInputHint(InputHint inputHint) { #pragma warning disable CS0618 InputHint = inputHint; #pragma warning restore CS0618 return this; } public MessageActivity WithSummary(string summary) { Summary = summary; return this; } public MessageActivity WithTextFormat(TextFormat textFormat) { TextFormat = textFormat; return this; } public MessageActivity WithAttachmentLayout(Attachment.Layout attachmentLayout) { AttachmentLayout = attachmentLayout; return this; } public MessageActivity WithSuggestedActions(SuggestedActions suggestedActions) { SuggestedActions = suggestedActions; return this; } [Obsolete("This will be removed by end of summer 2026.")] public MessageActivity WithImportance(Importance importance) { #pragma warning disable CS0618 Importance = importance; #pragma warning restore CS0618 return this; } public MessageActivity WithDeliveryMode(DeliveryMode deliveryMode) { DeliveryMode = deliveryMode; return this; } [Obsolete("This will be removed by end of summer 2026.")] public MessageActivity WithExpiration(DateTime expiration) { #pragma warning disable CS0618 Expiration = expiration; #pragma warning restore CS0618 return this; } public MessageActivity AddText(string text) { Text += text; return this; } public override MessageActivity WithRecipient(Account value) { return (MessageActivity)base.WithRecipient(value); } [Experimental("ExperimentalTeamsTargeted")] #pragma warning disable ExperimentalTeamsTargeted public override MessageActivity WithRecipient(Account value, bool isTargeted = false) { return (MessageActivity)base.WithRecipient(value, isTargeted); } #pragma warning restore ExperimentalTeamsTargeted /// /// Add a quoted message reference and append a placeholder to text. /// Teams renders the quoted message as a preview bubble above the response text. /// If text is provided, it is appended to the quoted message placeholder. /// /// the ID of the message to quote /// optional text, appended to the quoted message placeholder public MessageActivity AddQuote(string messageId, string? text = null) { Entities ??= new List(); Entities.Add(new QuotedReplyEntity { QuotedReply = new QuotedReplyData { MessageId = messageId } }); AddText($""); if (text != null) { AddText($" {text}"); } return this; } /// /// Prepend a QuotedReply entity and placeholder before existing text. /// Used by Reply()/Quote() for quote-above-response. /// public MessageActivity PrependQuote(string messageId) { Entities ??= new List(); Entities.Add(new QuotedReplyEntity { QuotedReply = new QuotedReplyData { MessageId = messageId } }); var placeholder = $""; var hasText = !string.IsNullOrWhiteSpace(Text); Text = hasText ? $"{placeholder} {Text}" : placeholder; return this; } public MessageActivity AddAttachment(params Attachment[] value) { Attachments ??= []; foreach (var attachment in value) { Attachments.Add(attachment); } return this; } public MessageActivity AddAttachment(Teams.Cards.AdaptiveCard card) { return AddAttachment(new Attachment(card)); } public MessageActivity AddAttachment(Cards.OAuthCard card) { return AddAttachment(new Attachment(card)); } public MessageActivity AddAttachment(Cards.SignInCard card) { return AddAttachment(new Attachment(card)); } public MessageActivity AddMention(Account account, string? text = null, bool addText = true) { var mentionText = text ?? account.Name; if (addText) { Text = $"{mentionText} {Text}"; } AddEntity(new MentionEntity() { Mentioned = account, Text = $"{mentionText}" }); return this; } public MessageActivity AddStreamFinal() { ChannelData ??= new(); ChannelData.StreamId ??= Id; ChannelData.StreamType = StreamType.Final; AddEntity(new StreamInfoEntity() { StreamId = Id, StreamType = StreamType.Final }); return this; } public MentionEntity? GetAccountMention(string accountId) { return (MentionEntity?)(Entities ?? []).FirstOrDefault(e => e is MentionEntity mention && mention.Mentioned.Id == accountId); } public MessageActivity Merge(MessageActivity from) { base.Merge(from); Text ??= from.Text; #pragma warning disable CS0618 Speak ??= from.Speak; InputHint ??= from.InputHint; Importance ??= from.Importance; Expiration ??= from.Expiration; #pragma warning restore CS0618 Summary ??= from.Summary; TextFormat ??= from.TextFormat; AttachmentLayout ??= from.AttachmentLayout; SuggestedActions ??= from.SuggestedActions; DeliveryMode ??= from.DeliveryMode; Value ??= from.Value; AddAttachment(from.Attachments?.ToArray() ?? []); return this; } }