diff --git a/meshcentral.js b/meshcentral.js index 6f220444..20904768 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -4031,6 +4031,7 @@ function mainStart() { if (config.messaging.telegram != null) { modules.push('telegram'); modules.push('input'); } if (config.messaging.discord != null) { if (nodeVersion >= 17) { modules.push('discord.js@14.6.0'); } else { delete config.messaging.discord; addServerWarning('This NodeJS version does not support Discord.js.', 26); } } if (config.messaging.xmpp != null) { modules.push('@xmpp/client'); } + if (config.messaging.pushover != null) { modules.push('node-pushover'); } } // Setup web based push notifications diff --git a/meshmessaging.js b/meshmessaging.js index 88e3ea9c..e3572c42 100644 --- a/meshmessaging.js +++ b/meshmessaging.js @@ -62,19 +62,29 @@ } } +// For Pushover +{ + "messaging": { + "pushover": { + "token": "xxxxxxx" + } + } +} + */ // 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 + obj.providers = 0; // 1 = Telegram, 2 = Signal, 4 = Discord, 8 = XMPP, 16 = CallMeBot, 32 = Pushover obj.telegramClient = null; obj.discordClient = null; obj.discordUrl = null; obj.xmppClient = null; var xmppXml = null; obj.callMeBotClient = null; + obj.pushoverClient = null; // Telegram client setup if (parent.config.messaging.telegram) { @@ -192,6 +202,19 @@ module.exports.CreateServer = function (parent) { obj.providers += 16; // Enable CallMeBot messaging } + // Pushover client setup (https://pushover.net) + if (parent.config.messaging.pushover) { + // Validate Pushover configuration values + var pushoverOK = true; + if (typeof parent.config.messaging.pushover.token != 'string') { console.log('Invalid or missing Pushover token.'); pushoverOK = false; } + + if (pushoverOK) { + // Setup PushOver + obj.pushoverClient = true; + obj.providers += 32; // Enable Pushover 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; }); @@ -221,7 +244,7 @@ module.exports.CreateServer = function (parent) { } // Send an user message - obj.sendMessage = function(to, msg, func) { + obj.sendMessage = function(to, msg, domain, func) { if ((to.startsWith('telegram:')) && (obj.telegramClient != null)) { // Telegram async function sendTelegramMessage(to, msg, func) { if (obj.telegramClient == null) return; @@ -251,6 +274,10 @@ module.exports.CreateServer = function (parent) { var url = 'https://api.callmebot.com/facebook/send.php?apikey=' + encodeURIComponent(toData[1]) + '&text=' + encodeURIComponent(msg); require('https').get(url, function (r) { if (func != null) { func(r.statusCode == 200); } }); } + } else if ((to.startsWith('pushover:')) && (obj.pushoverClient != null)) { // Pushover + const Pushover = require('node-pushover'); + const push = new Pushover({ token: parent.config.messaging.pushover.token, user: to.substring(9) }); + push.send(domain.title ? domain.title : 'MeshCentral', msg, function (err, res) { if (func != null) { func(err == null); } }); } else { // No providers found func(false, "No messaging providers found for this message."); @@ -324,7 +351,7 @@ module.exports.CreateServer = function (parent) { sms = sms.split('[[1]]').join(verificationCode); // Send the message - obj.sendMessage(to, sms, func); + obj.sendMessage(to, sms, domain, func); }; // Send 2FA verification @@ -339,7 +366,7 @@ module.exports.CreateServer = function (parent) { sms = sms.split('[[1]]').join(verificationCode); // Send the message - obj.sendMessage(to, sms, func); + obj.sendMessage(to, sms, domain, func); }; return obj; diff --git a/meshuser.js b/meshuser.js index a4389878..a90cd89e 100644 --- a/meshuser.js +++ b/meshuser.js @@ -6570,7 +6570,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (errMsg != null) { displayNotificationMessage(errMsg); return; } - parent.parent.msgserver.sendMessage(msguser.msghandle, command.msg, function (success, msg) { + parent.parent.msgserver.sendMessage(msguser.msghandle, command.msg, domain, function (success, msg) { if (success) { displayNotificationMessage("Message succesfuly sent.", null, null, null, 32); } else { @@ -6701,6 +6701,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((command.service == 4) && ((parent.parent.msgserver.providers & 4) != 0)) { handle = 'discord:' + command.handle; } if ((command.service == 8) && ((parent.parent.msgserver.providers & 8) != 0)) { handle = 'xmpp:' + command.handle; } if ((command.service == 16) && ((parent.parent.msgserver.providers & 16) != 0)) { handle = parent.parent.msgserver.callmebotUrlToHandle(command.handle); } + if ((command.service == 32) && ((parent.parent.msgserver.providers & 32) != 0)) { handle = 'pushover:' + command.handle; } if (handle == null) return; // Send a verification message @@ -6844,9 +6845,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((parent.parent.msgserver.providers & 2) != 0) { r.push("Usage: MSG \"signal:UserHandle\" \"Message\"."); } if ((parent.parent.msgserver.providers & 4) != 0) { r.push("Usage: MSG \"discord:Username#0000\" \"Message\"."); } if ((parent.parent.msgserver.providers & 8) != 0) { r.push("Usage: MSG \"xmpp:username@server.com\" \"Message\"."); } + if ((parent.parent.msgserver.providers & 32) != 0) { r.push("Usage: MSG \"pushover:userkey\" \"Message\"."); } cmdData.result = r.join('\r\n'); } else { - parent.parent.msgserver.sendMessage(cmdData.cmdargs['_'][0], cmdData.cmdargs['_'][1], function (status, msg) { + parent.parent.msgserver.sendMessage(cmdData.cmdargs['_'][0], cmdData.cmdargs['_'][1], domain, function (status, msg) { if (typeof msg == 'string') { try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? ('Success: ' + msg) : ('Failed: ' + msg), tag: cmdData.command.tag })); } catch (ex) { } } else { diff --git a/package.json b/package.json index 1513ebc2..ead232d3 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "sample-config-advanced.json" ], "dependencies": { + "@yetzt/nedb": "^1.8.0", "archiver": "^5.3.1", "body-parser": "^1.19.0", "cbor": "~5.2.0", @@ -48,8 +49,8 @@ "ipcheck": "^0.1.0", "minimist": "^1.2.5", "multiparty": "^4.2.1", - "@yetzt/nedb": "^1.8.0", "node-forge": "^1.0.0", + "node-pushover": "^1.0.0", "ws": "^5.2.3", "yauzl": "^2.10.0" }, diff --git a/views/default.handlebars b/views/default.handlebars index c37dd625..705aff46 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -11986,6 +11986,7 @@ if ((serverinfo.userMsgProviders & 4) != 0) { y += ''; } if ((serverinfo.userMsgProviders & 8) != 0) { y += ''; } if ((serverinfo.userMsgProviders & 16) != 0) { y += ''; } + if ((serverinfo.userMsgProviders & 32) != 0) { y += ''; } y += ''; x += '
' + "Service" + '' + y; x += '
' + "Handle" + ''; @@ -12004,6 +12005,7 @@ 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 { Q('d2handleinput')['placeholder'] = "Username"; } var ok = (Q('d2handleinput').value.length > 0); QE('idx_dlgOkButton', ok); if ((x == 1) && ok) { dialogclose(1); } } @@ -15867,6 +15869,7 @@ if ((serverinfo.userMsgProviders & 4) != 0) { y += ''; } if ((serverinfo.userMsgProviders & 8) != 0) { y += ''; } if ((serverinfo.userMsgProviders & 16) != 0) { y += ''; } + if ((serverinfo.userMsgProviders & 32) != 0) { y += ''; } y += ''; x += '
' + "Service" + '' + y; x += '
' + "Handle" + ''; @@ -15886,6 +15889,7 @@ if ((toData[0] == 'whatsapp') && (toData.length == 3)) { Q('d2handleinput').value = 'https://api.callmebot.com/whatsapp.php?phone=' + decodeURIComponent(toData[1]) + '&apikey=' + decodeURIComponent(toData[2]); } if ((toData[0] == 'facebook') && (toData.length == 2)) { Q('d2handleinput').value = 'https://api.callmebot.com/facebook/send.php?apikey=' + decodeURIComponent(toData[1]); } } + if (userinfo.msghandle.startsWith('pushover:') && ((serverinfo.userMsgProviders & 32) != 0)) { Q('d2serviceselect').value = 32; Q('d2handleinput').value = userinfo.msghandle.substring(9); } } p30editMessagingValidate(); } @@ -15898,6 +15902,7 @@ else 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 { Q('d2handleinput')['placeholder'] = "Username"; } if (x == 1) { dialogclose(1); } }