1
votes

I have built an app that needs to connect to a Bot DirectLine - websockets channel to interact in conversations via LUIS and sms with Twilio. To make the bot talk to the app I wrote a mvc controller that relays messages. I am not sure this approach is correct, I made it up from some samples. It works, but the main problem is that my code seems to always start a new conversation when a message is received from the client, so the context is not maintained. How can I keep the conversation flowing and not restarting at every message? I mean, the steps should be, for example:

Bot: Hello, what's your name?
User: Carl
Bot: Pleased to meet you Carl!


instead I get:
Bot: Hello, what's your name?
User: Carl
Bot: Sorry, I can't help you with that.

like the conversation is restarted from scratch.

Here is my controller code (the Twilio webhook is set to https://mySmsMVCapp.azurewebsites.net/smsapp/):

public class smsappController : TwilioController
{

    private static string directLineSecret = ConfigurationManager.AppSettings["DirectLineSecret"];
    private static string botId = ConfigurationManager.AppSettings["BotId"];


    const string accountSid = "obfuscated";
    const string authToken = "obfuscated";

    private static string fromUser = "DirectLineSampleClientUser";
    private string SMSreply = "";


    public async Task<TwiMLResult> Index(SmsRequest incomingMessage)
    {

            // Obtain a token using the Direct Line secret
            var tokenResponse = await new DirectLineClient(directLineSecret).Tokens.GenerateTokenForNewConversationAsync();

            // Use token to create conversation
            var directLineClient = new DirectLineClient(tokenResponse.Token);
            var conversation = await directLineClient.Conversations.StartConversationAsync();


        using (var webSocketClient = new WebSocket(conversation.StreamUrl))
        {
            webSocketClient.OnMessage += WebSocketClient_OnMessage;
            // You have to specify TLS version to 1.2 or connection will be failed in handshake.
            webSocketClient.SslConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12;
            webSocketClient.Connect();

            while (true)
            {
                string input = incomingMessage.Body;
                if (!string.IsNullOrEmpty(input))
                {
                    if (input.ToLower() == "exit")
                    {
                        break;
                    }
                    else
                    {
                        if (input.Length > 0)
                        {
                            Activity userMessage = new Activity
                            {
                                From = new ChannelAccount(fromUser),
                                Text = input,
                                Type = ActivityTypes.Message
                            };

                            await directLineClient.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
                            //break;

                            if (!string.IsNullOrEmpty(SMSreply))
                            {
                                var messagingResponse = new MessagingResponse();
                                var message = messagingResponse.AddChild("Message");

                                message.AddText(SMSreply); //send text


                                SMSreply = string.Empty;
                                return TwiML(messagingResponse);
                            }

                        }
                    }
                }
            }
        }

        return null;

    }


    private void WebSocketClient_OnMessage(object sender, MessageEventArgs e)
    {
        // Occasionally, the Direct Line service sends an empty message as a liveness ping. Ignore these messages.
        if (!string.IsNullOrWhiteSpace(e.Data))
        {

            var activitySet = JsonConvert.DeserializeObject<ActivitySet>(e.Data);
            var activities = from x in activitySet.Activities
                             where x.From.Id == botId
                             select x;

            foreach (Activity activity in activities)
            {
                if (!string.IsNullOrEmpty(activity.Text))
                {

                    SMSreply = activity.Text;

                }

            }
        }
    }
}
1
I have many questions. When you say "Bot DirectLine - websockets channel" are you talking about Direct Line Speech or just Direct Line? Why have you created an intermediate app to forward messages between Twilio and Direct Line instead of just using the Twilio channel? Have you verified that the bot is saving its dialog state correctly? Have you verified that the activities your app is sending to the bot actually have the same user ID and conversation ID? - Kyle Delaney
Directline, not speech. Because I need the channel to be as more customizable as possible for future developments (for example speech). The issue was actually I wasn't saving and retrieving conversationID. - clurv
So you've resolved the issue? Would you like to post that as an answer so you can accept it? - Kyle Delaney
at the moment I store the conversationID in a static variable. Do you have any suggestion about what is the best practice for storing it? Thank you - clurv
With this code I also have an issue with some kind of timeout at the first time I message the bot after some time, I get an http error Bad Gateway, like something needs to be awaken, then at the second message the bot responds. Do you have any idea? Here is the Twilio error Twilio was unable to fetch content from: http://.... Error: Total timeout is triggered. Configured tt is 15000ms and we attempted 1 time(s) - clurv

1 Answers

0
votes

The issue was actually I wasn't saving and retrieving conversationID. For the moment I am testing using a static variable to store the value. Then I reconnect to the conversation with it and the conversation with the bot keeps in context.