/// <summary> /// Sends activities to the conversation. /// </summary> /// <param name="turnContext">The context object for the turn.</param> /// <param name="activities">The activities to send.</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 activities are successfully sent, the task result contains /// an array of <see cref="ResourceResponse"/> objects containing the SIDs that /// Twilio assigned to the activities.</remarks> /// <seealso cref="ITurnContext.OnSendActivities(SendActivitiesHandler)"/> public override async Task <ResourceResponse[]> SendActivitiesAsync(ITurnContext turnContext, Activity[] activities, CancellationToken cancellationToken) { var responses = new List <ResourceResponse>(); foreach (var activity in activities) { if (activity.Type != ActivityTypes.Message) { _logger.LogTrace( $"Unsupported Activity Type: '{activity.Type}'. Only Activities of type 'Message' are supported."); } else { var messageOptions = TwilioHelper.ActivityToTwilio(activity, _twilioClient.Options.TwilioNumber); var res = await _twilioClient.SendMessageAsync(messageOptions, cancellationToken) .ConfigureAwait(false); var response = new ResourceResponse() { Id = res, }; responses.Add(response); } } return(responses.ToArray()); }
/// <summary> /// Sends activities to the conversation. /// </summary> /// <param name="turnContext">The context object for the turn.</param> /// <param name="activities">The activities to send.</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 activities are successfully sent, the task result contains /// an array of <see cref="ResourceResponse"/> objects containing the SIDs that /// Twilio assigned to the activities.</remarks> /// <seealso cref="ITurnContext.OnSendActivities(SendActivitiesHandler)"/> public override async Task <ResourceResponse[]> SendActivitiesAsync(ITurnContext turnContext, Activity[] activities, CancellationToken cancellationToken) { var responses = new List <ResourceResponse>(); foreach (var activity in activities) { if (activity.Type == ActivityTypes.Message) { var messageOptions = TwilioHelper.ActivityToTwilio(activity, _options.TwilioNumber); var res = await _twilioClient.SendMessage(messageOptions).ConfigureAwait(false); var response = new ResourceResponse() { Id = res, }; responses.Add(response); } else { throw new ArgumentException("Unknown message type of Activity.", nameof(activities)); } } return(responses.ToArray()); }
/// <summary> /// Creates a turn context and runs the middleware pipeline for an incoming activity. /// </summary> /// <param name="httpRequest">The incoming HTTP request.</param> /// <param name="httpResponse">When this method completes, the HTTP response to send.</param> /// <param name="bot">The bot that will handle the incoming activity.</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> /// <exception cref="ArgumentNullException"><paramref name="httpRequest"/>, /// <paramref name="httpResponse"/>, or <paramref name="bot"/> is <c>null</c>.</exception> public async Task ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken = default) { if (httpRequest == null) { throw new ArgumentNullException(nameof(httpRequest)); } if (httpResponse == null) { throw new ArgumentNullException(nameof(httpResponse)); } if (bot == null) { throw new ArgumentNullException(nameof(bot)); } var activity = await TwilioHelper.RequestToActivity(httpRequest, _options.ValidationUrl, _options.AuthToken).ConfigureAwait(false); // create a conversation reference using (var context = new TurnContext(this, activity)) { context.TurnState.Add("httpStatus", HttpStatusCode.OK.ToString("D")); await RunPipelineAsync(context, bot.OnTurnAsync, cancellationToken).ConfigureAwait(false); httpResponse.StatusCode = Convert.ToInt32(context.TurnState.Get <string>("httpStatus"), CultureInfo.InvariantCulture); httpResponse.ContentType = "text/plain"; var text = context.TurnState.Get <object>("httpBody") != null?context.TurnState.Get <object>("httpBody").ToString() : string.Empty; await httpResponse.WriteAsync(text, cancellationToken).ConfigureAwait(false); } }
/// <summary> /// Creates a turn context and runs the middleware pipeline for an incoming activity. /// </summary> /// <param name="httpRequest">The incoming HTTP request.</param> /// <param name="httpResponse">When this method completes, the HTTP response to send.</param> /// <param name="bot">The bot that will handle the incoming activity.</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> /// <exception cref="ArgumentNullException"><paramref name="httpRequest"/>, /// <paramref name="httpResponse"/>, or <paramref name="bot"/> is <c>null</c>.</exception> public async Task ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken) { if (httpRequest == null) { throw new ArgumentNullException(nameof(httpRequest)); } if (httpResponse == null) { throw new ArgumentNullException(nameof(httpResponse)); } if (bot == null) { throw new ArgumentNullException(nameof(bot)); } Dictionary <string, string> bodyDictionary; using (var bodyStream = new StreamReader(httpRequest.Body)) { bodyDictionary = TwilioHelper.QueryStringToDictionary(await bodyStream.ReadToEndAsync().ConfigureAwait(false)); } if (_options.ValidateIncomingRequests && !_twilioClient.ValidateSignature(httpRequest, bodyDictionary)) { throw new AuthenticationException("WARNING: Webhook received message with invalid signature. Potential malicious behavior!"); } var activity = TwilioHelper.PayloadToActivity(bodyDictionary); var message = (TwilioMessage)activity.ChannelData; // create a conversation reference using (var context = new TurnContext(this, activity)) { context.TurnState.Add("httpStatus", HttpStatusCode.OK.ToString("D")); var claimsIdentity = new ClaimsIdentity(new List <Claim> { // Adding claims for both Emulator and Channel. new Claim(AuthenticationConstants.AudienceClaim, _configuration["MicrosoftAppId"]), new Claim(AuthenticationConstants.AppIdClaim, _configuration["MicrosoftAppId"]), }); context.TurnState.Add(BotIdentityKey, claimsIdentity); await RunPipelineAsync(context, bot.OnTurnAsync, cancellationToken).ConfigureAwait(false); var statusCode = Convert.ToInt32(context.TurnState.Get <string>("httpStatus"), CultureInfo.InvariantCulture); var text = context.TurnState.Get <object>("httpBody") != null ? context.TurnState.Get <object>("httpBody").ToString() : string.Empty; await TwilioHelper.WriteAsync(httpResponse, statusCode, text, Encoding.UTF8, cancellationToken) .ConfigureAwait(false); } }
/// <summary> /// Creates a turn context and runs the middleware pipeline for an incoming activity. /// </summary> /// <param name="httpRequest">The incoming HTTP request.</param> /// <param name="httpResponse">When this method completes, the HTTP response to send.</param> /// <param name="bot">The bot that will handle the incoming activity.</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> /// <exception cref="ArgumentNullException"><paramref name="httpRequest"/>, /// <paramref name="httpResponse"/>, or <paramref name="bot"/> is <c>null</c>.</exception> public async Task ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken) { if (httpRequest == null) { throw new ArgumentNullException(nameof(httpRequest)); } if (httpResponse == null) { throw new ArgumentNullException(nameof(httpResponse)); } if (bot == null) { throw new ArgumentNullException(nameof(bot)); } Dictionary <string, string> bodyDictionary; using (var bodyStream = new StreamReader(httpRequest.Body)) { bodyDictionary = TwilioHelper.QueryStringToDictionary(await bodyStream.ReadToEndAsync().ConfigureAwait(false)); } if (!_twilioClient.ValidateSignature(httpRequest, bodyDictionary)) { throw new Exception("WARNING: Webhook received message with invalid signature. Potential malicious behavior!"); } var activity = TwilioHelper.PayloadToActivity(bodyDictionary); // create a conversation reference using (var context = new TurnContext(this, activity)) { context.TurnState.Add("httpStatus", HttpStatusCode.OK.ToString("D")); await RunPipelineAsync(context, bot.OnTurnAsync, cancellationToken).ConfigureAwait(false); var statusCode = Convert.ToInt32(context.TurnState.Get <string>("httpStatus"), CultureInfo.InvariantCulture); var text = context.TurnState.Get <object>("httpBody") != null?context.TurnState.Get <object>("httpBody").ToString() : string.Empty; await TwilioHelper.WriteAsync(httpResponse, statusCode, text, Encoding.UTF8, cancellationToken).ConfigureAwait(false); } }