• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

djsuperchief / Kyameru / 8401706343

23 Mar 2024 12:18PM UTC coverage: 89.113% (-7.0%) from 96.15%
8401706343

push

github

web-flow
Merge pull request #104 from djsuperchief/103-release-config

103 release config

308 of 387 branches covered (79.59%)

Branch coverage included in aggregate %.

1812 of 1992 relevant lines covered (90.96%)

21.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.0
/source/components/Kyameru.Component.Slack/Implementation/SlackTo.cs
1
using Kyameru.Core.Contracts;
2
using Kyameru.Core.Entities;
3
using System;
4
using System.Collections.Generic;
5
using System.Net.Http;
6
using System.Text;
7
using System.Text.Json;
8
using System.Threading;
9
using System.Threading.Tasks;
10

11
namespace Kyameru.Component.Slack
12
{
13
    /// <summary>
14
    /// Main To Component.
15
    /// </summary>
16
    public class SlackTo : ISlackTo
17
    {
18
        /// <summary>
19
        /// Allowed headers.
20
        /// </summary>
21
        private readonly string[] allowedHeaders = new string[] { "Target", "MessageSource", "Username", "Channel" };
7✔
22

23
        /// <summary>
24
        /// Slack webhook URI
25
        /// </summary>
26
        private const string SLACKURI = "https://hooks.slack.com/services";
27

28
        /// <summary>
29
        /// Headers added.
30
        /// </summary>
31
        private readonly Dictionary<string, string> headers;
32

33
        /// <summary>
34
        /// Http message handler for test mocking.
35
        /// </summary>
36
        private readonly HttpMessageHandler httpHandler;
37

38
        /// <summary>
39
        /// Initializes a new instance of the <see cref="SlackTo"/> class.
40
        /// </summary>
41
        /// <param name="incomingHeaders">Incoming Headers.</param>
42
        /// <param name="handler">Http Message handler for unit test mocking.</param>
43
        public SlackTo(Dictionary<string, string> incomingHeaders, HttpMessageHandler handler = null)
7✔
44
        {
7✔
45
            this.headers = this.ParseHeaders(incomingHeaders);
7✔
46
            this.httpHandler = handler;
7✔
47
        }
7✔
48

49
        /// <summary>
50
        /// Event raised for logging.
51
        /// </summary>
52
        public event EventHandler<Log> OnLog;
53

54
        /// <summary>
55
        /// Parses headers that are valid.
56
        /// </summary>
57
        /// <param name="incomingHeaders">Incoming headers.</param>
58
        /// <returns>Returns a dictionary of valid headers.</returns>
59
        private Dictionary<string, string> ParseHeaders(Dictionary<string, string> incomingHeaders)
60
        {
7✔
61
            Dictionary<string, string> response = new Dictionary<string, string>();
7✔
62
            for (int i = 0; i < this.allowedHeaders.Length; i++)
70✔
63
            {
28✔
64
                if (incomingHeaders.ContainsKey(this.allowedHeaders[i]))
28✔
65
                {
26✔
66
                    response.Add(this.allowedHeaders[i], incomingHeaders[this.allowedHeaders[i]]);
26✔
67
                }
26✔
68
            }
28✔
69

70
            return response;
7✔
71
        }
7✔
72

73
        /// <summary>
74
        /// Processes the message.
75
        /// </summary>
76
        /// <param name="item">Message to process.</param>
77
        public void Process(Routable item)
78
        {
5✔
79
            Payload slackPayload = new Payload()
5✔
80
            {
5✔
81
                text = this.GetMessageSource(item),
5✔
82
                channel = this.GetHeader("Channel"),
5✔
83
                username = this.GetHeader("Username")
5✔
84
            };
5✔
85

86
            if (item.Error == null)
5✔
87
            {
4✔
88
                var payloadJson = JsonSerializer.Serialize(slackPayload);
4✔
89
                string uri = $"{SLACKURI}{this.headers["Target"]}";
4✔
90
                var dataContent = new StringContent(payloadJson, Encoding.UTF8, "application/json");
4✔
91
                using (HttpClient client = this.GetHttpClient())
4✔
92
                {
4✔
93
                    this.OnLog?.Invoke(this, new Log(Microsoft.Extensions.Logging.LogLevel.Information, "Sending slack message"));
4✔
94
                    var response = client.PostAsync(uri, dataContent).Result;
4✔
95
                    if (!response.IsSuccessStatusCode)
4✔
96
                    {
1✔
97
                        item.SetInError(this.RaiseError("SendSlackMessage", "Error communicating with slack."));
1✔
98
                    }
1✔
99
                }
4✔
100
            }
4✔
101
        }
5✔
102

103
        public async Task ProcessAsync(Routable routable, CancellationToken cancellationToken)
104
        {
1✔
105
            Payload slackPayload = new Payload()
1✔
106
            {
1✔
107
                text = this.GetMessageSource(routable),
1✔
108
                channel = this.GetHeader("Channel"),
1✔
109
                username = this.GetHeader("Username")
1✔
110
            };
1✔
111

112
            if (routable.Error == null)
1✔
113
            {
1✔
114
                var payloadJson = JsonSerializer.Serialize(slackPayload);
1✔
115
                string uri = $"{SLACKURI}{this.headers["Target"]}";
1✔
116
                var dataContent = new StringContent(payloadJson, Encoding.UTF8, "application/json");
1✔
117
                using (HttpClient client = this.GetHttpClient())
1✔
118
                {
1✔
119
                    OnLog?.Invoke(this, new Log(Microsoft.Extensions.Logging.LogLevel.Information, "Sending slack message"));
1!
120
                    var response = await client.PostAsync(uri, dataContent, cancellationToken);
1✔
121
                    if (!response.IsSuccessStatusCode)
1!
122
                    {
×
123
                        routable.SetInError(this.RaiseError("SendSlackMessage", "Error communicating with slack."));
×
124
                    }
×
125
                }
1✔
126
            }
1✔
127
        }
1✔
128

129
        /// <summary>
130
        /// Raises an error.
131
        /// </summary>
132
        /// <param name="action">Current action.</param>
133
        /// <param name="message">Error message.</param>
134
        /// <returns>Returns an instance of the <see cref="Error"/> class.</returns>
135
        private Error RaiseError(string action, string message)
136
        {
2✔
137
            return new Error("Slack", action, message);
2✔
138
        }
2✔
139

140
        /// <summary>
141
        /// Gets a HttpClient.
142
        /// </summary>
143
        /// <returns>Returns an instance of the <see cref="HttpClient"/> class.</returns>
144
        private HttpClient GetHttpClient()
145
        {
5✔
146
            HttpClient response;
147
            if (this.httpHandler == null)
5!
148
            {
×
149
                response = new HttpClient();
×
150
            }
×
151
            else
152
            {
5✔
153
                response = new HttpClient(this.httpHandler);
5✔
154
            }
5✔
155

156
            return response;
5✔
157
        }
5✔
158

159
        /// <summary>
160
        /// Gets the message source.
161
        /// </summary>
162
        /// <param name="routable">Message to process.</param>
163
        /// <returns>Returns the message to send via slack.</returns>
164
        private string GetMessageSource(Routable routable)
165
        {
6✔
166
            string response = string.Empty;
6✔
167
            if (this.headers.ContainsKey("MessageSource") && this.headers["MessageSource"].ToLower() == "body")
6!
168
            {
4✔
169
                response = (string)routable.Body;
4✔
170
            }
4✔
171
            else if (routable.Headers.ContainsKey("SlackMessage"))
2✔
172
            {
1✔
173
                response = routable.Headers["SlackMessage"];
1✔
174
            }
1✔
175
            else
176
            {
1✔
177
                routable.SetInError(this.RaiseError("GettingMessageSource", "Error getting message source."));
1✔
178
            }
1✔
179

180

181

182
            return response;
6✔
183
        }
6✔
184

185
        private string GetHeader(string header)
186
        {
12✔
187
            string response = string.Empty;
12✔
188
            if(this.headers.ContainsKey(header))
12✔
189
            {
12✔
190
                response = this.headers[header];
12✔
191
            }
12✔
192

193
            return response;
12✔
194
        }
12✔
195
    }
196
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc