/// <summary> /// Get the raw signin link to be sent to the user for signin for a connection name. /// </summary> /// <param name="turnContext">Context for the current turn of conversation with the user.</param> /// <param name="connectionName">Name of the auth connection to use.</param> /// <param name="userId">The user id that will be associated with the token.</param> /// <param name="finalRedirect">The final URL that the OAuth flow will redirect to.</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> /// <remarks>If the task completes successfully, the result contains the raw signin link.</remarks> public async Task <string> GetOauthSignInLinkAsync(ITurnContext turnContext, string connectionName, string userId, string finalRedirect = null, CancellationToken cancellationToken = default(CancellationToken)) { BotAssert.ContextNotNull(turnContext); if (string.IsNullOrWhiteSpace(connectionName)) { throw new ArgumentNullException(nameof(connectionName)); } if (string.IsNullOrWhiteSpace(userId)) { throw new ArgumentNullException(nameof(userId)); } var tokenExchangeState = new TokenExchangeState() { ConnectionName = connectionName, Conversation = new ConversationReference() { ActivityId = null, Bot = new ChannelAccount { Role = "bot" }, ChannelId = "directline", Conversation = new ConversationAccount(), ServiceUrl = null, User = new ChannelAccount { Role = "user", Id = userId, }, }, MsAppId = (this._credentialProvider as MicrosoftAppCredentials)?.MicrosoftAppId, }; var serializedState = JsonConvert.SerializeObject(tokenExchangeState); var encodedState = Encoding.UTF8.GetBytes(serializedState); var state = Convert.ToBase64String(encodedState); var client = await CreateOAuthApiClientAsync(turnContext).ConfigureAwait(false); return(await client.GetSignInLinkAsync(state, finalRedirect, cancellationToken).ConfigureAwait(false)); }
/// <summary> /// Log an activity to the transcript. /// </summary> /// <param name="activity">The activity to transcribe.</param> /// <returns>A task that represents the work queued to execute.</returns> public Task LogActivityAsync(IActivity activity) { BotAssert.ActivityNotNull(activity); if (_traceActivity) { Trace.TraceInformation(JsonConvert.SerializeObject(activity, _serializationSettings)); } else { if (Debugger.IsAttached && activity.Type == ActivityTypes.Message) { Trace.TraceInformation($"{activity.From.Name ?? activity.From.Id ?? activity.From.Role} [{activity.Type}] {activity.AsMessageActivity()?.Text}"); } else { Trace.TraceInformation($"{activity.From.Name ?? activity.From.Id ?? activity.From.Role} [{activity.Type}]"); } } return(Task.CompletedTask); }
private async Task <ResourceResponse> UpdateActivityInternalAsync( Activity activity, IEnumerable <UpdateActivityHandler> updateHandlers, Func <Task <ResourceResponse> > callAtBottom, CancellationToken cancellationToken) { BotAssert.ActivityNotNull(activity); if (updateHandlers == null) { throw new ArgumentException($"{nameof(updateHandlers)} is null.", nameof(updateHandlers)); } // No middleware to run. if (!updateHandlers.Any()) { if (callAtBottom != null) { return(await callAtBottom().ConfigureAwait(false)); } return(null); } // Default to "No more Middleware after this". async Task <ResourceResponse> Next() { // Remove the first item from the list of middleware to call, // so that the next call just has the remaining items to worry about. IEnumerable <UpdateActivityHandler> remaining = updateHandlers.Skip(1); var result = await UpdateActivityInternalAsync(activity, remaining, callAtBottom, cancellationToken).ConfigureAwait(false); activity.Id = result.Id; return(result); } // Grab the current middleware, which is the 1st element in the array, and execute it UpdateActivityHandler toCall = updateHandlers.First(); return(await toCall(this, activity, Next).ConfigureAwait(false)); }
private async Task DeleteActivityInternalAsync( ConversationReference cr, IEnumerable <DeleteActivityHandler> deleteHandlers, Func <Task> callAtBottom, CancellationToken cancellationToken) { BotAssert.ConversationReferenceNotNull(cr); if (deleteHandlers == null) { throw new ArgumentException($"{nameof(deleteHandlers)} is null", nameof(deleteHandlers)); } // No middleware to run. if (!deleteHandlers.Any()) { if (callAtBottom != null) { await callAtBottom().ConfigureAwait(false); } return; } // Default to "No more Middleware after this". async Task Next() { // Remove the first item from the list of middleware to call, // so that the next call just has the remaining items to worry about. IEnumerable <DeleteActivityHandler> remaining = deleteHandlers.Skip(1); await DeleteActivityInternalAsync(cr, remaining, callAtBottom, cancellationToken).ConfigureAwait(false); } // Grab the current middleware, which is the 1st element in the array, and execute it. DeleteActivityHandler toCall = deleteHandlers.First(); await toCall(this, cr, Next).ConfigureAwait(false); }
/// <summary> /// Sends an activity to the sender of the incoming activity. /// </summary> /// <param name="activity">The activity to send.</param> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>A task that represents the work queued to execute.</returns> /// <exception cref="ArgumentNullException"><paramref name="activity"/> is <c>null</c>.</exception> /// <remarks>If the activity is successfully sent, the task result contains /// a <see cref="ResourceResponse"/> object containing the ID that the receiving /// channel assigned to the activity.</remarks> public async Task <ResourceResponse> SendActivityAsync(IActivity activity, CancellationToken cancellationToken = default(CancellationToken)) { if (_disposed) { throw new ObjectDisposedException(nameof(SendActivityAsync)); } BotAssert.ActivityNotNull(activity); ResourceResponse[] responses = await SendActivitiesAsync(new[] { activity }, cancellationToken).ConfigureAwait(false); if (responses == null || responses.Length == 0) { // It's possible an interceptor prevented the activity from having been sent. // Just return an empty response in that case. return(new ResourceResponse()); } else { return(responses[0]); } }
/// <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> /// Retrieves Azure Active Directory tokens for particular resources on a configured connection. /// </summary> /// <param name="context">Context for the current turn of conversation with the user.</param> /// <param name="connectionName">The name of the Azure Active Direcotry connection configured with this bot.</param> /// <param name="resourceUrls">The list of resource URLs to retrieve tokens for.</param> /// <param name="userId">The user Id for which tokens are retrieved. If passing in null the userId is taken from the Activity in the ITurnContext.</param> /// <returns>Dictionary of resourceUrl to the corresponding TokenResponse.</returns> public async Task <Dictionary <string, TokenResponse> > GetAadTokensAsync(ITurnContext context, string connectionName, string[] resourceUrls, string userId = null) { BotAssert.ContextNotNull(context); if (string.IsNullOrWhiteSpace(connectionName)) { throw new ArgumentNullException(nameof(connectionName)); } if (resourceUrls == null) { throw new ArgumentNullException(nameof(userId)); } if (string.IsNullOrWhiteSpace(userId)) { userId = context.Activity?.From?.Id; } var client = await this.CreateOAuthApiClientAsync(context).ConfigureAwait(false); return(await client.GetAadTokensAsync(userId, connectionName, resourceUrls).ConfigureAwait(false)); }
/// <summary> /// Log an activity to the transcript /// </summary> /// <param name="activity">activity to log</param> /// <returns></returns> public Task LogActivity(IActivity activity) { BotAssert.ActivityNotNull(activity); Trace.TraceInformation(JsonConvert.SerializeObject(activity, serializationSettings)); return(Task.CompletedTask); }
/// <summary> /// Adds a middleware object to the end of the set. /// </summary> /// <param name="middleware">The middleware to add.</param> /// <returns>The updated middleware set.</returns> /// <see cref="BotAdapter.Use(IMiddleware)"/> public MiddlewareSet Use(IMiddleware middleware) { BotAssert.MiddlewareNotNull(middleware); _middleware.Add(middleware); return(this); }
/// <summary> /// Gets the cached bot state instance that wraps the raw cached data for this <see cref="BotState"/> /// from the turn context. /// </summary> /// <param name="turnContext">The context object for this turn.</param> /// <returns>The cached bot state instance.</returns> /// <exception cref="ArgumentNullException"><paramref name="turnContext"/> is <c>null</c>.</exception> public CachedBotState GetCachedState(ITurnContext turnContext) { BotAssert.ContextNotNull(turnContext); return(turnContext.TurnState.Get <CachedBotState>(_contextServiceKey)); }
/// <summary> /// Log an activity to the transcript /// </summary> /// <param name="activity">activity to log</param> /// <returns></returns> public async Task LogActivity(IActivity activity) { BotAssert.ActivityNotNull(activity); await Console.Out.WriteLineAsync(JsonConvert.SerializeObject(activity, serializationSettings)); }