diff --git a/docs/docs/meshcentral/config.md b/docs/docs/meshcentral/config.md index 5e790616..d42287d5 100644 --- a/docs/docs/meshcentral/config.md +++ b/docs/docs/meshcentral/config.md @@ -3419,6 +3419,11 @@ See description for information about each item. "default": false, "description": "Enabled CallMeBot integration support." }, + "slack": { + "type": "boolean", + "default": false, + "description": "Enabled Slack integration support." + }, "pushover": { "type": "object", "description": "Configure Pushover messaging system", diff --git a/docs/docs/messaging/index.md b/docs/docs/messaging/index.md index b462ed6f..40be9b88 100644 --- a/docs/docs/messaging/index.md +++ b/docs/docs/messaging/index.md @@ -231,6 +231,21 @@ You can enable the MeshCentral [Zulip](https://zulip.com/) integration with the } ``` +## Slack setup + +[Slack](https://slack.com/) integration is achieved by the use of Incoming Webhooks. +You can get started by following the Slack guide [here](https://api.slack.com/messaging/webhooks) and getting your URL + +Once you have your incoming webhooks url, You can enable the [Slack](https://slack.com/) integration with the following config.json section + +```json +{ + "messaging": { + "slack": true + } +} +``` + ## User Setup 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. diff --git a/meshcentral-config-schema.json b/meshcentral-config-schema.json index 0b22f9cd..d1d7f70f 100644 --- a/meshcentral-config-schema.json +++ b/meshcentral-config-schema.json @@ -3412,6 +3412,11 @@ "default": false, "description": "Enabled CallMeBot integration support." }, + "slack": { + "type": "boolean", + "default": false, + "description": "Enabled Slack integration support." + }, "pushover": { "type": "object", "description": "Configure Pushover messaging system", diff --git a/meshmessaging.js b/meshmessaging.js index 751814e3..47e1a6b4 100644 --- a/meshmessaging.js +++ b/meshmessaging.js @@ -107,13 +107,20 @@ } } +// For Slack Webhook +{ + "messaging": { + "slack": true + } +} + */ // Construct a messaging server object module.exports.CreateServer = function (parent) { var obj = {}; obj.parent = parent; - obj.providers = 0; // 1 = Telegram, 2 = Signal, 4 = Discord, 8 = XMPP, 16 = CallMeBot, 32 = Pushover, 64 = ntfy, 128 = Zulip + obj.providers = 0; // 1 = Telegram, 2 = Signal, 4 = Discord, 8 = XMPP, 16 = CallMeBot, 32 = Pushover, 64 = ntfy, 128 = Zulip, 256 = Slack obj.telegramClient = null; obj.discordClient = null; obj.discordUrl = null; @@ -122,6 +129,7 @@ module.exports.CreateServer = function (parent) { obj.callMeBotClient = null; obj.pushoverClient = null; obj.zulipClient = null; + obj.slackClient = null; const sortCollator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }) // Telegram client setup @@ -270,6 +278,12 @@ module.exports.CreateServer = function (parent) { obj.providers += 128; // Enable zulip messaging } + // Slack Webhook setup (https://slack.com) + if (parent.config.messaging.slack) { + obj.slackClient = true; + obj.providers += 256; // Enable slack messaging + } + // Send a direct message to a specific userid async function discordSendMsg(userId, message) { const user = await obj.discordClient.users.fetch(userId).catch(function () { return null; }); @@ -350,6 +364,11 @@ module.exports.CreateServer = function (parent) { subject: domain.title ? domain.title : 'MeshCentral' }); if (func != null) { func(true); } + }else if ((to.startsWith('slack:')) && (obj.slackClient != null)) { //slack + const req = require('https').request(new URL(to.substring(6)), { method: 'POST' }, function (res) { if (func != null) { func(true); } }); + req.on('error', function (err) { if (func != null) { func(false); } }); + req.write(JSON.stringify({"text": msg })); + req.end(); } else { // No providers found if (func != null) { func(false, "No messaging providers found for this message."); } diff --git a/meshuser.js b/meshuser.js index 5e82293d..54abdf52 100644 --- a/meshuser.js +++ b/meshuser.js @@ -1,4 +1,4 @@ -/** +/** * @description MeshCentral MeshAgent * @author Ylian Saint-Hilaire & Bryan Roe * @copyright Intel Corporation 2018-2022 @@ -6775,6 +6775,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((command.service == 32) && ((parent.parent.msgserver.providers & 32) != 0)) { handle = 'pushover:' + command.handle; } if ((command.service == 64) && ((parent.parent.msgserver.providers & 64) != 0)) { handle = 'ntfy:' + command.handle; } if ((command.service == 128) && ((parent.parent.msgserver.providers & 128) != 0)) { handle = 'zulip:' + command.handle; } + if ((command.service == 256) && ((parent.parent.msgserver.providers & 256) != 0)) { handle = 'slack:' + command.handle; } if (handle == null) return; // Send a verification message @@ -6921,6 +6922,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((parent.parent.msgserver.providers & 32) != 0) { r.push("Usage: MSG \"pushover:[userkey]\" \"Message\"."); } if ((parent.parent.msgserver.providers & 64) != 0) { r.push("Usage: MSG \"ntfy:[topic]\" \"Message\"."); } if ((parent.parent.msgserver.providers & 128) != 0) { r.push("Usage: MSG \"zulip:[topic]\" \"Message\"."); } + if ((parent.parent.msgserver.providers & 256) != 0) { r.push("Usage: MSG \"slack:[webhook]\" \"Message\"."); } cmdData.result = r.join('\r\n'); } else { parent.parent.msgserver.sendMessage(cmdData.cmdargs['_'][0], cmdData.cmdargs['_'][1], domain, function (status, msg) { diff --git a/views/default.handlebars b/views/default.handlebars index 2bdfc968..fd4b5271 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -12276,6 +12276,7 @@ if ((serverinfo.userMsgProviders & 32) != 0) { y += ''; } if ((serverinfo.userMsgProviders & 64) != 0) { y += ''; } if ((serverinfo.userMsgProviders & 128) != 0) { y += ''; } + if ((serverinfo.userMsgProviders & 256) != 0) { y += ''; } y += ''; x += '
' + "Service" + '' + y; x += '
' + "Handle" + ''; @@ -12285,6 +12286,7 @@ x += ''; console.log(serverinfo.userMsgNftyUrl); x += ''; + x += ''; setDialogMode(2, "Messaging Notifications", 3, account_manageMessagingAdd, x, 'verifyMessaging'); Q('d2handleinput').focus(); account_manageMessagingValidate(); @@ -12296,12 +12298,14 @@ QV('d2callmebotinfo', Q('d2serviceselect').value == 16); QV('d2pushoverinfo', Q('d2serviceselect').value == 32); QV('d2ntfyinfo', Q('d2serviceselect').value == 64); + QV('d2slackinfo', Q('d2serviceselect').value == 256); if (Q('d2serviceselect').value == 4) { Q('d2handleinput')['placeholder'] = "Username:0000"; } else if (Q('d2serviceselect').value == 8) { Q('d2handleinput')['placeholder'] = "username@server.com"; } else if (Q('d2serviceselect').value == 16) { Q('d2handleinput')['placeholder'] = "https://api.callmebot.com/..."; } else if (Q('d2serviceselect').value == 32) { Q('d2handleinput')['placeholder'] = "User key"; } else if (Q('d2serviceselect').value == 64) { Q('d2handleinput')['placeholder'] = "Topic"; } else if (Q('d2serviceselect').value == 128) { Q('d2handleinput')['placeholder'] = "username@sample.com"; } + else if (Q('d2serviceselect').value == 256) { Q('d2handleinput')['placeholder'] = "https://hooks.slack.com/..."; } else { Q('d2handleinput')['placeholder'] = "Username"; } var ok = (Q('d2handleinput').value.length > 0); QE('idx_dlgOkButton', ok); if ((x == 1) && ok) { dialogclose(1); } } @@ -16185,6 +16189,7 @@ if ((serverinfo.userMsgProviders & 32) != 0) { y += ''; } if ((serverinfo.userMsgProviders & 64) != 0) { y += ''; } if ((serverinfo.userMsgProviders & 128) != 0) { y += ''; } + if ((serverinfo.userMsgProviders & 256) != 0) { y += ''; } y += ''; x += '
' + "Service" + '' + y; x += '
' + "Handle" + ''; @@ -16193,6 +16198,7 @@ x += ''; x += ''; x += ''; + x += ''; setDialogMode(2, "Messaging Notifications", 3, p30editMessagingEx, x, 'verifyMessaging'); Q('d2handleinput').focus(); if (currentUser.msghandle) { @@ -16209,6 +16215,7 @@ if (currentUser.msghandle.startsWith('pushover:') && ((serverinfo.userMsgProviders & 32) != 0)) { Q('d2serviceselect').value = 32; Q('d2handleinput').value = currentUser.msghandle.substring(9); } if (currentUser.msghandle.startsWith('ntfy:') && ((serverinfo.userMsgProviders & 64) != 0)) { Q('d2serviceselect').value = 64; Q('d2handleinput').value = currentUser.msghandle.substring(5); } if (currentUser.msghandle.startsWith('zulip:') && ((serverinfo.userMsgProviders & 128) != 0)) { Q('d2serviceselect').value = 128; Q('d2handleinput').value = currentUser.msghandle.substring(6); } + if (currentUser.msghandle.startsWith('slack:') && ((serverinfo.userMsgProviders & 256) != 0)) { Q('d2serviceselect').value = 256; Q('d2handleinput').value = currentUser.msghandle.substring(6); } } p30editMessagingValidate(); } @@ -16219,6 +16226,7 @@ QV('d2callmebotinfo', Q('d2serviceselect').value == 16); QV('d2pushoverinfo', Q('d2serviceselect').value == 32); QV('d2ntfyinfo', Q('d2serviceselect').value == 64); + QV('d2slackinfo', Q('d2serviceselect').value == 256); if (Q('d2serviceselect').value == 0) { Q('d2handleinput')['placeholder'] = ''; } else if (Q('d2serviceselect').value == 4) { Q('d2handleinput')['placeholder'] = "Username:0000"; } else if (Q('d2serviceselect').value == 8) { Q('d2handleinput')['placeholder'] = "username@server.com"; } @@ -16226,6 +16234,7 @@ else if (Q('d2serviceselect').value == 32) { Q('d2handleinput')['placeholder'] = "User key"; } else if (Q('d2serviceselect').value == 64) { Q('d2handleinput')['placeholder'] = "Topic"; } else if (Q('d2serviceselect').value == 128) { Q('d2handleinput')['placeholder'] = "username@sample.com"; } + else if (Q('d2serviceselect').value == 256) { Q('d2handleinput')['placeholder'] = "https://hooks.slack.com/..."; } else { Q('d2handleinput')['placeholder'] = "Username"; } if (x == 1) { dialogclose(1); } } @@ -16241,6 +16250,7 @@ else if (Q('d2serviceselect').value == 32) { handle = 'pushover:' + Q('d2handleinput').value; } else if (Q('d2serviceselect').value == 64) { handle = 'ntfy:' + Q('d2handleinput').value; } else if (Q('d2serviceselect').value == 128) { handle = 'zulip:' + Q('d2handleinput').value; } + else if (Q('d2serviceselect').value == 256) { handle = 'slack:' + Q('d2handleinput').value; } if (handle != null) { meshserver.send({ action: 'edituser', id: currentUser._id, msghandle: handle }); } }