Browse code

slack: new module, send message to slack channel

Arsen Semenov authored on 30/08/2021 14:09:55 • Daniel-Constantin Mierla committed on 01/09/2021 10:32:54
Showing 8 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,31 @@
1
+#
2
+# Slac client for Kamailio
3
+#
4
+#
5
+# WARNING: do not run this directly, it should be run by the main Makefile
6
+
7
+include ../../Makefile.defs
8
+auto_gen=
9
+NAME=slack.so
10
+
11
+ifeq ($(CROSS_COMPILE),)
12
+CURL_BUILDER=$(shell \
13
+        if pkg-config --exists libcurl; then \
14
+                echo 'pkg-config libcurl'; \
15
+        else \
16
+                which curl-config; \
17
+        fi)
18
+endif
19
+
20
+ifneq ($(CURL_BUILDER),)
21
+        CURLDEFS += $(shell $(CURL_BUILDER) --cflags)
22
+        CURLLIBS += $(shell $(CURL_BUILDER) --libs)
23
+else
24
+        CURLDEFS+=-I$(LOCALBASE)/include -I$(SYSBASE)/include
25
+        CURLLIBS+=-L$(LOCALBASE)/lib -L$(SYSBASE)/lib -lcurl
26
+endif
27
+
28
+DEFS+=$(CURLDEFS)
29
+LIBS=$(CURLLIBS)
30
+
31
+include ../../Makefile.modules
0 32
new file mode 100644
... ...
@@ -0,0 +1,154 @@
1
+Slack Module
2
+
3
+Arsen Semenov
4
+
5
+   <arsperger@gmail.com>
6
+
7
+   Copyright � 2021 arsperger.com
8
+     __________________________________________________________________
9
+
10
+   Table of Contents
11
+
12
+   1. Admin Guide
13
+
14
+        1. Overview
15
+        2. Dependencies
16
+
17
+              2.1. Kamailio Modules
18
+              2.2. External Libraries or Applications
19
+
20
+        3. Parameters
21
+
22
+              3.1. slack url (str)
23
+              3.2. channel (str)
24
+              3.3. username (str)
25
+              3.4. icon_emogi (str)
26
+
27
+        4. Functions
28
+
29
+              4.1. slack_send(format)
30
+
31
+   List of Examples
32
+
33
+   1.1. Set slack webhook URL parameter
34
+   1.2. Set channel parameter
35
+   1.3. Set username parameter
36
+   1.4. Set icon_emogi parameter
37
+   1.5. slack_send usage
38
+
39
+Chapter 1. Admin Guide
40
+
41
+   Table of Contents
42
+
43
+   1. Overview
44
+   2. Dependencies
45
+
46
+        2.1. Kamailio Modules
47
+        2.2. External Libraries or Applications
48
+
49
+   3. Parameters
50
+
51
+        3.1. slack url (str)
52
+        3.2. channel (str)
53
+        3.3. username (str)
54
+        3.4. icon_emogi (str)
55
+
56
+   4. Functions
57
+
58
+        4.1. slack_send(format)
59
+
60
+1. Overview
61
+
62
+   This module provides integration with Slack over webhooks. Slack
63
+   integration (https://api.slack.com/messaging/webhooks)
64
+
65
+   It relays on libcurl. library (https://curl.se/libcurl).
66
+
67
+2. Dependencies
68
+
69
+   2.1. Kamailio Modules
70
+   2.2. External Libraries or Applications
71
+
72
+2.1. Kamailio Modules
73
+
74
+   The following modules must be loaded before this module:
75
+     * none.
76
+
77
+2.2. External Libraries or Applications
78
+
79
+   The following libraries or applications must be installed before
80
+   running Kamailio with this module loaded:
81
+     * libcurl
82
+
83
+3. Parameters
84
+
85
+   3.1. slack url (str)
86
+   3.2. channel (str)
87
+   3.3. username (str)
88
+   3.4. icon_emogi (str)
89
+
90
+3.1. slack url (str)
91
+
92
+   Slack webhook url
93
+
94
+   Default value is not set (empty)
95
+
96
+   Example 1.1. Set slack webhook URL parameter
97
+...
98
+modparam("slack", "slack_url", "https://hooks.slack.com/services/T00000000/B0000
99
+0000/XXXXXXXXXXXXXXXXXXXXXXXX")
100
+...
101
+
102
+3.2. channel (str)
103
+
104
+   Slack channel name
105
+
106
+   Default value is #kamailio
107
+
108
+   Example 1.2. Set channel parameter
109
+...
110
+modparam("slack", "channel", "#kamailio")
111
+...
112
+
113
+3.3. username (str)
114
+
115
+   Specify the username for the published message
116
+
117
+   Default value is webhookbot.
118
+
119
+   Example 1.3. Set username parameter
120
+...
121
+modparam("slack", "username", "webhookbot")
122
+...
123
+
124
+3.4. icon_emogi (str)
125
+
126
+   specify an emoji (using colon shortcodes, eg. :white_check_mark:) to
127
+   use as the profile photo alongside the message.
128
+
129
+   Default value is :ghost:
130
+
131
+   Example 1.4. Set icon_emogi parameter
132
+...
133
+modparam("slack", "icon_emogi", ":ghost:")
134
+...
135
+
136
+4. Functions
137
+
138
+   4.1. slack_send(format)
139
+
140
+4.1.  slack_send(format)
141
+
142
+   Send a formatted message to slack channel.
143
+
144
+   The parameters are:
145
+     * format - The formatted string to be send.
146
+
147
+   The parameters can contain pseudo-variables.
148
+
149
+   This function can be used from ANY_ROUTE.
150
+
151
+   Example 1.5. slack_send usage
152
+...
153
+    slack_send("Hello from Kamailio! caller=$fU;callee=$tU;callid=$ci");
154
+...
0 155
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+docs = slack.xml
2
+
3
+docbook_dir = ../../../../doc/docbook
4
+include $(docbook_dir)/Makefile.module
0 5
new file mode 100644
... ...
@@ -0,0 +1,468 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml">
4
+  <head>
5
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6
+    <title>Slack Module</title>
7
+    <link rel="stylesheet" type="text/css" href="/css/sr-doc.css" />
8
+    <meta name="generator" content="DocBook XSL Stylesheets V1.79.1" />
9
+    <link rel="home" href="#idm1" title="Slack Module" />
10
+    <link rel="next" href="#idm14" title="Chapter 1. Admin Guide" />
11
+  </head>
12
+  <body>
13
+    <div class="book">
14
+      <div class="titlepage">
15
+        <div>
16
+          <div>
17
+            <h1 class="title"><a id="idm1"></a>Slack Module</h1>
18
+          </div>
19
+          <div>
20
+            <div class="authorgroup">
21
+              <div class="author">
22
+                <h3 class="author"><span class="firstname">Arsen</span> <span class="surname">Semenov</span></h3>
23
+                <code class="email">&lt;<a class="email" href="mailto:arsperger@gmail.com">arsperger@gmail.com</a>&gt;</code>
24
+              </div>
25
+            </div>
26
+          </div>
27
+          <div>
28
+            <p class="copyright">Copyright © 2021 arsperger.com</p>
29
+          </div>
30
+        </div>
31
+        <hr />
32
+      </div>
33
+      <div class="toc">
34
+        <p>
35
+          <strong>Table of Contents</strong>
36
+        </p>
37
+        <dl class="toc">
38
+          <dt>
39
+            <span class="chapter">
40
+              <a href="#idm14">1. Admin Guide</a>
41
+            </span>
42
+          </dt>
43
+          <dd>
44
+            <dl>
45
+              <dt>
46
+                <span class="section">
47
+                  <a href="#idm16">1. Overview</a>
48
+                </span>
49
+              </dt>
50
+              <dt>
51
+                <span class="section">
52
+                  <a href="#idm20">2. Dependencies</a>
53
+                </span>
54
+              </dt>
55
+              <dd>
56
+                <dl>
57
+                  <dt>
58
+                    <span class="section">
59
+                      <a href="#idm22">2.1. Kamailio Modules</a>
60
+                    </span>
61
+                  </dt>
62
+                  <dt>
63
+                    <span class="section">
64
+                      <a href="#idm29">2.2. External Libraries or Applications</a>
65
+                    </span>
66
+                  </dt>
67
+                </dl>
68
+              </dd>
69
+              <dt>
70
+                <span class="section">
71
+                  <a href="#idm36">3. Parameters</a>
72
+                </span>
73
+              </dt>
74
+              <dd>
75
+                <dl>
76
+                  <dt>
77
+                    <span class="section">
78
+                      <a href="#slack.p.url">3.1. <code class="varname">slack url</code> (str)</a>
79
+                    </span>
80
+                  </dt>
81
+                  <dt>
82
+                    <span class="section">
83
+                      <a href="#slack.p.channel">3.2. <code class="varname">channel</code> (str)</a>
84
+                    </span>
85
+                  </dt>
86
+                  <dt>
87
+                    <span class="section">
88
+                      <a href="#lwsc.p.username">3.3. <code class="varname">username</code> (str)</a>
89
+                    </span>
90
+                  </dt>
91
+                  <dt>
92
+                    <span class="section">
93
+                      <a href="#slack.p.icon_emogi">3.4. <code class="varname">icon_emogi</code> (str)</a>
94
+                    </span>
95
+                  </dt>
96
+                </dl>
97
+              </dd>
98
+              <dt>
99
+                <span class="section">
100
+                  <a href="#idm78">4. Functions</a>
101
+                </span>
102
+              </dt>
103
+              <dd>
104
+                <dl>
105
+                  <dt>
106
+                    <span class="section">
107
+                      <a href="#slack.f.slack_send">4.1. 
108
+		<code class="function">slack_send(format)</code>
109
+	    </a>
110
+                    </span>
111
+                  </dt>
112
+                </dl>
113
+              </dd>
114
+            </dl>
115
+          </dd>
116
+        </dl>
117
+      </div>
118
+      <div class="list-of-examples">
119
+        <p>
120
+          <strong>List of Examples</strong>
121
+        </p>
122
+        <dl>
123
+          <dt>1.1. <a href="#idm44">Set <code class="varname">slack webhook URL</code> parameter</a></dt>
124
+          <dt>1.2. <a href="#idm54">Set <code class="varname">channel</code> parameter</a></dt>
125
+          <dt>1.3. <a href="#idm64">Set <code class="varname">username</code> parameter</a></dt>
126
+          <dt>1.4. <a href="#idm74">Set <code class="varname">icon_emogi</code> parameter</a></dt>
127
+          <dt>1.5. <a href="#idm90"><code class="function">slack_send</code> usage</a></dt>
128
+        </dl>
129
+      </div>
130
+      <div class="chapter">
131
+        <div class="titlepage">
132
+          <div>
133
+            <div>
134
+              <h1 class="title"><a id="idm14"></a>Chapter 1. Admin Guide</h1>
135
+            </div>
136
+          </div>
137
+        </div>
138
+        <div class="toc">
139
+          <p>
140
+            <strong>Table of Contents</strong>
141
+          </p>
142
+          <dl class="toc">
143
+            <dt>
144
+              <span class="section">
145
+                <a href="#idm16">1. Overview</a>
146
+              </span>
147
+            </dt>
148
+            <dt>
149
+              <span class="section">
150
+                <a href="#idm20">2. Dependencies</a>
151
+              </span>
152
+            </dt>
153
+            <dd>
154
+              <dl>
155
+                <dt>
156
+                  <span class="section">
157
+                    <a href="#idm22">2.1. Kamailio Modules</a>
158
+                  </span>
159
+                </dt>
160
+                <dt>
161
+                  <span class="section">
162
+                    <a href="#idm29">2.2. External Libraries or Applications</a>
163
+                  </span>
164
+                </dt>
165
+              </dl>
166
+            </dd>
167
+            <dt>
168
+              <span class="section">
169
+                <a href="#idm36">3. Parameters</a>
170
+              </span>
171
+            </dt>
172
+            <dd>
173
+              <dl>
174
+                <dt>
175
+                  <span class="section">
176
+                    <a href="#slack.p.url">3.1. <code class="varname">slack url</code> (str)</a>
177
+                  </span>
178
+                </dt>
179
+                <dt>
180
+                  <span class="section">
181
+                    <a href="#slack.p.channel">3.2. <code class="varname">channel</code> (str)</a>
182
+                  </span>
183
+                </dt>
184
+                <dt>
185
+                  <span class="section">
186
+                    <a href="#lwsc.p.username">3.3. <code class="varname">username</code> (str)</a>
187
+                  </span>
188
+                </dt>
189
+                <dt>
190
+                  <span class="section">
191
+                    <a href="#slack.p.icon_emogi">3.4. <code class="varname">icon_emogi</code> (str)</a>
192
+                  </span>
193
+                </dt>
194
+              </dl>
195
+            </dd>
196
+            <dt>
197
+              <span class="section">
198
+                <a href="#idm78">4. Functions</a>
199
+              </span>
200
+            </dt>
201
+            <dd>
202
+              <dl>
203
+                <dt>
204
+                  <span class="section">
205
+                    <a href="#slack.f.slack_send">4.1. 
206
+		<code class="function">slack_send(format)</code>
207
+	    </a>
208
+                  </span>
209
+                </dt>
210
+              </dl>
211
+            </dd>
212
+          </dl>
213
+        </div>
214
+        <div class="section">
215
+          <div class="titlepage">
216
+            <div>
217
+              <div>
218
+                <h2 class="title"><a id="idm16"></a>1. Overview</h2>
219
+              </div>
220
+            </div>
221
+          </div>
222
+          <p>
223
+		This module provides integration with Slack over webhooks.
224
+		Slack integration (https://api.slack.com/messaging/webhooks)
225
+	</p>
226
+          <p>
227
+		It relays on libcurl. library (https://curl.se/libcurl).
228
+	</p>
229
+        </div>
230
+        <div class="section">
231
+          <div class="titlepage">
232
+            <div>
233
+              <div>
234
+                <h2 class="title"><a id="idm20"></a>2. Dependencies</h2>
235
+              </div>
236
+            </div>
237
+          </div>
238
+          <div class="section">
239
+            <div class="titlepage">
240
+              <div>
241
+                <div>
242
+                  <h3 class="title"><a id="idm22"></a>2.1. Kamailio Modules</h3>
243
+                </div>
244
+              </div>
245
+            </div>
246
+            <p>
247
+		The following modules must be loaded before this module:
248
+			</p>
249
+            <div class="itemizedlist">
250
+              <ul class="itemizedlist" type="disc">
251
+                <li class="listitem">
252
+                  <p>
253
+				<span class="emphasis"><em>none</em></span>.
254
+			</p>
255
+                </li>
256
+              </ul>
257
+            </div>
258
+            <p>
259
+		</p>
260
+          </div>
261
+          <div class="section">
262
+            <div class="titlepage">
263
+              <div>
264
+                <div>
265
+                  <h3 class="title"><a id="idm29"></a>2.2. External Libraries or Applications</h3>
266
+                </div>
267
+              </div>
268
+            </div>
269
+            <p>
270
+		The following libraries or applications must be installed before running
271
+		Kamailio with this module loaded:
272
+			</p>
273
+            <div class="itemizedlist">
274
+              <ul class="itemizedlist" type="disc">
275
+                <li class="listitem">
276
+                  <p>
277
+				<span class="emphasis"><em>libcurl</em></span>
278
+			</p>
279
+                </li>
280
+              </ul>
281
+            </div>
282
+            <p>
283
+		</p>
284
+          </div>
285
+        </div>
286
+        <div class="section">
287
+          <div class="titlepage">
288
+            <div>
289
+              <div>
290
+                <h2 class="title"><a id="idm36"></a>3. Parameters</h2>
291
+              </div>
292
+            </div>
293
+          </div>
294
+          <div class="section">
295
+            <div class="titlepage">
296
+              <div>
297
+                <div>
298
+                  <h3 class="title"><a id="slack.p.url"></a>3.1. <code class="varname">slack url</code> (str)</h3>
299
+                </div>
300
+              </div>
301
+            </div>
302
+            <p>
303
+			Slack webhook url
304
+		</p>
305
+            <p>
306
+		<span class="emphasis"><em>
307
+			Default value is not set (empty)
308
+		</em></span>
309
+		</p>
310
+            <div class="example">
311
+              <a id="idm44"></a>
312
+              <p class="title">
313
+                <strong>Example 1.1. Set <code class="varname">slack webhook URL</code> parameter</strong>
314
+              </p>
315
+              <div class="example-contents">
316
+                <pre class="programlisting">...
317
+modparam("slack", "slack_url", "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX")
318
+...</pre>
319
+              </div>
320
+            </div>
321
+            <br class="example-break" />
322
+          </div>
323
+          <div class="section">
324
+            <div class="titlepage">
325
+              <div>
326
+                <div>
327
+                  <h3 class="title"><a id="slack.p.channel"></a>3.2. <code class="varname">channel</code> (str)</h3>
328
+                </div>
329
+              </div>
330
+            </div>
331
+            <p>
332
+			Slack channel name
333
+		</p>
334
+            <p>
335
+		<span class="emphasis"><em>
336
+			Default value is #kamailio
337
+		</em></span>
338
+		</p>
339
+            <div class="example">
340
+              <a id="idm54"></a>
341
+              <p class="title">
342
+                <strong>Example 1.2. Set <code class="varname">channel</code> parameter</strong>
343
+              </p>
344
+              <div class="example-contents">
345
+                <pre class="programlisting">...
346
+modparam("slack", "channel", "#kamailio")
347
+...</pre>
348
+              </div>
349
+            </div>
350
+            <br class="example-break" />
351
+          </div>
352
+          <div class="section">
353
+            <div class="titlepage">
354
+              <div>
355
+                <div>
356
+                  <h3 class="title"><a id="lwsc.p.username"></a>3.3. <code class="varname">username</code> (str)</h3>
357
+                </div>
358
+              </div>
359
+            </div>
360
+            <p>
361
+			Specify the username for the published message
362
+		</p>
363
+            <p>
364
+		<span class="emphasis"><em>
365
+			Default value is webhookbot.
366
+		</em></span>
367
+		</p>
368
+            <div class="example">
369
+              <a id="idm64"></a>
370
+              <p class="title">
371
+                <strong>Example 1.3. Set <code class="varname">username</code> parameter</strong>
372
+              </p>
373
+              <div class="example-contents">
374
+                <pre class="programlisting">...
375
+modparam("slack", "username", "webhookbot")
376
+...</pre>
377
+              </div>
378
+            </div>
379
+            <br class="example-break" />
380
+          </div>
381
+          <div class="section">
382
+            <div class="titlepage">
383
+              <div>
384
+                <div>
385
+                  <h3 class="title"><a id="slack.p.icon_emogi"></a>3.4. <code class="varname">icon_emogi</code> (str)</h3>
386
+                </div>
387
+              </div>
388
+            </div>
389
+            <p>
390
+			specify an emoji (using colon shortcodes, eg. :white_check_mark:)
391
+			to use as the profile photo alongside the message.
392
+		</p>
393
+            <p>
394
+		<span class="emphasis"><em>
395
+			Default value is :ghost:
396
+		</em></span>
397
+		</p>
398
+            <div class="example">
399
+              <a id="idm74"></a>
400
+              <p class="title">
401
+                <strong>Example 1.4. Set <code class="varname">icon_emogi</code> parameter</strong>
402
+              </p>
403
+              <div class="example-contents">
404
+                <pre class="programlisting">...
405
+modparam("slack", "icon_emogi", ":ghost:")
406
+...</pre>
407
+              </div>
408
+            </div>
409
+            <br class="example-break" />
410
+          </div>
411
+        </div>
412
+        <div class="section">
413
+          <div class="titlepage">
414
+            <div>
415
+              <div>
416
+                <h2 class="title"><a id="idm78"></a>4. Functions</h2>
417
+              </div>
418
+            </div>
419
+          </div>
420
+          <div class="section">
421
+            <div class="titlepage">
422
+              <div>
423
+                <div>
424
+                  <h3 class="title"><a id="slack.f.slack_send"></a>4.1. 
425
+		<code class="function">slack_send(format)</code>
426
+	    </h3>
427
+                </div>
428
+              </div>
429
+            </div>
430
+            <p>
431
+		Send a formatted message to slack channel.
432
+		</p>
433
+            <p>
434
+		The parameters are:
435
+		</p>
436
+            <div class="itemizedlist">
437
+              <ul class="itemizedlist" type="disc">
438
+                <li class="listitem">
439
+                  <p>
440
+			format - The formatted string to be send.
441
+			</p>
442
+                </li>
443
+              </ul>
444
+            </div>
445
+            <p>
446
+		The parameters can contain pseudo-variables.
447
+		</p>
448
+            <p>
449
+		This function can be used from ANY_ROUTE.
450
+		</p>
451
+            <div class="example">
452
+              <a id="idm90"></a>
453
+              <p class="title">
454
+                <strong>Example 1.5. <code class="function">slack_send</code> usage</strong>
455
+              </p>
456
+              <div class="example-contents">
457
+                <pre class="programlisting">...
458
+    slack_send("Hello from Kamailio! caller=$fU;callee=$tU;callid=$ci");
459
+...</pre>
460
+              </div>
461
+            </div>
462
+            <br class="example-break" />
463
+          </div>
464
+        </div>
465
+      </div>
466
+    </div>
467
+  </body>
468
+</html>
0 469
new file mode 100644
... ...
@@ -0,0 +1,28 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
3
+	<!-- Include general documentation entities -->
4
+	<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
5
+	%docentities;
6
+]>
7
+
8
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
9
+	<bookinfo>
10
+		<title>Slack Module</title>
11
+		<productname class="trade">&kamailioname;</productname>
12
+		<authorgroup>
13
+			<author>
14
+				<firstname>Arsen</firstname>
15
+				<surname>Semenov</surname>
16
+				<email>arsperger@gmail.com</email>
17
+			</author>
18
+		</authorgroup>
19
+		<copyright>
20
+			<year>2021</year>
21
+			<holder>arsperger.com</holder>
22
+		</copyright>
23
+	</bookinfo>
24
+	<toc></toc>
25
+
26
+	<xi:include href="slack_admin.xml" />
27
+
28
+</book>
0 29
\ No newline at end of file
1 30
new file mode 100644
... ...
@@ -0,0 +1,175 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+<!-- Module User's Guide -->
11
+
12
+<chapter>
13
+
14
+	<title>&adminguide;</title>
15
+
16
+	<section>
17
+	<title>Overview</title>
18
+	<para>
19
+		This module provides integration with Slack over webhooks.
20
+		Slack integration (https://api.slack.com/messaging/webhooks)
21
+	</para>
22
+	<para>
23
+		It relays on libcurl. library (https://curl.se/libcurl).
24
+	</para>
25
+	</section>
26
+
27
+	<section>
28
+	<title>Dependencies</title>
29
+	<section>
30
+		<title>&kamailio; Modules</title>
31
+		<para>
32
+		The following modules must be loaded before this module:
33
+			<itemizedlist>
34
+			<listitem>
35
+			<para>
36
+				<emphasis>none</emphasis>.
37
+			</para>
38
+			</listitem>
39
+			</itemizedlist>
40
+		</para>
41
+	</section>
42
+	<section>
43
+		<title>External Libraries or Applications</title>
44
+		<para>
45
+		The following libraries or applications must be installed before running
46
+		&kamailio; with this module loaded:
47
+			<itemizedlist>
48
+			<listitem>
49
+			<para>
50
+				<emphasis>libcurl</emphasis>
51
+			</para>
52
+			</listitem>
53
+			</itemizedlist>
54
+		</para>
55
+	</section>
56
+	</section>
57
+
58
+	<section>
59
+	<title>Parameters</title>
60
+	<section id="slack.p.url">
61
+		<title><varname>slack url</varname> (str)</title>
62
+		<para>
63
+			Slack webhook url
64
+		</para>
65
+		<para>
66
+		<emphasis>
67
+			Default value is not set (empty)
68
+		</emphasis>
69
+		</para>
70
+		<example>
71
+		<title>Set <varname>slack webhook URL</varname> parameter</title>
72
+		<programlisting format="linespecific">
73
+...
74
+modparam("slack", "slack_url", "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX")
75
+...
76
+		</programlisting>
77
+		</example>
78
+	</section>
79
+	<section id="slack.p.channel">
80
+		<title><varname>channel</varname> (str)</title>
81
+		<para>
82
+			Slack channel name
83
+		</para>
84
+		<para>
85
+		<emphasis>
86
+			Default value is #kamailio
87
+		</emphasis>
88
+		</para>
89
+		<example>
90
+		<title>Set <varname>channel</varname> parameter</title>
91
+		<programlisting format="linespecific">
92
+...
93
+modparam("slack", "channel", "#kamailio")
94
+...
95
+</programlisting>
96
+		</example>
97
+	</section>
98
+	<section id="lwsc.p.username">
99
+		<title><varname>username</varname> (str)</title>
100
+		<para>
101
+			Specify the username for the published message
102
+		</para>
103
+		<para>
104
+		<emphasis>
105
+			Default value is webhookbot.
106
+		</emphasis>
107
+		</para>
108
+		<example>
109
+		<title>Set <varname>username</varname> parameter</title>
110
+		<programlisting format="linespecific">
111
+...
112
+modparam("slack", "username", "webhookbot")
113
+...
114
+</programlisting>
115
+		</example>
116
+	</section>
117
+	<section id="slack.p.icon_emogi">
118
+		<title><varname>icon_emogi</varname> (str)</title>
119
+		<para>
120
+			specify an emoji (using colon shortcodes, eg. :white_check_mark:)
121
+			to use as the profile photo alongside the message.
122
+		</para>
123
+		<para>
124
+		<emphasis>
125
+			Default value is :ghost:
126
+		</emphasis>
127
+		</para>
128
+		<example>
129
+		<title>Set <varname>icon_emogi</varname> parameter</title>
130
+		<programlisting format="linespecific">
131
+...
132
+modparam("slack", "icon_emogi", ":ghost:")
133
+...
134
+</programlisting>
135
+		</example>
136
+	</section>
137
+
138
+	</section>
139
+
140
+	<section>
141
+	<title>Functions</title>
142
+	<section id="slack.f.slack_send">
143
+	    <title>
144
+		<function moreinfo="none">slack_send(format)</function>
145
+	    </title>
146
+	    <para>
147
+		Send a formatted message to slack channel.
148
+		</para>
149
+		<para>
150
+		The parameters are:
151
+		</para>
152
+		<itemizedlist>
153
+			<listitem>
154
+			<para>
155
+			format - The formatted string to be send.
156
+			</para>
157
+			</listitem>
158
+		</itemizedlist>
159
+		<para>
160
+		The parameters can contain pseudo-variables.
161
+		</para>
162
+		<para>
163
+		This function can be used from ANY_ROUTE.
164
+		</para>
165
+		<example>
166
+		<title><function>slack_send</function> usage</title>
167
+		<programlisting format="linespecific">
168
+...
169
+    slack_send("Hello from Kamailio! caller=$fU;callee=$tU;callid=$ci");
170
+...
171
+</programlisting>
172
+	    </example>
173
+	</section>
174
+	</section>
175
+</chapter>
0 176
new file mode 100644
... ...
@@ -0,0 +1,298 @@
1
+/*
2
+ * Copyright (C) 2021 Arsen Semenov arsperger@gmail.com
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * Kamailio is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ * Kamailio is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
+ */
20
+
21
+
22
+#include <stdio.h>
23
+#include <stdlib.h>
24
+
25
+#include "slack.h"
26
+
27
+MODULE_VERSION
28
+
29
+static char *_slmsg_buf = NULL;
30
+static int mod_init(void);
31
+static void mod_destroy(void);
32
+
33
+static int buf_size = 4096;
34
+static char *slack_url = NULL;
35
+static char *slack_channel = SLACK_DEFAULT_CHANNEL;
36
+static char *slack_username = SLACK_DEFAULT_USERNAME;
37
+static char *slack_icon = SLACK_DEFAULT_ICON;
38
+
39
+/**
40
+ * Exported functions
41
+ */
42
+static cmd_export_t cmds[] = {
43
+	{"slack_send",	  		(cmd_function)slack_send1,			1, slack_fixup,  0, ANY_ROUTE},
44
+	{0, 0, 0, 0, 0, 0}
45
+};
46
+
47
+
48
+/**
49
+ * Exported parameters
50
+ */
51
+static param_export_t mod_params[] = {
52
+	{ "slack_url", 			PARAM_STRING|USE_FUNC_PARAM, (void*)_slack_url_param},
53
+	{ "channel",			PARAM_STRING, &slack_channel }, // channel starts with #
54
+	{ "username",			PARAM_STRING, &slack_username },
55
+	{ "icon_emogi",			PARAM_STRING, &slack_icon },
56
+	{0, 0, 0}
57
+};
58
+
59
+/**
60
+ * Module description
61
+ */
62
+struct module_exports exports = {
63
+	"slack",        /* 1 module name */
64
+	DEFAULT_DLFLAGS, /* 2 dlopen flags */
65
+	cmds,            /* 3 exported functions */
66
+	mod_params,      /* 4 exported parameters */
67
+	0,               /* 5 exported RPC functions */
68
+	0,         		 /* 6 exported pseudo-variables */
69
+	0,               /* 7 response function */
70
+	mod_init,        /* 8 module initialization function */
71
+	0,      		 /* 9 per-child init function */
72
+	mod_destroy      /* 0 destroy function */
73
+};
74
+
75
+/**
76
+ * Module init
77
+ */
78
+static int mod_init(void) {
79
+	LM_INFO("slack module init\n");
80
+
81
+	_slmsg_buf = (char*)pkg_malloc((buf_size+1)*sizeof(char));
82
+	if(_slmsg_buf==NULL)
83
+	{
84
+		PKG_MEM_ERROR;
85
+		return -1;
86
+	}
87
+	return(0);
88
+}
89
+
90
+/**
91
+ * Module destroy
92
+ */
93
+static void mod_destroy() {
94
+	LM_INFO("slack module destroy\n");
95
+	if(_slmsg_buf)
96
+		pkg_free(_slmsg_buf);
97
+	if(slack_url)
98
+		pkg_free(slack_url);
99
+	return;
100
+}
101
+
102
+/**
103
+ * send message with curl
104
+ * @return 0 on success, -1 on error
105
+ */
106
+static int _curl_send(const char* uri, str *post_data)
107
+{
108
+	int datasz;
109
+	char* send_data;
110
+	CURL *curl_handle;
111
+	CURLcode res;
112
+	// LM_DBG("sending to[%s]\n", uri);
113
+
114
+	datasz = snprintf(NULL, 0, BODY_FMT, slack_channel, slack_username, post_data->s, slack_icon);
115
+	send_data = (char*)pkg_malloc((datasz+1)*sizeof(char));
116
+	if(send_data==NULL) {
117
+        LM_ERR("Error: can not allocate pkg memory [%d] bytes\n", datasz);
118
+        return -1;
119
+    }
120
+    snprintf(send_data, datasz+1, BODY_FMT, slack_channel, slack_username, post_data->s, slack_icon);
121
+
122
+	curl_global_init(CURL_GLOBAL_ALL);
123
+
124
+	if((curl_handle=curl_easy_init())==NULL) {
125
+    	LM_ERR("Error: Unable to init cURL library\n");
126
+		curl_global_cleanup();
127
+        return -1;
128
+    }
129
+
130
+	curl_easy_setopt(curl_handle, CURLOPT_URL, uri);
131
+	curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, send_data);
132
+	res = curl_easy_perform(curl_handle);
133
+
134
+	if (res != CURLE_OK) {
135
+		LM_ERR("slack request send error: %s\n", curl_easy_strerror(res));
136
+		curl_easy_cleanup(curl_handle);
137
+		curl_global_cleanup();
138
+		if(send_data) {
139
+			pkg_free(send_data);
140
+		}
141
+		return -1;
142
+	}
143
+
144
+	LM_INFO("slack request sent [%d]\n", datasz);
145
+	curl_easy_cleanup(curl_handle);
146
+	curl_global_cleanup();
147
+	if (send_data) {
148
+		pkg_free(send_data);
149
+	}
150
+	return 0;
151
+}
152
+
153
+/**
154
+ * parse slack_url param2
155
+ */
156
+static int _slack_parse_url_param(char *val)
157
+{
158
+	int len;
159
+	len = strlen(val);
160
+	if(len > SLACK_URL_MAX_SIZE) {
161
+		LM_ERR("webhook url max size exceeded %d\n", SLACK_URL_MAX_SIZE);
162
+		return -1;
163
+	}
164
+
165
+	if(strncmp(val, "https://hooks.slack.com", 23)) {
166
+		LM_ERR("slack invalid webhook url [%s]\n", val);
167
+		return -1;
168
+	}
169
+
170
+	// TODO: parse webhook to multiple channels? eg.: chan1=>https://AAA/BBB/CC, chan2=>...
171
+
172
+	slack_url = (char*)pkg_malloc(len + 1);
173
+	if (slack_url==NULL) {
174
+		PKG_MEM_ERROR;
175
+		return -1;
176
+	}
177
+	strcpy(slack_url, val);
178
+	slack_url[len] = '\0';
179
+
180
+	return 0;
181
+}
182
+
183
+/**
184
+ * parse slack_url param
185
+ */
186
+int _slack_url_param(modparam_t type, void *val)
187
+{
188
+	if(val==NULL) {
189
+		LM_ERR("webhook url not specified\n");
190
+		return -1;
191
+	}
192
+
193
+	return _slack_parse_url_param((char*)val);
194
+}
195
+
196
+static int slack_fixup_helper(void** param, int param_no)
197
+{
198
+	sl_msg_t *sm;
199
+	str s;
200
+
201
+	sm = (sl_msg_t*)pkg_malloc(sizeof(sl_msg_t));
202
+	if(sm==NULL)
203
+	{
204
+		PKG_MEM_ERROR;
205
+		return -1;
206
+	}
207
+	memset(sm, 0, sizeof(sl_msg_t));
208
+	s.s = (char*)(*param);
209
+	s.len = strlen(s.s);
210
+
211
+	if(pv_parse_format(&s, &sm->m)<0)
212
+	{
213
+		LM_ERR("wrong format[%s]\n", (char*)(*param));
214
+		pkg_free(sm);
215
+		return E_UNSPEC;
216
+	}
217
+	*param = (void*)sm;
218
+	return 0;
219
+}
220
+
221
+
222
+static int slack_fixup(void** param, int param_no)
223
+{
224
+	if(param_no!=1 || param==NULL || *param==NULL)
225
+	{
226
+		LM_ERR("invalid parameter number %d\n", param_no);
227
+		return E_UNSPEC;
228
+	}
229
+	return slack_fixup_helper(param, param_no);
230
+}
231
+
232
+/**
233
+ * send text message to slack
234
+ */
235
+static inline int slack_helper(struct sip_msg* msg, sl_msg_t *sm)
236
+{
237
+	str txt;
238
+	txt.len = buf_size;
239
+
240
+	if(_slack_print_log(msg, sm->m, _slmsg_buf, &txt.len)<0)
241
+		return -1;
242
+
243
+	txt.s = _slmsg_buf;
244
+
245
+	return _curl_send(slack_url, &txt);
246
+}
247
+
248
+static int slack_send1(struct sip_msg* msg, char* frm, char* str2)
249
+{
250
+	return slack_helper(msg, (sl_msg_t*)frm);
251
+}
252
+
253
+
254
+/**
255
+ * Kemi
256
+ * send slack msg after evaluation of pvars
257
+ * @return 0 on success, -1 on error
258
+ */
259
+static int ki_slack_send(sip_msg_t *msg, str *slmsg)
260
+{
261
+	pv_elem_t *xmodel=NULL;
262
+	str txt = STR_NULL;
263
+	int res;
264
+
265
+	if(pv_parse_format(slmsg, &xmodel)<0) {
266
+		LM_ERR("wrong format[%s]\n", slmsg->s);
267
+		return -1;
268
+	}
269
+	if(pv_printf_s(msg, xmodel, &txt)!=0) {
270
+		LM_ERR("Error: cannot eval reparsed value\n");
271
+		pv_elem_free_all(xmodel);
272
+		return -1;
273
+	}
274
+
275
+	res = _curl_send(slack_url, &txt);
276
+	pv_elem_free_all(xmodel);
277
+	return res;
278
+}
279
+
280
+
281
+/* clang-format off */
282
+static sr_kemi_t sr_kemi_slack_exports[] = {
283
+	{ str_init("slack"), str_init("slack_send"),
284
+		SR_KEMIP_INT, ki_slack_send,
285
+		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
286
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
287
+	},
288
+
289
+	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
290
+};
291
+/* clang-format on */
292
+
293
+
294
+int mod_register(char *path, int *dlflags, void *p1, void *p2)
295
+{
296
+	sr_kemi_modules_add(sr_kemi_slack_exports);
297
+	return 0;
298
+}
0 299
new file mode 100644
... ...
@@ -0,0 +1,58 @@
1
+/*
2
+ * Copyright (C) 2021 Arsen Semenov arsperger@gmail.com
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * Kamailio is free software; you can redistribute it and/or modify
7
+ * it under the tertc of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ * Kamailio is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
+ */
20
+
21
+
22
+#ifndef slack_h
23
+#define slack_h
24
+
25
+#include "../../core/sr_module.h"
26
+#include "../../core/dprint.h"
27
+#include "../../core/parser/parse_content.h"
28
+#include "../../core/pvar.h"
29
+#include "../../core/kemi.h"
30
+
31
+#include <string.h>
32
+#include <curl/curl.h>
33
+
34
+#define BODY_FMT "{\"channel\": \"%s\", \"username\": \"%s\", \"text\": \"%s\", \"icon_emoji\": \"%s\" }"
35
+#define SLACK_URL_MAX_SIZE 128
36
+#define SLACK_DEFAULT_CHANNEL "#webtest"
37
+#define SLACK_DEFAULT_USERNAME "webhookbot"
38
+#define SLACK_DEFAULT_ICON ":ghost:"
39
+
40
+static int _slack_print_log(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
41
+{
42
+	return pv_printf(msg, list, buf, len);
43
+}
44
+
45
+static int _curl_send(const char* uri, str *post_data );
46
+static int _slack_parse_url_param(char *val);
47
+static int _slack_url_param(modparam_t type, void *val);
48
+
49
+static int slack_fixup(void** param, int param_no);
50
+static int slack_send1(struct sip_msg* msg, char* frm, char* str2);
51
+static int slack_fixup_helper(void** param, int param_no);
52
+
53
+typedef struct _sl_msg
54
+{
55
+	pv_elem_t *m;
56
+} sl_msg_t;
57
+
58
+#endif /* slack_h */