// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System.Text; using System.Text.Json; using Microsoft.Bot.Builder.Integration.AspNet.Core.Handlers; using Microsoft.Bot.Schema; using Microsoft.Bot.Schema.Teams; using Microsoft.Teams.Core.Schema; using Newtonsoft.Json; namespace Microsoft.Teams.Apps.BotBuilder; /// /// Extension methods for converting between Bot Framework Activity and CoreActivity/TeamsActivity. /// public static class ActivitySchemaMapper { private static string? GetStringValue(object? value) => value switch { null => null, string s => s, JsonElement { ValueKind: JsonValueKind.String } el => el.GetString(), JsonElement el => el.GetRawText(), _ => value.ToString() }; /// /// Converts a to a Bot Framework . /// /// The core activity to convert. /// The equivalent Bot Framework activity. public static Activity ToBotFrameworkActivity(this CoreActivity activity) { ArgumentNullException.ThrowIfNull(activity); using JsonTextReader reader = new(new StringReader(activity.ToJson())); return BotMessageHandlerBase.BotMessageSerializer.Deserialize(reader)!; } /// /// Converts a Bot Framework to a . /// /// The Bot Framework activity to convert. /// The equivalent core activity. public static CoreActivity FromBotFrameworkActivity(this Activity activity) { StringBuilder sb = new(); using StringWriter stringWriter = new(sb); using JsonTextWriter json = new(stringWriter); BotMessageHandlerBase.BotMessageSerializer.Serialize(json, activity); string jsonString = sb.ToString(); return CoreActivity.FromJsonString(jsonString); } /// /// Converts a to a Bot Framework . /// /// The conversation account to convert. /// The equivalent channel account. public static Microsoft.Bot.Schema.ChannelAccount ToCompatChannelAccount(this Microsoft.Teams.Core.Schema.ChannelAccount account) { ArgumentNullException.ThrowIfNull(account); Microsoft.Bot.Schema.ChannelAccount channelAccount; channelAccount = new() { Id = account.Id, Name = account.Name }; if (account.Properties.TryGetValue("aadObjectId", out object? aadObjectId)) { channelAccount.AadObjectId = GetStringValue(aadObjectId); } if (account.Properties.TryGetValue("userRole", out object? userRole)) { channelAccount.Role = GetStringValue(userRole); } if (account.Properties.TryGetValue("userPrincipalName", out object? userPrincipalName)) { channelAccount.Properties.Add("userPrincipalName", GetStringValue(userPrincipalName) ?? string.Empty); } if (account.Properties.TryGetValue("givenName", out object? givenName)) { channelAccount.Properties.Add("givenName", GetStringValue(givenName) ?? string.Empty); } if (account.Properties.TryGetValue("surname", out object? surname)) { channelAccount.Properties.Add("surname", GetStringValue(surname) ?? string.Empty); } if (account.Properties.TryGetValue("email", out object? email)) { channelAccount.Properties.Add("email", GetStringValue(email) ?? string.Empty); } if (account.Properties.TryGetValue("tenantId", out object? tenantId)) { channelAccount.Properties.Add("tenantId", GetStringValue(tenantId) ?? string.Empty); } return channelAccount; } /// /// Converts a to a with all known properties. /// /// The conversation account to convert. /// The equivalent Teams channel account. public static Microsoft.Bot.Schema.Teams.TeamsChannelAccount ToCompatTeamsChannelAccount2(this Microsoft.Teams.Core.Schema.ChannelAccount account) { ArgumentNullException.ThrowIfNull(account); return new Microsoft.Bot.Schema.Teams.TeamsChannelAccount { Id = account.Id, Name = account.Name, AadObjectId = GetStringValue(account.Properties["aadObjectId"]) ?? string.Empty, Email = GetStringValue(account.Properties["email"]) ?? string.Empty, GivenName = GetStringValue(account.Properties["givenName"]) ?? string.Empty, Surname = GetStringValue(account.Properties["surname"]) ?? string.Empty, UserPrincipalName = GetStringValue(account.Properties["userPrincipalName"]) ?? string.Empty, UserRole = GetStringValue(account.Properties["userRole"]) ?? string.Empty, TenantId = GetStringValue(account.Properties["tenantId"]) ?? string.Empty }; } /// /// Converts a Core PagedMembersResult to a Bot Framework TeamsPagedMembersResult. /// /// The paged members result to convert. /// The equivalent Bot Framework paged members result. public static Microsoft.Bot.Schema.Teams.TeamsPagedMembersResult ToCompatTeamsPagedMembersResult(this Microsoft.Teams.Core.PagedMembersResult pagedMembers) { ArgumentNullException.ThrowIfNull(pagedMembers); return new Microsoft.Bot.Schema.Teams.TeamsPagedMembersResult { ContinuationToken = pagedMembers.ContinuationToken, Members = pagedMembers.Members?.Select(m => m.ToCompatTeamsChannelAccount()).ToList() }; } /// /// Converts a to a . /// /// The conversation account to convert. /// The equivalent Teams channel account. public static Microsoft.Bot.Schema.Teams.TeamsChannelAccount ToCompatTeamsChannelAccount(this Microsoft.Teams.Core.Schema.ChannelAccount account) { ArgumentNullException.ThrowIfNull(account); TeamsChannelAccount teamsChannelAccount = new() { Id = account.Id, Name = account.Name }; // Extract properties from Properties dictionary if (account.Properties.TryGetValue("aadObjectId", out object? aadObjectId)) { teamsChannelAccount.AadObjectId = GetStringValue(aadObjectId); } if (account.Properties.TryGetValue("userPrincipalName", out object? userPrincipalName)) { teamsChannelAccount.UserPrincipalName = GetStringValue(userPrincipalName); } if (account.Properties.TryGetValue("givenName", out object? givenName)) { teamsChannelAccount.GivenName = GetStringValue(givenName); } if (account.Properties.TryGetValue("surname", out object? surname)) { teamsChannelAccount.Surname = GetStringValue(surname); } if (account.Properties.TryGetValue("email", out object? email)) { teamsChannelAccount.Email = GetStringValue(email); } if (account.Properties.TryGetValue("tenantId", out object? tenantId)) { teamsChannelAccount.Properties.Add("tenantId", GetStringValue(tenantId) ?? string.Empty); } return teamsChannelAccount; } /// /// Converts a Bot Framework ChannelAccount to a Core ChannelAccount. /// public static Microsoft.Teams.Core.Schema.ChannelAccount FromCompatChannelAccount(this Microsoft.Bot.Schema.ChannelAccount account) { ArgumentNullException.ThrowIfNull(account); Microsoft.Teams.Core.Schema.ChannelAccount result = new() { Id = account.Id, Name = account.Name }; if (!string.IsNullOrEmpty(account.AadObjectId)) { result.Properties["aadObjectId"] = account.AadObjectId; } if (!string.IsNullOrEmpty(account.Role)) { result.Properties["userRole"] = account.Role; } return result; } /// /// Converts a Bot Framework ConversationParameters to a Core ConversationParameters. /// public static Microsoft.Teams.Core.ConversationParameters FromCompatConversationParameters(this Microsoft.Bot.Schema.ConversationParameters parameters) { ArgumentNullException.ThrowIfNull(parameters); return new Microsoft.Teams.Core.ConversationParameters { IsGroup = parameters.IsGroup, Bot = parameters.Bot?.FromCompatChannelAccount(), Members = parameters.Members?.Select(m => m.FromCompatChannelAccount()).ToList(), TopicName = parameters.TopicName, Activity = parameters.Activity?.FromBotFrameworkActivity(), ChannelData = parameters.ChannelData, TenantId = parameters.TenantId, }; } /// /// Gets the TeamInfo object from the current activity. /// /// The activity. /// The current activity's team's information, or null. public static TeamInfo? TeamsGetTeamInfo(this IActivity activity) { ArgumentNullException.ThrowIfNull(activity); Microsoft.Bot.Schema.Teams.TeamsChannelData channelData = activity.GetChannelData(); return channelData?.Team; } }