Esempio n. 1
0
        public static async Task VerifyScript(ILifetimeScope container, Func <IDialog <object> > makeRoot, bool proactive, StreamReader stream, Action <IDialogStack, string> extraCheck, string[] expected, string locale)
        {
            var toBot = DialogTestBase.MakeTestMessage();

            if (!string.IsNullOrEmpty(locale))
            {
                toBot.Locale = locale;
            }

            string input, label;
            int    current = 0;

            while ((input = ReadLine(stream, out label)) != null)
            {
                var adapter = new TestAdapter();
                await adapter.ProcessActivity((Activity)toBot, async (ctx) =>
                {
                    using (var scope = DialogModule.BeginLifetimeScope(container, ctx))
                    {
                        var task  = scope.Resolve <IPostToBot>();
                        var queue = adapter.ActiveQueue;

                        Action <IDialogStack> check = (stack) =>
                        {
                            var count = int.Parse((proactive && current == 0) ? input : stream.ReadLine());
                            Assert.AreEqual(count, queue.Count);
                            for (var i = 0; i < count; ++i)
                            {
                                var toUser      = queue.Dequeue();
                                var expectedOut = ReadLine(stream, out label);
                                if (label == "ToUserText")
                                {
                                    Assert.AreEqual(expectedOut, JsonConvert.SerializeObject(toUser.Text));
                                }
                                else
                                {
                                    Assert.AreEqual(expectedOut, JsonConvert.SerializeObject(toUser.Attachments));
                                }
                            }

                            extraCheck?.Invoke(stack, ReadLine(stream, out label));
                        };

                        Func <IDialog <object> > scriptMakeRoot = () =>
                        {
                            return(makeRoot().Do(async(context, value) => context.PrivateConversationData.SetValue("result", JsonConvert.SerializeObject(await value))));
                        };
                        scope.Resolve <Func <IDialog <object> > >(TypedParameter.From(scriptMakeRoot));

                        if (proactive && current == 0)
                        {
                            var loop = scriptMakeRoot().Loop();
                            var data = scope.Resolve <IBotData>();
                            await data.LoadAsync(CancellationToken.None);
                            var stack = scope.Resolve <IDialogTask>();
                            stack.Call(loop, null);
                            await stack.PollAsync(CancellationToken.None);
                            check(stack);
                            input = ReadLine(stream, out label);
                        }

                        if (input.StartsWith("\""))
                        {
                            try
                            {
                                toBot.Text = input.Substring(1, input.Length - 2);
                                Assert.IsTrue(current < expected.Length && toBot.Text == expected[current++]);
                                await task.PostAsync(toBot, CancellationToken.None);
                                var data = scope.Resolve <IBotData>();
                                await data.LoadAsync(CancellationToken.None);
                                var stack = scope.Resolve <IDialogStack>();
                                check(stack);
                            }
                            catch (Exception e)
                            {
                                Assert.AreEqual(ReadLine(stream, out label), e.Message);
                            }
                        }
                        else if (label.ToLower().StartsWith("result"))
                        {
                            var data = scope.Resolve <IBotData>();
                            await data.LoadAsync(CancellationToken.None);
                            string result;
                            Assert.IsTrue(data.PrivateConversationData.TryGetValue("result", out result));
                            Assert.AreEqual(input.Trim(), result);
                        }
                    }
                });
            }
        }
Esempio n. 2
0
        public async Task If_Root_Dialog_Throws_Propagate_Exception_Reset_Store()
        {
            const string userId = "testUser";
            const string botId  = "testBot";

            var dialog = new Mock <IDialogThatFails>(MockBehavior.Loose);

            dialog
            .Setup(d => d.StartAsync(It.IsAny <IDialogContext>()))
            .Returns <IDialogContext>(async context => { context.Wait(dialog.Object.MessageReceived); });

            dialog
            .Setup(d => d.MessageReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()))
            .Returns <IDialogContext, IAwaitable <Message> >(async(context, result) => { context.Wait(dialog.Object.Throw); });

            dialog
            .Setup(d => d.Throw(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()))
            .Throws <ApplicationException>();

            Func <IDialog <object> > MakeRoot = () => dialog.Object;
            var toBot = new Message()
            {
                From = new ChannelAccount {
                    Id = userId
                },
                ConversationId = Guid.NewGuid().ToString(),
                To             = new ChannelAccount {
                    Id = botId
                }
            };

            using (new FiberTestBase.ResolveMoqAssembly(dialog.Object))
                using (var container = Build(Options.MockConnectorFactory, dialog.Object))
                {
                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();
                        await task.PostAsync(toBot, CancellationToken.None);
                    }

                    dialog.Verify(d => d.StartAsync(It.IsAny <IDialogContext>()), Times.Once);
                    dialog.Verify(d => d.MessageReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()), Times.Once);
                    dialog.Verify(d => d.Throw(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()), Times.Never);

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IDialogStack>();
                        Assert.AreNotEqual(0, task.Frames.Count);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();

                        try
                        {
                            await task.PostAsync(toBot, CancellationToken.None);

                            Assert.Fail();
                        }
                        catch (ApplicationException)
                        {
                        }
                        catch
                        {
                            Assert.Fail();
                        }
                    }

                    dialog.Verify(d => d.StartAsync(It.IsAny <IDialogContext>()), Times.Once);
                    dialog.Verify(d => d.MessageReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()), Times.Once);
                    dialog.Verify(d => d.Throw(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()), Times.Once);

                    //make sure that data is persisted with connector
                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var connectorFactory = scope.Resolve <IConnectorClientFactory>();
                        var botData          = await connectorFactory.Make().Bots.GetPerUserConversationDataAsync(botId, toBot.ConversationId, userId);

                        toBot.BotPerUserInConversationData = botData.Data;
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var stack = scope.Resolve <IDialogStack>();
                        Assert.AreEqual(0, stack.Frames.Count);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();
                        await task.PostAsync(toBot, CancellationToken.None);
                    }

                    dialog.Verify(d => d.StartAsync(It.IsAny <IDialogContext>()), Times.Exactly(2));
                    dialog.Verify(d => d.MessageReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()), Times.Exactly(2));
                    dialog.Verify(d => d.Throw(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()), Times.Once);
                }
        }
Esempio n. 3
0
        static async Task Interactive <T>(IDialog <T> form) where T : class
        {
            // NOTE: I use the DejaVuSansMono fonts as described here: http://stackoverflow.com/questions/21751827/displaying-arabic-characters-in-c-sharp-console-application
            // But you don't have to reboot.
            // If you don't want the multi-lingual support just comment this out
            Console.OutputEncoding = Encoding.GetEncoding(65001);
            var message = new Activity()
            {
                From = new ChannelAccount {
                    Id = "ConsoleUser"
                },
                Conversation = new ConversationAccount {
                    Id = Guid.NewGuid().ToString()
                },
                Recipient = new ChannelAccount {
                    Id = "FormTest"
                },
                ChannelId  = "Console",
                ServiceUrl = "http://localhost:9000/",
                Text       = ""
            };

            var builder = new ContainerBuilder();

            builder.RegisterModule(new DialogModule_MakeRoot());

            builder.RegisterType <InMemoryDataStore>()
            .AsSelf()
            .SingleInstance();

            builder.Register(c => new CachingBotDataStore(c.Resolve <InMemoryDataStore>(), CachingBotDataStoreConsistencyPolicy.ETagBasedConsistency))
            .As <IBotDataStore <BotData> >()
            .AsSelf()
            .InstancePerLifetimeScope();

            builder
            .Register(c => new BotToUserTextWriter(new BotToUserQueue(message, new Queue <IMessageActivity>()), Console.Out))
            .As <IBotToUser>()
            .InstancePerLifetimeScope();

            // Trace activities to debug output
            builder
            .RegisterType <TraceActivityLogger>()
            .AsImplementedInterfaces()
            .InstancePerLifetimeScope();

            using (var container = builder.Build())
                using (var scope = DialogModule.BeginLifetimeScope(container, message))
                {
                    Func <IDialog <object> > MakeRoot = () => form;
                    DialogModule_MakeRoot.Register(scope, MakeRoot);

                    var task = scope.Resolve <IPostToBot>();
                    await scope.Resolve <IBotData>().LoadAsync(default(CancellationToken));

                    var stack = scope.Resolve <IDialogTask>();

                    stack.Call(MakeRoot(), null);
                    await stack.PollAsync(CancellationToken.None);

                    while (true)
                    {
                        message.Timestamp = DateTime.UtcNow;
                        message.Text      = await Console.In.ReadLineAsync();

                        message.Locale = Locale;
                        await task.PostAsync(message, CancellationToken.None);
                    }
                }
        }
Esempio n. 4
0
        private async Task <Activity> HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.Event && message.Name == "initializeBot")
            {
                IConversationUpdateActivity conversationupdate = message;
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var client = scope.Resolve <IConnectorClient>();
                    var reply  = message.CreateReply();
                    reply.Text      = "you asked: " + message.Value;
                    reply.ReplyToId = message.Recipient.Id;
                    await client.Conversations.ReplyToActivityAsync(reply);
                }
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels
                IConversationUpdateActivity conversationupdate = message;
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var client = scope.Resolve <IConnectorClient>();
                    if (conversationupdate.MembersAdded.Any())
                    {
                        var reply = message.CreateReply();
                        foreach (var newMember in conversationupdate.MembersAdded)
                        {
                            if (newMember.Id != message.Recipient.Id)
                            {
                                reply.Text = $"Welcome to the person bot {newMember.Name}! ";
                            }
                            else
                            {
                                reply.Text = $"Welcome to the person bot {message.From.Name}";
                            }
                            reply.ReplyToId = message.Recipient.Id;
                            await client.Conversations.ReplyToActivityAsync(reply);
                        }
                    }
                }
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }

            return(null);
        }
