示例#1
0
        public static async Task Run(
            [QueueTrigger("sms-received-messages")]
            dynamic incomingSms,
            TraceWriter log,
            ExecutionContext context)
        {
            currentContext = context;

            try
            {
                string          mobileNumber = incomingSms?.Value?.source_number;
                BotConversation conversation = await GetConversationByMobileNumber(mobileNumber);

                if (conversation == null)
                {
                    await StartNewConversation(incomingSms, log);
                }
                else
                {
                    await PostToConversation(incomingSms, conversation, log);
                }
            }
            catch (Exception e)
            {
                log.Info($"Bot Connector Exception: {e.Message}");
                DirectLineClient.CancelPendingRequests();
                throw new BotConnectorException(
                          "Something went wrong when relaying the message to the bot framework",
                          e);
            }
        }
示例#2
0
        private static async Task <BotConversation> GetConversationByMobileNumber(string mobileNumber)
        {
            // TODO: extract this and inject an instance of IBotConversationProvider
            DocumentCollection collection = await DocumentClient.GetDocumentCollectionAsync();

            BotConversation conversation = await DocumentClient.GetItemAsync <BotConversation>(c => c.MobileNumber == mobileNumber);

            return(conversation);
        }
示例#3
0
 public static Conversation ToConversation(this BotConversation botConversation)
 {
     return(new Conversation
     {
         Id = botConversation.ConversationId,
         ActivityId = botConversation.ActivityId,
         TurnId = botConversation.TurnId
     });
 }
示例#4
0
        private static async Task PostToConversation(dynamic incomingSms, BotConversation conversation, TraceWriter log)
        {
            log.Info($"Received response from {incomingSms?.Value?.source_number}");

            dynamic from = new ExpandoObject();

            from.id   = incomingSms?.Value?.source_number;
            from.name = incomingSms?.Value?.source_number;
            from.role = null;

            dynamic channelData = new ExpandoObject();

            channelData.NotifyMessage = new NotifyMessage()
            {
                Id                = incomingSms?.Value?.id,
                DateReceived      = incomingSms?.Value?.date_received,
                DestinationNumber =
                    incomingSms?.Value?.destination_number,
                SourceNumber = incomingSms?.Value?.source_number,
                Message      = incomingSms?.Value?.message,
                Type         = "callback",
            };

            var messageContent = new BotConversationMessage()
            {
                Type        = "message",
                From        = from,
                Text        = incomingSms?.Value?.message,
                ChannelData = channelData
            };

            var         json    = JsonConvert.SerializeObject(messageContent);
            HttpContent content = new StringContent(json);

            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            HttpResponseMessage postMessageTask = await DirectLineClient.PostAsync($"/v3/directline/conversations/{conversation.ConversationId}/activities", content);

            if (postMessageTask.IsSuccessStatusCode)
            {
                string response = await postMessageTask.Content.ReadAsStringAsync();

                dynamic jsonResponse = JsonConvert.DeserializeObject(response);
                log.Info($"Received response from Bot Client: {jsonResponse.id}");
            }
            else
            {
                log.Info($"Could not post conversation. {postMessageTask.StatusCode}: {postMessageTask.ReasonPhrase}");
                log.Info($"{JsonConvert.SerializeObject(postMessageTask)}");
            }
        }
示例#5
0
        public async Task <string> CreateSupplierAsync(BotConversation conversation, string supplierName = null)
        {
            supplierName = fixture.Create <string>().Replace("-", "");

            var response = await CommandExecutor.ExecuteAndWaitForResponseAsync(
                conversation,
                $"#nowyDostawca {supplierName}",
                fixture.Create <TestUser>());

            if (response != $"Nowy dostawca: '{supplierName}'")
            {
                throw new OperationFailedException($"Failed to create supplier {supplierName}. Received response: {response}");
            }

            return(supplierName);
        }
示例#6
0
        public async Task PickRandomOperatorAsync(
            BotConversation conversation,
            string supplierName,
            TestUser user = null)
        {
            user = user ?? fixture.Create <TestUser>();

            var response = await CommandExecutor.ExecuteAndWaitForResponseAsync(
                conversation,
                $"#losuj {supplierName}",
                user);

            if (!response.Contains("Dokonano losowania"))
            {
                throw new OperationFailedException(
                          $"Failed to pick random operator. Supplier: {supplierName}, User: {user.Name}. Received response: {response}");
            }
        }
