Skip to content
This repository has been archived by the owner on Jan 15, 2025. It is now read-only.

fix: Send message to teams channel support both adapters #1174

Merged
merged 3 commits into from
Jun 30, 2021
Merged
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
49 changes: 41 additions & 8 deletions packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.

using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Claims;
using System.Threading;
Expand Down Expand Up @@ -119,20 +120,52 @@ public SendMessageToTeamsChannel([CallerFilePath] string callerPath = "", [Calle
teamsChannelId = dc.Context.Activity.TeamsGetChannelId();
}

// Retrieve the bot appid from TurnState's ClaimsIdentity
string appId;
if (dc.Context.TurnState.Get<ClaimsIdentity>(BotAdapter.BotIdentityKey) is ClaimsIdentity botIdentity)
Tuple<ConversationReference, string> result;

// Check for legacy adapter
if (dc.Context.Adapter is BotFrameworkAdapter)
{
// TeamsInfo.SendMessageToTeamsChannelAsync requires AppCredentials
var credentials = dc.Context.TurnState.Get<IConnectorClient>()?.Credentials as MicrosoftAppCredentials;
if (credentials == null)
{
throw new InvalidOperationException($"Missing credentials as {nameof(MicrosoftAppCredentials)} in {nameof(IConnectorClient)} from TurnState");
}

// The result comes back as a tuple, which is used to set the two properties (if present).
result = await TeamsInfo.SendMessageToTeamsChannelAsync(dc.Context, activity, teamsChannelId, credentials, cancellationToken: cancellationToken).ConfigureAwait(false);
}
else if (dc.Context.Adapter is CloudAdapterBase)
{
appId = JwtTokenValidation.GetAppIdFromClaims(botIdentity.Claims);
// Retrieve the bot appid from TurnState's ClaimsIdentity
string appId;
if (dc.Context.TurnState.Get<ClaimsIdentity>(BotAdapter.BotIdentityKey) is ClaimsIdentity botIdentity)
{
// Apparently 'version' is sometimes empty, which will result in no id returned from GetAppIdFromClaims
appId = JwtTokenValidation.GetAppIdFromClaims(botIdentity.Claims);
if (string.IsNullOrEmpty(appId))
{
appId = botIdentity.Claims.FirstOrDefault(claim => claim.Type == AuthenticationConstants.AudienceClaim)?.Value;
}

if (string.IsNullOrEmpty(appId))
{
throw new InvalidOperationException($"Missing AppIdClaim in ClaimsIdentity.");
}
}
else
{
throw new InvalidOperationException($"Missing {BotAdapter.BotIdentityKey} in {nameof(ITurnContext)} TurnState.");
}

// The result comes back as a tuple, which is used to set the two properties (if present).
result = await TeamsInfo.SendMessageToTeamsChannelAsync(dc.Context, activity, teamsChannelId, appId, cancellationToken: cancellationToken).ConfigureAwait(false);
}
else
{
throw new InvalidOperationException($"Missing {BotAdapter.BotIdentityKey} in {nameof(ITurnContext)} TurnState");
throw new InvalidOperationException($"The adapter does not support {nameof(SendMessageToTeamsChannel)}.");
}

// The result comes back as a tuple, which is used to set the two properties (if present).
var result = await TeamsInfo.SendMessageToTeamsChannelAsync(dc.Context, activity, teamsChannelId, appId, cancellationToken: cancellationToken).ConfigureAwait(false);

if (ConversationReferenceProperty != null)
{
dc.State.SetValue(ConversationReferenceProperty.GetValue(dc.State), result.Item1);
Expand Down