protected async Task Respond(string text)
 {
     var post   = _conversationReference.GetPostToBotMessage();
     var reply  = post.CreateReply(text);
     var client = new ConnectorClient(new Uri(post.ServiceUrl));
     await client.Conversations.ReplyToActivityAsync(reply);
 }
        /// <summary>
        /// Sends a proactive message from the bot to a conversation.
        /// </summary>
        /// <param name="botAppId">The application ID of the bot.</param>
        /// <param name="reference">A reference to the conversation to continue.</param>
        /// <param name="callback">The method to call for the resulting bot turn.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="botAppId"/>, <paramref name="reference"/>, or
        /// <paramref name="callback"/> is <c>null</c>.</exception>
        /// <remarks>Call this method to proactively send a message to a conversation.
        /// Most channels require a user to initaiate a conversation with a bot
        /// before the bot can send activities to the user.
        /// <para>This method registers the following services for the turn.<list type="bullet">
        /// <item><see cref="IIdentity"/> (key = "BotIdentity"), a claims identity for the bot.</item>
        /// <item><see cref="IConnectorClient"/>, the channel connector client to use this turn.</item>
        /// </list></para>
        /// </remarks>
        /// <seealso cref="ProcessActivity(string, Activity, Func{ITurnContext, Task})"/>
        /// <seealso cref="BotAdapter.RunPipeline(ITurnContext, Func{ITurnContext, Task}, System.Threading.CancellationTokenSource)"/>
        public async Task ContinueConversation(string botAppId, ConversationReference reference, Func <ITurnContext, Task> callback)
        {
            if (string.IsNullOrWhiteSpace(botAppId))
            {
                throw new ArgumentNullException(nameof(botAppId));
            }

            if (reference == null)
            {
                throw new ArgumentNullException(nameof(reference));
            }

            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            var context = new TurnContext(this, reference.GetPostToBotMessage());

            // Hand craft Claims Identity.
            var claimsIdentity = new ClaimsIdentity(new List <Claim>
            {
                // Adding claims for both Emulator and Channel.
                new Claim(AuthenticationConstants.AudienceClaim, botAppId),
                new Claim(AuthenticationConstants.AppIdClaim, botAppId)
            });

            context.Services.Add <IIdentity>("BotIdentity", claimsIdentity);
            var connectorClient = await this.CreateConnectorClientAsync(reference.ServiceUrl, claimsIdentity);

            context.Services.Add <IConnectorClient>(connectorClient);
            await RunPipeline(context, callback);
        }