示例#7
0
        public async Task AddOrderItemAsync(
            BotConversation conversation,
            string supplierName,
            string orderText = null,
            TestUser user    = null)
        {
            orderText = orderText ?? fixture.Create <string>();
            user      = user ?? fixture.Create <TestUser>();

            var response = await CommandExecutor.ExecuteAndWaitForResponseAsync(
                conversation,
                $"[{supplierName}] {orderText}",
                user);

            if (!response.Contains($"'{user.Name}' -> '{supplierName}'"))
            {
                throw new OperationFailedException(
                          $"Failed to add order item. Supplier: {supplierName}, User: {user.Name}, Order text: {orderText}. Received response: {response}");
            }
        }
示例#8
0
        private static async Task StartNewConversation(dynamic incomingSms, TraceWriter log)
        {
            log.Info($"Starting new conversation with {incomingSms?.Value?.source_number}");

            var content = new StringContent(string.Empty);

            var startConversationTask = await DirectLineClient.PostAsync("/v3/directline/conversations", content);

            var conversation = new BotConversation();

            if (startConversationTask.IsSuccessStatusCode)
            {
                string response = await startConversationTask.Content.ReadAsStringAsync();

                dynamic jsonResponse = JsonConvert.DeserializeObject(response);
                log.Info($"Started new conversation with id {jsonResponse.conversationId}");

                // TODO: write the conversation ID to a session log with the mobile phone number
                conversation.MobileNumber   = incomingSms?.Value.source_number;
                conversation.ConversationId = jsonResponse.conversationId;

                BotConversation newSession = await DocumentClient.UpsertItemAsync(conversation);

                if (newSession.IsNull())
                {
                    throw new BotConnectorException($"Could not create session object for conversation id {conversation.ConversationId}");
                }

                if (incomingSms != null)
                {
                    await PostToConversation(incomingSms, conversation, log);
                }
            }
            else
            {
                log.Info($"Could not start new conversation. {startConversationTask.StatusCode}: {startConversationTask.ReasonPhrase}");
                log.Info($"{JsonConvert.SerializeObject(startConversationTask)}");
            }
        }
        static void Main(string[] args)
        {
            IBotConversationTalkingPoint defaultTalkingPoint = new BotConversationTalkingPoint();

            // Handle Conversation About An Item
            IBotConversationTalkingPoint askAboutItemTalkingPoint = new BotConversationTalkingPoint();

            // Handle Conversation About An Items' Details.
            IBotConversationTalkingPoint askAboutItemDetailsTalkingPoint = new BotConversationTalkingPoint();

            // Fallback
            IBotConversationTalkingPoint fallBackTalkingPoint = new BotConversationTalkingPoint
            {
                Text = "Sorry, I could not understand."
            };

            // Bot Conversation Handle
            IBotConversation botConversation = new BotConversation(defaultTalkingPoint, fallBackTalkingPoint)
            {
                TalkingPoints = new List <IBotConversationTalkingPoint>()
                {
                    defaultTalkingPoint,
                    askAboutItemTalkingPoint
                }
            };

            defaultTalkingPoint.Transitions = new List <IBotConversationTalkingPoint>()
            {
                askAboutItemTalkingPoint
            };
            defaultTalkingPoint.TransitionPriorities = new Dictionary <IBotConversationTalkingPoint, int>()
            {
                { askAboutItemTalkingPoint, 1 }
            };
            defaultTalkingPoint.ActivateOn = new Func <EchoState, IBotConversationTalkingPoint, LuisResult, (bool success, Action <object> callback)>((EchoState state, IBotConversationTalkingPoint contextTalkingPoint, LuisResult luisResult) => {
                return(success: true, callback: null);
            });

            askAboutItemDetailsTalkingPoint.Transitions = new List <IBotConversationTalkingPoint>()
            {
                askAboutItemDetailsTalkingPoint
            };
            askAboutItemDetailsTalkingPoint.ActivateOn = new Func <EchoState, IBotConversationTalkingPoint, LuisResult, (bool success, Action <object> callback)>((EchoState state, IBotConversationTalkingPoint contextTalkingPoint, LuisResult luisResult) =>
            {
                var intentAskAboutItemSize   = luisResult.Entities.FirstOrDefault(entity => entity.Type == "MyItems::Size");
                var intentAskAboutItemColor  = luisResult.Entities.FirstOrDefault(entity => entity.Type == "MyItems::Color");
                var intentAskAboutItemObject = luisResult.Entities.FirstOrDefault(entity => entity.Type == "MyItems::Item" && entity.Entity != state.ItemContext);

                if (intentAskAboutItemObject != null)
                {
                    if (intentAskAboutItemSize != null)
                    {
                        askAboutItemDetailsTalkingPoint.Text = $"I thought we were talking about the size of my '{state.ItemContext}' ? Ok, let's talk about my '{intentAskAboutItemObject.Entity}'!";

                        return(true, ((object sender) =>
                        {
                            state.ItemContext = intentAskAboutItemObject.Entity;
                        }));
                    }
                    else if (intentAskAboutItemColor != null)
                    {
                        askAboutItemDetailsTalkingPoint.Text = $"I thought we were talking about the color of my '{state.ItemContext}' ? Ok, let's talk about my '{intentAskAboutItemObject.Entity}'!";

                        return(true, ((object sender) =>
                        {
                            state.ItemContext = intentAskAboutItemObject.Entity;
                        }));
                    }
                    else
                    {
                        askAboutItemDetailsTalkingPoint.Text = $"Did you have a question about my '{state.ItemContext}'? (Size/Color)";
                    }

                    //return false;
                }
                else if (intentAskAboutItemSize != null)
                {
                    askAboutItemDetailsTalkingPoint.Text = $"The size of my {state.ItemContext} is small!";
                }

                else if (intentAskAboutItemColor != null)
                {
                    askAboutItemDetailsTalkingPoint.Text = $"The color of my {state.ItemContext} is red!";
                }
                return(success: true, callback: null);
            });

            askAboutItemTalkingPoint.Transitions = new List <IBotConversationTalkingPoint>()
            {
                askAboutItemDetailsTalkingPoint
            };
            askAboutItemTalkingPoint.ActivateOn = new Func <EchoState, IBotConversationTalkingPoint, LuisResult, (bool success, Action <object> callback)>((EchoState state, IBotConversationTalkingPoint contextTalkingPoint, LuisResult luisResult) => {
                var intentAskAboutItem       = luisResult.Intents.FirstOrDefault().Intent == "AskAboutItem";
                var intentAskAboutItemSize   = luisResult.Entities.FirstOrDefault(entity => entity.Type == "MyItems::Size");
                var intentAskAboutItemColor  = luisResult.Entities.FirstOrDefault(entity => entity.Type == "MyItems::Color");
                var intentAskAboutItemObject = luisResult.Entities.FirstOrDefault(entity => entity.Type == "MyItems::Item");

                if (intentAskAboutItem && intentAskAboutItemSize != null && intentAskAboutItemObject != null)
                {
                    state.ItemContext = intentAskAboutItemObject.Entity;

                    askAboutItemTalkingPoint.Text = $"The size of my {state.ItemContext} is small!";
                }

                else if (intentAskAboutItem && intentAskAboutItemColor != null && intentAskAboutItemObject != null)
                {
                    state.ItemContext = intentAskAboutItemObject.Entity;

                    askAboutItemTalkingPoint.Text = $"The color of my {state.ItemContext} is red!";
                }

                return(success: true, callback: null);
            });


            // Speak To Bot
            // Context: Cat
            // Response: The color of my cat is red!
            Task botTask = botConversation.Say("What size is your cat?");

            botTask.Wait();

            // Context: Cat
            // Response: The color of my cat is red!
            Task botTask2 = botConversation.Say("What color is he?");

            botTask2.Wait();

            // Context: Cat => Dog
            // Response: I thought we were talking about the color of my 'cat' ? Ok, let's talk about my 'dog'!
            Task botTask3 = botConversation.Say("What color is your dog?");

            botTask3.Wait();

            // Context: Dog
            // Response: The color of my dog is red!
            Task botTask4 = botConversation.Say("What color is he?");

            botTask4.Wait();

            // Context: Dog
            // Response: The color of my dog is red
            // Note: We are still aware that the context is about the dog's size
            Task botTask5 = botConversation.Say("What about the dog?");

            botTask5.Wait();

            // Context: Dog
            // Response: I thought we were talking about the size of my 'dog' ? Ok, let's talk about my 'cat'!
            Task botTask6 = botConversation.Say("What color is your cat?");

            botTask6.Wait();
        }
 public OutgoingSmsBuilder WithConversation(BotConversation conversation)
 {
     _conversation = conversation;
     return(this);
 }