Esempio n. 5
0
        public async Task DialogTask_Forward()
        {
            var          dialogOne   = new Mock <IDialogFrames <string> >(MockBehavior.Loose);
            var          dialogTwo   = new Mock <IDialogFrames <string> >(MockBehavior.Loose);
            const string testMessage = "foo";

            dialogOne
            .Setup(d => d.StartAsync(It.IsAny <IDialogContext>()))
            .Returns <IDialogContext>(async context => { context.Wait(dialogOne.Object.ItemReceived); });

            dialogOne
            .Setup(d => d.ItemReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()))
            .Returns <IDialogContext, IAwaitable <Message> >(async(context, message) =>
            {
                var msg = await message;
                await context.Forward(dialogTwo.Object, dialogOne.Object.ItemReceived <string>, msg, CancellationToken.None);
            });

            dialogOne
            .Setup(d => d.ItemReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <string> >()))
            .Returns <IDialogContext, IAwaitable <string> >(async(context, message) =>
            {
                var msg = await message;
                Assert.AreEqual(testMessage, msg);
                context.Wait(dialogOne.Object.ItemReceived);
            });


            dialogTwo
            .Setup(d => d.StartAsync(It.IsAny <IDialogContext>()))
            .Returns <IDialogContext>(async context => { context.Wait(dialogTwo.Object.ItemReceived); });

            dialogTwo
            .Setup(d => d.ItemReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()))
            .Returns <IDialogContext, IAwaitable <Message> >(async(context, message) =>
            {
                var msg = await message;
                context.Done(msg.Text);
            });

            Func <IDialog <object> > MakeRoot = () => dialogOne.Object;
            var toBot = MakeTestMessage();

            using (new FiberTestBase.ResolveMoqAssembly(dialogOne.Object, dialogTwo.Object))
                using (var container = Build(Options.None, dialogOne.Object, dialogTwo.Object))
                {
                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);
                        var task = scope.Resolve <IPostToBot>();
                        toBot.Text = testMessage;
                        await task.PostAsync(toBot, CancellationToken.None);

                        dialogOne.Verify(d => d.StartAsync(It.IsAny <IDialogContext>()), Times.Once);
                        dialogOne.Verify(d => d.ItemReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()), Times.Once);
                        dialogOne.Verify(d => d.ItemReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <string> >()), Times.Once);

                        dialogTwo.Verify(d => d.StartAsync(It.IsAny <IDialogContext>()), Times.Once);
                        dialogTwo.Verify(d => d.ItemReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()), Times.Once);
                    }
                }
        }
Esempio n. 6
0
        private async Task EchoDialogFlow(IDialog <object> echoDialog)
        {
            // arrange
            var toBot = DialogTestBase.MakeTestMessage();

            toBot.From.Id = Guid.NewGuid().ToString();
            toBot.Text    = "Test";

            Func <IDialog <object> > MakeRoot = () => echoDialog;

            using (new FiberTestBase.ResolveMoqAssembly(echoDialog))
                using (var container = Build(Options.MockConnectorFactory | Options.ScopedQueue, echoDialog))
                {
                    // act: sending the message
                    IMessageActivity toUser = await GetResponse(container, MakeRoot, toBot);

                    // assert: check if the dialog returned the right response
                    Assert.IsTrue(toUser.Text.StartsWith("1"));
                    Assert.IsTrue(toUser.Text.Contains("Test"));

                    // act: send the message 10 times
                    for (int i = 0; i < 10; i++)
                    {
                        // pretend we're the intercom switch, and copy the bot data from message to message
                        toBot.Text = toUser.Text;
                        toUser     = await GetResponse(container, MakeRoot, toBot);
                    }

                    // assert: check the counter at the end
                    Assert.IsTrue(toUser.Text.StartsWith("11"));

                    toBot.Text = "reset";
                    toUser     = await GetResponse(container, MakeRoot, toBot);

                    // checking if there is any cards in the attachment and promote the card.text to message.text
                    if (toUser.Attachments != null && toUser.Attachments.Count > 0)
                    {
                        var card = (HeroCard)toUser.Attachments.First().Content;
                        toUser.Text = card.Text;
                    }
                    Assert.IsTrue(toUser.Text.ToLower().Contains("are you sure"));

                    toBot.Text = "yes";
                    toUser     = await GetResponse(container, MakeRoot, toBot);

                    Assert.IsTrue(toUser.Text.ToLower().Contains("reset count"));

                    //send a random message and check count
                    toBot.Text = "test";
                    toUser     = await GetResponse(container, MakeRoot, toBot);

                    Assert.IsTrue(toUser.Text.StartsWith("1"));

                    toBot.Text = "/deleteprofile";
                    toUser     = await GetResponse(container, MakeRoot, toBot);

                    Assert.IsTrue(toUser.Text.ToLower().Contains("deleted"));
                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var botData = scope.Resolve <IBotData>();
                        await botData.LoadAsync(default(CancellationToken));

                        var stack = scope.Resolve <IDialogStack>();
                        Assert.AreEqual(0, stack.Frames.Count);
                    }
                }
        }
        public async Task <HttpResponseMessage> Callback([FromUri] string code, [FromUri] string state, CancellationToken cancellationToken)
        {
            try
            {
                // Use the state parameter to get correct IAuthProvider and ResumptionCookie
                var           decoded      = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(state));
                var           queryString  = HttpUtility.ParseQueryString(decoded);
                var           assembly     = Assembly.Load(queryString["providerassembly"]);
                var           type         = assembly.GetType(queryString["providertype"]);
                var           providername = queryString["providername"];
                IAuthProvider authProvider;
                if (type.GetConstructor(new Type[] { typeof(string) }) != null)
                {
                    authProvider = (IAuthProvider)Activator.CreateInstance(type, providername);
                }
                else
                {
                    authProvider = (IAuthProvider)Activator.CreateInstance(type);
                }

                // Get the conversation reference
                var conversationRef = UrlToken.Decode <ConversationReference>(queryString["conversationRef"]);

                var message = conversationRef.GetPostToBotMessage();

                if (message.From.Id.Contains("sip:"))
                {
                    message.From.Id = message.From.Id.Replace("sip:", "");
                }

                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    // Get the UserData from the original conversation
                    IStateClient sc       = scope.Resolve <IStateClient>();
                    BotData      userData = await sc.BotState.GetUserDataAsync(message.ChannelId, message.From.Id);

                    // Get Access Token using authorization code
                    var authOptions = userData.GetProperty <AuthenticationOptions>($"{authProvider.Name}{ContextConstants.AuthOptions}");
                    var token       = await authProvider.GetTokenByAuthCodeAsync(authOptions, code);

                    // Generate magic number and attempt to write to userdata
                    int  magicNumber     = GenerateRandomNumber();
                    bool writeSuccessful = false;
                    uint writeAttempts   = 0;
                    while (!writeSuccessful && writeAttempts++ < MaxWriteAttempts)
                    {
                        try
                        {
                            userData.SetProperty($"{authProvider.Name}{ContextConstants.AuthResultKey}", token);
                            userData.SetProperty($"{authProvider.Name}{ContextConstants.MagicNumberKey}", magicNumber);
                            userData.SetProperty($"{authProvider.Name}{ContextConstants.MagicNumberValidated}", "false");

                            sc.BotState.SetUserData(message.ChannelId, message.From.Id, userData);
                            writeSuccessful = true;
                        }
                        catch (HttpOperationException)
                        {
                            writeSuccessful = false;
                        }
                    }
                    var resp = new HttpResponseMessage(HttpStatusCode.OK);
                    if (!writeSuccessful)
                    {
                        message.Text = String.Empty; // fail the login process if we can't write UserData
                        await Conversation.ResumeAsync(conversationRef, message);

                        resp.Content = new StringContent("<html><body>Could not log you in at this time, please try again later</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    else
                    {
                        await Conversation.ResumeAsync(conversationRef, message);

                        resp.Content = new StringContent($"<html><body>Almost done! Please copy this number and paste it back to your chat so your authentication can complete:<br/> <h1>{magicNumber}</h1>.</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    return(resp);
                }
            }
            catch (Exception ex)
            {
                // Callback is called with no pending message as a result the login flow cannot be resumed.
                return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex));
            }
        }
Esempio n. 8
0
        private async Task <Activity> HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels
                string welcomeMessage = "Welcome";
                if (message.MembersAdded != null)
                {
                    welcomeMessage += " " + message.MembersAdded.FirstOrDefault().Name.ToString();
                }
                var msg = message.CreateReply(welcomeMessage);
                // await SendToConversationAsync(msg);
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }
            else if (message.Type == ActivityTypes.Event)
            {
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var cancellationToken = default(CancellationToken);
                    var agentService      = scope.Resolve <IAgentService>();
                    switch (message.AsEventActivity().Name)
                    {
                    case "connect":
                        await agentService.RegisterAgentAsync(message, cancellationToken);

                        break;

                    case "disconnect":
                        await agentService.UnregisterAgentAsync(message, cancellationToken);

                        break;

                    case "stopConversation":
                        await StopConversation(agentService, message, cancellationToken);

                        await agentService.RegisterAgentAsync(message, cancellationToken);

                        break;

                    default:
                        break;
                    }
                }
            }

            return(null);
        }
Esempio n. 9
0
        protected async void btnLogin_OnClick(object sender, EventArgs e)
        {
            try
            {
                phInfo.Visible = true;
                var state = JsonConvert.DeserializeObject <State>((string)Session["state"]);
                var token = "fakeToken";
                if (!string.IsNullOrWhiteSpace(token))
                {
                    int magicNumber = GenerateRandomNumber();
                    // Create the message that is send to conversation to resume the login flow
                    var message = state.ConversationReference.GetPostToUserMessage();
                    using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                    {
                        var authResult = new AuthResult();
                        authResult.AccessToken = token;
                        authResult.UserName    = txtUserId.Text;
                        IStateClient sc = scope.Resolve <IStateClient>();
                        bool         writeSuccessful = false;
                        uint         writeAttempts   = 0;
                        //將資料存回 botState 之中
                        while (!writeSuccessful && writeAttempts++ < MaxWriteAttempts)
                        {
                            try
                            {
                                var userData = sc.BotState.GetUserData(message.ChannelId, message.Recipient.Id);
                                userData.SetProperty(ContextConstants.AuthResultKey, authResult);
                                userData.SetProperty(ContextConstants.MagicNumberKey, magicNumber);
                                userData.SetProperty(ContextConstants.MagicNumberValidated, "false");
                                sc.BotState.SetUserData(message.ChannelId, message.Recipient.Id, userData);
                                writeSuccessful = true;
                            }
                            catch (HttpOperationException)
                            {
                                writeSuccessful = false;
                            }
                        }

                        if (!writeSuccessful)
                        {
                            message.Text = String.Empty; // fail the login process if we can't write UserData
                            await Conversation.ResumeAsync(state.ConversationReference, message);

                            txtAlertMsg.Text = "無法登入,請再試一次,謝謝您!";
                        }
                        else
                        {
                            await Conversation.ResumeAsync(state.ConversationReference, message);

                            txtAlertMsg.Text = $"請將以下的{ContextConstants.MagicNumberLength}個數字驗證碼輸入到IM之中,以完成登入程序,謝謝您!<br/> <h1>{magicNumber}</h1>";
                        }
                    }
                }
                else
                {
                    // login fail
                    txtAlertMsg.Text = "登入失敗! 請重新輸入! ";
                }
            }
            catch
            {
                txtAlertMsg.Text = "不是從 IM 進來的!";
            }
        }
