Exemplo n.º 1
0
 public override void OnCommand(List <string> args)
 {
     if (string.IsNullOrWhiteSpace(Comment))
     {
         var response = new SlashCommandResponse
         {
             response_type = "ephemeral",                // visible to only the user
             text          = new ParamParser <ExampleSlashCommand>().Help()
         };
         SlackApp !.Push(new AcknowledgeResponse <SlashCommandResponse>
                             (Envelope !.envelope_id, response));
     }
     else
     {
         var response = new SlashCommandResponse()
                        .Add(new HeaderLayout("Slash command response"))
                        .Add(new SectionLayout {
             block_id = "wave_id", text = $":wave: {Comment}"
         })
                        .Add(new SectionLayout
         {
             block_id  = "button-section",
             text      = "*Welcome*",
             accessory = new ButtonElement {
                 text = "Just a button", action_id = "just-a-button"
             }
         });
         SlackApp !.Push(new AcknowledgeResponse <SlashCommandResponse>(Envelope !.envelope_id, response));
     }
 }
Exemplo n.º 2
0
        public ActionResult <SlashCommandResponse> DoSlashCommand([FromForm] SlackCommandInput input)
        {
            if (!input.TeamDomain.Equals(SlackConfig.Workspace, StringComparison.CurrentCultureIgnoreCase))
            {
                return(Forbid());
            }
            string command = input.Command.ToLower();

            if (!SlackConfig.IsKnownCommand(command))
            {
                return(BadRequest());
            }

            string caseCmd         = input.Text.Trim();
            bool   intParseSuccess = int.TryParse(caseCmd, out int caseNumber);

            if (!intParseSuccess)
            {
                return(SlashCommandResponse.ForBadCommand(
                           errorOrHelpText: "Please enter a single, numeric value."));
            }

            var jobInfo = new FogBugzSlashCommandInfo(
                command: command,
                caseNumber: caseNumber,
                channelId: input.ChannelId,
                triggerId: input.TriggerId,
                responseUrl: input.ResponseUrl.ToString());

            BackgroundJob.Enqueue(() => RespondToSlashCommand(jobInfo));

            return(SlashCommandResponse.ForCommandAcknowledgement());
        }
        public async Task <IActionResult> DelayedResponsePost()
        {
            var streamHelper = new StreamHelper();
            var requestBody  = streamHelper.ReadAsString(Request.Body).Result;

            var slashCommandPayload = new SlashCommandPayload(requestBody);

            // Verify Slack request signature
            if (!SignatureValidationService.SignatureValid(Request.Headers["X-Slack-Signature"], Request.Headers["X-Slack-Request-Timestamp"], requestBody, SlackSettings.SignatureSecret))
            {
                return(BadRequest());
            }

            // Queue background task
            var exampleDelayedWorkService = new ExampleDelayedWorkService(new SlackDelayedResponseService());

            BackgroundJob.Enqueue(() => exampleDelayedWorkService.DoWork(slashCommandPayload));

            // Return an immediate response to Slack while the backgroundjob is still processing
            var slashCommandResponse = new SlashCommandResponse()
            {
                ResponseType = "ephemeral",
                Text         = "Processing your request."
            };

            return(Ok(slashCommandResponse));
        }
Exemplo n.º 4
0
        public async Task <IActionResult> SlashCommand()
        {
            var form = await Request.ReadFormAsync();

            var slashRequest = new SlashCommandRequest(form);

            var commandType = DetermineCommand(slashRequest);
            SlashCommandResponse response = null;

            switch (commandType)
            {
            case ReportBotCommand.AddItem:
                response = await ProcessAddItem(slashRequest);

                break;

            case ReportBotCommand.GenerateReport:
                response = await ProcessGenerate(slashRequest);

                break;

            default:
                response = ProcessUnknownRequest(slashRequest);
                break;
            }

            return(Ok(response));
        }
