add slack webhooks messaging (#5569)

* add slack webhooks messaging Signed-off-by: si458 <simonsmith5521@gmail.com> * remove my test slack incoming webhook Signed-off-by: si458 <simonsmith5521@gmail.com> --------- Signed-off-by: si458 <simonsmith5521@gmail.com>

Simon Smith committed Nov 25, 2023 at 20:45 UTC 5581f3ace8ee324a06d11bb949b023ec27f4d6fb
6 files changed +58 -2
docs/docs/meshcentral/config.md
+5
@@ -3419,6 +3419,11 @@ See description for information about each item.
3419 "default": false,
3420 "description": "Enabled CallMeBot integration support."
3421 },
3422 + "slack": {
3423 + "type": "boolean",
3424 + "default": false,
3425 + "description": "Enabled Slack integration support."
3426 + },
3427 "pushover": {
3428 "type": "object",
3429 "description": "Configure Pushover messaging system",
docs/docs/messaging/index.md
+15
@@ -231,6 +231,21 @@ You can enable the MeshCentral [Zulip](https://zulip.com/) integration with the
231 }
232 ```
233
234 +## Slack setup
235 +
236 +[Slack](https://slack.com/) integration is achieved by the use of Incoming Webhooks.
237 +You can get started by following the Slack guide [here](https://api.slack.com/messaging/webhooks) and getting your URL
238 +
239 +Once you have your incoming webhooks url, You can enable the [Slack](https://slack.com/) integration with the following config.json section
240 +
241 +```json
242 +{
243 + "messaging": {
244 + "slack": true
245 + }
246 +}
247 +```
248 +
249 ## User Setup
250
251 Once one or more messaging systems are setup with MeshCentral, users will be able to register their handle and verify that they own that account by typing in a 6 digit code.
meshcentral-config-schema.json
+5
@@ -3412,6 +3412,11 @@
3412 "default": false,
3413 "description": "Enabled CallMeBot integration support."
3414 },
3415 + "slack": {
3416 + "type": "boolean",
3417 + "default": false,
3418 + "description": "Enabled Slack integration support."
3419 + },
3420 "pushover": {
3421 "type": "object",
3422 "description": "Configure Pushover messaging system",
meshmessaging.js
+20 -1
@@ -107,13 +107,20 @@
107 }
108 }
109
110 +// For Slack Webhook
111 +{
112 + "messaging": {
113 + "slack": true
114 + }
115 +}
116 +
117 */
118
119 // Construct a messaging server object
120 module.exports.CreateServer = function (parent) {
121 var obj = {};
122 obj.parent = parent;
116 - obj.providers = 0; // 1 = Telegram, 2 = Signal, 4 = Discord, 8 = XMPP, 16 = CallMeBot, 32 = Pushover, 64 = ntfy, 128 = Zulip
123 + obj.providers = 0; // 1 = Telegram, 2 = Signal, 4 = Discord, 8 = XMPP, 16 = CallMeBot, 32 = Pushover, 64 = ntfy, 128 = Zulip, 256 = Slack
124 obj.telegramClient = null;
125 obj.discordClient = null;
126 obj.discordUrl = null;
@@ -122,6 +129,7 @@ module.exports.CreateServer = function (parent) {
129 obj.callMeBotClient = null;
130 obj.pushoverClient = null;
131 obj.zulipClient = null;
132 + obj.slackClient = null;
133 const sortCollator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' })
134
135 // Telegram client setup
@@ -270,6 +278,12 @@ module.exports.CreateServer = function (parent) {
278 obj.providers += 128; // Enable zulip messaging
279 }
280
281 + // Slack Webhook setup (https://slack.com)
282 + if (parent.config.messaging.slack) {
283 + obj.slackClient = true;
284 + obj.providers += 256; // Enable slack messaging
285 + }
286 +
287 // Send a direct message to a specific userid
288 async function discordSendMsg(userId, message) {
289 const user = await obj.discordClient.users.fetch(userId).catch(function () { return null; });
@@ -350,6 +364,11 @@ module.exports.CreateServer = function (parent) {
364 subject: domain.title ? domain.title : 'MeshCentral'
365 });
366 if (func != null) { func(true); }
367 + }else if ((to.startsWith('slack:')) && (obj.slackClient != null)) { //slack
368 + const req = require('https').request(new URL(to.substring(6)), { method: 'POST' }, function (res) { if (func != null) { func(true); } });
369 + req.on('error', function (err) { if (func != null) { func(false); } });
370 + req.write(JSON.stringify({"text": msg }));
371 + req.end();
372 } else {
373 // No providers found
374 if (func != null) { func(false, "No messaging providers found for this message."); }
meshuser.js
+3 -1
@@ -1,4 +1,4 @@
1 -/**
1 +/**
2 * @description MeshCentral MeshAgent
3 * @author Ylian Saint-Hilaire & Bryan Roe
4 * @copyright Intel Corporation 2018-2022
@@ -6775,6 +6775,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
6775 if ((command.service == 32) && ((parent.parent.msgserver.providers & 32) != 0)) { handle = 'pushover:' + command.handle; }
6776 if ((command.service == 64) && ((parent.parent.msgserver.providers & 64) != 0)) { handle = 'ntfy:' + command.handle; }
6777 if ((command.service == 128) && ((parent.parent.msgserver.providers & 128) != 0)) { handle = 'zulip:' + command.handle; }
6778 + if ((command.service == 256) && ((parent.parent.msgserver.providers & 256) != 0)) { handle = 'slack:' + command.handle; }
6779 if (handle == null) return;
6780
6781 // Send a verification message
@@ -6921,6 +6922,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
6922 if ((parent.parent.msgserver.providers & 32) != 0) { r.push("Usage: MSG \"pushover:[userkey]\" \"Message\"."); }
6923 if ((parent.parent.msgserver.providers & 64) != 0) { r.push("Usage: MSG \"ntfy:[topic]\" \"Message\"."); }
6924 if ((parent.parent.msgserver.providers & 128) != 0) { r.push("Usage: MSG \"zulip:[topic]\" \"Message\"."); }
6925 + if ((parent.parent.msgserver.providers & 256) != 0) { r.push("Usage: MSG \"slack:[webhook]\" \"Message\"."); }
6926 cmdData.result = r.join('\r\n');
6927 } else {
6928 parent.parent.msgserver.sendMessage(cmdData.cmdargs['_'][0], cmdData.cmdargs['_'][1], domain, function (status, msg) {
views/default.handlebars
+10
@@ -12276,6 +12276,7 @@
12276 if ((serverinfo.userMsgProviders & 32) != 0) { y += '<option value=32>' + "Pushover" + '</option>'; }
12277 if ((serverinfo.userMsgProviders & 64) != 0) { y += '<option value=64>' + "ntfy" + '</option>'; }
12278 if ((serverinfo.userMsgProviders & 128) != 0) { y += '<option value=128>' + "Zulip" + '</option>'; }
12279 + if ((serverinfo.userMsgProviders & 256) != 0) { y += '<option value=256>' + "Slack" + '</option>'; }
12280 y += '</select>';
12281 x += '<table><tr><td>' + "Service" + '<td>' + y;
12282 x += '<tr><td>' + "Handle" + '<td><input maxlength=1024 style=width:160px;margin-left:8px id=d2handleinput onKeyUp=account_manageMessagingValidate() onkeypress="if (event.key==\'Enter\') account_manageMessagingValidate(1)">';
@@ -12285,6 +12286,7 @@
12286 x += '<div id=d2pushoverinfo style=display:none><br /><a href=https://pushover.net/ target="_pushover">' + "Information at Pushover.net" + '</a></div>';
12287 console.log(serverinfo.userMsgNftyUrl);
12288 x += '<div id=d2ntfyinfo style=display:none><br /><a href="' + (serverinfo.userMsgNftyUrl ? serverinfo.userMsgNftyUrl : 'https://ntfy.sh/') + '" target="_ntfy">' + "Free service at ntfy.sh" + '</a></div>';
12289 + x += '<div id=d2slackinfo style=display:none><br /><a href=https://api.slack.com/messaging/webhooks target="_slack">' + "Slack Webhook Setup" + '</a></div>';
12290 setDialogMode(2, "Messaging Notifications", 3, account_manageMessagingAdd, x, 'verifyMessaging');
12291 Q('d2handleinput').focus();
12292 account_manageMessagingValidate();
@@ -12296,12 +12298,14 @@
12298 QV('d2callmebotinfo', Q('d2serviceselect').value == 16);
12299 QV('d2pushoverinfo', Q('d2serviceselect').value == 32);
12300 QV('d2ntfyinfo', Q('d2serviceselect').value == 64);
12301 + QV('d2slackinfo', Q('d2serviceselect').value == 256);
12302 if (Q('d2serviceselect').value == 4) { Q('d2handleinput')['placeholder'] = "Username:0000"; }
12303 else if (Q('d2serviceselect').value == 8) { Q('d2handleinput')['placeholder'] = "username@server.com"; }
12304 else if (Q('d2serviceselect').value == 16) { Q('d2handleinput')['placeholder'] = "https://api.callmebot.com/..."; }
12305 else if (Q('d2serviceselect').value == 32) { Q('d2handleinput')['placeholder'] = "User key"; }
12306 else if (Q('d2serviceselect').value == 64) { Q('d2handleinput')['placeholder'] = "Topic"; }
12307 else if (Q('d2serviceselect').value == 128) { Q('d2handleinput')['placeholder'] = "username@sample.com"; }
12308 + else if (Q('d2serviceselect').value == 256) { Q('d2handleinput')['placeholder'] = "https://hooks.slack.com/..."; }
12309 else { Q('d2handleinput')['placeholder'] = "Username"; }
12310 var ok = (Q('d2handleinput').value.length > 0); QE('idx_dlgOkButton', ok); if ((x == 1) && ok) { dialogclose(1); }
12311 }
@@ -16185,6 +16189,7 @@
16189 if ((serverinfo.userMsgProviders & 32) != 0) { y += '<option value=32>' + "Pushover" + '</option>'; }
16190 if ((serverinfo.userMsgProviders & 64) != 0) { y += '<option value=64>' + "ntfy" + '</option>'; }
16191 if ((serverinfo.userMsgProviders & 128) != 0) { y += '<option value=128>' + "Zulip" + '</option>'; }
16192 + if ((serverinfo.userMsgProviders & 256) != 0) { y += '<option value=256>' + "Slack" + '</option>'; }
16193 y += '</select>';
16194 x += '<table style=margin-top:12px><tr><td>' + "Service" + '<td>' + y;
16195 x += '<tr><td>' + "Handle" + '<td><input maxlength=1024 style=width:160px;margin-left:8px id=d2handleinput onKeyUp=p30editMessagingValidate() onkeypress="if (event.key==\'Enter\') p30editMessagingValidate(1)">';
@@ -16193,6 +16198,7 @@
16198 x += '<div id=d2callmebotinfo style=display:none><br /><a href=https://www.callmebot.com/blog/free-api-signal-send-messages/ target="_callmebot">' + "Signal" + '</a>, <a href=https://www.callmebot.com/blog/free-api-whatsapp-messages/ target="_callmebot">' + "Whatsapp" + '</a>, <a href=https://www.callmebot.com/blog/free-api-facebook-messenger/ target="_callmebot">' + "Facebook" + '</a>, <a href=https://www.callmebot.com/blog/telegram-text-messages/ target="_callmebot">' + "Telegram" + '</a></div>';
16199 x += '<div id=d2pushoverinfo style=display:none><br /><a href=https://pushover.net/ target="_pushover">' + "Information at Pushover.net" + '</a></div>';
16200 x += '<div id=d2ntfyinfo style=display:none><br /><a href="' + (serverinfo.userMsgNftyUrl ? serverinfo.userMsgNftyUrl : 'https://ntfy.sh/') + '" target="_ntfy">' + "Free service at ntfy.sh" + '</a></div>';
16201 + x += '<div id=d2slackinfo style=display:none><br /><a href=https://api.slack.com/messaging/webhooks target="_slack">' + "Slack Webhook Setup" + '</a></div>';
16202 setDialogMode(2, "Messaging Notifications", 3, p30editMessagingEx, x, 'verifyMessaging');
16203 Q('d2handleinput').focus();
16204 if (currentUser.msghandle) {
@@ -16209,6 +16215,7 @@
16215 if (currentUser.msghandle.startsWith('pushover:') && ((serverinfo.userMsgProviders & 32) != 0)) { Q('d2serviceselect').value = 32; Q('d2handleinput').value = currentUser.msghandle.substring(9); }
16216 if (currentUser.msghandle.startsWith('ntfy:') && ((serverinfo.userMsgProviders & 64) != 0)) { Q('d2serviceselect').value = 64; Q('d2handleinput').value = currentUser.msghandle.substring(5); }
16217 if (currentUser.msghandle.startsWith('zulip:') && ((serverinfo.userMsgProviders & 128) != 0)) { Q('d2serviceselect').value = 128; Q('d2handleinput').value = currentUser.msghandle.substring(6); }
16218 + if (currentUser.msghandle.startsWith('slack:') && ((serverinfo.userMsgProviders & 256) != 0)) { Q('d2serviceselect').value = 256; Q('d2handleinput').value = currentUser.msghandle.substring(6); }
16219 }
16220 p30editMessagingValidate();
16221 }
@@ -16219,6 +16226,7 @@
16226 QV('d2callmebotinfo', Q('d2serviceselect').value == 16);
16227 QV('d2pushoverinfo', Q('d2serviceselect').value == 32);
16228 QV('d2ntfyinfo', Q('d2serviceselect').value == 64);
16229 + QV('d2slackinfo', Q('d2serviceselect').value == 256);
16230 if (Q('d2serviceselect').value == 0) { Q('d2handleinput')['placeholder'] = ''; }
16231 else if (Q('d2serviceselect').value == 4) { Q('d2handleinput')['placeholder'] = "Username:0000"; }
16232 else if (Q('d2serviceselect').value == 8) { Q('d2handleinput')['placeholder'] = "username@server.com"; }
@@ -16226,6 +16234,7 @@
16234 else if (Q('d2serviceselect').value == 32) { Q('d2handleinput')['placeholder'] = "User key"; }
16235 else if (Q('d2serviceselect').value == 64) { Q('d2handleinput')['placeholder'] = "Topic"; }
16236 else if (Q('d2serviceselect').value == 128) { Q('d2handleinput')['placeholder'] = "username@sample.com"; }
16237 + else if (Q('d2serviceselect').value == 256) { Q('d2handleinput')['placeholder'] = "https://hooks.slack.com/..."; }
16238 else { Q('d2handleinput')['placeholder'] = "Username"; }
16239 if (x == 1) { dialogclose(1); }
16240 }
@@ -16241,6 +16250,7 @@
16250 else if (Q('d2serviceselect').value == 32) { handle = 'pushover:' + Q('d2handleinput').value; }
16251 else if (Q('d2serviceselect').value == 64) { handle = 'ntfy:' + Q('d2handleinput').value; }
16252 else if (Q('d2serviceselect').value == 128) { handle = 'zulip:' + Q('d2handleinput').value; }
16253 + else if (Q('d2serviceselect').value == 256) { handle = 'slack:' + Q('d2handleinput').value; }
16254 if (handle != null) { meshserver.send({ action: 'edituser', id: currentUser._id, msghandle: handle }); }
16255 }
16256