Esempio n. 10
0
        /// <summary>
        /// POST: api/Messages
        /// Receive a message from a user and reply to it
        /// </summary>
        //[ResponseType(typeof(void))]
        public async Task <HttpResponseMessage> Post([FromBody] Activity activity)
        {
            //trust Webchat & SMS channel
            MicrosoftAppCredentials.TrustServiceUrl(@"https://webchat.botframework.com", DateTime.MaxValue);
            MicrosoftAppCredentials.TrustServiceUrl(@"https://sms.botframework.com", DateTime.MaxValue);

            Trace.TraceInformation($"Incoming Activity is {activity.ToJson()}");
            if (activity.Type == ActivityTypes.Message)
            {
                if (!string.IsNullOrEmpty(activity.Text))
                {
                    //detect language of input text
                    var userLanguage = TranslationHandler.DetectLanguage(activity);

                    //save user's LanguageCode to Azure Table Storage
                    var message = activity as IMessageActivity;

                    try
                    {
                        using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                        {
                            var botDataStore = scope.Resolve <IBotDataStore <BotData> >();
                            var key          = new AddressKey()
                            {
                                BotId          = message.Recipient.Id,
                                ChannelId      = message.ChannelId,
                                UserId         = message.From.Id,
                                ConversationId = message.Conversation.Id,
                                ServiceUrl     = message.ServiceUrl
                            };

                            var userData = await botDataStore.LoadAsync(key, BotStoreType.BotUserData, CancellationToken.None);

                            var storedLanguageCode = userData.GetProperty <string>(StringConstants.UserLanguageKey);

                            //update user's language in Azure Table Storage
                            if (storedLanguageCode != userLanguage)
                            {
                                userData.SetProperty(StringConstants.UserLanguageKey, userLanguage);
                                await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);

                                await botDataStore.FlushAsync(key, CancellationToken.None);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    //translate activity.Text to English before sending to LUIS for intent
                    activity.Text = TranslationHandler.TranslateTextToDefaultLanguage(activity, userLanguage);

                    await Conversation.SendAsync(activity, MakeRoot);
                }
            }
            else
            {
                HandleSystemMessage(activity);
            }
            var response = Request.CreateResponse(HttpStatusCode.OK);

            return(response);
        }
Esempio n. 11
0
        public async Task InMemoryBotDataStoreTest()
        {
            var chain = Chain.PostToChain().Select(m => m.Text).ContinueWith <string, string>(async(context, result) =>
            {
                int t = 0;
                context.UserData.TryGetValue("count", out t);
                if (t > 0)
                {
                    int value;
                    Assert.IsTrue(context.ConversationData.TryGetValue("conversation", out value));
                    Assert.AreEqual(t - 1, value);
                    Assert.IsTrue(context.UserData.TryGetValue("user", out value));
                    Assert.AreEqual(t + 1, value);
                    Assert.IsTrue(context.PrivateConversationData.TryGetValue("PrivateConversationData", out value));
                    Assert.AreEqual(t + 2, value);
                }

                context.ConversationData.SetValue("conversation", t);
                context.UserData.SetValue("user", t + 2);
                context.PrivateConversationData.SetValue("PrivateConversationData", t + 3);
                context.UserData.SetValue("count", ++t);
                return(Chain.Return($"{t}:{await result}"));
            }).PostToUser();
            Func <IDialog <object> > MakeRoot = () => chain;

            using (new FiberTestBase.ResolveMoqAssembly(chain))
                using (var container = Build(Options.InMemoryBotDataStore, new MockConnectorFactory(new BotIdResolver("testBot")), chain))
                {
                    var msg = DialogTestBase.MakeTestMessage();
                    msg.Text = "test";
                    using (var scope = DialogModule.BeginLifetimeScope(container, msg))
                    {
                        scope.Resolve <Func <IDialog <object> > >(TypedParameter.From(MakeRoot));

                        await Conversation.SendAsync(scope, msg);

                        var reply = scope.Resolve <Queue <IMessageActivity> >().Dequeue();
                        Assert.AreEqual("1:test", reply.Text);
                        var store = scope.Resolve <CachingBotDataStore_LastWriteWins>();
                        Assert.AreEqual(0, store.cache.Count);
                        var dataStore = scope.Resolve <InMemoryDataStore>();
                        Assert.AreEqual(3, dataStore.store.Count);
                    }

                    for (int i = 0; i < 10; i++)
                    {
                        using (var scope = DialogModule.BeginLifetimeScope(container, msg))
                        {
                            scope.Resolve <Func <IDialog <object> > >(TypedParameter.From(MakeRoot));
                            await Conversation.SendAsync(scope, msg);

                            var reply = scope.Resolve <Queue <IMessageActivity> >().Dequeue();
                            Assert.AreEqual($"{i+2}:test", reply.Text);
                            var store = scope.Resolve <CachingBotDataStore_LastWriteWins>();
                            Assert.AreEqual(0, store.cache.Count);
                            var dataStore = scope.Resolve <InMemoryDataStore>();
                            Assert.AreEqual(3, dataStore.store.Count);
                            string val = string.Empty;
                            Assert.IsTrue(scope.Resolve <IBotData>().PrivateConversationData.TryGetValue(DialogModule.BlobKey, out val));
                            Assert.AreNotEqual(string.Empty, val);
                        }
                    }
                }
        }
Esempio n. 12
0
        private async Task <Activity> HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)// && message.ChannelId != "directline")
            {
                MicrosoftAppCredentials.TrustServiceUrl(message.ServiceUrl);
                IConversationUpdateActivity iConversationUpdated = message as IConversationUpdateActivity;
                if (iConversationUpdated != null)
                {
                    ConnectorClient connector = new ConnectorClient(new System.Uri(message.ServiceUrl));
                    foreach (var member in iConversationUpdated.MembersAdded ?? System.Array.Empty <ChannelAccount>())
                    {
                        if (member.Id == iConversationUpdated.Recipient.Id && message.ChannelId != "directline")
                        {
                            var cardText = await CardService.GetCardAttachment("FirstWelcome");

                            var reply = RootDialog.GetCardReply(message, cardText);

                            await connector.Conversations.ReplyToActivityAsync(reply);
                        }
                    }
                }
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }
            else if (message.Type == ActivityTypes.Event)
            {
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var cancellationToken = default(CancellationToken);
                    var agentService      = scope.Resolve <IAgentService>();
                    switch (message.AsEventActivity().Name)
                    {
                    case "connect":
                        await agentService.RegisterAgentAsync(message, cancellationToken);

                        break;

                    case "disconnect":
                        await agentService.UnregisterAgentAsync(message, cancellationToken);

                        break;

                    case "stopConversation":
                        await StopConversation(agentService, message, cancellationToken);

                        await agentService.RegisterAgentAsync(message, cancellationToken);

                        break;

                    default:
                        break;
                    }
                }
            }
            return(null);
        }
