Esempio n. 1
0
        /// <summary>
        /// Executes the router to find an appropriate processor for the incoming message
        /// </summary>
        /// <param name="type">The type of incoming message from Slack.</param>
        /// <param name="context">The <see cref="HttpContext"/> for the current request.</param>
        /// <param name="httpClient">The <see cref="HttpClient"/> instance to use for any network calls (to promote reuse)</param>
        /// <returns>A task that represents the execution of the router.</returns>
        /// <exception cref="ArgumentNullException">Throws when <paramref name="context"/> or <paramref name="httpClient"/> is <c>null</c>.</exception>
        public async Task ProcessAsync(IncomingMessageType type, HttpContext context, HttpClient httpClient)
        {
            _ = context ?? throw new ArgumentNullException(nameof(context));
            _ = httpClient ?? throw new ArgumentNullException(nameof(httpClient));

            // Ensure it's a POST coming from Slack
            if (context.Request.Method != "POST")
            {
                context.Response.StatusCode = 404;
                return;
            }

            AppResponse response      = null;
            var         isRespondable = false;

            try
            {
                switch (type)
                {
                case IncomingMessageType.Command:
                    isRespondable = true;
                    response      = await ProcessCommandAsync(context);

                    break;

                case IncomingMessageType.Action:
                    isRespondable = true;
                    response      = await ProcessActionAsync(context);

                    break;

                case IncomingMessageType.Event:
                    await ProcessEventAsync(context);

                    break;
                }
            }
            catch (Exception e)
            {
                var message = $"An exception occurred while processing this {type}";
                _logger.LogError(e, message, null);

                if (isRespondable)
                {
                    if (response == null)
                    {
                        response = new AppResponse();
                    }
                    response.ImmediateMessage = SlackMessage.CreateErrorMessage($"message: {e.Message}");
                    response.ResponseUrlMessages.Clear();

                    context.Response.StatusCode = 200;
                }
                else
                {
                    context.Response.StatusCode = 500;
                }
            }

            if (!isRespondable)
            {
                return;
            }

            if (response.ImmediateMessage != null)
            {
                // Respond immediately with a message
                // Per Slack docs, this keeps the original message in the channel
                // See https://api.slack.com/slash-commands#delayed_responses_and_multiple_responses
                context.Response.ContentType = "application/json";
                await context.Response.WriteAsync(response.ImmediateMessage.ToJson());
            }
            if (response.ResponseUrlMessages.Count > 0 && !string.IsNullOrEmpty(response.response_url))
            {
                foreach (var message in response.ResponseUrlMessages)
                {
                    // Send the message back to the response_url
                    // Per Slack docs, this replaces the original message in the channel
                    // See https://api.slack.com/slash-commands#delayed_responses_and_multiple_responses
                    var requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(response.response_url))
                    {
                        Content = new StringContent(message.ToJson(), Encoding.UTF8, "application/json")
                    };

                    try
                    {
                        var result = await httpClient.SendAsync(requestMessage);

                        if (!result.IsSuccessStatusCode)
                        {
                            throw new Exception($"Failed to post to Slack: Status Code \"{result.StatusCode}\" ({(int)result.StatusCode}).");
                        }
                    }
                    catch (Exception e)
                    {
                        // Something happened posting back to the response_url, so log the error
                        _logger.LogError(e, "An exception occurred while sending a message to the response_url", null);
                    }
                }
            }
        }