예제 #1
0
        /// <summary>
        /// Creates a conversation on the specified channel.
        /// </summary>
        /// <param name="channelId">The ID for the channel.</param>
        /// <param name="serviceUrl">The channel's service URL endpoint.</param>
        /// <param name="credentials">The application credentials for the bot.</param>
        /// <param name="conversationParameters">The conversation information to use to
        /// create the conversation.</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>To start a conversation, your bot must know its account information
        /// and the user's account information on that channel.
        /// Most _channels only support initiating a direct message (non-group) conversation.
        /// <para>The adapter attempts to create a new conversation on the channel, and
        /// then sends a <c>conversationUpdate</c> activity through its middleware pipeline
        /// to the <paramref name="callback"/> method.</para>
        /// <para>If the conversation is established with the
        /// specified users, the ID of the activity's <see cref="IActivity.Conversation"/>
        /// will contain the ID of the new conversation.</para>
        /// </remarks>
        public virtual async Task CreateConversation(string channelId, string serviceUrl, MicrosoftAppCredentials credentials, ConversationParameters conversationParameters, Func <ITurnContext, Task> callback)
        {
            var connectorClient = CreateConnectorClient(serviceUrl, credentials);

            var result = await connectorClient.Conversations.CreateConversationAsync(conversationParameters).ConfigureAwait(false);

            // Create a conversation update activity to represent the result.
            var conversationUpdate = Activity.CreateConversationUpdateActivity();

            conversationUpdate.ChannelId    = channelId;
            conversationUpdate.TopicName    = conversationParameters.TopicName;
            conversationUpdate.ServiceUrl   = serviceUrl;
            conversationUpdate.MembersAdded = conversationParameters.Members;
            conversationUpdate.Id           = result.ActivityId ?? Guid.NewGuid().ToString("n");
            conversationUpdate.Conversation = new ConversationAccount(id: result.Id);
            conversationUpdate.Recipient    = conversationParameters.Bot;

            using (TurnContext context = new TurnContext(this, (Activity)conversationUpdate))
            {
                await this.RunPipeline(context, callback).ConfigureAwait(false);
            }
        }
        /// <summary>
        /// Creates a turn context and runs the middleware pipeline for an incoming activity.
        /// </summary>
        /// <param name="identity">A <see cref="ClaimsIdentity"/> for the request.</param>
        /// <param name="activity">The incoming activity.</param>
        /// <param name="callback">The code to run at the end of the adapter's middleware pipeline.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        public async Task <InvokeResponse> ProcessActivityAsync(ClaimsIdentity identity, Activity activity, BotCallbackHandler callback, CancellationToken cancellationToken)
        {
            BotAssert.ActivityNotNull(activity);

            _logger.LogInformation($"Received an incoming activity.  ActivityId: {activity.Id}");

            using (var context = new TurnContext(this, activity))
            {
                context.TurnState.Add <IIdentity>(BotIdentityKey, identity);

                var connectorClient = await CreateConnectorClientAsync(activity.ServiceUrl, identity, cancellationToken).ConfigureAwait(false);

                context.TurnState.Add(connectorClient);

                await RunPipelineAsync(context, callback, cancellationToken).ConfigureAwait(false);

                // Handle Invoke scenarios, which deviate from the request/response model in that
                // the Bot will return a specific body and return code.
                if (activity.Type == ActivityTypes.Invoke)
                {
                    var activityInvokeResponse = context.TurnState.Get <Activity>(InvokeReponseKey);
                    if (activityInvokeResponse == null)
                    {
                        return(new InvokeResponse {
                            Status = (int)HttpStatusCode.NotImplemented
                        });
                    }
                    else
                    {
                        return((InvokeResponse)activityInvokeResponse.Value);
                    }
                }

                // For all non-invoke scenarios, the HTTP layers above don't have to mess
                // withthe Body and return codes.
                return(null);
            }
        }
        /// <summary>
        /// Sends a proactive message from the bot to a conversation.
        /// </summary>
        /// <param name="botAppId">The application ID of the bot. This is the appId returned by Portal registration, and is
        /// generally found in the "MicrosoftAppId" parameter in appSettings.json.</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>
        /// <param name="cancellationToken">Cancellation token.</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>
        /// <para>
        /// This overload differers from the Node implementation by requiring the BotId to be
        /// passed in. The .Net code allows multiple bots to be hosted in a single adapter which
        /// isn't something supported by Node.
        /// </para>
        /// </remarks>
        /// <seealso cref="ProcessActivityAsync(string, Activity, BotCallbackHandler, CancellationToken)"/>
        /// <seealso cref="BotAdapter.RunPipelineAsync(ITurnContext, BotCallbackHandler, CancellationToken)"/>
        public override async Task ContinueConversationAsync(string botAppId, ConversationReference reference, BotCallbackHandler callback, CancellationToken cancellationToken)
        {
            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));
            }

            _logger.LogInformation($"Sending proactive message.  botAppId: {botAppId}");

            using (var context = new TurnContext(this, reference.GetContinuationActivity()))
            {
                // 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.TurnState.Add <IIdentity>(BotIdentityKey, claimsIdentity);
                var connectorClient = await CreateConnectorClientAsync(reference.ServiceUrl, claimsIdentity, cancellationToken).ConfigureAwait(false);

                context.TurnState.Add(connectorClient);
                await RunPipelineAsync(context, callback, cancellationToken).ConfigureAwait(false);
            }
        }