Esempio n. 13
0
        /// <summary>
        /// POST: api/Messages
        /// Receive a message from a user and reply to it
        /// </summary>
        public async Task <HttpResponseMessage> Post([FromBody] Activity activity)
        {
            if (activity.Type == ActivityTypes.Message)
            {
                //to show user that bot is typing
                //var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
                //Activity isTypingReply = activity.CreateReply();
                //isTypingReply.Type = ActivityTypes.Typing;
                //isTypingReply.Text = null;
                //await connector.Conversations.ReplyToActivityAsync(isTypingReply);


                if (!string.IsNullOrEmpty(activity.Text))
                {
                    var userLanguage = TranslationHandler.DetectLanguage(activity);

                    //save user's LanguageCode to Azure Storage
                    var message = activity as IMessageActivity;

                    try
                    {
                        using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                        {
                            var botDataStore = scope.Resolve <IBotDataStore <BotData> >();
                            var key          = new AddressKey()
                            {
                                BotId          = message.Recipient.Id,
                                ChannelId      = message.ChannelId,
                                UserId         = message.From.Id,
                                ConversationId = message.Conversation.Id,
                                ServiceUrl     = message.ServiceUrl
                            };

                            var userData = await botDataStore.LoadAsync(key, BotStoreType.BotUserData, CancellationToken.None);

                            var storedLanguageCode = userData.GetProperty <string>(StringConstants.UserLanguageKey);

                            //update user's language in Azure Storage
                            if (storedLanguageCode != userLanguage)
                            {
                                userData.SetProperty(StringConstants.UserLanguageKey, userLanguage);
                                await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);

                                await botDataStore.FlushAsync(key, CancellationToken.None);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }

                    activity.Text = TranslationHandler.TranslateTextToDefaultLanguage(activity, userLanguage);
                }
                //await Conversation.SendAsync(activity, MakeRootDialog);
                //await Conversation.SendAsync(activity, () => new RootDialog());
                //await Conversation.SendAsync(activity, () => new Dialogs.SimpleQnADialog());
                await SendAsync(activity, (scope) => new RootDialog(scope.Resolve <IUserToAgent>()));
            }
            else
            {
                await HandleSystemMessage(activity);
            }
            var response = Request.CreateResponse(HttpStatusCode.OK);

            return(response);
        }
Esempio n. 14
0
        public static async Task RecordScript(ILifetimeScope container,
                                              bool proactive,
                                              StreamWriter stream,
                                              Func <string> extraInfo,
                                              params string[] inputs)
        {
            var toBot = MakeTestMessage();

            var adapter = new TestAdapter();
            await adapter.ProcessActivity((Activity)toBot, async (ctx) =>
            {
                using (var containerScope = DialogModule.BeginLifetimeScope(container, ctx))
                {
                    var task  = containerScope.Resolve <IPostToBot>();
                    var queue = adapter.ActiveQueue;

                    Action drain = () =>
                    {
                        stream.WriteLine($"{queue.Count()}");
                        while (queue.Count > 0)
                        {
                            var toUser = queue.Dequeue();
                            if (!string.IsNullOrEmpty(toUser.Text))
                            {
                                stream.WriteLine($"ToUserText:{JsonConvert.SerializeObject(toUser.Text)}");
                            }
                            else
                            {
                                stream.WriteLine($"ToUserButtons:{JsonConvert.SerializeObject(toUser.Attachments)}");
                            }
                        }
                    };
                    string result = null;
                    var root      = containerScope.Resolve <IDialog <object> >().Do(async(context, value) =>
                                                                                    result = JsonConvert.SerializeObject(await value));

                    using (var innerScope = containerScope.BeginLifetimeScope(
                               async(builder) =>
                    {
                        if (proactive)
                        {
                            var loop = root.Loop();
                            var data = containerScope.Resolve <IBotData>();
                            await data.LoadAsync(CancellationToken.None);
                            var stack = containerScope.Resolve <IDialogTask>();
                            stack.Call(loop, null);
                            await stack.PollAsync(CancellationToken.None);
                            drain();
                        }
                        else
                        {
                            builder
                            .RegisterInstance(root)
                            .AsSelf()
                            .As <IDialog <object> >();
                        }
                    }))
                    {
                        foreach (var input in inputs)
                        {
                            stream.WriteLine($"FromUser:{JsonConvert.SerializeObject(input)}");
                            toBot.Text = input;
                            try
                            {
                                await task.PostAsync(toBot, CancellationToken.None);
                                drain();
                                if (extraInfo != null)
                                {
                                    var extra = extraInfo();
                                    stream.WriteLine(extra);
                                }
                            }
                            catch (Exception e)
                            {
                                stream.WriteLine($"Exception:{e.Message}");
                            }
                        }
                        if (result != null)
                        {
                            stream.WriteLine($"Result: {result}");
                        }
                    }
                }
            });
        }
Esempio n. 15
0
        public async Task <HttpResponseMessage> OAuthCallback([FromUri] string code, [FromUri] string state)
        {
            try
            {
                object tokenCache = null;
                if (string.Equals(AuthSettings.Mode, "v1", StringComparison.OrdinalIgnoreCase))
                {
                    tokenCache = new Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache();
                }
                else if (string.Equals(AuthSettings.Mode, "v2", StringComparison.OrdinalIgnoreCase))
                {
                    tokenCache = new Microsoft.Identity.Client.TokenCache();
                }
                else if (string.Equals(AuthSettings.Mode, "b2c", StringComparison.OrdinalIgnoreCase))
                {
                }

                // Get the resumption cookie
                var resumptionCookie = UrlToken.Decode <ResumptionCookie>(state);
                // Create the message that is send to conversation to resume the login flow
                var message = resumptionCookie.GetMessage();

                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var client = scope.Resolve <IConnectorClient>();

                    AuthResult authResult = null;

                    if (string.Equals(AuthSettings.Mode, "v1", StringComparison.OrdinalIgnoreCase))
                    {
                        // Exchange the Auth code with Access token
                        var token = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, (Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache) tokenCache);

                        authResult = token;
                    }
                    else if (string.Equals(AuthSettings.Mode, "v2", StringComparison.OrdinalIgnoreCase))
                    {
                        //TODO: Scopes definition here
                        // Exchange the Auth code with Access token
                        var token = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, (Microsoft.Identity.Client.TokenCache) tokenCache, new string[] { "User.Read" });

                        authResult = token;
                    }
                    else if (string.Equals(AuthSettings.Mode, "b2c", StringComparison.OrdinalIgnoreCase))
                    {
                    }

                    var reply = await Conversation.ResumeAsync(resumptionCookie, message);

                    var data = await client.Bots.GetPerUserConversationDataAsync(resumptionCookie.BotId, resumptionCookie.ConversationId, resumptionCookie.UserId);

                    reply.SetBotUserData(ContextConstants.AuthResultKey, authResult);
                    int magicNumber = GenerateRandomNumber();
                    reply.SetBotUserData(ContextConstants.MagicNumberKey, magicNumber);
                    reply.SetBotUserData(ContextConstants.MagicNumberValidated, "false");

                    //data.SetProperty(ContextConstants.AuthResultKey, authResult);
                    //data.SetProperty(ContextConstants.MagicNumberKey, magicNumber);
                    //data.SetProperty(ContextConstants.MagicNumberValidated, "false");

                    //await client.Bots.SetUserDataAsync(resumptionCookie.BotId, resumptionCookie.UserId, data);



                    reply.To   = message.From;
                    reply.From = message.To;

                    await client.Messages.SendMessageAsync(reply);

                    var resp = new HttpResponseMessage(HttpStatusCode.OK);
                    resp.Content = new StringContent($"<html><body>Almost done! Please copy this number and paste it back to your chat so your authentication can complete: {magicNumber}.</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    return(resp);
                }
            }
            catch (Exception ex)
            {
                // Callback is called with no pending message as a result the login flow cannot be resumed.
                return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, new InvalidOperationException("Cannot resume!")));
            }
        }
Esempio n. 16
0
        private async Task HandleSystemMessageAsync(Activity message, ConnectorClient connectorClient, CancellationToken cancellationToken)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // This shows how to send a welcome message in response to a conversationUpdate event

                // We're only interested in member added events
                if (message.MembersAdded?.Count > 0)
                {
                    // Determine if the bot was added to the team/conversation
                    var botId       = message.Recipient.Id;
                    var botWasAdded = message.MembersAdded.Any(member => member.Id == botId);

                    // Create the welcome message to send
                    Activity welcomeMessage = message.CreateReply();
                    welcomeMessage.Text = Strings.BotWelcomeMessage;

                    if (!(message.Conversation.IsGroup ?? false))
                    {
                        // 1:1 conversation event

                        // If the user hasn't received a first-run message yet, then send a message to the user
                        // introducing your bot and what it can do. Do NOT send this blindly, as your bot can receive
                        // spurious conversationUpdate events, especially if you use proactive messaging.
                        using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                        {
                            var address      = Address.FromActivity(message);
                            var botDataStore = scope.Resolve <IBotDataStore <BotData> >();
                            var botData      = await botDataStore.LoadAsync(address, BotStoreType.BotUserData, cancellationToken);

                            if (!botData.GetProperty <bool>("IsFreSent"))
                            {
                                await connectorClient.Conversations.ReplyToActivityWithRetriesAsync(welcomeMessage, cancellationToken);

                                // Remember that we sent the welcome message already
                                botData.SetProperty("IsFreSent", true);
                                await botDataStore.SaveAsync(address, BotStoreType.BotUserData, botData, cancellationToken);
                            }
                            else
                            {
                                // First-run message has already been sent, so skip sending it again.
                                // Do not remove the check for IsFreSent above. Your bot can receive spurious conversationUpdate
                                // activities from chat service, so if you always respond to all of them, you will send random
                                // welcome messages to users who have already received the welcome.
                            }
                        }
                    }
                    else
                    {
                        // Not 1:1 chat event (bot or user was added to a team or group chat)
                        if (botWasAdded)
                        {
                            // Bot was added to the team
                            // Send a message to the team's channel, introducing your bot and what you can do
                            await connectorClient.Conversations.ReplyToActivityWithRetriesAsync(welcomeMessage, cancellationToken);
                        }
                        else
                        {
                            // Other users were added to the team/conversation
                        }
                    }
                }
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing that the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }
        }
Esempio n. 17
0
 public override void Init()
 {
     dm = GameMain.GetInstance().GetModule <DialogModule> ();
 }
