private string BuildPayload(Notification notification) { // Get some more data about this commit via "svnlook" notification.CommitMessage = CommandLineHelper.ExecuteProcess(ConfigurationHelper.SVNLookProcessPath, string.Format("log -r {0} {1}", notification.Revision, notification.RepositoryPath)); notification.CommitAuthor = CommandLineHelper.ExecuteProcess(ConfigurationHelper.SVNLookProcessPath, string.Format("author -r {0} {1}", notification.Revision, notification.RepositoryPath)); // Ensure valid formatting of message if(notification.CommitMessage.Contains("\"")) notification.CommitMessage = notification.CommitMessage.Replace("\"", "\\\""); if (notification.CommitAuthor.Contains("\"")) notification.CommitAuthor = notification.CommitAuthor.Replace("\"", "\\\""); // Trim off unnecessary trailing CRLFs notification.CommitMessage = notification.CommitMessage.TrimEnd(new char[] { '\r', '\n' }); notification.CommitAuthor = notification.CommitAuthor.TrimEnd(new char[] { '\r', '\n' }); // Use advanced message formatting for incoming webhooks var payloadBody = new StringBuilder(); payloadBody.Append("{"); // begin payload payloadBody.Append(" \"username\" : \"VisualSVN Server\", "); payloadBody.Append(" \"icon_url\" : \"http://s3.amazonaws.com/scs-public/visualsvn_96.png\", "); payloadBody.Append(" \"attachments\" : [ { "); // begin attachments if (!string.IsNullOrEmpty(notification.Channel)) payloadBody.Append(string.Format(" \"channel\" : \"{0}\", ", notification.Channel)); if (!string.IsNullOrEmpty(notification.RepositoryName)) { payloadBody.Append(string.Format(" \"fallback\" : \"[{0}] New commit by {1}: r{2}: {3}\", ", notification.RepositoryName, notification.CommitAuthor, notification.Revision, notification.CommitMessage)); payloadBody.Append(string.Format(" \"pretext\" : \"[{0}] New commit by {1}\", ", notification.RepositoryName, notification.CommitAuthor)); } else { payloadBody.Append(string.Format(" \"fallback\" : \"New commit by {0}: r{1}: {2}\", ", notification.CommitAuthor, notification.Revision, notification.CommitMessage)); payloadBody.Append(string.Format(" \"pretext\" : \"New commit by {0}\", ", notification.CommitAuthor)); } if (!string.IsNullOrEmpty(notification.RepositoryURL)) { if (notification.RepositoryURL.Contains("/svn/")) notification.RepositoryURL = notification.RepositoryURL.Replace("/svn/", "/!/#"); notification.RepositoryURL += "/commit/r" + notification.Revision; payloadBody.Append(string.Format(" \"text\" : \"<{0}|r{1}>: {2}\", ", notification.RepositoryURL, notification.Revision, notification.CommitMessage)); } else payloadBody.Append(string.Format(" \"text\" : \"r{0}: {1}\", ", notification.Revision, notification.CommitMessage)); payloadBody.Append(" \"color\" : \"#3886C0\" "); payloadBody.Append("} ]"); // end attachments payloadBody.Append("}"); // end payload return payloadBody.ToString(); }
public async Task<bool> PostNotificationAsync(Notification notification) { var isSuccess = false; try { if (string.IsNullOrEmpty(ConfigurationHelper.SlackWebhookURL)) Logger.Shared.WriteError("Missing Slack Webhook URL"); else if(ConfigurationHelper.SlackWebhookURL == "https://hooks.slack.com/services/foo/bar/baz") Logger.Shared.WriteError("Found default Slack Webhook URL in config file. Ensure you've replaced it with your own."); else if (string.IsNullOrEmpty(notification.RepositoryPath)) Logger.Shared.WriteError("Missing repo path"); else if (string.IsNullOrEmpty(notification.Revision)) Logger.Shared.WriteError("Missing revision number"); else { // Post to Slack using (var client = new HttpClient()) { var request = new HttpRequestMessage(HttpMethod.Post, ConfigurationHelper.SlackWebhookURL); var keyValues = new List<KeyValuePair<string, string>>(); var payload = BuildPayload(notification); keyValues.Add(new KeyValuePair<string, string>("payload", payload)); request.Content = new FormUrlEncodedContent(keyValues); using (var response = await client.SendAsync(request)) using (var content = response.Content) { if (!response.IsSuccessStatusCode) { var result = await content.ReadAsStringAsync(); Logger.Shared.WriteError("Failed to send notification: " + response.StatusCode + " => " + result); if (result == "Payload was not valid JSON") Logger.Shared.WriteError("payload = " + payload); } } } } } catch(Exception e) { Logger.Shared.WriteError(e); } if (OnFinished != null) OnFinished(this, null); return isSuccess; }
static void Main() { string[] args = Environment.GetCommandLineArgs(); if (args != null && args.Length > 0) { var argList = args.ToList(); var notification = new Notification(); foreach(var arg in argList) { if (arg.ToLower().StartsWith(FLAG_PATH) && arg.Length > FLAG_PATH.Length) notification.RepositoryPath = arg.Substring(FLAG_PATH.Length); else if (arg.ToLower().StartsWith(FLAG_REVISION) && arg.Length > FLAG_REVISION.Length) notification.Revision = arg.Substring(FLAG_REVISION.Length); else if (arg.ToLower().StartsWith(FLAG_NAME) && arg.Length > FLAG_NAME.Length) notification.RepositoryName = arg.Substring(FLAG_NAME.Length); else if (arg.ToLower().StartsWith(FLAG_URL) && arg.Length > FLAG_URL.Length) notification.RepositoryURL = arg.Substring(FLAG_URL.Length); else if (arg.ToLower().StartsWith(FLAG_CHANNEL) && arg.Length > FLAG_CHANNEL.Length) notification.Channel = arg.Substring(FLAG_CHANNEL.Length); } Task.Run(() => new SlackNotifier().PostNotificationAsync(notification)).Wait(); } }