Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions core/samples/AllFeatures/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

await context.SendTypingActivityAsync(cancellationToken);

TeamsActivity reply = TeamsActivity.CreateBuilder()
.WithType(TeamsActivityType.Message)
MessageActivity reply = MessageActivity.CreateBuilder()
.WithConversationReference(context.Activity)
.WithText(replyText)
.Build();
Expand Down
2 changes: 1 addition & 1 deletion core/samples/CompatBot/EchoBot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivi
// await turnContext.SendActivityAsync(MessageFactory.Text($"Send a proactive message `/api/notify/{turnContext.Activity.Conversation.Id}`"), cancellationToken);

var incomingCoreActivity = ((Activity)turnContext.Activity).FromCompatActivity();
TeamsActivity tm = TeamsActivity.CreateBuilder()
MessageActivity tm = MessageActivity.CreateBuilder()
.WithConversation(new Conversation { Id = incomingCoreActivity.Conversation?.Id! })
.WithText("Hello TM !")
.WithRecipient(incomingCoreActivity.From, true)
Expand Down
3 changes: 1 addition & 2 deletions core/samples/TabApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@
conversationId = cached!;
}

TeamsActivity activity = TeamsActivity.CreateBuilder()
.WithType(TeamsActivityType.Message)
MessageActivity activity = MessageActivity.CreateBuilder()
.WithText("Hello from the tab!")
.WithServiceUrl(serviceUrl)
.WithConversation(new TeamsConversation { Id = conversationId! })
Expand Down
23 changes: 8 additions & 15 deletions core/samples/TeamsBot/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ await context.SendActivityAsync(
}, cancellationToken);


