// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System.Text.Json; using Microsoft.Teams.Apps.Routing; using Microsoft.Teams.Apps.Schema; namespace Microsoft.Teams.Apps.Handlers.MessageExtension; /// /// Delegate for handling message extension query invoke activities. /// public delegate Task> MessageExtensionQueryHandler(Context> context, CancellationToken cancellationToken = default); /// /// Delegate for handling message extension submit action invoke activities. /// Can return either a TaskModuleResponse or MessageExtensionResponse. /// public delegate Task> MessageExtensionSubmitActionHandler(Context> context, CancellationToken cancellationToken = default); /// /// Delegate for handling message extension fetch task invoke activities. /// Can return either a TaskModuleResponse or MessageExtensionResponse. /// public delegate Task> MessageExtensionFetchTaskHandler(Context> context, CancellationToken cancellationToken = default); /// /// Delegate for handling message extension query link invoke activities. /// public delegate Task> MessageExtensionQueryLinkHandler(Context> context, CancellationToken cancellationToken = default); /// /// Delegate for handling message extension anonymous query link invoke activities. /// public delegate Task> MessageExtensionAnonQueryLinkHandler(Context> context, CancellationToken cancellationToken = default); /// /// Delegate for handling message extension select item invoke activities. /// public delegate Task> MessageExtensionSelectItemHandler(Context> context, CancellationToken cancellationToken = default); /// /// Delegate for handling message extension query setting URL invoke activities. /// public delegate Task> MessageExtensionQuerySettingUrlHandler(Context> context, CancellationToken cancellationToken = default); /* /// /// Delegate for handling message extension card button clicked invoke activities. /// public delegate Task MessageExtensionCardButtonClickedHandler(Context> context, CancellationToken cancellationToken = default); /// /// Delegate for handling message extension setting invoke activities. /// public delegate Task MessageExtensionSettingHandler(Context> context, CancellationToken cancellationToken = default); */ /// /// Extension methods for registering message extension invoke handlers. /// public static class MessageExtensionExtensions { //TODO : add msg ext prefix to handlers ? very confusing right now as we have both onFetchTask and onTaskFetch. //onSubmitAction is confusing as it is similar to adaptive cards /// /// Registers a handler for message extension query invoke activities. /// Cannot be combined with . /// /// /// Breaking change: previously a catch-all invoke handler could be registered alongside specific invoke handlers. This combination now throws at registration time. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnQuery(this TeamsBotApplication app, MessageExtensionQueryHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", TeamsActivityTypes.Invoke, InvokeNames.MessageExtensionQuery), Selector = activity => activity.Name == InvokeNames.MessageExtensionQuery, HandlerWithReturn = async (ctx, cancellationToken) => { InvokeActivity typedActivity = new(ctx.Activity); var typedContext = ctx.CreateDerivedContext(typedActivity); return await handler(typedContext, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for message extension submit action invoke activities. /// Cannot be combined with . /// /// /// Breaking change: previously a catch-all invoke handler could be registered alongside specific invoke handlers. This combination now throws at registration time. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnSubmitAction(this TeamsBotApplication app, MessageExtensionSubmitActionHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", TeamsActivityTypes.Invoke, InvokeNames.MessageExtensionSubmitAction), Selector = activity => activity.Name == InvokeNames.MessageExtensionSubmitAction, HandlerWithReturn = async (ctx, cancellationToken) => { InvokeActivity typedActivity = new(ctx.Activity); var typedContext = ctx.CreateDerivedContext(typedActivity); return await handler(typedContext, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for message extension query link invoke activities. /// Cannot be combined with . /// /// /// Breaking change: previously a catch-all invoke handler could be registered alongside specific invoke handlers. This combination now throws at registration time. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnQueryLink(this TeamsBotApplication app, MessageExtensionQueryLinkHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", TeamsActivityTypes.Invoke, InvokeNames.MessageExtensionQueryLink), Selector = activity => activity.Name == InvokeNames.MessageExtensionQueryLink, HandlerWithReturn = async (ctx, cancellationToken) => { InvokeActivity typedActivity = new(ctx.Activity); var typedContext = ctx.CreateDerivedContext(typedActivity); return await handler(typedContext, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for message extension anonymous query link invoke activities. /// Cannot be combined with . /// /// /// Breaking change: previously a catch-all invoke handler could be registered alongside specific invoke handlers. This combination now throws at registration time. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnAnonQueryLink(this TeamsBotApplication app, MessageExtensionAnonQueryLinkHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", TeamsActivityTypes.Invoke, InvokeNames.MessageExtensionAnonQueryLink), Selector = activity => activity.Name == InvokeNames.MessageExtensionAnonQueryLink, HandlerWithReturn = async (ctx, cancellationToken) => { InvokeActivity typedActivity = new(ctx.Activity); var typedContext = ctx.CreateDerivedContext(typedActivity); return await handler(typedContext, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for message extension fetch task invoke activities. /// Cannot be combined with . /// /// /// Breaking change: previously a catch-all invoke handler could be registered alongside specific invoke handlers. This combination now throws at registration time. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnFetchTask(this TeamsBotApplication app, MessageExtensionFetchTaskHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", TeamsActivityTypes.Invoke, InvokeNames.MessageExtensionFetchTask), Selector = activity => activity.Name == InvokeNames.MessageExtensionFetchTask, HandlerWithReturn = async (ctx, cancellationToken) => { InvokeActivity typedActivity = new(ctx.Activity); var typedContext = ctx.CreateDerivedContext(typedActivity); return await handler(typedContext, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for message extension select item invoke activities. /// Cannot be combined with . /// /// /// Breaking change: previously a catch-all invoke handler could be registered alongside specific invoke handlers. This combination now throws at registration time. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnSelectItem(this TeamsBotApplication app, MessageExtensionSelectItemHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", TeamsActivityTypes.Invoke, InvokeNames.MessageExtensionSelectItem), Selector = activity => activity.Name == InvokeNames.MessageExtensionSelectItem, HandlerWithReturn = async (ctx, cancellationToken) => { InvokeActivity typedActivity = new(ctx.Activity); var typedContext = ctx.CreateDerivedContext(typedActivity); return await handler(typedContext, cancellationToken).ConfigureAwait(false); } }); return app; } /// /// Registers a handler for message extension query setting URL invoke activities. /// Cannot be combined with . /// /// /// Breaking change: previously a catch-all invoke handler could be registered alongside specific invoke handlers. This combination now throws at registration time. /// /// The Teams bot application. /// The handler to register. /// The updated Teams bot application. public static TeamsBotApplication OnQuerySettingUrl(this TeamsBotApplication app, MessageExtensionQuerySettingUrlHandler handler) { ArgumentNullException.ThrowIfNull(app, nameof(app)); app.Router.Register(new Route { Name = string.Join("/", TeamsActivityTypes.Invoke, InvokeNames.MessageExtensionQuerySettingUrl), Selector = activity => activity.Name == InvokeNames.MessageExtensionQuerySettingUrl, HandlerWithReturn = async (ctx, cancellationToken) => { InvokeActivity typedActivity = new(ctx.Activity); var typedContext = ctx.CreateDerivedContext(typedActivity); return await handler(typedContext, cancellationToken).ConfigureAwait(false); } }); return app; } }