/// <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); } }
/// <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)); }
public Task SetAsync(TurnContext context, object value) { throw new NotImplementedException(); }
public Task <IEnumerable <SlotHistoryValue <object> > > HistoryAsync(TurnContext context) { throw new NotImplementedException(); }
public Task <bool> HasAsync(TurnContext context) { throw new NotImplementedException(); }
public Task <object> GetAsync(TurnContext context) { throw new NotImplementedException(); }
public Task DeleteAsync(TurnContext context) { throw new NotImplementedException(); }
/// <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}"); } } }
public Task SlotValueChangedAsync(TurnContext context, List <string> tags, object value) { throw new NotImplementedException(); }
public Task LoadAsync(TurnContext context, bool accessed = false) { throw new NotImplementedException(); }