using System; using System.Text.Json; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; using SlackAPI; using sera_slackbot.Commands; using sera_slackbot.Library; namespace sera_slackbot.Controllers { [ApiController] [Route("event")] [Produces("application/json")] public class SlackEventController : ControllerBase { private readonly ILogger logger; private readonly IConfiguration configuration; private SlackClient client; private BotCommandFactory factory; private JsonFileReader jsonFileReader; private JsonFileSaver jsonFileSaver; public SlackEventController(IConfiguration config, ILogger log) { configuration = config; logger = log; var token = configuration.GetSection("Slackbot").GetValue("Bot-User-OAuth-Access-Token"); this.jsonFileReader = new JsonFileReader(configuration); this.jsonFileSaver = new JsonFileSaver(configuration); client = new SlackClient(token); factory = new BotCommandFactory(this.jsonFileReader, this.jsonFileSaver); } [HttpGet] public IActionResult Get() { // Console.WriteLine("***Event***"); // foreach (var header in Request.Headers) // { // Console.WriteLine(header.Key + ": " + header.Value); // } dynamic response = new { name = "Slack Event Bot", code = StatusCodes.Status200OK, datetime = DateTime.Now }; return Ok(response); } [HttpPost] public IActionResult HttpPost([FromBody] dynamic body) { // Console.WriteLine("***Event***"); // foreach (var header in Request.Headers) // { // Console.WriteLine(header.Key + ": " + header.Value); // } // Console.WriteLine(JsonSerializer.Serialize(body, new JsonSerializerOptions { WriteIndented = true })); var typeProperty = body.GetProperty("type"); var type = typeProperty.ToString(); dynamic response = new { code = StatusCodes.Status200OK, body = "" }; switch (type) { case "url_verification": response = UrlVerification(body); break; case "event_callback": response = EventCallback(body); break; default: var bodyString = ((object)body).ToString(); logger.LogError($"Unknown Request Type: '{type}' = {bodyString}"); break; } return StatusCode(response.code, response); } private dynamic UrlVerification(dynamic body) { var challenge = body.GetProperty("challenge"); var token = body.GetProperty("token"); //TODO: should save off the token? logger.LogInformation($"Url Verification: Got Token: {token}"); return new { code = StatusCodes.Status200OK, challenge = challenge, body = "" }; } private dynamic EventCallback(dynamic body) { this.jsonFileSaver.Save("lastevent.json", body); var slackEvent = body.GetProperty("event"); dynamic response = new { code = StatusCodes.Status200OK, body = "" }; var eventType = slackEvent.GetProperty("type").ToString(); var eventString = JsonSerializer.Serialize(slackEvent, new JsonSerializerOptions { WriteIndented = true }); switch (eventType) { case "app_mention": response = AppMention(slackEvent); break; case "message": // logger.LogInformation($"Got Message: '{eventType}' = {eventString}"); break; case "reaction_added": // logger.LogInformation($"Got Reaction Added: '{eventType}' = {eventString}"); break; default: logger.LogError($"Unknown Event Type: '{eventType}' = {eventString}"); break; } return response; } private dynamic AppMention(JsonElement slackEvent) { var command = ParseText(slackEvent); return command.Run(client); } private IBotCommand ParseText(JsonElement slackEvent) { JsonElement commandList = this.jsonFileReader.Read("commandlist.json"); IBotCommand command; foreach (var commandString in commandList.EnumerateArray()) { command = this.factory.CreateCommand(commandString.ToString()); if (command.WillTrigger(slackEvent)) { command.ExtractValidData(slackEvent); return command; } } command = new UnhelpfulBotCommand(); command.ExtractValidData(slackEvent); return command; } } }