Esempio n. 3
0
 /// <summary>
 /// Sends a proactive message to a conversation.
 /// </summary>
 /// <param name="botId">The application ID of the bot. This paramter is ignored in
 /// single tenant the Adpters (Console, Test, etc) but is critical to the BotFrameworkAdapter
 /// which is multi-tenant aware. </param>
 /// <param name="reference">A reference to the conversation to continue.</param>
 /// <param name="callback">The method to call for the resulting bot turn.</param>
 /// <returns>A task that represents the work queued to execute.</returns>
 /// <remarks>Call this method to proactively send a message to a conversation.
 /// Most _channels require a user to initaiate a conversation with a bot
 /// before the bot can send activities to the user.</remarks>
 /// <seealso cref="RunPipeline(ITurnContext, Func{ITurnContext, Task})"/>
 public virtual Task ContinueConversation(string botId, ConversationReference reference, Func <ITurnContext, Task> callback)
 {
     using (var context = new TurnContext(this, reference.GetPostToBotMessage()))
     {
         return(RunPipeline(context, callback));
     }
 }
        public async Task <HttpResponseMessage> Get(string code, string state, CancellationToken cancellationToken)
        {
            // 從 state 參數轉換為原本的 ConversationReference
            ConversationReference conversationReference = UrlToken.Decode <ConversationReference>(state);

            // 請求拿到 Google OAuth 的 Access Token
            var accessToken = await GoogleOAuthHelper.ExchangeCodeForGoogleAccessToken(code, BotUtility.OAuthCallbackURL);

            var msg = conversationReference.GetPostToBotMessage();

            // 取得目前談話對象的容器,並且把 UserData 加入 Access Token
            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, msg))
            {
                IStateClient sc       = scope.Resolve <IStateClient>();
                BotData      userData = sc.BotState.GetUserData(msg.ChannelId, msg.From.Id);
                userData.SetProperty(BotUtility.AccessToken, accessToken.AccessToken);
                sc.BotState.SetUserData(msg.ChannelId, msg.From.Id, userData);
            }

            // 設定 ResumeAsync 回到 MessagesController 的識別值 (例如: 使用 token 關鍵字, 真實案例不適合這樣用)
            msg.Text = "token:" + accessToken.AccessToken;

            // 要記得使用 RsumeAsync 才能夠接回原本的 converstaion
            await Conversation.ResumeAsync(conversationReference, msg);

            return(Request.CreateResponse("ok"));
        }
        public static async Task StartSurvey(ConversationReference conversationReference, CancellationToken token)
        {
            var container = WebApiApplication.FindContainer();

            // the ConversationReference has the "key" necessary to resume the conversation
            var message = conversationReference.GetPostToBotMessage();

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

            try
            {
                var conversation = await client.Conversations.CreateDirectConversationAsync(message.Recipient, message.From);

                message.Conversation.Id = conversation.Id;
            }
            catch (HttpOperationException ex)
            {
                var reply = message.CreateReply();
                reply.Text = ex.Message;

                await client.Conversations.SendToConversationAsync(reply);

                return;
            }

            // we instantiate our dependencies based on an IMessageActivity implementation
            using (var scope = DialogModule.BeginLifetimeScope(container, message))
            {
                // find the bot data interface and load up the conversation dialog state
                var botData = scope.Resolve <IBotData>();
                await botData.LoadAsync(token);

                // resolve the dialog task
                IDialogTask task = scope.Resolve <IDialogTask>();

                // make a dialog to push on the top of the stack
                var child = scope.Resolve <SurveyDialog>();

                // wrap it with an additional dialog that will restart the wait for
                // messages from the user once the child dialog has finished
                var interruption = child.Void <object, IMessageActivity>();

                try
                {
                    // put the interrupting dialog on the stack
                    task.Call(interruption, null);

                    // start running the interrupting dialog
                    await task.PollAsync(token);
                }
                finally
                {
                    // save out the conversation dialog state
                    await botData.FlushAsync(token);
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Resume a conversation and post the data to the dialog waiting.
        /// </summary>
        /// <param name="conversationReference"> The resumption cookie.</param>
        /// <param name="toBot"> The data sent to bot.</param>
        /// <param name="token"> The cancellation token.</param>
        /// <returns> A task that represent the message to send back to the user after resumption of the conversation.</returns>
        public static async Task ResumeAsync(ConversationReference conversationReference, IActivity toBot, CancellationToken token = default(CancellationToken))
        {
            var continuationMessage = conversationReference.GetPostToBotMessage();

            using (var scope = DialogModule.BeginLifetimeScope(Container, continuationMessage))
            {
                Func <IDialog <object> > MakeRoot = () => { throw new InvalidOperationException(); };
                DialogModule_MakeRoot.Register(scope, MakeRoot);

                await SendAsync(scope, toBot, token);
            }
        }
Esempio n. 7
0
        public async Task <HttpResponseMessage> OAuthCallback([FromUri] string code, [FromUri] string state, [FromUri] string cookie, CancellationToken cancellationToken)
        {
            GitHubClient client = new GitHubClient(new ProductHeaderValue(Constants.ProductHeader));

            OauthTokenRequest request = new OauthTokenRequest(ConfigurationManager.AppSettings[Constants.GitHubClientIdKey], ConfigurationManager.AppSettings[Constants.GitHubClientSecretKey], code);
            OauthToken        token   = await client.Oauth.CreateAccessToken(request);

            // Send a message to the conversation to resume the flow
            ConversationReference cr = GetConversationReference(cookie);
            Activity msg             = cr.GetPostToBotMessage();

            msg.Text = "authenticated";

            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, msg))
            {
                var dataBag = scope.Resolve <IBotData>();
                await dataBag.LoadAsync(cancellationToken);

                string csrf;
                if (dataBag.UserData.TryGetValue(Constants.StateKey, out csrf) && csrf == state)
                {
                    // remove persisted cookie
                    dataBag.UserData.RemoveValue(Constants.StateKey);
                    dataBag.UserData.SetValue(Constants.AuthTokenKey, token.AccessToken);
                    await dataBag.FlushAsync(cancellationToken);

                    // Resume the conversation
                    await Conversation.ResumeAsync(cr, msg);

                    var response = Request.CreateResponse("You are now logged in! Please return to your Bot conversation to continue.");
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
                    return(response);
                }

                // no state or state doesn't match
                var responseError = Request.CreateResponse("Invalid state, please try again.");
                responseError.StatusCode = HttpStatusCode.BadRequest;
                responseError.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
                return(responseError);
            }
        }
Esempio n. 8
0
        public Task ContinueConversation(string botAppId, ConversationReference reference, Func <ITurnContext, Task> callback)
        {
            if (string.IsNullOrWhiteSpace(botAppId))
            {
                throw new ArgumentNullException(nameof(botAppId));
            }

            if (reference == null)
            {
                throw new ArgumentNullException(nameof(reference));
            }

            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            var context = new BotFrameworkTurnContext(botAppId, this, reference.GetPostToBotMessage());

            return(RunPipeline(context, callback));
        }
        //This will interrupt the conversation and send the user to SurveyDialog, then wait until that's done
        public static async Task Resume()
        {
            //var message = ResumptionCookie.GZipDeserialize(resumptionCookie).GetMessage();
            var message = resumeReference.GetPostToBotMessage();

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

            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
            {
                var botData = scope.Resolve <IBotData>();
                await botData.LoadAsync(CancellationToken.None);

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

                //interrupt the stack
                var dialog = new Childs.CrowdSourceDialog();
                task.Call(dialog.Void <object, IMessageActivity>(), null);

                await task.PollAsync(CancellationToken.None);

                //flush dialog stack
                await botData.FlushAsync(CancellationToken.None);
            }
        }