Exemple #1
0
        /// <summary>
        /// Process an incoming message within the conversation.
        /// </summary>
        /// <remarks>
        /// This method:
        /// 1. instantiates and composes the required components
        /// 2. deserializes the dialog state (the dialog stack and each dialog's state) from the <see cref="toBot"/> <see cref="Message"/>
        /// 3. resumes the conversation processes where the dialog suspended to wait for a <see cref="Message"/>
        /// 4. queues <see cref="Message"/>s to be sent to the user
        /// 5. serializes the updated dialog state in the messages to be sent to the user.
        ///
        /// The <see cref="MakeRoot"/> factory method is invoked for new conversations only,
        /// because existing conversations have the dialog stack and state serialized in the <see cref="Message"/> data.
        /// </remarks>
        /// <param name="toBot">The message sent to the bot.</param>
        /// <param name="MakeRoot">The factory method to make the root dialog.</param>
        /// <param name="token">The cancellation token.</param>
        /// <param name="singletons">An optional list of object instances that should not be serialized.</param>
        /// <returns>A task that represents the message to send inline back to the user.</returns>
        public static async Task <Message> SendAsync(Message toBot, Func <IDialog> MakeRoot, CancellationToken token = default(CancellationToken), params object[] singletons)
        {
            IWaitFactory     waits   = new WaitFactory();
            IFrameFactory    frames  = new FrameFactory(waits);
            IBotData         botData = new JObjectBotData(toBot);
            IConnectorClient client  = new ConnectorClient();
            var botToUser            = new ReactiveBotToUser(toBot, client);
            var provider             = new Serialization.SimpleServiceLocator(singletons)
            {
                waits, frames, botData, botToUser
            };
            var formatter = Conversation.MakeBinaryFormatter(provider);

            IDialogContextStore contextStore = new DialogContextStore(formatter);
            IDialogContextStore store        = new ErrorResilientDialogContextStore(contextStore);

            IDialogContext context;

            if (!store.TryLoad(botData.PerUserInConversationData, BlobKey, out context))
            {
                IFiberLoop fiber = new Fiber(frames);
                context = new Internals.DialogContext(botToUser, botData, fiber);
                var root = MakeRoot();
                var loop = root.Loop();
                context.Call <object>(loop, null);
                await fiber.PollAsync();
            }

            IUserToBot userToBot = (IUserToBot)context;
            await userToBot.SendAsync(toBot, token);

            store.Save(context, botData.PerUserInConversationData, BlobKey);

            return(botToUser.ToUser);
        }
Exemple #2
0
        public static async Task <IBotData> GetBotDataAsync(IAddress userAddress, IBotDataStore <BotData> botDataStore, CancellationToken cancellationToken)
        {
            var botData = new JObjectBotData(userAddress, botDataStore);
            await botData.LoadAsync(cancellationToken);

            return(botData);
        }
Exemple #3
0
        public static async Task <DialogContext> MakeContextAsync(IDialog root, IBotToUser botToUser)
        {
            var        data    = new JObjectBotData(new Connector.Message());
            IFiberLoop fiber   = new Fiber(new FrameFactory(new WaitFactory()));
            var        context = new DialogContext(botToUser, data, fiber);
            var        loop    = Methods.Void(Methods.Loop(context.ToRest(root.StartAsync), int.MaxValue));

            fiber.Call(loop, null);
            await fiber.PollAsync();

            return(context);
        }
        public async Task <HttpResponseMessage> OAuthCallback([FromUri] string userId, [FromUri] string conversationId, [FromUri] string code, [FromUri] string state)
        {
            // Check if the bot is running against emulator
            var connectorType = HttpContext.Current.Request.IsLocal ? ConnectorType.Emulator : ConnectorType.Cloud;

            // Exchange the Facebook Auth code with Access toekn
            var token = await FacebookHelpers.ExchangeCodeForAccessToken(userId, conversationId, code, SimpleFacebookAuthDialog.FacebookOauthCallback.ToString());

            // Create the message that is send to conversation to resume the login flow
            var msg = new Message
            {
                Text = $"token:{token.AccessToken}",
                From = new ChannelAccount {
                    Id = userId
                },
                To = new ChannelAccount {
                    Id = botId.Value
                },
                ConversationId = conversationId
            };

            // Resume the conversation to SimpleFacebookAuthDialog
            var reply = await Conversation.ResumeAsync(botId.Value, userId, conversationId, msg, connectorType : connectorType);

            // Remove the pending message because login flow is complete
            IBotData       dataBag = new JObjectBotData(reply);
            PendingMessage pending;

            if (dataBag.PerUserInConversationData.TryGetValue("pendingMessage", out pending))
            {
                dataBag.PerUserInConversationData.RemoveValue("pendingMessage");
                var pendingMessage = pending.GetMessage();
                reply.To   = pendingMessage.From;
                reply.From = pendingMessage.To;

                // Send the login success asynchronously to user
                var client = Conversation.ResumeContainer.Resolve <IConnectorClient>(TypedParameter.From(connectorType));
                await client.Messages.SendMessageAsync(reply);

                return(Request.CreateResponse("You are now logged in! Continue talking to the bot."));
            }
            else
            {
                // 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!")));
            }
        }
        public async Task <HttpResponseMessage> OAuthCallback([FromUri] string userId, [FromUri] string conversationId, [FromUri] string channelId, [FromUri] string language, [FromUri] string code, [FromUri] string state)
        {
            // Get the resumption cookie
            var resumptionCookie = new ResumptionCookie(userId, botId.Value, conversationId, channelId, language);

            // Exchange the Facebook Auth code with Access token
            var token = await FacebookHelpers.ExchangeCodeForAccessToken(resumptionCookie, code, SimpleFacebookAuthDialog.FacebookOauthCallback.ToString());

            // Create the message that is send to conversation to resume the login flow
            var msg = resumptionCookie.GetMessage();

            msg.Text = $"token:{token.AccessToken}";

            // Resume the conversation to SimpleFacebookAuthDialog
            var reply = await Conversation.ResumeAsync(resumptionCookie, msg);

            // Remove the pending message because login flow is complete
            IBotData         dataBag = new JObjectBotData(reply);
            ResumptionCookie pending;

            if (dataBag.PerUserInConversationData.TryGetValue("persistedCookie", out pending))
            {
                dataBag.PerUserInConversationData.RemoveValue("persistedCookie");

                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, reply))
                {
                    // make sure that we have the right Channel info for the outgoing message
                    var persistedCookie = pending.GetMessage();
                    reply.To   = persistedCookie.From;
                    reply.From = persistedCookie.To;

                    // Send the login success asynchronously to user
                    var client = scope.Resolve <IConnectorClient>();
                    await client.Messages.SendMessageAsync(reply);
                }

                return(Request.CreateResponse("You are now logged in! Continue talking to the bot."));
            }
            else
            {
                // 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!")));
            }
        }