var helpActivity = TeamsActivity.CreateBuilder()
.WithType(TeamsActivityType.Message)
var helpActivity = MessageActivity.CreateBuilder()
.WithText(WelcomeMessageMiddleware.WelcomeMessage, TextFormats.Markdown)
.WithSuggestedActions(new SuggestedActions()
{
Expand All @@ -57,8 +56,7 @@ await context.SendActivityAsync(

string replyText = $"You sent: `{context.Activity.Text}`. Type `help` to see available commands.";

TeamsActivity ta = TeamsActivity.CreateBuilder()
.WithType(TeamsActivityType.Message)
MessageActivity ta = MessageActivity.CreateBuilder()
.WithText(replyText)
.AddMention(context.Activity.From)
.Build();
Expand Down Expand Up @@ -144,8 +142,7 @@ [Visit Microsoft](https://www.microsoft.com)
ArgumentNullException.ThrowIfNull(context.Activity.ServiceUrl);

// Send a targeted message visible only to the sender
TeamsActivity targeted = TeamsActivity.CreateBuilder()
.WithType(TeamsActivityType.Message)
MessageActivity targeted = MessageActivity.CreateBuilder()
.WithText("This is a targeted message only you can see!")
.WithRecipient(context.Activity.From, isTargeted: true)
.Build();
Expand All @@ -155,8 +152,7 @@ [Visit Microsoft](https://www.microsoft.com)
await Task.Delay(2000, cancellationToken);

// Update the targeted message (must use UpdateTargetedAsync to avoid setting Recipient on the update payload)
TeamsActivity updated = TeamsActivity.CreateBuilder()
.WithType(TeamsActivityType.Message)
MessageActivity updated = MessageActivity.CreateBuilder()
.WithText("This targeted message was updated!")
.WithServiceUrl(context.Activity.ServiceUrl)
.Build();
Expand All @@ -183,8 +179,7 @@ await context.TeamsBotApplication.Api.Conversations.Activities.DeleteTargetedAsy
ArgumentNullException.ThrowIfNull(context.Activity.Conversation);
ArgumentNullException.ThrowIfNull(context.Activity.ServiceUrl);

var tmMsgToReact = TeamsActivity.CreateBuilder()
.WithType(TeamsActivityType.Message)
var tmMsgToReact = MessageActivity.CreateBuilder()
.WithText("I'm going to add and remove reactions to this message.")
.WithRecipient(context.Activity.From, false)
.WithServiceUrl(context.Activity.ServiceUrl)
Expand Down Expand Up @@ -264,8 +259,7 @@ await context.TeamsBotApplication.Api.Conversations.Reactions.DeleteAsync(
]
};

var reply = TeamsActivity.CreateBuilder()
.WithType(TeamsActivityType.Message)
var reply = MessageActivity.CreateBuilder()
.WithText("Here are some suggested actions for you:")
.WithSuggestedActions(suggestedActions)
.Build();
Expand Down Expand Up @@ -329,7 +323,7 @@ await context.TeamsBotApplication.Api.Conversations.Reactions.DeleteAsync(
string? feedbackValue = context.Activity.Value?.Action?.Data?["feedback"]?.ToString();

TeamsActivity reply = TeamsActivity.CreateBuilder()
.WithAttachment(TeamsAttachment.CreateBuilder()
.AddAttachment(TeamsAttachment.CreateBuilder()
.WithAdaptiveCard(Cards.ResponseCard(feedbackValue))
.Build()
)
Expand Down Expand Up @@ -366,8 +360,7 @@ await context.TeamsBotApplication.Api.Conversations.Reactions.DeleteAsync(
string? name = data?["userName"]?.ToString();
string? comment = data?["userComment"]?.ToString();

TeamsActivity reply = TeamsActivity.CreateBuilder()
.WithType(TeamsActivityType.Message)
MessageActivity reply = MessageActivity.CreateBuilder()
.WithText($"**Task module submitted!**\n- Name: {name ?? "(empty)"}\n- Comment: {comment ?? "(empty)"}")
.Build();

Expand Down
4 changes: 2 additions & 2 deletions core/samples/TeamsBot/WelcomeMessageMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public async Task OnTurnAsync(BotApplication botApplication, CoreActivity activi
{
if (!_hasSentWelcomeMessage)
{
var welcomeActivity = TeamsActivity.CreateBuilder()
var welcomeActivity = MessageActivity.CreateBuilder()
.WithType("message")
.WithText(WelcomeMessage, TextFormats.Markdown)
.WithConversationReference(TeamsActivity.FromActivity(activity))
.WithConversationReference(activity)
.Build();

await botApplication.SendActivityAsync(welcomeActivity, cancellationToken);
Expand Down
2 changes: 1 addition & 1 deletion core/src/Microsoft.Teams.Bot.Apps/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class Context<TActivity>(TeamsBotApplication botApplication, TActivity ac
/// <returns></returns>
public Task<SendActivityResponse?> SendActivityAsync(string text, CancellationToken cancellationToken = default)
=> TeamsBotApplication.SendActivityAsync(
new TeamsActivityBuilder()
MessageActivity.CreateBuilder()
.WithConversationReference(Activity)
.WithText(text)
.Build(), cancellationToken);
Expand Down
3 changes: 1 addition & 2 deletions core/src/Microsoft.Teams.Bot.Apps/Handlers/InvokeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ public static class InvokeExtensions
{
/// <summary>
/// Registers a catch-all handler for all invoke activities.
/// Cannot be combined with specific invoke handlers such as <see cref="AdaptiveCardExtensions.OnAdaptiveCardAction"/>,
/// <see cref="TaskExtensions.OnTaskFetch"/>, etc.
/// Cannot be combined with specific invoke handlers such as <see cref="AdaptiveCardExtensions.OnAdaptiveCardAction"/>
/// </summary>
/// <remarks>
/// Breaking change: previously a catch-all invoke handler could be registered alongside specific invoke handlers. This combination now throws at registration time.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using Microsoft.Teams.Bot.Apps.Routing;
using Microsoft.Teams.Bot.Apps.Schema;

namespace Microsoft.Teams.Bot.Apps.Handlers;
namespace Microsoft.Teams.Bot.Apps.Handlers.TaskModules;

/// <summary>
/// Delegate for handling task module invoke activities.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,43 @@
// Licensed under the MIT License.

using System.Text.Json.Serialization;
using Microsoft.Teams.Bot.Apps.Schema;

namespace Microsoft.Teams.Bot.Apps.Schema.Entities;

/// <summary>
/// Extension methods for activity product info.
/// </summary>
public static class ActivityProductInfoExtensions
{
/// <summary>
/// Adds a product info entity to the activity.
/// </summary>
/// <param name="activity">The activity to add product info to. Cannot be null.</param>
/// <param name="id">The product identifier.</param>
/// <returns>The created ProductInfoEntity that was added to the activity.</returns>
public static ProductInfoEntity AddProductInfo(this TeamsActivity activity, string id)
{
ArgumentNullException.ThrowIfNull(activity);
ProductInfoEntity productInfo = new() { Id = id };
activity.Entities ??= [];
activity.Entities.Add(productInfo);
activity.Rebase();
return productInfo;
}

/// <summary>
/// Gets the product info entity from the activity's entity collection, if present.
/// </summary>
/// <param name="activity">The activity to read from. Cannot be null.</param>
/// <returns>The ProductInfoEntity if found; otherwise, null.</returns>
public static ProductInfoEntity? GetProductInfo(this TeamsActivity activity)
{
ArgumentNullException.ThrowIfNull(activity);
return activity.Entities?.FirstOrDefault(e => e is ProductInfoEntity) as ProductInfoEntity;
}
}




Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,50 @@
// Licensed under the MIT License.

using System.Text.Json.Serialization;
using Microsoft.Teams.Bot.Apps.Schema;

namespace Microsoft.Teams.Bot.Apps.Schema.Entities;

/// <summary>
/// Extension methods for activity stream info.
/// </summary>
public static class ActivityStreamInfoExtensions
{
/// <summary>
/// Adds a stream info entity to the activity.
/// </summary>
/// <param name="activity">The activity to add stream info to. Cannot be null.</param>
/// <param name="streamType">The stream type. See <see cref="StreamType"/> for possible values.</param>
/// <param name="streamId">Optional stream identifier.</param>
/// <param name="streamSequence">Optional stream sequence number.</param>
/// <returns>The created StreamInfoEntity that was added to the activity.</returns>
public static StreamInfoEntity AddStreamInfo(this TeamsActivity activity, string streamType, string? streamId = null, int? streamSequence = null)
{
ArgumentNullException.ThrowIfNull(activity);
StreamInfoEntity streamInfo = new()
{
StreamType = streamType,
StreamId = streamId,
StreamSequence = streamSequence
};
activity.Entities ??= [];
activity.Entities.Add(streamInfo);
activity.Rebase();
return streamInfo;
}

/// <summary>
/// Gets the stream info entity from the activity's entity collection, if present.
/// </summary>
/// <param name="activity">The activity to read from. Cannot be null.</param>
/// <returns>The StreamInfoEntity if found; otherwise, null.</returns>
public static StreamInfoEntity? GetStreamInfo(this TeamsActivity activity)
{
ArgumentNullException.ThrowIfNull(activity);
return activity.Entities?.FirstOrDefault(e => e is StreamInfoEntity) as StreamInfoEntity;
}
}

/// <summary>
/// Stream info entity.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Microsoft.Teams.Bot.Apps.Schema.Entities;
using Microsoft.Teams.Bot.Core.Schema;

namespace Microsoft.Teams.Bot.Apps.Schema;

/// <summary>
/// Provides a fluent API for building <see cref="MessageActivity"/> instances.
/// Uses typed property setters for first-class message fields (Text, TextFormat, SuggestedActions).
/// </summary>
public class MessageActivityBuilder : TeamsActivityBuilder<MessageActivity, MessageActivityBuilder>
{
/// <summary>
/// Initializes a new instance of the MessageActivityBuilder class.
/// </summary>
internal MessageActivityBuilder() : base(new MessageActivity())
{
}

/// <summary>
/// Initializes a new instance of the MessageActivityBuilder class with an existing activity.
/// </summary>
/// <param name="activity">The activity to build upon.</param>
internal MessageActivityBuilder(MessageActivity activity) : base(activity)
{
}

/// <summary>
/// Sets the text content and text format of the message.
/// </summary>
public MessageActivityBuilder WithText(string text, string textFormat = "plain")
{
_activity.Text = text;
_activity.TextFormat = textFormat;
return this;
}

/// <summary>
/// Sets the suggested actions for the message.
/// </summary>
public MessageActivityBuilder WithSuggestedActions(SuggestedActions suggestedActions)
{
_activity.SuggestedActions = suggestedActions;
return this;
}

/// <summary>
/// Adds a mention to the activity.
/// </summary>
/// <param name="account">The account to mention.</param>
/// <param name="text">Optional custom text for the mention. If null, uses the account name.</param>
/// <param name="addText">Whether to prepend the mention text to the activity's text content.</param>
public MessageActivityBuilder AddMention(ConversationAccount account, string? text = null, bool addText = true)
{
ArgumentNullException.ThrowIfNull(account);
string? mentionText = text ?? account.Name;

if (addText)
{
_activity.Text = $"<at>{mentionText}</at> {_activity.Text}";
}

_activity.Entities ??= [];
_activity.Entities.Add(new MentionEntity(account, $"<at>{mentionText}</at>"));

return this;
}

/// <summary>
/// Builds and returns the configured MessageActivity instance.
/// </summary>
public override MessageActivity Build()
{
_activity.Rebase();
return _activity;
}
}
20 changes: 15 additions & 5 deletions core/src/Microsoft.Teams.Bot.Apps/Schema/MessageActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ protected MessageActivity(CoreActivity activity) : base(activity)
{
SuggestedActions = JsonSerializer.Deserialize<SuggestedActions>(je.GetRawText());
}
else
{
SuggestedActions = suggestedActions as SuggestedActions;
}
activity.Properties.Remove("suggestedActions");
}
/*
Expand Down Expand Up @@ -135,7 +131,21 @@ protected MessageActivity(CoreActivity activity) : base(activity)
[JsonPropertyName("attachmentLayout")]
public string? AttachmentLayout { get; set; }


/// <summary>
/// Gets or sets the suggested actions for the message.
/// </summary>
[JsonPropertyName("suggestedActions")]
public SuggestedActions? SuggestedActions { get; set; }

/// <summary>
/// Creates a new <see cref="MessageActivityBuilder"/> instance.
/// </summary>
public static new MessageActivityBuilder CreateBuilder() => new();

/// <summary>
/// Creates a new <see cref="MessageActivityBuilder"/> initialized with an existing activity.
/// </summary>
public static MessageActivityBuilder CreateBuilder(MessageActivity activity) => new(activity);

//TODO : Review properties
/*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace Microsoft.Teams.Bot.Apps.Schema;

/// <summary>
/// Provides a fluent API for building <see cref="StreamingActivity"/> instances.
/// </summary>
public class StreamingActivityBuilder : TeamsActivityBuilder<StreamingActivity, StreamingActivityBuilder>
{
/// <summary>
/// Initializes a new instance of the StreamingActivityBuilder class with an initial text chunk.
/// </summary>
/// <param name="text">The initial text content of the streaming chunk.</param>
internal StreamingActivityBuilder(string text = "") : base(new StreamingActivity(text))
{
}

/// <summary>
/// Sets the text content of the streaming chunk.
/// </summary>
public StreamingActivityBuilder WithText(string text)
{
_activity.Text = text;
return this;
}

/// <summary>
/// Builds and returns the configured StreamingActivity instance.
/// </summary>
public override StreamingActivity Build()
{
_activity.Rebase();
return _activity;
}
}
Loading
Loading