Esempio n. 18
0
        /// <summary>
        /// POST: api/Messages
        /// Receive a message from a user and reply to it
        /// </summary>
        public async Task <HttpResponseMessage> Post([FromBody] Activity activity, CancellationToken cancellationToken)
        {
            var connectorClient = new ConnectorClient(new Uri(activity.ServiceUrl));

            if (activity.Type == ActivityTypes.Message)
            {
                // Special handling for a command to simulate a reset of the bot chat
                if (!(activity.Conversation.IsGroup ?? false) && (activity.Text == "/resetbotchat"))
                {
                    return(await HandleResetBotChatAsync(activity, cancellationToken));
                }

                //Set the Locale for Bot
                activity.Locale = TemplateUtility.GetLocale(activity);

                //Strip At mention from incoming request text
                activity = Middleware.StripAtMentionText(activity);

                //Convert incoming activity text to lower case, to match the intent irrespective of incoming text case
                activity = Middleware.ConvertActivityTextToLower(activity);

                //Set the OFFICE_365_TENANT_FILTER key in web.config file with Tenant Information
                //Validate bot for specific teams tenant if any
                if (Middleware.RejectMessageBasedOnTenant(activity, activity.GetTenantId()))
                {
                    Activity replyActivity = activity.CreateReply();
                    replyActivity.Text = Strings.TenantLevelDeniedAccess;

                    await connectorClient.Conversations.ReplyToActivityAsync(replyActivity);

                    return(Request.CreateResponse(HttpStatusCode.OK));
                }

                await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
            }
            else if (activity.Type == ActivityTypes.MessageReaction)
            {
                var      reactionsAdded   = activity.ReactionsAdded;
                var      reactionsRemoved = activity.ReactionsRemoved;
                var      replytoId        = activity.ReplyToId;
                Activity reply;

                if (reactionsAdded != null && reactionsAdded.Count > 0)
                {
                    reply = activity.CreateReply(Strings.LikeMessage);
                    await connectorClient.Conversations.ReplyToActivityAsync(reply);
                }
                else if (reactionsRemoved != null && reactionsRemoved.Count > 0)
                {
                    reply = activity.CreateReply(Strings.RemoveLike);
                    await connectorClient.Conversations.ReplyToActivityAsync(reply);
                }

                return(Request.CreateResponse(HttpStatusCode.OK));
            }
            else if (activity.Type == ActivityTypes.Invoke) // Received an invoke
            {
                // Handle ComposeExtension query
                if (activity.IsComposeExtensionQuery())
                {
                    WikipediaComposeExtension wikipediaComposeExtension = new WikipediaComposeExtension();
                    HttpResponseMessage       httpResponse = null;

                    using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
                    {
                        var botDataStore = scope.Resolve <IBotDataStore <BotData> >();
                        // Handle compose extension selected item
                        if (activity.Name == "composeExtension/selectItem")
                        {
                            // This handler is used to process the event when a user in Teams selects wiki item from wiki result
                            ComposeExtensionResponse selectedItemResponse = await wikipediaComposeExtension.HandleComposeExtensionSelectedItem(activity, botDataStore);

                            httpResponse = Request.CreateResponse <ComposeExtensionResponse>(HttpStatusCode.OK, selectedItemResponse);
                        }
                        else
                        {
                            // Handle the wiki compose extension request and returned the wiki result response
                            ComposeExtensionResponse composeExtensionResponse = await wikipediaComposeExtension.GetComposeExtensionResponse(activity, botDataStore);

                            httpResponse = Request.CreateResponse <ComposeExtensionResponse>(HttpStatusCode.OK, composeExtensionResponse);
                        }

                        var address = Address.FromActivity(activity);
                        await botDataStore.FlushAsync(address, CancellationToken.None);
                    }
                    return(httpResponse);
                }
                //Actionable Message
                else if (activity.IsO365ConnectorCardActionQuery())
                {
                    // this will handle the request coming any action on Actionable messages
                    return(await HandleO365ConnectorCardActionQuery(activity));
                }
                //PopUp SignIn
                else if (activity.Name == "signin/verifyState")
                {
                    // this will handle the request coming from PopUp SignIn
                    return(await PopUpSignInHandler(activity));
                }
                // Handle rest of the invoke request
                else
                {
                    var messageActivity = (IMessageActivity)null;

                    //this will parse the invoke value and change the message activity as well
                    messageActivity = InvokeHandler.HandleInvokeRequest(activity);

                    await Conversation.SendAsync(messageActivity, () => new Dialogs.RootDialog());

                    return(Request.CreateResponse(HttpStatusCode.OK));
                }
            }
            else
            {
                await HandleSystemMessageAsync(activity, connectorClient, cancellationToken);
            }

            var response = Request.CreateResponse(HttpStatusCode.OK);

            return(response);
        }
Esempio n. 19
0
        public async Task AlarmDialogFlow()
        {
            var luis = new Mock <ILuisService>();

            // arrange
            var now         = DateTime.UtcNow;
            var entityTitle = EntityFor(SimpleAlarmBot.SimpleAlarmDialog.Entity_Alarm_Title, "title");
            var entityDate  = EntityFor(SimpleAlarmBot.SimpleAlarmDialog.Entity_Alarm_Start_Date, now.ToString("d", DateTimeFormatInfo.InvariantInfo));
            var entityTime  = EntityFor(SimpleAlarmBot.SimpleAlarmDialog.Entity_Alarm_Start_Time, now.ToString("t", DateTimeFormatInfo.InvariantInfo));

            Func <IDialog <object> > MakeRoot = () => new SimpleAlarmBot.SimpleAlarmDialog(luis.Object);
            var toBot = new Message()
            {
                ConversationId = Guid.NewGuid().ToString()
            };

            using (new FiberTestBase.ResolveMoqAssembly(luis.Object))
                using (var container = Build(Options.ScopedQueue, luis.Object))
                {
                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var task = scope.Resolve <IDialogTask>();

                        // arrange
                        SetupLuis(luis, a => a.SetAlarm(null, null), entityTitle, entityDate, entityTime);

                        // act
                        await task.PostAsync(toBot, MakeRoot);

                        // assert
                        luis.VerifyAll();
                        AssertMentions("created", scope);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var task = scope.Resolve <IDialogTask>();

                        // arrange
                        SetupLuis(luis, a => a.FindAlarm(null, null), entityTitle);

                        // act
                        await task.PostAsync(toBot, MakeRoot);

                        // assert
                        luis.VerifyAll();
                        AssertMentions("found", scope);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var task = scope.Resolve <IDialogTask>();

                        // arrange
                        SetupLuis(luis, a => a.AlarmSnooze(null, null), entityTitle);

                        // act
                        await task.PostAsync(toBot, MakeRoot);

                        // assert
                        luis.VerifyAll();
                        AssertMentions("snoozed", scope);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var task = scope.Resolve <IDialogTask>();

                        // arrange
                        SetupLuis(luis, a => a.TurnOffAlarm(null, null), entityTitle);

                        // act
                        await task.PostAsync(toBot, MakeRoot);

                        // assert
                        luis.VerifyAll();
                        AssertMentions("sure", scope);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var task = scope.Resolve <IDialogTask>();

                        // arrange
                        toBot.Text = "blah";

                        // act
                        await task.PostAsync(toBot, MakeRoot);

                        // assert
                        luis.VerifyAll();
                        AssertMentions("sure", scope);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var task = scope.Resolve <IDialogTask>();

                        // arrange
                        toBot.Text = "yes";

                        // act
                        await task.PostAsync(toBot, MakeRoot);

                        // assert
                        luis.VerifyAll();
                        AssertMentions("disabled", scope);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var task = scope.Resolve <IDialogTask>();

                        // arrange
                        SetupLuis(luis, a => a.DeleteAlarm(null, null), entityTitle);

                        // act
                        await task.PostAsync(toBot, MakeRoot);

                        // assert
                        luis.VerifyAll();
                        AssertMentions("did not find", scope);
                    }
                }
        }
Esempio n. 20
0
        private async Task <Activity> HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                IConversationUpdateActivity update = message;
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var client = scope.Resolve <IConnectorClient>();
                    if (update.MembersAdded.Any())
                    {
                        var reply = message.CreateReply();
                        foreach (var newMember in update.MembersAdded)
                        {
                            //var reply1 = message.CreateReply();
                            //reply1.Text = "new member" +  newMember.Name.ToLower();
                            //await client.Conversations.ReplyToActivityAsync(reply1);
                            // the bot is always added as a user of the conversation, since we don't
                            // want to display the adaptive card twice ignore the conversation update triggered by the bot
                            if (newMember.Name.ToLower() != "you")
                            {
                                try
                                {
                                    // read the json in from our file
                                    string json = File.ReadAllText(HttpContext.Current.Request.MapPath("~\\AdaptiveCards\\MyCard.json"));
                                    // use Newtonsofts JsonConvert to deserialized the json into a C# AdaptiveCard object
                                    AdaptiveCards.AdaptiveCard card = JsonConvert.DeserializeObject <AdaptiveCards.AdaptiveCard>(json);
                                    // put the adaptive card as an attachment to the reply message
                                    reply.Attachments.Add(new Attachment
                                    {
                                        ContentType = AdaptiveCard.ContentType,
                                        Content     = card
                                    });
                                }
                                catch (Exception e)
                                {
                                    // if an error occured add the error text as the message
                                    reply.Text = e.Message;
                                }
                                await client.Conversations.ReplyToActivityAsync(reply);
                            }
                        }
                    }
                }
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }
            else if (message.Type == ActivityTypes.Event)
            {
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var cancellationToken = default(CancellationToken);
                    var agentService      = scope.Resolve <IAgentService>();
                    switch (message.AsEventActivity().Name)
                    {
                    case "connect":
                        await agentService.RegisterAgentAsync(message, cancellationToken);

                        break;

                    case "disconnect":
                        await agentService.UnregisterAgentAsync(message, cancellationToken);

                        break;

                    case "stopConversation":
                        await StopConversation(agentService, message, cancellationToken);

                        await agentService.RegisterAgentAsync(message, cancellationToken);

                        break;

                    default:
                        break;
                    }
                }
            }

            return(null);
        }
        private async Task HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels

                IConversationUpdateActivity update = message;
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var client = scope.Resolve <IConnectorClient>();
                    if (update.MembersAdded.Any())
                    {
                        var reply = message.CreateReply();
                        foreach (var newMember in update.MembersAdded)
                        {
                            // the bot is always added as a user of the conversation, since we don't
                            // want to display the adaptive card twice ignore the conversation update triggered by the bot
                            if (newMember.Name.ToLower() != "bot")
                            {
                                try
                                {
                                    // read the json in from our file
                                    //string json = File.ReadAllText(HttpContext.Current.Request.MapPath("~\\AdaptiveCards\\MyCard.json"));
                                    // use Newtonsofts JsonConvert to deserialized the json into a C# AdaptiveCard object
                                    //AdaptiveCards.AdaptiveCard card = JsonConvert.DeserializeObject<AdaptiveCards.AdaptiveCard>(json);
                                    // put the adaptive card as an attachment to the reply message
                                    //reply.Attachments.Add(new Attachment
                                    //{
                                    //    ContentType = AdaptiveCard.ContentType,
                                    //    Content = card
                                    //});
                                    reply.Text = "Welcome message from Bot";
                                }
                                catch (Exception e)
                                {
                                    // if an error occured add the error text as the message
                                    reply.Text = e.Message;
                                }
                                await client.Conversations.ReplyToActivityAsync(reply);
                            }
                        }
                    }
                }
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }
        }
