/
SlackNotification.fs
150 lines (129 loc) · 5.64 KB
/
SlackNotification.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
namespace Fake.Api
open System.Net.Http
open Newtonsoft.Json
/// <summary>
/// Contains a task to send notification messages to a <a href="https://slack.com/">Slack</a> webhook
/// </summary>
[<RequireQualifiedAccess>]
module Slack =
/// The Slack notification attachment field parameter type
type NotificationAttachmentFieldParams =
{
/// (Required) The field title
Title: string
/// (Required) Text value of the field
Value: string
/// Whether the value is short enough to be displayed side-by-side with other values
Short: bool
}
/// The Slack notification attachment parameter type
type NotificationAttachmentParams =
{
/// (Required) Text summary of the attachment that is shown by clients that understand attachments but choose not to show them
Fallback: string
/// The title of the attachment
Title: string
/// Content to which the title should link
TitleLink: string
/// Text that should appear within the attachment
Text: string
/// Text that should appear above the formatted data
Pretext: string
/// Color of the attachment text. Can be hex-value(e.g. "#AABBCC") or one of "'good', 'warning', 'danger'.
Color: string
/// Text to be displayed as a table below the message
Fields: NotificationAttachmentFieldParams[]
}
/// The Slack notification parameter type
type NotificationParams =
{
/// (Required) The message body
Text: string
/// Name the message will appear to be sent from. Default value: Specified in your Slack Webhook configuration.
Username: string
/// Channel to which the message will be posted. Default value: Specified in your Slack Webhook configuration.
Channel: string
/// The icon to be displayed with the message. Default value: Specified in your slack Webhook configuration.
IconURL: string
/// The emoji to be displayed with the message. Default value: Specified in your slack Webhook configuration.
IconEmoji: string
/// Whether to force inline unfurling of attached links. Default value: false.
UnfurlLinks: bool
// Richly formatted message attachments for the notification
Attachments: NotificationAttachmentParams[]
// Whether or not to link names of users or channels (beginning with @ or #), Default value : false
LinkNames: bool
}
/// The default Slack notification parameters
let NotificationDefaults =
{ Text = ""
Username = null
Channel = null
IconURL = null
IconEmoji = null
UnfurlLinks = false
Attachments = Array.empty
LinkNames = false }
/// The default parameters for Slack notification attachments
let NotificationAttachmentDefaults =
{ Fallback = ""
Title = null
TitleLink = null
Text = null
Pretext = null
Color = null
Fields = Array.empty }
/// The default parameters for Slack notification attachment fields
let NotificationAttachmentFieldDefaults =
{ Title = ""
Value = ""
Short = false }
let private lowerCaseContractResolver =
{ new Newtonsoft.Json.Serialization.DefaultContractResolver() with
override this.ResolvePropertyName(key: string) = key.ToLower() }
let private ValidateParams webhookURL (param: NotificationParams) =
if webhookURL = "" then
failwith "You must specify a webhook URL"
if param.Text = "" && param.Attachments.Length = 0 then
failwith "You must specify a message or include an attachment"
let validateField (field: NotificationAttachmentFieldParams) =
if field.Title = "" then
failwith "Each field must have a title"
if field.Value = "" then
failwith "Each field must have a value"
let validateAttachment (attachment: NotificationAttachmentParams) =
if attachment.Fallback = "" then
failwith "Each attachment must have a fallback"
Array.iter (fun field -> validateField field) attachment.Fields
Array.iter (fun attachment -> validateAttachment attachment) param.Attachments
param
let private SerializeData data =
JsonConvert.SerializeObject(
data,
Formatting.None,
JsonSerializerSettings(
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = lowerCaseContractResolver
)
)
/// <summary>
/// Sends a notification to a Slack Channel
/// </summary>
///
/// <param name="webhookURL">The Slack webhook URL</param>
/// <param name="setParams">Function used to override the default notification parameters</param>
let sendNotification (webhookURL: string) (setParams: NotificationParams -> NotificationParams) =
let sendNotification param =
use client = (new HttpClient())
let response =
client
.PostAsync(
webhookURL,
new StringContent(SerializeData param, System.Text.Encoding.UTF8, "application/json")
)
.Result
response.Content.ReadAsStringAsync().Result
NotificationDefaults
|> setParams
|> ValidateParams webhookURL
|> sendNotification