Exemplo n.º 5
0
        private async Task SendCommandResponse(SlashCommand command, IList <Block> msgBlocks)
        {
            var message = new SlashCommandResponse()
            {
                Message = new Message
                {
                    Blocks  = msgBlocks,
                    Channel = command.ChannelId,
                    AsUser  = false,
                },
                ResponseType = ResponseType.InChannel
            };

            // Add information about command caller
            var callerInfo = new PlainText($"Command from: {command.UserName}.");

            if (message.Message.Blocks.Last() is ContextBlock ctx)
            {
                ctx.Elements.Add(callerInfo);
            }
            else
            {
                message.Message.Blocks.Add(new ContextBlock()
                {
                    Elements = new List <IContextElement>()
                    {
                        callerInfo
                    }
                });
            }

            await slack.Respond(command, message);
        }
        private static async Task ProcessSlashCommand(SlashCommandRequest slashCommandRequest)
        {
            var slashCommandResponse = new SlashCommandResponse
            {
                ResponseType = ResponseType.Ephemeral,
                Text         = ExceptionResponse
            };

            try
            {
                var slackRequest  = RequestMapper.Map(slashCommandRequest);
                var slackResponse = Processor.Process(slackRequest);
                slashCommandResponse = ResponseMapper.MapToSlashCommandResponse(slackResponse);
            }
            catch (Exception e)
            {
                Log.Error("Encountered error while processing slash command.", e);
            }
            finally
            {
                var content = JsonConvert.SerializeObject(slashCommandResponse, JsonSerializerSettings);
                Log.Debug($"Response to Slack hook: {content}");
                await HttpClient.PostAsync(slashCommandRequest.response_url,
                                           new StringContent(content)
                {
                    Headers = { ContentType = new MediaTypeHeaderValue("application/json") }
                });
            }
        }
        public void SlashCommandResponseTests(string text, ResponseType responseType, string stringThatSlackExpects)
        {
            var owr = new SlashCommandResponse
            {
                Text         = text,
                ResponseType = responseType
            };
            var s = JsonConvert.SerializeObject(owr, _converter);

            s.ShouldBeEquivalentTo(stringThatSlackExpects);
        }
Exemplo n.º 8
0
        public void DoWork(SlashCommandPayload slashCommandPayload)
        {
            // Do stuff here

            // Build Slack response model
            var responseModel = new SlashCommandResponse()
            {
                ResponseType = "in_channel",
                Text         = "It's 80 degrees right now."
            };

            // Send delayed response to Slack
            SlackDelayedResponseService.SendDelayedResponse(slashCommandPayload.ResponseUrl, responseModel);
        }
Exemplo n.º 9
0
        public async Task Handle(RunEndedEvent notification, CancellationToken cancellationToken)
        {
            if (!notification.TryGetCallbackState(out var callbackData))
            {
                return;
            }

            var orders = notification.Orders.ToList();

            // Create a dictionary of all usernames in the current order (including the runner)
            var userIds = new HashSet <long>(orders.Select(o => o.User.Id))
            {
                notification.RunnerUserId
            };

            var usernames = (await Task.WhenAll(userIds.Select(async uid =>
                                                               new KeyValuePair <long, string>(uid, await GetSlackUsername(uid)))))
                            .ToDictionary(k => k.Key, v => v.Value);

            var messageBuilder = new StringBuilder();

            messageBuilder
            .Append("Congratulations ")
            .Append(usernames[notification.RunnerUserId])
            .Append(" you drew the short straw :cup_with_straw: \n\nHere's the order:\n");

            for (var i = 0; i < orders.Count; i++)
            {
                var o = orders[i];

                messageBuilder
                .Append("- ")
                .Append(usernames[o.User.Id])
                .Append(": ")
                .Append(o.Option.Name);

                if (i < orders.Count - 1)
                {
                    messageBuilder.Append("\n");
                }
            }

            var data = new SlashCommandResponse(messageBuilder.ToString(), ResponseType.Channel);

            await _slackApiClient.PostResponseAsync(callbackData.ResponseUrl, data).ConfigureAwait(false);
        }