Esempio n. 22
0
        public async Task <HttpResponseMessage> OAuthCallback([FromUri] string code, [FromUri] string state, CancellationToken cancellationToken)
        {
            try
            {
                object tokenCache = null;
                if (string.Equals(AuthSettings.Mode, "v1", StringComparison.OrdinalIgnoreCase))
                {
                    tokenCache = new Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache();
                }
                else if (string.Equals(AuthSettings.Mode, "v2", StringComparison.OrdinalIgnoreCase))
                {
                    tokenCache = new Microsoft.Identity.Client.TokenCache();
                }
                else if (string.Equals(AuthSettings.Mode, "b2c", StringComparison.OrdinalIgnoreCase))
                {
                }

                // Get the resumption cookie
                var resumptionCookie = UrlToken.Decode <ResumptionCookie>(state);
                // Create the message that is send to conversation to resume the login flow
                var message = resumptionCookie.GetMessage();

                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var        client     = scope.Resolve <IConnectorClient>();
                    AuthResult authResult = null;
                    if (string.Equals(AuthSettings.Mode, "v1", StringComparison.OrdinalIgnoreCase))
                    {
                        // Exchange the Auth code with Access token
                        var token = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, (Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache) tokenCache);

                        authResult = token;
                    }
                    else if (string.Equals(AuthSettings.Mode, "v2", StringComparison.OrdinalIgnoreCase))
                    {
                        // Exchange the Auth code with Access token
                        var token = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, (Microsoft.Identity.Client.TokenCache) tokenCache, Models.AuthSettings.Scopes);

                        authResult = token;
                    }
                    else if (string.Equals(AuthSettings.Mode, "b2c", StringComparison.OrdinalIgnoreCase))
                    {
                    }

                    IStateClient sc = scope.Resolve <IStateClient>();

                    //IMPORTANT: DO NOT REMOVE THE MAGIC NUMBER CHECK THAT WE DO HERE. THIS IS AN ABSOLUTE SECURITY REQUIREMENT
                    //REMOVING THIS WILL REMOVE YOUR BOT AND YOUR USERS TO SECURITY VULNERABILITIES.
                    //MAKE SURE YOU UNDERSTAND THE ATTACK VECTORS AND WHY THIS IS IN PLACE.
                    var dataBag = scope.Resolve <IBotData>();
                    await dataBag.LoadAsync(cancellationToken);

                    int magicNumber = GenerateRandomNumber();
                    dataBag.UserData.SetValue(ContextConstants.AuthResultKey, authResult);
                    dataBag.UserData.SetValue(ContextConstants.MagicNumberKey, magicNumber);
                    dataBag.UserData.SetValue(ContextConstants.MagicNumberValidated, "false");
                    await dataBag.FlushAsync(cancellationToken);

                    await Conversation.ResumeAsync(resumptionCookie, message);

                    var resp = new HttpResponseMessage(HttpStatusCode.OK);
                    resp.Content = new StringContent($"<html><body>Almost done! Please copy this number and paste it back to your chat so your authentication can complete: {magicNumber}.</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    return(resp);
                }
            }
            catch (Exception ex)
            {
                // Callback is called with no pending message as a result the login flow cannot be resumed.
                return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex));
            }
        }
Esempio n. 23
0
        public async Task If_Root_Dialog_Throws_Propagate_Exception_Reset_Store()
        {
            var dialog = new Mock <IDialogThatFails>(MockBehavior.Loose);

            dialog
            .Setup(d => d.StartAsync(It.IsAny <IDialogContext>()))
            .Returns <IDialogContext>(async context => { context.Wait(dialog.Object.MessageReceived); });

            dialog
            .Setup(d => d.MessageReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <IMessageActivity> >()))
            .Returns <IDialogContext, IAwaitable <IMessageActivity> >(async(context, result) => { context.Wait(dialog.Object.Throw); });

            dialog
            .Setup(d => d.Throw(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <IMessageActivity> >()))
            .Throws <ApplicationException>();

            Func <IDialog <object> > MakeRoot = () => dialog.Object;
            var toBot = DialogTestBase.MakeTestMessage();

            using (new FiberTestBase.ResolveMoqAssembly(dialog.Object))
                using (var container = Build(Options.MockConnectorFactory, dialog.Object))
                {
                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();
                        await task.PostAsync(toBot, CancellationToken.None);
                    }

                    dialog.Verify(d => d.StartAsync(It.IsAny <IDialogContext>()), Times.Once);
                    dialog.Verify(d => d.MessageReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <IMessageActivity> >()), Times.Once);
                    dialog.Verify(d => d.Throw(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <IMessageActivity> >()), Times.Never);

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        await scope.Resolve <IBotData>().LoadAsync(default(CancellationToken));

                        var task = scope.Resolve <IDialogStack>();
                        Assert.AreNotEqual(0, task.Frames.Count);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();

                        try
                        {
                            await task.PostAsync(toBot, CancellationToken.None);

                            Assert.Fail();
                        }
                        catch (ApplicationException)
                        {
                        }
                        catch
                        {
                            Assert.Fail();
                        }
                    }

                    dialog.Verify(d => d.StartAsync(It.IsAny <IDialogContext>()), Times.Once);
                    dialog.Verify(d => d.MessageReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <IMessageActivity> >()), Times.Once);
                    dialog.Verify(d => d.Throw(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <IMessageActivity> >()), Times.Once);

                    //make sure that data is persisted with connector
                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        var connectorFactory = scope.Resolve <IConnectorClientFactory>();
                        var botDataStore     = scope.Resolve <IBotDataStore <BotData> >();
                        var botData          = scope.Resolve <IBotData>();
                        await botData.LoadAsync(default(CancellationToken));

                        Assert.AreEqual(1, botData.PrivateConversationData.Count);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        await scope.Resolve <IBotData>().LoadAsync(default(CancellationToken));

                        var stack = scope.Resolve <IDialogStack>();
                        Assert.AreEqual(0, stack.Frames.Count);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();
                        await task.PostAsync(toBot, CancellationToken.None);
                    }

                    dialog.Verify(d => d.StartAsync(It.IsAny <IDialogContext>()), Times.Exactly(2));
                    dialog.Verify(d => d.MessageReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <IMessageActivity> >()), Times.Exactly(2));
                    dialog.Verify(d => d.Throw(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <IMessageActivity> >()), Times.Once);
                }
        }
Esempio n. 24
0
        /// <summary>
        /// POST: api/Messages
        /// Receive a message from a user and reply to it
        /// </summary>
        public async Task <HttpResponseMessage> Post([FromBody] Activity activity)
        {
            if (activity.Type == ActivityTypes.Message)
            {
                await Conversation.SendAsync(activity, () => new RootDialog(CommandsHelper.GetValidTriggers(DialogModule.BeginLifetimeScope(Conversation.Container, activity)).ToArray()));
            }
            else
            {
                this.HandleSystemMessage(activity);
            }

            var response = Request.CreateResponse(HttpStatusCode.OK);

            return(response);
        }
Esempio n. 25
0
        public async Task DialogTask_Frame_Scoring()
        {
            var dialogOne = new Mock <IDialogFrames <string> >(MockBehavior.Loose);
            var dialogTwo = new Mock <IDialogFrames <Guid> >(MockBehavior.Loose);
            var dialogNew = new Mock <IDialogFrames <DateTime> >(MockBehavior.Loose);

            const string TriggerTextTwo = "foo";
            const string TriggerTextNew = "bar";

            // IDialogFrames<T> StartAsync and ItemReceived

            dialogOne
            .Setup(d => d.StartAsync(It.IsAny <IDialogContext>()))
            .Returns <IDialogContext>(async context => { context.Call(dialogTwo.Object, dialogOne.Object.ItemReceived); });

            dialogOne
            .Setup(d => d.ItemReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Guid> >()))
            .Returns <IDialogContext, IAwaitable <Guid> >(async(context, message) => { context.Wait(dialogOne.Object.ItemReceived); });

            dialogTwo
            .Setup(d => d.StartAsync(It.IsAny <IDialogContext>()))
            .Returns <IDialogContext>(async context => { context.Wait(dialogTwo.Object.ItemReceived); });

            dialogTwo
            .Setup(d => d.ItemReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()))
            .Returns <IDialogContext, IAwaitable <Message> >(async(context, message) =>
            {
                if ((await message).Text == TriggerTextTwo)
                {
                    context.Done(Guid.NewGuid());
                }
                else
                {
                    context.Wait(dialogTwo.Object.ItemReceived);
                }
            });

            dialogNew
            .Setup(d => d.StartAsync(It.IsAny <IDialogContext>()))
            .Returns <IDialogContext>(async context => { context.Wait(dialogNew.Object.ItemReceived); });

            dialogNew
            .Setup(d => d.ItemReceived(It.IsAny <IDialogContext>(), It.IsAny <IAwaitable <Message> >()))
            .Returns <IDialogContext, IAwaitable <Message> >(async(context, message) => { context.Done(DateTime.UtcNow); });

            // ScoringDialogTask.IScorable

            dialogOne
            .As <IScorable <double> >()
            .Setup(s => s.PrepareAsync(It.IsAny <Message>(), It.IsAny <Delegate>(), It.IsAny <CancellationToken>()))
            .Returns <Message, Delegate, CancellationToken>(async(m, d, t) => m);

            double scoreOne = 1.0;

            dialogOne
            .As <IScorable <double> >()
            .Setup(s => s.TryScore(It.IsAny <Message>(), out scoreOne))
            .Returns <Message, double>((m, s) => m.Text == TriggerTextNew);

            dialogTwo
            .As <IScorable <double> >()
            .Setup(s => s.PrepareAsync(It.IsAny <Message>(), It.IsAny <Delegate>(), It.IsAny <CancellationToken>()))
            .Returns <Message, Delegate, CancellationToken>(async(m, d, t) => m);

            double scoreTwo = 0.5;

            dialogTwo
            .As <IScorable <double> >()
            .Setup(s => s.TryScore(It.IsAny <Message>(), out scoreTwo))
            .Returns <Message, double>((m, s) => m.Text == TriggerTextNew);

            Func <IDialog <object> > MakeRoot = () => dialogOne.Object;
            var toBot = MakeTestMessage();

            using (new FiberTestBase.ResolveMoqAssembly(dialogOne.Object, dialogTwo.Object, dialogNew.Object))
                using (var container = Build(Options.None, dialogOne.Object, dialogTwo.Object, dialogNew.Object))
                {
                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task  = scope.Resolve <IPostToBot>();
                        var stack = scope.Resolve <IDialogStack>();

                        // set up dialogOne to call dialogNew when triggered
                        dialogOne
                        .As <IScorable <double> >()
                        .Setup(s => s.PostAsync(It.IsAny <IPostToBot>(), It.IsAny <Message>(), It.IsAny <Message>(), It.IsAny <CancellationToken>()))
                        .Returns <IPostToBot, Message, Message, CancellationToken>(async(inner, message, state, token) =>
                        {
                            stack.Call(dialogNew.Object.Void <DateTime, Message>(), null);
                            await stack.PollAsync(token);
                        });

                        // the stack is empty when we first start
                        Assert.AreEqual(0, stack.Frames.Count);

                        await task.PostAsync(toBot, CancellationToken.None);

                        // now the stack has the looping root frame plus the 1st and 2nd active dialogs
                        // nothing special in the message, so we still have the 1st and 2nd active dialogs
                        Assert.AreEqual(3, stack.Frames.Count);
                        Assert.AreEqual(dialogTwo.Object, stack.Frames[0].Target);
                        Assert.AreEqual(dialogOne.Object, stack.Frames[1].Target);

                        toBot.Text = TriggerTextNew;

                        await task.PostAsync(toBot, CancellationToken.None);

                        // now the trigger has occurred - the interrupting dialog is at the top of the stack,
                        // then the void dialog, then the existing 1st and 2nd dialogs that were interrupted
                        Assert.AreEqual(5, stack.Frames.Count);
                        Assert.AreEqual(dialogNew.Object, stack.Frames[0].Target);
                        Assert.AreEqual(dialogTwo.Object, stack.Frames[2].Target);
                        Assert.AreEqual(dialogOne.Object, stack.Frames[3].Target);

                        toBot.Text = string.Empty;

                        await task.PostAsync(toBot, CancellationToken.None);

                        // now the interrupted dialog will exit, and the void dialog is waiting for original message that
                        // the 2nd dialog had wanted
                        Assert.AreEqual(4, stack.Frames.Count);
                        Assert.AreEqual(dialogTwo.Object, stack.Frames[1].Target);
                        Assert.AreEqual(dialogOne.Object, stack.Frames[2].Target);

                        toBot.Text = TriggerTextTwo;

                        await task.PostAsync(toBot, CancellationToken.None);

                        // and now that the void dialog was able to capture the message, it returns it to the 2nd dialog,
                        // which returns a guid to the 1st dialog
                        Assert.AreEqual(2, stack.Frames.Count);
                        Assert.AreEqual(dialogOne.Object, stack.Frames[0].Target);
                    }
                }

            dialogOne.VerifyAll();
            dialogTwo.VerifyAll();
            dialogNew.VerifyAll();
        }
