2

I'm working on a Teams bot that needs the ability to start a new 1:1 conversation with a known user (i.e., we know the Teams user ID).

I've looked at the "complete-csharp" OfficeDev samples on GitHub (https://github.com/OfficeDev/microsoft-teams-sample-complete-csharp) as well as the Teams-related parts of the Graph API but I don't see any affordance for starting a new conversation.

Our goal is to have our bot ping a known user on a schedule by inviting them into a 1:1 chat and requesting their feedback. A button in the bot's message will reveal the feedback form (via task module).

Easy Rhino
  • 63
  • 1
  • 6

1 Answers1

4

Update

Bot Framework has added in code specific for Teams that makes a lot of the code in this answer moot or incorrect. See this sample for sending proactive messages in Teams, now.

Teams calls that a "Proactive Message". So long as you get the user ID that Teams uses, it's fairly easy to do.

Per the docs, Proactive messaging for bots:

Bots can create new conversations with an individual Microsoft Teams user as long as your bot has user information obtained through previous addition in a personal, groupChat or team scope. This information enables your bot to proactively notify them. For instance, if your bot was added to a team, it could query the team roster and send users individual messages in personal chats, or a user could @mention another user to trigger the bot to send that user a direct message.

The easiest way to do this is through the Microsoft.Bot.Builder.Teams middleware.

Note: The Microsoft.Bot.Builder.Teams extension is still in Prerelease for V4, which is why samples and code are kind of hard to find for it.

Adding the Middleware

In Startup.cs:

var credentials = new SimpleCredentialProvider(Configuration["MicrosoftAppId"], Configuration["MicrosoftAppPassword"]);

services.AddSingleton(credentials);

[...]

services.AddBot<YourBot>(options =>
{
    options.CredentialProvider = credentials;

    options.Middleware.Add(
        new TeamsMiddleware(
            new ConfigurationCredentialProvider(this.Configuration)));
[...]

Prepping Your Bot

In your main <YourBot>.cs:

private readonly SimpleCredentialProvider _credentialProvider;

[...]

public <YourBot>(ConversationState conversationState, SimpleCredentialProvider CredentialProvider)
{
     _credentialProvider = CredentialProvider;

[...]

Sending the Message

var teamConversationData = turnContext.Activity.GetChannelData<TeamsChannelData>();
var connectorClient = new ConnectorClient(new Uri(activity.ServiceUrl), _credentialProvider.AppId, _credentialProvider.Password);

var userId = <UserIdToSendTo>;
var tenantId = teamConversationData.Tenant.Id;
var parameters = new ConversationParameters
{
    Members = new[] { new ChannelAccount(userId) },
    ChannelData = new TeamsChannelData
    {
        Tenant = new TenantInfo(tenantId),
    },
};

var conversationResource = await connectorClient.Conversations.CreateConversationAsync(parameters);
var message = Activity.CreateMessageActivity();
message.Text = "This is a proactive message.";
await connectorClient.Conversations.SendToConversationAsync(conversationResource.Id, (Activity)message);

Note: If you need to get user ID's, you can use:

var members = (await turnContext.TurnState.Get<IConnectorClient>().Conversations.GetConversationMembersAsync(
    turnContext.Activity.GetChannelData<TeamsChannelData>().Team.Id).ConfigureAwait(false)).ToList();

Also, I didn't need this in my testing, but if you get 401 errors, you may need to trust the Teams ServiceUrl:

MicrosoftAppCredentials.TrustServiceUrl(turnContext.Activity.ServiceUrl); 

Resources

mdrichardson
  • 7,141
  • 1
  • 7
  • 21
  • What is TeamsChannelData, it is user define class or do we need any library for this? – iVikashJha Mar 10 '20 at 08:24
  • @VikashRanjanJha This answer is outdated since Bot Framework started developing specific adapters for Teams last year. See [this sample](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/csharp_dotnetcore/57.teams-conversation-bot/Bots/TeamsConversationBot.cs#L107) for sending Proactive messages in Teams, now. – mdrichardson Mar 10 '20 at 17:09
  • @mdrichardson-MSFT - that sample you reference with the new GetSingleMemberAsync method does't help for sending a proactive message from an external system/event though correct? I've been using the proactive message [sample](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/csharp_dotnetcore/16.proactive-messages/Controllers/NotifyController.cs). Is there an updated way to send a proactive message to a user in Teams (whose Teams ID is known) from an external system? Possibly without needing to build a ConversationReference object? – Ryan Buening Apr 10 '20 at 00:23
  • @RyanBuening The samples in the `master` branch are the most updated we've got. You can send it via some kind of external event, but you need to build the ConversationReference object manually. To do so, you probably need to [get a list of your team members](https://github.com/microsoft/botbuilder-dotnet/blob/master/libraries/Microsoft.Bot.Builder/Teams/TeamsInfo.cs#L33) first. [This answer](https://stackoverflow.com/questions/60008422/calling-my-net-core-teams-bot-from-angular/60064606#60064606) may help with that. – mdrichardson Apr 10 '20 at 14:33