Exemplo n.º 10
0
        public void Execute(SlashCommandPayload slashCommandPayload)
        {
            // Parse the command
            var slackCommand = CommandParseService.ParseCommand(slashCommandPayload.Text);
            // Find the right command to execute
            var command = VirtualMachineCommandFactory.GetCommand(slackCommand);

            // Execute command
            command.Execute();

            // Send response to slack
            var responseModel = new SlashCommandResponse()
            {
                ResponseType = "in_channel",
                Text         = command.GetResultMessage()
            };

            SlackDelayedResponseService.SendDelayedResponse(slashCommandPayload.ResponseUrl, responseModel);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Send channel message in response to given command.
        /// </summary>
        private async Task SendPublicResponse(SlashCommand command, string markdown)
        {
            var message = new SlashCommandResponse()
            {
                Message = new Message
                {
                    Blocks = new List <Block>()
                    {
                        new SectionBlock()
                        {
                            Text = new Markdown(markdown)
                        }
                    },
                    Channel = command.ChannelId,
                    AsUser  = false,
                },
                ResponseType = ResponseType.InChannel
            };

            await slack.Respond(command, message);
        }
        public async Task <IActionResult> Post()
        {
            var streamHelper = new StreamHelper();
            var requestBody  = streamHelper.ReadAsString(Request.Body).Result;

            var slashCommandPayload = new SlashCommandPayload(requestBody);

            // Verify request signature
            if (!SignatureValidationService.SignatureValid(Request.Headers["X-Slack-Signature"], Request.Headers["X-Slack-Request-Timestamp"], requestBody, SlackSettings.SignatureSecret))
            {
                return(BadRequest());
            }

            // Validate command and return error to Slack if the command is invalid
            if (!CommandExecutionService.IsCommandValid(slashCommandPayload.Text))
            {
                // No command was found to execute this request, send error response to Slack
                var slashCommandErrorResponse = new SlashCommandResponse()
                {
                    ResponseType = "ephemeral",
                    Text         = "Sorry, we were unable to understand your request. Please try again or type /help for more information."
                };

                // Even though an error occured, Slack needs a 200 OK response code (see Slack docs)
                return(Ok(slashCommandErrorResponse));
            }

            BackgroundJob.Enqueue(() => CommandExecutionService.Execute(slashCommandPayload));
            //CommandExecutionService.Execute(slashCommandPayload);

            // Send response to Slack
            var slashCommandResponse = new SlashCommandResponse()
            {
                ResponseType = "in_channel",
                Text         = "Executing Command"
            };

            return(Ok(slashCommandResponse));
        }
        public async Task <IActionResult> ImmediateResponsePost()
        {
            var streamHelper = new StreamHelper();
            var requestBody  = streamHelper.ReadAsString(Request.Body).Result;

            var slashCommandPayload = new SlashCommandPayload(requestBody);

            // Verify Slack request signature
            if (!SignatureValidationService.SignatureValid(Request.Headers["X-Slack-Signature"], Request.Headers["X-Slack-Request-Timestamp"], requestBody, SlackSettings.SignatureSecret))
            {
                return(BadRequest());
            }

            // Do stuff here

            // Return an immediate response to slack
            var slashCommandErrorResponse = new SlashCommandResponse()
            {
                ResponseType = "in_channel",
                Text         = "It's 80 degrees right now."
            };

            return(Ok(slashCommandErrorResponse));
        }
Exemplo n.º 14
0
 public Task PostResponseAsync(string callbackUrl, SlashCommandResponse response)
 {
     return(PostAsync(callbackUrl, response));
 }
Exemplo n.º 15
0
 private async Task RespondToSlack(string responseUrl, SlashCommandResponse response)
 {
     await WebClient.PostAsJsonAsync(responseUrl, response);
 }
Exemplo n.º 16
0
 protected ICommandResult Response(SlashCommandResponse response)
 {
     return(StringResult(SlackJsonSerializer.Serialize(response)));
 }
Exemplo n.º 17
0
        public async Task RespondToSlashCommand(FogBugzSlashCommandInfo info)
        {
            var request = new FogBugzSearchRequest(
                apiToken: FogBugzConfig.GetApiToken(),
                caseNumber: info.CaseNumber);

            FogBugzSearchResponse responseFromFogBugz;
            SlashCommandResponse  responseToSlack;
            string stepName;

            /* 📜 𝕾𝖙𝖊𝖕 𝕿𝖍𝖊 𝖅𝖊𝖗𝖔𝖙𝖍 📜 */
            {
                responseToSlack = null;
                stepName        = "calling the FogBugz API";
            }
            try
            {
                using (var httpResponse = await WebClient.PostAsJsonAsync(FogBugzConfig.ApiUri, request))
                    using (var message = await httpResponse.Content.ReadAsHttpResponseMessageAsync())
                    {
                        if (!message.IsSuccessStatusCode)
                        {
                            string errorText = GetFriendlyHttpErrorMsg(httpResponse);
                            responseToSlack = SlashCommandResponse.ForFogBugzApiCallResult(
                                text: $"There was an error calling the FogBugz API for Case {info.CaseNumber}.",
                                attachments: new SlashCommandReponseAttachment(errorText, SlackAttachmentColorType.Danger));
                            throw new SlashCommandException(errorText);
                        }

                        {
                            responseToSlack = null;
                            stepName        = "reading the FogBugz API response";
                        }
                        using (var contentStream = await message.Content.ReadAsStreamAsync())
                        {
                            responseFromFogBugz = (FogBugzSearchResponse) new DataContractJsonSerializer(typeof(FogBugzSearchResponse))
                                                  .ReadObject(contentStream);
                        }
                    }

                /* 📜 𝕾𝖙𝖊𝖕 𝕿𝖍𝖊 𝕱𝖎𝖗𝖘𝖙 📜 */
                {
                    responseToSlack = null;
                    stepName        = "reading the FogBugz API message";
                }
                var theCase = responseFromFogBugz?.ResponseData?.Cases?
                              .FirstOrDefault(c => c.CaseNumber == info.CaseNumber);
                if (theCase == null)
                {
                    if (responseFromFogBugz.Errors?.Any() == true)
                    {
                        var error = responseFromFogBugz.Errors.First();
                        responseToSlack = SlashCommandResponse.ForFogBugzApiCallResult(
                            text: $"There was an error reading the FogBugz API message for Case {info.CaseNumber}.",
                            attachments: new SlashCommandReponseAttachment($"{ error.Code }: { error.Message }", SlackAttachmentColorType.Danger));
                        throw new SlashCommandException($"{ error.Code }: { error.Message }");
                    }
                    else
                    {
                        responseToSlack = SlashCommandResponse.ForFogBugzApiCallResult(
                            text: $"Case {info.CaseNumber} does not seem to exist.");
                    }
                }
                else
                {
                    /* 📜 𝕾𝖙𝖊𝖕 𝕿𝖍𝖊 𝕾𝖊𝖈𝖔𝖓𝖉 📜 */
                    {
                        responseToSlack = null;
                        stepName        = "generating the command response";
                    }
                    (decimal Elapsed, decimal Total)? estimate = null;
                    if (theCase.EstimatedHours > 0)
                    {
                        estimate = (Elapsed : theCase.ElapsedHours, Total : theCase.EstimatedHours);
                    }
                    responseToSlack = GetSuccessfulResponseText(
                        caseNumber: info.CaseNumber.ToString(),
                        title: theCase.Title,
                        estimate: estimate);
                }
            }
            catch (Exception ex)
            {
                if (responseToSlack == null)
                {
                    responseToSlack = SlashCommandResponse.ForFogBugzApiCallResult(
                        text: $"There was an error {stepName} for Case {info.CaseNumber}.",
                        attachments: new SlashCommandReponseAttachment(ex.Message, SlackAttachmentColorType.Danger));
                }
                throw ex;
            }
            finally
            {
                await RespondToSlack(info.ResponseUrl, responseToSlack);
            }
        }
 public static Task Respond(this ISlackApiClient client, SlashCommand slashCommand, SlashCommandResponse response, CancellationToken?cancellationToken = null) =>
 client.Respond(slashCommand.ResponseUrl, new SlashCommandMessageResponse(response), cancellationToken);
Exemplo n.º 19
0
        public void SendDelayedResponse(string responseUrl, SlashCommandResponse response)
        {
            var content = new StringContent(JsonConvert.SerializeObject(response), Encoding.UTF8, "application/json");

            var result = HttpClient.PostAsync(responseUrl, content).Result;
        }
Exemplo n.º 20
0
 public SlashCommandMessageResponse(SlashCommandResponse response) : base(response) => _commandResponse = response;