Esempio n. 26
0
        public async Task Can_Fill_In_Scalar_Types()
        {
            var mock = new Mock <IFormTarget>();

            mock.SetupAllProperties();

            Func <IDialog <IFormTarget> > MakeRoot = () => new FormDialog <IFormTarget>(mock.Object);

            // arrange
            var toBot = MakeTestMessage();

            using (new FiberTests.ResolveMoqAssembly(mock.Object))
                using (var container = Build(Options.ScopedQueue, mock.Object))
                {
                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();

                        // act
                        await task.PostAsync(toBot, CancellationToken.None);

                        // assert
                        AssertMentions(nameof(mock.Object.Text), scope);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();

                        // arrange
                        // note: this can not be "text" as that is a navigation command
                        toBot.Text = "words";

                        // act
                        await task.PostAsync(toBot, CancellationToken.None);

                        // assert
                        AssertMentions(nameof(mock.Object.Integer), scope);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();

                        // arrange
                        toBot.Text = "3";

                        // act
                        await task.PostAsync(toBot, CancellationToken.None);

                        // assert
                        AssertMentions(nameof(mock.Object.Float), scope);
                    }

                    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
                    {
                        DialogModule_MakeRoot.Register(scope, MakeRoot);

                        var task = scope.Resolve <IPostToBot>();

                        // arrange
                        toBot.Text = "3.5";

                        // act
                        await task.PostAsync(toBot, CancellationToken.None);

                        // assert
                        AssertNoMessages(scope);
                    }

                    mock.VerifyAll();
                }
        }
Esempio n. 27
0
        public async Task <HttpResponseMessage> AuthResume(
            [FromUri] string code,
            [FromUri] string state,
            CancellationToken cancellationToken)
        {
            try
            {
                var    queryParams = state;
                object tokenCache  = null;
                if (string.Equals(AuthSettings.Mode, "v1", StringComparison.OrdinalIgnoreCase))
                {
                    tokenCache = new Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache();
                }
                else if (string.Equals(AuthSettings.Mode, "v2", StringComparison.OrdinalIgnoreCase))
                {
                    tokenCache = new Microsoft.Identity.Client.TokenCache();
                }
                else if (string.Equals(AuthSettings.Mode, "b2c", StringComparison.OrdinalIgnoreCase))
                {
                }

                var resumptionCookie = UrlToken.Decode <ResumptionCookie>(queryParams);
                // Create the message that is send to conversation to resume the login flow
                var message = resumptionCookie.GetMessage();

                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var        client     = scope.Resolve <IConnectorClient>();
                    AuthResult authResult = null;
                    if (string.Equals(AuthSettings.Mode, "v1", StringComparison.OrdinalIgnoreCase))
                    {
                        // Exchange the Auth code with Access token
                        var token = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, (Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache) tokenCache);

                        authResult = token;
                    }
                    else if (string.Equals(AuthSettings.Mode, "v2", StringComparison.OrdinalIgnoreCase))
                    {
                        // Exchange the Auth code with Access token
                        var token = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, (Microsoft.Identity.Client.TokenCache) tokenCache, Models.AuthSettings.Scopes);

                        authResult = token;
                    }
                    else if (string.Equals(AuthSettings.Mode, "b2c", StringComparison.OrdinalIgnoreCase))
                    {
                    }

                    IStateClient sc = scope.Resolve <IStateClient>();

                    //IMPORTANT: DO NOT REMOVE THE MAGIC NUMBER CHECK THAT WE DO HERE. THIS IS AN ABSOLUTE SECURITY REQUIREMENT
                    //REMOVING THIS WILL REMOVE YOUR BOT AND YOUR USERS TO SECURITY VULNERABILITIES.
                    //MAKE SURE YOU UNDERSTAND THE ATTACK VECTORS AND WHY THIS IS IN PLACE.
                    int  magicNumber     = GenerateRandomNumber();
                    bool writeSuccessful = false;
                    uint writeAttempts   = 0;
                    while (!writeSuccessful && writeAttempts++ < MaxWriteAttempts)
                    {
                        try
                        {
                            BotData userData = sc.BotState.GetUserData(message.ChannelId, message.From.Id);
                            userData.SetProperty(ContextConstants.AuthResultKey, authResult);
                            userData.SetProperty(ContextConstants.MagicNumberKey, magicNumber);
                            userData.SetProperty(ContextConstants.MagicNumberValidated, "false");
                            sc.BotState.SetUserData(message.ChannelId, message.From.Id, userData);
                            writeSuccessful = true;
                        }
                        catch (HttpOperationException)
                        {
                            writeSuccessful = false;
                        }
                    }
                    var resp = new HttpResponseMessage(HttpStatusCode.OK);
                    if (!writeSuccessful)
                    {
                        message.Text = String.Empty; // fail the login process if we can't write UserData
                        await Conversation.ResumeAsync(resumptionCookie, message);

                        resp.Content = new StringContent("<html><body>Could not log you in at this time, please try again later</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    else
                    {
                        await Conversation.ResumeAsync(resumptionCookie, message);

                        resp.Content = new StringContent($"<html><body>Almost done! Please copy this number and paste it back to your chat so your authentication can complete:<br/> <h1>{magicNumber}</h1>.</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    return(resp);
                }
            }
            catch (Exception ex)
            {
                // Callback is called with no pending message as a result the login flow cannot be resumed.
                return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex));
            }
        }
