// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.Teams.Apps.Routing; using Microsoft.Teams.Apps.Schema; namespace Microsoft.Teams.Apps.Handlers; /// /// Delegate for handling conversation update activities. /// /// The context for the conversation update activity. /// A cancellation token that can be used to cancel the operation. /// A task representing the asynchronous operation. public delegate Task ConversationUpdateHandler(Context context, CancellationToken cancellationToken = default); /// /// Extension methods for registering conversation update activity handlers. /// public static class ConversationUpdateExtensions { /// /// Registers a handler for conversation update activities. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnConversationUpdate(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = TeamsActivityTypes.ConversationUpdate, Selector = _ => true, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for conversation update activities where members were added. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnMembersAdded(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, "membersAdded"]), Selector = activity => activity.MembersAdded?.Count > 0, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for conversation update activities where members were removed. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnMembersRemoved(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, "membersRemoved"]), Selector = activity => activity.MembersRemoved?.Count > 0, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } // Channel Event Handlers /// /// Registers a handler for channel created events. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnChannelCreated(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.ChannelCreated]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.ChannelCreated, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for channel deleted events. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnChannelDeleted(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.ChannelDeleted]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.ChannelDeleted, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for channel renamed events. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnChannelRenamed(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.ChannelRenamed]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.ChannelRenamed, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for channel shared events. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnChannelShared(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.ChannelShared]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.ChannelShared, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for channel unshared events. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnChannelUnshared(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.ChannelUnShared]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.ChannelUnShared, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for channel member added events. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnChannelMemberAdded(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.ChannelMemberAdded]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.ChannelMemberAdded, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for channel member removed events. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnChannelMemberRemoved(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.ChannelMemberRemoved]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.ChannelMemberRemoved, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /* /// /// Registers a handler for channel restored events. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnChannelRestored(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.ChannelRestored]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.ChannelRestored, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } */ // Team Event Handlers /// /// Registers a handler for team member added events. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnTeamMemberAdded(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.TeamMemberAdded]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.TeamMemberAdded, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for team member removed events. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnTeamMemberRemoved(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.TeamMemberRemoved]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.TeamMemberRemoved, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for team archived events. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnTeamArchived(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.TeamArchived]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.TeamArchived, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for team deleted events. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnTeamDeleted(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.TeamDeleted]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.TeamDeleted, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for team renamed events. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnTeamRenamed(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.TeamRenamed]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.TeamRenamed, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for team unarchived events. /// /// /// Breaking change: previously only the first matching handler was invoked. All matching handlers are now invoked sequentially. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnTeamUnarchived(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.TeamUnarchived]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.TeamUnarchived, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /* /// Registers a handler for team restored events. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnTeamRestored(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.TeamRestored]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.TeamRestored, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for team hard deleted events. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnTeamHardDeleted(this TeamsBotApplication app, ConversationUpdateHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", [TeamsActivityTypes.ConversationUpdate, ConversationEventTypes.TeamHardDeleted]), Selector = activity => activity.ChannelData?.EventType == ConversationEventTypes.TeamHardDeleted, Handler = async (ctx, cancellationToken) => { await handler(ctx, cancellationToken).ConfigureAwait(false); } }); return app; } */ }