예제 #4
0
        /// <summary>
        /// Sends a proactive message to a conversation.
        /// </summary>
        /// <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}, CancellationTokenSource)"/>
        public virtual Task ContinueConversation(ConversationReference reference, Func <ITurnContext, Task> callback)
        {
            var context = new TurnContext(this, reference.GetPostToBotMessage());

            return(RunPipeline(context, callback));
        }
예제 #5
0
 public Task SetAsync(TurnContext context, object value)
 {
     throw new NotImplementedException();
 }
예제 #6
0
 public Task <IEnumerable <SlotHistoryValue <object> > > HistoryAsync(TurnContext context)
 {
     throw new NotImplementedException();
 }
예제 #7
0
 public Task <bool> HasAsync(TurnContext context)
 {
     throw new NotImplementedException();
 }
예제 #8
0
 public Task <object> GetAsync(TurnContext context)
 {
     throw new NotImplementedException();
 }
예제 #9
0
 public Task DeleteAsync(TurnContext context)
 {
     throw new NotImplementedException();
 }
예제 #10
0
        /// <summary>
        /// initialization for middleware turn
        /// </summary>
        /// <param name="context"></param>
        /// <param name="nextTurn"></param>
        /// <returns></returns>
        public async Task OnTurn(ITurnContext context, MiddlewareSet.NextDelegate nextTurn)
        {
            // log incoming activity at beginning of turn
            if (context.Activity != null)
            {
                if (String.IsNullOrEmpty((String)context.Activity.From.Properties["role"]))
                {
                    context.Activity.From.Properties["role"] = "user";
                }

                LogActivity(CloneActivity(context.Activity));
            }

            // hook up onSend pipeline
            context.OnSendActivities(async(ctx, activities, nextSend) =>
            {
                // run full pipeline
                var responses = await nextSend();

                foreach (var activity in activities)
                {
                    LogActivity(CloneActivity(activity));
                }
                return(responses);
            });

            // hook up update activity pipeline
            context.OnUpdateActivity(async(ctx, activity, nextUpdate) =>
            {
                // run full pipeline
                var response = await nextUpdate();

                // add Message Update activity
                var updateActivity  = CloneActivity(activity);
                updateActivity.Type = ActivityTypes.MessageUpdate;
                LogActivity(updateActivity);
                return(response);
            });

            // hook up delete activity pipeline
            context.OnDeleteActivity(async(ctx, reference, nextDelete) =>
            {
                // run full pipeline
                await nextDelete();

                // add MessageDelete activity
                // log as MessageDelete activity
                var deleteActivity = TurnContext.ApplyConversationReference(new Activity()
                {
                    Type = ActivityTypes.MessageDelete,
                    Id   = reference.ActivityId
                }, reference, isIncoming: false).AsMessageDeleteActivity();

                LogActivity(deleteActivity);
            });

            // process bot logic
            await nextTurn().ConfigureAwait(false);

            // flush transcript at end of turn
            while (transcript.Count > 0)
            {
                try
                {
                    var activity = transcript.Dequeue();
                    await logger.LogActivity(activity);
                }
                catch (Exception err)
                {
                    System.Diagnostics.Trace.TraceError($"Transcript logActivity failed with {err}");
                }
            }
        }
예제 #11
0
 public Task SlotValueChangedAsync(TurnContext context, List <string> tags, object value)
 {
     throw new NotImplementedException();
 }
예제 #12
0
 public Task LoadAsync(TurnContext context, bool accessed = false)
 {
     throw new NotImplementedException();
 }