0
votes

So to explain my problem, I have to give you the context.

I got a Bot built with microsoft bot framework deployed on slack. Now it can happen these "events" on my backend that the bot communicates with. When a event occurs, I want to notify my bot of it and then let it send a message to all of it's conversations that something has happend. So basicly:

Backend>Microserivce>Bot>users

To do this I have to store all conversations in my backend, which I do in a database there. When a event happends, the backend will post an activity to the bot with all the conversations(basicly their id's) and the event it should show them.

So in essence my backend need to post a message to my bot.

For doing this I found the microsoft directline api which acts as a middleman here, a more abstract way to talk with the bot. The problem is that I don't know how to do it. I followed microsofts own tutorial but it doesn't seem to work for me:

This is the endpoint that my backend uses to notify the bot. "content" contains conversations and events as a json formated string.

    [HttpPost]
    [Route("conversationsEvents")]
    public HttpResponseMessage PostConversationsEvents([FromBody]string content)
    {
        NotifyBot.Notify(content);
        return Request.CreateResponse(HttpStatusCode.NoContent );
    }

NotifyBot.Notify(content) looks like this:

        private static async Task StartBotConversation( string contents)
    {
        string directLineSecret = "secret";
        string fromUser = "microserviceNotifyEndpoint";
        Activity activity = new Activity
        {
            From = new ChannelAccount(fromUser),
            Text = contents,
            Type = ActivityTypes.Event
        };
        DirectLineClient client = new DirectLineClient(directLineSecret);
        var conversation = await client.Conversations.StartConversationAsync();
        await client.Conversations.PostActivityAsync(conversation.ConversationId, activity);
    }

Basicly the execution get's stuck at var conversation = await client.Conversations.StartConversationAsync(); , it just waits forever. I tried changing it to var conversation = await client.Conversations.StartConversationAsync().ConfigureAwait(continueOnCapturedContext: false);´the execution goes on but the activity doesn't seem to get posted.

2

2 Answers

0
votes

I'm not sure why the call to .StartConversationAsync() would freeze in your case. Maybe you haven't enabled the Direct Line channel on dev.botframework.com/bots? Nonetheless, as pointed out by Sergey, the Direct Line is a Channel and not a means for communicating with your bot on other channels.

Check out the Connector Client: bot-builder-dotnet-connector

Here is a static example of using it to proactively send a message to a user from a bot: MicrosoftDX/botFramework-proactiveMessages - sample: ConversationStarter.cs

pertinent code from sample:

public static async Task Resume(string conversationId,string channelId)
    {
        var userAccount = new ChannelAccount(toId,toName);
        var botAccount = new ChannelAccount(fromId, fromName);
        var connector = new ConnectorClient(new Uri(serviceUrl));

        IMessageActivity message = Activity.CreateMessageActivity();
        if (!string.IsNullOrEmpty(conversationId) && !string.IsNullOrEmpty(channelId))
        {
            message.ChannelId = channelId;
        }
        else
        {
            conversationId = (await connector.Conversations.CreateDirectConversationAsync( botAccount, userAccount)).Id;
        }
        message.From = botAccount;
        message.Recipient = userAccount;
        message.Conversation = new ConversationAccount(id: conversationId);
        message.Text = "Hello, this is a notification";
        message.Locale = "en-Us";
        await connector.Conversations.SendToConversationAsync((Activity)message);
    }

The serviceUrl, the channelId, conversationId, toId, fromId, etc are cached from previous communication by the user to the bot (these are statically stored in this example, so only work for one user). This example shows how it is possible to proactively send a message to a user from a bot. The Direct Line api is not required.

0
votes

You don't need to use DirectLine, it is designed for creating alternative bot UIs.

To implementing what your want, you may try the following:

First, you need to store users addresses to whom you want to send the messages. It my be done by storing the ResumptionCookie of a user last message in your backend database.

var state = new ResumptionCookie(message).GZipSerialize();

When your PostConversationsEvents is called, you may resume the conversation at the latest point with each users.

        var resumptionCookie = ResumptionCookie.GZipDeserialize(state);
        var message = resumptionCookie.GetMessage();
        message.Text = content;
        await Conversation.ResumeAsync(resumptionCookie, message);

It is not the only solution. As I said, in this case you just resumed the conversation with the user at the latest point. Another solution is to save the user address (user the same ResumptionCookie class) but start the conversation when you need to:

        var resumptionCookie = ResumptionCookie.GZipDeserialize(state);
        var message = cookie.GetMessage();

        ConnectorClient client = new ConnectorClient(new Uri(message.ServiceUrl));

        var conversation = await 
        client.Conversations.CreateDirectConversationAsync(message.Recipient, message.From);
        message.Conversation.Id = conversation.Id;
        var newMessage = message.CreateReply();
        newMessage.Text = content;
        await client.Conversations.SendToConversationAsync(newMessage);

See more details on BotFramework documentation.