From baaeb7b1161e3220894b8a7f1b1296ffaea9e36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 30 May 2017 22:17:28 +0300 Subject: [PATCH 1/3] Add option to relay bot messages with usernames Added a new option, `muteBridgedUsers` which controls whether to mute bridged users. This option is disabled by default. When enabled, all messages which specify a username and are posted by a bot will be relayed to IRC. --- README.md | 1 + lib/bot.js | 19 +++++++++++++++---- test/bot-events.test.js | 23 +++++++++++++++++++++++ test/bot.test.js | 26 ++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b177a4f..a6eaeae 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ Valid JSON cannot contain comments, so remember to remove them first! // Prevent messages posted by Slackbot (e.g. Slackbot responses) // from being posted into the IRC channel: "muteSlackbot": true, // Off by default + "muteBridgedUsers": false, // On by default // Sends messages to Slack whenever a user joins/leaves an IRC channel: "ircStatusNotices": { "join": false, // Don't send messages about joins diff --git a/lib/bot.js b/lib/bot.js index f5f8276..bdecf03 100644 --- a/lib/bot.js +++ b/lib/bot.js @@ -35,6 +35,7 @@ class Bot { this.commandCharacters = options.commandCharacters || []; this.channels = _.values(options.channelMapping); this.muteSlackbot = options.muteSlackbot || false; + this.muteBridgedUsers = options.muteBridgedUsers || true; this.muteUsers = { slack: [], irc: [], @@ -100,10 +101,13 @@ class Bot { }); this.slack.rtm.on('message', (message) => { - // Ignore bot messages and people leaving/joining - if (message.type === 'message' && - (!message.subtype || ALLOWED_SUBTYPES.indexOf(message.subtype) > -1)) { - this.sendToIRC(message); + // Ignore bot messages and people leaving/joining + if (message.type === 'message') { + if (!message.subtype || ALLOWED_SUBTYPES.indexOf(message.subtype) > -1) { + this.sendToIRC(message); + } else if (message.subtype === 'bot_message' && message.username) { + this.sendToIRC(message); + } } }); @@ -207,6 +211,11 @@ class Bot { return; } + if (this.muteBridgedUsers && message.subtype === 'bot_message') { + logger.debug(`Muted message from a bridged user ${message.username}: ${message.text}`); + return; + } + const channelName = channel.is_channel ? `#${channel.name}` : channel.name; const ircChannel = this.channelMapping[channelName]; @@ -219,6 +228,8 @@ class Bot { this.ircClient.say(ircChannel, prelude); } else if (!message.subtype) { text = `<${user.name}> ${text}`; + } else if (message.subtype === 'bot_message') { + text = `<${message.username}> ${text}`; } else if (message.subtype === 'file_share') { text = `<${user.name}> File uploaded ${message.file.permalink} / ${message.file.permalink_public}`; if (message.file.initial_comment) { diff --git a/test/bot-events.test.js b/test/bot-events.test.js index 6302c26..cf76ae0 100644 --- a/test/bot-events.test.js +++ b/test/bot-events.test.js @@ -107,6 +107,29 @@ describe('Bot Events', function () { this.bot.sendToIRC.should.have.not.have.been.called; }); + it('should not send bot messages without usernames to irc', function () { + const message = { + type: 'message', + subtype: 'bot_message', + text: 'a message from a bot', + bot_id: 'ROBOT' + }; + this.bot.slack.rtm.emit('message', message); + this.bot.sendToIRC.should.have.not.have.been.called; + }); + + it('should send bot messages with usernames to irc', function () { + const message = { + type: 'message', + subtype: 'bot_message', + text: 'a message from a user', + username: 'realuser', + bot_id: 'ROBOT' + }; + this.bot.slack.rtm.emit('message', message); + this.bot.sendToIRC.should.have.have.been.called; + }); + it('should send messages to slack', function () { const channel = '#channel'; const author = 'user'; diff --git a/test/bot.test.js b/test/bot.test.js index 0234d4a..bcec8e4 100644 --- a/test/bot.test.js +++ b/test/bot.test.js @@ -310,6 +310,32 @@ describe('Bot', function () { ClientStub.prototype.say.should.not.have.been.called; }); + it('should not send messages from bots with usernames if bridged user muting is on', function () { + this.bot.muteBridgedUsers = true; + const message = { + type: 'message', + subtype: 'bot_message', + bot_id: 'SOMEBOT', + username: 'someuser', + text: 'hello world!' + }; + this.bot.sendToIRC(message); + ClientStub.prototype.say.should.not.have.been.called; + }); + + it('should send bot messages with usernames to irc', function () { + this.bot.muteBridgedUsers = false; + const message = { + type: 'message', + subtype: 'bot_message', + bot_id: 'SOMEBOT', + username: 'someuser', + text: 'hello world!' + }; + this.bot.sendToIRC(message); + ClientStub.prototype.say.should.have.been.called; + }); + it('should parse text from slack when sending messages', function () { const text = '<@USOMEID> <@USOMEID|readable>'; const message = { From 2c44cb2bf383d42b52a625ec31dc0c3d04ee521f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 31 May 2017 18:54:29 +0300 Subject: [PATCH 2/3] Fix echoing of IRC messages IRC messages are not properly muted. --- lib/bot.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/bot.js b/lib/bot.js index bdecf03..50dc3fe 100644 --- a/lib/bot.js +++ b/lib/bot.js @@ -35,7 +35,7 @@ class Bot { this.commandCharacters = options.commandCharacters || []; this.channels = _.values(options.channelMapping); this.muteSlackbot = options.muteSlackbot || false; - this.muteBridgedUsers = options.muteBridgedUsers || true; + this.muteBridgedUsers = options.muteBridgedUsers; this.muteUsers = { slack: [], irc: [], @@ -206,14 +206,19 @@ class Bot { const user = dataStore.getUserById(message.user); - if (this.muteUsers.slack.indexOf(user.name) !== -1) { + if (user && this.muteUsers.slack.indexOf(user.name) !== -1) { logger.debug(`Muted message from Slack ${user.name}: ${message.text}`); return; } - if (this.muteBridgedUsers && message.subtype === 'bot_message') { - logger.debug(`Muted message from a bridged user ${message.username}: ${message.text}`); - return; + if (message.subtype === 'bot_message') { + if (message.username && message.username.search(/[(]IRC[)]/) !== -1) { + logger.debug(`Muted self-generated message ${message.username}: ${message.text}`); + return; + } else if (this.muteBridgedUsers === true) { + logger.debug(`Muted message from a bridged user ${message.username}: ${message.text} ${this.muteBridgedUsers} ${message.subtype}`); + return; + } } const channelName = channel.is_channel ? `#${channel.name}` : channel.name; From ec34e6bc302c425b93239de9e059cf7c15056804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 23 May 2018 13:19:33 +0300 Subject: [PATCH 3/3] Split large messages If a message to IRC exceeds 510 characters, it is split into multiple messages. --- lib/bot.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/bot.js b/lib/bot.js index 50dc3fe..e5c649b 100644 --- a/lib/bot.js +++ b/lib/bot.js @@ -244,7 +244,12 @@ class Bot { text = `Action: ${user.name} ${text}`; } logger.debug('Sending message to IRC', channelName, text); - this.ircClient.say(ircChannel, text); + + while (text.length > 0) { + const msg = text.substring(0, 510); + text = text.substr(510); + this.ircClient.say(ircChannel, msg); + } } }