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)); } }
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)); }
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)); }
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); }
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); }
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); }
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); }
/// <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)); }
public Task PostResponseAsync(string callbackUrl, SlashCommandResponse response) { return(PostAsync(callbackUrl, response)); }
private async Task RespondToSlack(string responseUrl, SlashCommandResponse response) { await WebClient.PostAsJsonAsync(responseUrl, response); }
protected ICommandResult Response(SlashCommandResponse response) { return(StringResult(SlackJsonSerializer.Serialize(response))); }
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);
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; }
public SlashCommandMessageResponse(SlashCommandResponse response) : base(response) => _commandResponse = response;