Esempio n. 28
0
        private async Task MessageReceivedAsync(IDialogContext context, IAwaitable <object> result)
        {
            var activity = await result as Activity;

            //// calculate something for us to return
            //int length = (activity.Text ?? string.Empty).Length;

            //// return our reply to the user
            //await context.PostAsync($"You sent {activity.Text} which was {length} characters");

            if (activity.Text == "login")
            {
                // create state (passing data) for OAuth
                var convRef  = context.Activity.ToConversationReference();
                var stateCol = System.Web.HttpUtility.ParseQueryString(string.Empty);
                stateCol["userId"]         = convRef.User.Id;
                stateCol["botId"]          = convRef.Bot.Id;
                stateCol["conversationId"] = convRef.Conversation.Id;
                stateCol["serviceUrl"]     = convRef.ServiceUrl;
                stateCol["channelId"]      = convRef.ChannelId;

                //var uriBuilder = new UriBuilder(ConfigurationManager.AppSettings["OAuthCallbackUrl"]);
                //var query = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);
                //query["userId"] = convRef.User.Id;
                //query["botId"] = convRef.Bot.Id;
                //query["conversationId"] = convRef.Conversation.Id;
                //query["serviceUrl"] = convRef.ServiceUrl;
                //query["channelId"] = convRef.ChannelId;
                //uriBuilder.Query = query.ToString();
                //var redirectUrl = uriBuilder.ToString();

                // create Azure AD signin context
                var authContext = new AuthenticationContext("https://login.microsoftonline.com/common");
                var authUri     = authContext.GetAuthorizationRequestUrlAsync(
                    "https://outlook.office365.com/",
                    ConfigurationManager.AppSettings["ClientId"],
                    new Uri(ConfigurationManager.AppSettings["OAuthCallbackUrl"]),
                    UserIdentifier.AnyUser,
                    "&state=" + System.Web.HttpUtility.UrlEncode(stateCol.ToString()));

                // show SignIn card (setting oauth sign-in url to SignIn card)
                var reply = context.MakeMessage();
                reply.Text = "Authentication Required";
                reply.Attachments.Add(SigninCard.Create(
                                          "Login",
                                          "Please login to Office 365",
                                          authUri.Result.ToString()).ToAttachment());
                await context.PostAsync(reply);
            }
            else if (activity.Text == "get mail")
            {
                string accessToken = string.Empty;

                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
                {
                    var dataStore = scope.Resolve <IBotDataStore <BotData> >();
                    var convRef   = context.Activity.ToConversationReference();
                    var address   = new Microsoft.Bot.Builder.Dialogs.Address
                                    (
                        botId: convRef.Bot.Id,
                        channelId: convRef.ChannelId,
                        userId: convRef.User.Id,
                        conversationId: convRef.Conversation.Id,
                        serviceUrl: convRef.ServiceUrl
                                    );
                    var userData = await dataStore.LoadAsync(
                        address,
                        BotStoreType.BotUserData,
                        CancellationToken.None);

                    accessToken = userData.GetProperty <string>("AccessToken");
                }

                if (string.IsNullOrEmpty(accessToken))
                {
                    await context.PostAsync("Not logging-in (type \"login\")");
                }
                else
                {
                    // Get recent 10 e-mail from Office 365
                    HttpClient cl           = new HttpClient();
                    var        acceptHeader =
                        new MediaTypeWithQualityHeaderValue("application/json");
                    cl.DefaultRequestHeaders.Accept.Add(acceptHeader);
                    cl.DefaultRequestHeaders.Authorization
                        = new AuthenticationHeaderValue("Bearer", accessToken);
                    HttpResponseMessage httpRes =
                        await cl.GetAsync("https://outlook.office365.com/api/v1.0/me/messages?$orderby=DateTimeSent%20desc&$top=10&$select=Subject,From");

                    if (httpRes.IsSuccessStatusCode)
                    {
                        var     strRes = httpRes.Content.ReadAsStringAsync().Result;
                        JObject jRes   = await httpRes.Content.ReadAsAsync <JObject>();

                        JArray jValue = (JArray)jRes["value"];
                        foreach (JObject jItem in jValue)
                        {
                            string sub = $"Subject={((JValue)jItem["Subject"]).Value}";
                            sub = sub.Replace('<', ' ').Replace('>', ' ').Replace('[', ' ').Replace(']', ' ');
                            await context.PostAsync(sub);
                        }
                    }
                    else
                    {
                        await context.PostAsync("Failed to get e-mail.\n\nPlease type \"login\" before you get e-mail.");
                    }
                }
            }
            else if (activity.Text == "revoke")
            {
                await context.PostAsync("Click [here](https://account.activedirectory.windowsazure.com/), login, and remove this app (Bot with Office 365 Authentication Example).");
            }
            else if (activity.Text == "login_succeed")
            {
                await context.PostAsync("You logged in !");
            }
            else
            {
                await context.PostAsync("# Bot Help\n\nType the following command. (You need your Office 365 Exchange Online subscription.)\n\n**login** -- Login to Office 365\n\n**get mail** -- Get your e-mail from Office 365\n\n**revoke** -- Revoke permissions for accessing your e-mail");
            }

            context.Wait(MessageReceivedAsync);
        }
        public async Task InputHintTest()
        {
            var chain = Chain.PostToChain().Select(m => m.Text).ContinueWith <string, string>(async(context, result) =>
            {
                var text = await result;
                if (text.ToLower().StartsWith("inputhint"))
                {
                    var reply       = context.MakeMessage();
                    reply.Text      = "reply";
                    reply.InputHint = InputHints.ExpectingInput;
                    await context.PostAsync(reply);
                    return(Chain.Return($"{text}"));
                }
                else if (!text.ToLower().StartsWith("reset"))
                {
                    for (int i = 0; i < 10; i++)
                    {
                        await context.PostAsync($"message:{i}");
                    }
                    return(Chain.Return($"{text}"));
                }
                else
                {
                    return(Chain.From(() => new PromptDialog.PromptConfirm("Are you sure you want to reset the count?",
                                                                           "Didn't get that!", 3, PromptStyle.Keyboard)).ContinueWith <bool, string>(async(ctx, res) =>
                    {
                        string reply;
                        if (await res)
                        {
                            ctx.UserData.SetValue("count", 0);
                            reply = "Reset count.";
                        }
                        else
                        {
                            reply = "Did not reset count.";
                        }
                        return Chain.Return(reply);
                    }));
                }
            }).PostToUser();
            Func <IDialog <object> > MakeRoot = () => chain;

            using (new FiberTestBase.ResolveMoqAssembly(chain))
                using (var container = Build(Options.InMemoryBotDataStore | Options.NeedsInputHint, chain))
                {
                    var msg = DialogTestBase.MakeTestMessage();
                    msg.Text = "test";
                    await new TestAdapter().ProcessActivity((Activity)msg, async(context) =>
                    {
                        using (var scope = DialogModule.BeginLifetimeScope(container, context))
                        {
                            scope.Resolve <Func <IDialog <object> > >(TypedParameter.From(MakeRoot));
                            await Conversation.SendAsync(scope, context);

                            var queue = ((TestAdapter)context.Adapter).ActiveQueue;
                            Assert.IsTrue(queue.Count > 0);
                            while (queue.Count > 0)
                            {
                                var toUser = queue.Dequeue();
                                if (queue.Count > 0)
                                {
                                    Assert.IsTrue(toUser.InputHint == InputHints.IgnoringInput);
                                }
                                else
                                {
                                    Assert.IsTrue(toUser.InputHint == InputHints.AcceptingInput);
                                }
                            }
                        }
                    });


                    msg.Text = "inputhint";
                    await new TestAdapter().ProcessActivity((Activity)msg, async(context) =>
                    {
                        using (var scope = DialogModule.BeginLifetimeScope(container, context))
                        {
                            scope.Resolve <Func <IDialog <object> > >(TypedParameter.From(MakeRoot));
                            await Conversation.SendAsync(scope, context);

                            var queue = ((TestAdapter)context.Adapter).ActiveQueue;
                            Assert.IsTrue(queue.Count == 2);
                            var toUser = queue.Dequeue();
                            Assert.AreEqual("reply", toUser.Text);
                            Assert.IsTrue(toUser.InputHint == InputHints.ExpectingInput);
                        }
                    });

                    msg.Text = "reset";
                    await new TestAdapter().ProcessActivity((Activity)msg, async(context) =>
                    {
                        using (var scope = DialogModule.BeginLifetimeScope(container, context))
                        {
                            scope.Resolve <Func <IDialog <object> > >(TypedParameter.From(MakeRoot));
                            await Conversation.SendAsync(scope, context);

                            var queue = ((TestAdapter)context.Adapter).ActiveQueue;
                            Assert.IsTrue(queue.Count == 1);
                            var toUser = queue.Dequeue();
                            Assert.IsTrue(toUser.InputHint == InputHints.ExpectingInput);
                            Assert.IsNotNull(toUser.LocalTimestamp);
                        }
                    });
                }
        }
Esempio n. 30
0
        /// <summary>
        /// Processes an <see cref="Activity"/> of <see cref="ActivityTypes.Message"/> type that is an adaptive card action.
        /// </summary>
        /// <param name="activity">The incoming activity from Bot Framework.</param>
        /// <returns>A <see cref="Task"/> that resolves to a <see cref="IHttpActionResult"/> with the response from the API.</returns>
        private async Task <IHttpActionResult> HandleAdaptiveCardActionAsync(Activity activity)
        {
            // Parse out the payload.
            var payload        = activity.Value as JObject;
            var sessionId      = payload.GetValue("sessionId").Value <string>();
            var conversationId = payload.GetValue("conversationId").Value <string>();
            var choice         = (Choices)Enum.Parse(typeof(Choices), payload.GetValue("GameChoice").Value <string>());

            Match match = null;

            // Load the correct conversation data record and update it with the user's choice.
            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
            {
                var botDataStore = scope.Resolve <IBotDataStore <BotData> >();
                var address      = new Address(activity.Recipient.Id, activity.ChannelId, activity.From.Id, conversationId, activity.ServiceUrl);
                var data         = await botDataStore.LoadAsync(address, BotStoreType.BotConversationData, CancellationToken.None);

                match = data.GetProperty <Match>(sessionId);
                foreach (var result in match.Results)
                {
                    if (result.User.Id == activity.From.Id)
                    {
                        result.Choice = choice;
                    }
                }
                data.SetProperty(sessionId, match);
                await botDataStore.SaveAsync(address, BotStoreType.BotConversationData, data, CancellationToken.None);

                await botDataStore.FlushAsync(address, CancellationToken.None);
            }

            var connectorClient = new ConnectorClient(new Uri(activity.ServiceUrl));

            // Remove the response card.
            var thankYouResponse = Activity.CreateMessageActivity();
            var thanksCard       = new ThanksForPlayingCard(choice);

            thankYouResponse.Attachments.Add(thanksCard.ToAttachment());
            await connectorClient.Conversations.UpdateActivityAsync(activity.Conversation.Id, activity.ReplyToId, (Activity)thankYouResponse);

            // Update the original card.
            var updateActivity = Activity.CreateMessageActivity();
            var resultCard     = new ResultCard(match.Results);

            updateActivity.Attachments.Add(resultCard.ToAttachment());
            await connectorClient.Conversations.UpdateActivityAsync(conversationId, match.MessageId, (Activity)updateActivity);

            // Update service records if the match is done.
            if (!match.Results.Any(result => result.Choice == Choices.None))
            {
                foreach (var result in match.Results)
                {
                    var wins   = match.Results.Count(otherResult => result.Choice.Beats(otherResult.Choice));
                    var losses = match.Results.Count(otherResult => otherResult.Choice.Beats(result.Choice));
                    var ties   = match.Results.Count(otherResult => otherResult.User.Id != result.User.Id && !result.Choice.Beats(otherResult.Choice) && !otherResult.Choice.Beats(result.Choice));

                    var serviceRecord = ServiceRecordStorage.GetServiceRecordForUserId(result.User.Id);
                    if (serviceRecord == null)
                    {
                        serviceRecord = new ServiceRecord()
                        {
                            User = result.User.AsTeamsChannelAccount(), Losses = 0, Wins = 0, Ties = 0
                        };
                    }
                    serviceRecord.Wins   += wins;
                    serviceRecord.Losses += losses;
                    serviceRecord.Ties   += ties;

                    ServiceRecordStorage.SetServiceRecordForUserId(result.User.Id, serviceRecord);
                }
            }

            return(Ok());
        }