public DiscordHookMessage(DiscordBot bot, string eventType, JiraUser user, JiraIssue issue, JiraIssueIcons issueIcons, JiraComment comment) { username = bot.Name; avatar_url = bot.AvatarUrl; List <DiscordAttachmentField> embedFields = null; if (!eventType.Contains("comment")) { embedFields = new List <DiscordAttachmentField>() { new DiscordAttachmentField() { name = "Summary", value = issue.Summary }, new DiscordAttachmentField() { name = "Description", value = issue.Description }, new DiscordAttachmentField() { name = "Assignee", value = issue.Assignee.Name, inline = true }, new DiscordAttachmentField() { name = "Status", value = issue.Status, inline = true }, new DiscordAttachmentField() { name = "Resolution", value = issue.Resolution, inline = true } }; } else { if (comment.Contents == "" || comment.Id == "") { return; } embedFields = new List <DiscordAttachmentField>() { new DiscordAttachmentField() { name = "Summary", value = issue.Summary }, new DiscordAttachmentField() { name = "Comment", value = comment.Contents }, new DiscordAttachmentField() { name = "Assignee", value = issue.Assignee.Name, inline = true }, new DiscordAttachmentField() { name = "Status", value = issue.Status, inline = true }, new DiscordAttachmentField() { name = "Resolution", value = issue.Resolution, inline = true } }; } if (embedFields == null) { return; } // Set the color decimal value for the issue type - values taken from Jira's default icons int embedColor; string footerText = eventType.Replace("Issue", issue.Type); string footerIconUrl = ""; switch (issue.Type) { case "Bug": embedColor = 15026490; // rgb: 229, 73, 58 footerIconUrl = issueIcons.BugIconURL; break; case "Task": embedColor = 4959720; // rgb: 75, 173, 232 footerIconUrl = issueIcons.TaskIconURL; break; case "Epic": embedColor = 9457378; // rgb: 144, 78, 226 footerIconUrl = issueIcons.EpicIconURL; break; default: embedColor = 8421504; // rgb: 128, 128, 128 break; } DiscordFooterField embedFooter = new DiscordFooterField() { text = footerText, icon_url = footerIconUrl }; embeds = new List <DiscordAttachment>() { new DiscordAttachment() { author = new DiscordAuthorField() { name = user.Name, icon_url = user.AvatarUrl }, color = embedColor, title = eventType + " – (" + issue.Key + ") " + issue.Summary, url = issue.Url, //description = eventType, fields = embedFields, footer = embedFooter, timestamp = issue.UpdatedTimestamp } }; }
public void StartListening() { if (GetServerStatus() == ServerStatus.Running) { return; } Debug.WriteLine("In StartListening"); SetServerStatus(ServerStatus.Running); while (true) { try { listener = new HttpListener(); listener.Prefixes.Add(prefs.LocalIP); listener.Start(); } catch (Exception e) { var msg = e.Message; Trace.WriteLine(msg); } Trace.WriteLine("Listening..."); if (stopListening) { Debug.WriteLine("Time to stop listening."); listener.Stop(); break; } HttpListenerContext context; HttpListenerRequest request; try { context = listener.GetContext(); request = context.Request; } catch (HttpListenerException e) { var msg = e.Message + "\n\n"; msg += "Either run this application as administrator, which you'll have to do every time it's started, or enter the following command (all in one line and without quotes) in an elevated command prompt, which you'll only have to do once: \n\n"; msg += "'netsh http add urlacl url=http://LOCAL_IP:PORT/ user=COMPUTER_NAME\\WIN_ACCOUNT_NAME'\n\n"; msg += "Change LOCAL_IP and PORT to the local IP and port to listen on, and COMPUTER_NAME and WIN_ACCOUNT_NAME to the computer name and Windows account username."; Trace.WriteLine(msg); MessageBox.Show(msg); return; } catch (InvalidOperationException e) { var msg = e.Message; Trace.WriteLine(msg); MessageBox.Show(msg); return; } if (stopListening) { Debug.WriteLine("Time to stop listening."); listener.Stop(); break; } HttpListenerResponse response = context.Response; if (request.InputStream != null) { using (var reader = new StreamReader(request.InputStream, Encoding.UTF8)) { var content = reader.ReadToEnd(); dynamic json = JObject.Parse(content); var eventType = ""; try { eventType = json.issue_event_type_name.Value; eventType = eventType.Replace("_", " "); eventType = eventType.First().ToString().ToUpper() + eventType.Substring(1); Trace.WriteLine("Issue event type name: " + eventType); if (eventType == "Issue generic") { eventType = "Issue moved to '" + json.issue.fields.status.name.Value + "'"; } } catch (Exception ex) { var msg = ex.Message; Trace.WriteLine(msg); eventType = json.webhookEvent.Value; Trace.WriteLine("Webhook event: " + eventType); return; } JiraUser user = new JiraUser(); dynamic author = null; try { author = json.user; user.Name = json.user.displayName.Value; //prefs.BotName = user.Name + " (JIRA)"; } catch (Exception ex) { var msg = ex.Message; Trace.WriteLine(msg); author = json.comment.author; user.Name = json.comment.author.displayName.Value; //prefs.BotName = user.Name + " (JIRA)"; } JiraIssue issue = new JiraIssue(); JiraComment comment = new JiraComment(); try { comment.Contents = json.comment.body.Value; comment.Id = json.comment.id.Value; issue.Key = json.issue.key.Value; issue.Url = prefs.JiraBaseURL + issue.Key + "?focusedCommentId=" + comment.Id; issue.Type = json.issue.fields.issuetype.name.Value; issue.Summary = json.issue.fields.summary.Value; issue.Description = json.issue.fields.description.Value; issue.Status = json.issue.fields.status.name.Value; issue.Resolution = json.issue.fields.resolution.Value; if (issue.Resolution == null) { issue.Resolution = "Unresolved"; } issue.Reporter = new JiraUser { Name = json.issue.fields.reporter.displayName.Value, AvatarUrl = ((json.issue.fields.reporter.avatarUrls as IEnumerable <object>).First() as dynamic).Value.Value }; if (json.issue.fields.assignee == null) { issue.Assignee = new JiraUser { Name = "*Unassigned*" }; } else { issue.Assignee = new JiraUser { Name = json.issue.fields.assignee.displayName.Value, AvatarUrl = ((json.issue.fields.assignee.avatarUrls as IEnumerable <object>).First() as dynamic).Value.Value }; } issue.UpdatedTimestamp = json.issue.fields.updated.Value; } catch (Exception ex) { var msg = ex.Message; Trace.WriteLine(msg); issue.Key = json.issue.key.Value; issue.Url = prefs.JiraBaseURL + issue.Key; issue.Type = json.issue.fields.issuetype.name.Value; issue.Summary = json.issue.fields.summary.Value; issue.Description = json.issue.fields.description.Value; issue.Status = json.issue.fields.status.name.Value; issue.Resolution = json.issue.fields.resolution.Value; if (issue.Resolution == null) { issue.Resolution = "Unresolved"; } issue.Reporter = new JiraUser { Name = json.issue.fields.reporter.displayName.Value, AvatarUrl = ((json.issue.fields.reporter.avatarUrls as IEnumerable <object>).First() as dynamic).Value.Value }; if (json.issue.fields.assignee == null) { issue.Assignee = new JiraUser { Name = "*Unassigned*" }; } else { issue.Assignee = new JiraUser { Name = json.issue.fields.assignee.displayName.Value, AvatarUrl = ((json.issue.fields.assignee.avatarUrls as IEnumerable <object>).First() as dynamic).Value.Value }; } issue.UpdatedTimestamp = json.issue.fields.updated.Value; } if (issue.Description != null && issue.Description != "") { // Convert code tags issue.Description = issue.Description.Replace("{{", "```\n"); issue.Description = issue.Description.Replace("}}", "\n```"); issue.Description = issue.Description.Replace("{code}\r\n", "```\n"); issue.Description = issue.Description.Replace("\r\n{code}", "\n```"); // Remove bold formatting issue.Description = issue.Description.Replace("*", ""); // Trim length if (issue.Description.Length > 250) { issue.Description = issue.Description.Substring(0, 250); // Is there an odd number of code tags? int numTags = Regex.Matches(issue.Description, "```").Count; if (numTags % 2 != 0) { // Close the last tag issue.Description += " ...\n```" + "\n([see full description](" + issue.Url + "))"; } else { issue.Description += " ... ([see full description](" + issue.Url + "))"; } } } else { issue.Description = "*No description*"; } try { user.AvatarUrl = ((author.avatarUrls as IEnumerable <object>).First() as dynamic).Value.Value; } catch (Exception ex) { var msg = ex.Message; Trace.WriteLine(msg); } DiscordBot bot = new DiscordBot { Name = prefs.BotName, AvatarUrl = prefs.JiraIconURL }; JiraIssueIcons issueIcons = new JiraIssueIcons { BugIconURL = prefs.BugIconURL, TaskIconURL = prefs.TaskIconURL, EpicIconURL = prefs.EpicIconURL }; Trace.WriteLine("Got webhook event '" + eventType + "' [" + issue.Summary + "]" + " by " + user.Name); try { var discordMessage = new DiscordHookMessage(bot, eventType, user, issue, issueIcons, comment); var discordMessageJSON = JsonConvert.SerializeObject(discordMessage, Formatting.Indented); var resp = client.PostAsync(prefs.DiscordURL, new StringContent(discordMessageJSON, Encoding.UTF8, "application/json")).Result; Trace.WriteLine("Discord response code: " + resp.StatusCode); } catch (Exception ex) { var msg = ex.Message; Trace.WriteLine(msg); //MessageBox.Show(msg); } } } try { using (var writer = new StreamWriter(response.OutputStream)) { writer.Write("Hello world!"); writer.Close(); } listener.Stop(); } catch (IOException ex) { var msg = ex.Message; Trace.WriteLine(msg); } catch (ObjectDisposedException ex) { var msg = ex.Message; Trace.WriteLine(msg); } } }