discord-irc
Advanced tools
Comparing version 2.2.1 to 2.3.0
# Changelog | ||
This project adheres to [Semantic Versioning](http://semver.org/). | ||
## [2.3.0] - 2017-04-03 | ||
A huge thank you to [Throne3d](https://github.com/Throne3d), | ||
[rahatarmanahmed](https://github.com/rahatarmanahmed) and | ||
[Ratismal](https://github.com/Ratismal) for all the fixes and features | ||
in this release. | ||
### Added | ||
* Bridge IRC join/part/quit messages to Discord | ||
(enable by setting ircStatusNotices to true) - | ||
[#207](https://github.com/reactiflux/discord-irc/pull/207). | ||
* Convert text styles between IRC and Discord | ||
[#205](https://github.com/reactiflux/discord-irc/pull/205). | ||
* Allow users to configure the patterns of messages on | ||
IRC and Discord using the format options object | ||
[#204](https://github.com/reactiflux/discord-irc/pull/204). | ||
* Add Discord channel ID matching to the channel mapping | ||
[#202](https://github.com/reactiflux/discord-irc/pull/202). | ||
### Fixed | ||
* Parse role mentions appropariately, as with channel and user mentions | ||
[#203](https://github.com/reactiflux/discord-irc/pull/203). | ||
* Make the bot not crash when a channel mentioned by ID fails to exist | ||
[#201](https://github.com/reactiflux/discord-irc/pull/201). | ||
### Changed | ||
* Convert username mentions even if nickname is set - | ||
[#208](https://github.com/reactiflux/discord-irc/pull/208). | ||
## [2.2.1] - 2017-03-12 | ||
@@ -5,0 +37,0 @@ ### Fixed |
156
dist/bot.js
@@ -29,2 +29,4 @@ 'use strict'; | ||
var _formatting = require('./formatting'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -34,2 +36,3 @@ | ||
const NICK_COLORS = ['light_blue', 'dark_blue', 'light_red', 'dark_red', 'light_green', 'dark_green', 'magenta', 'light_magenta', 'orange', 'yellow', 'cyan', 'light_cyan']; | ||
const patternMatch = /{\$(.+?)}/g; | ||
@@ -59,3 +62,25 @@ /** | ||
this.channels = _lodash2.default.values(options.channelMapping); | ||
this.ircStatusNotices = options.ircStatusNotices; | ||
this.announceSelfJoin = options.announceSelfJoin; | ||
this.format = options.format || {}; | ||
// "{$keyName}" => "variableValue" | ||
// nickname: discord nickname | ||
// displayUsername: nickname with wrapped colors | ||
// text: the (IRC-formatted) message content | ||
// discordChannel: Discord channel (e.g. #general) | ||
// ircChannel: IRC channel (e.g. #irc) | ||
// attachmentURL: the URL of the attachment (only applicable in formatURLAttachment) | ||
this.formatCommandPrelude = this.format.commandPrelude || 'Command sent from Discord by {$nickname}:'; | ||
this.formatIRCText = this.format.ircText || '<{$displayUsername}> {$text}'; | ||
this.formatURLAttachment = this.format.urlAttachment || '<{$displayUsername}> {$attachmentURL}'; | ||
// "{$keyName}" => "variableValue" | ||
// author: IRC nickname | ||
// text: the (Discord-formatted) message content | ||
// withMentions: text with appropriate mentions reformatted | ||
// discordChannel: Discord channel (e.g. #general) | ||
// ircChannel: IRC channel (e.g. #irc) | ||
this.formatDiscord = this.format.discord || '**<{$author}>** {$withMentions}'; | ||
this.channelMapping = {}; | ||
@@ -125,2 +150,20 @@ | ||
this.ircClient.on('join', (channel, nick) => { | ||
if (!this.ircStatusNotices) return; | ||
if (nick === this.nickname && !this.announceSelfJoin) return; | ||
this.sendExactToDiscord(channel, `*${nick}* has joined the channel`); | ||
}); | ||
this.ircClient.on('part', (channel, nick, reason) => { | ||
if (!this.ircStatusNotices || nick === this.nickname) return; | ||
this.sendExactToDiscord(channel, `*${nick}* has left the channel (${reason})`); | ||
}); | ||
this.ircClient.on('quit', (nick, reason, channels) => { | ||
if (!this.ircStatusNotices || nick === this.nickname) return; | ||
channels.forEach(channel => { | ||
this.sendExactToDiscord(channel, `*${nick}* has quit (${reason})`); | ||
}); | ||
}); | ||
this.ircClient.on('action', (author, to, text) => { | ||
@@ -163,3 +206,8 @@ this.sendToDiscord(author, to, `_${text}_`); | ||
const channel = this.discord.channels.get(channelId); | ||
return `#${channel.name}`; | ||
if (channel) return `#${channel.name}`; | ||
return '#deleted-channel'; | ||
}).replace(/<@&(\d+)>/g, (match, roleId) => { | ||
const role = message.guild.roles.get(roleId); | ||
if (role) return `@${role.name}`; | ||
return '@deleted-role'; | ||
}).replace(/<(:\w+:)\d+>/g, (match, emoteName) => emoteName); | ||
@@ -172,2 +220,6 @@ } | ||
static substitutePattern(message, patternMapping) { | ||
return message.replace(patternMatch, (match, varName) => patternMapping[varName] || match); | ||
} | ||
sendToIRC(message) { | ||
@@ -179,3 +231,3 @@ const author = message.author; | ||
const channelName = `#${message.channel.name}`; | ||
const ircChannel = this.channelMapping[channelName]; | ||
const ircChannel = this.channelMapping[message.channel.id] || this.channelMapping[channelName]; | ||
@@ -193,4 +245,12 @@ _winston2.default.debug('Channel Mapping', channelName, this.channelMapping[channelName]); | ||
const patternMap = { | ||
nickname, | ||
displayUsername, | ||
text, | ||
discordChannel: channelName, | ||
ircChannel | ||
}; | ||
if (this.isCommandMessage(text)) { | ||
const prelude = `Command sent from Discord by ${nickname}:`; | ||
const prelude = Bot.substitutePattern(this.formatCommandPrelude, patternMap); | ||
this.ircClient.say(ircChannel, prelude); | ||
@@ -200,3 +260,7 @@ this.ircClient.say(ircChannel, text); | ||
if (text !== '') { | ||
text = `<${displayUsername}> ${text}`; | ||
// Convert formatting | ||
text = (0, _formatting.formatFromDiscordToIRC)(text); | ||
patternMap.text = text; | ||
text = Bot.substitutePattern(this.formatIRCText, patternMap); | ||
_winston2.default.debug('Sending message to IRC', ircChannel, text); | ||
@@ -208,3 +272,5 @@ this.ircClient.say(ircChannel, text); | ||
message.attachments.forEach(a => { | ||
const urlMessage = `<${displayUsername}> ${a.url}`; | ||
patternMap.attachmentURL = a.url; | ||
const urlMessage = Bot.substitutePattern(this.formatURLAttachment, patternMap); | ||
_winston2.default.debug('Sending attachment URL to IRC', ircChannel, urlMessage); | ||
@@ -218,40 +284,70 @@ this.ircClient.say(ircChannel, urlMessage); | ||
sendToDiscord(author, channel, text) { | ||
const discordChannelName = this.invertedMapping[channel.toLowerCase()]; | ||
findDiscordChannel(ircChannel) { | ||
const discordChannelName = this.invertedMapping[ircChannel.toLowerCase()]; | ||
if (discordChannelName) { | ||
// #channel -> channel before retrieving and select only text channels: | ||
const discordChannel = this.discord.channels.filter(c => c.type === 'text').find('name', discordChannelName.slice(1)); | ||
const discordChannel = discordChannelName.startsWith('#') ? this.discord.channels.filter(c => c.type === 'text').find('name', discordChannelName.slice(1)) : this.discord.channels.get(discordChannelName); | ||
if (!discordChannel) { | ||
_winston2.default.info('Tried to send a message to a channel the bot isn\'t in: ', discordChannelName); | ||
return; | ||
return null; | ||
} | ||
return discordChannel; | ||
} | ||
return null; | ||
} | ||
const withMentions = text.replace(/@[^\s]+\b/g, match => { | ||
const search = match.substring(1); | ||
const guild = discordChannel.guild; | ||
const nickUser = guild.members.find('nickname', search); | ||
if (nickUser) { | ||
return nickUser; | ||
} | ||
sendToDiscord(author, channel, text) { | ||
const discordChannel = this.findDiscordChannel(channel); | ||
if (!discordChannel) return; | ||
const user = this.discord.users.find('username', search); | ||
if (user) { | ||
const nickname = guild.members.get(user.id).nickname; | ||
if (!nickname || nickname === search) { | ||
return user; | ||
} | ||
} | ||
// Convert text formatting (bold, italics, underscore) | ||
const withFormat = (0, _formatting.formatFromIRCToDiscord)(text); | ||
return match; | ||
}); | ||
const withMentions = withFormat.replace(/@[^\s]+\b/g, match => { | ||
const search = match.substring(1); | ||
const guild = discordChannel.guild; | ||
const nickUser = guild.members.find('nickname', search); | ||
if (nickUser) { | ||
return nickUser; | ||
} | ||
// Add bold formatting: | ||
const withAuthor = `**<${author}>** ${withMentions}`; | ||
_winston2.default.debug('Sending message to Discord', withAuthor, channel, '->', discordChannelName); | ||
discordChannel.sendMessage(withAuthor); | ||
} | ||
const user = this.discord.users.find('username', search); | ||
if (user) { | ||
return user; | ||
} | ||
const role = guild.roles.find('name', search); | ||
if (role && role.mentionable) { | ||
return role; | ||
} | ||
return match; | ||
}); | ||
const patternMap = { | ||
author, | ||
text: withFormat, | ||
withMentions, | ||
discordChannel: `#${discordChannel.name}`, | ||
ircChannel: channel | ||
}; | ||
// Add bold formatting: | ||
// Use custom formatting from config / default formatting with bold author | ||
const withAuthor = Bot.substitutePattern(this.formatDiscord, patternMap); | ||
_winston2.default.debug('Sending message to Discord', withAuthor, channel, '->', `#${discordChannel.name}`); | ||
discordChannel.sendMessage(withAuthor); | ||
} | ||
/* Sends a message to Discord exactly as it appears */ | ||
sendExactToDiscord(channel, text) { | ||
const discordChannel = this.findDiscordChannel(channel); | ||
if (!discordChannel) return; | ||
_winston2.default.debug('Sending special message to Discord', text, channel, '->', `#${discordChannel.name}`); | ||
discordChannel.sendMessage(text); | ||
} | ||
} | ||
exports.default = Bot; |
{ | ||
"name": "discord-irc", | ||
"version": "2.2.1", | ||
"version": "2.3.0", | ||
"description": "Connects IRC and Discord channels by sending messages back and forth.", | ||
@@ -43,3 +43,6 @@ "keywords": [ | ||
"irc": "0.5.2", | ||
"irc-colors": "^1.3.2", | ||
"irc-formatting": "^1.0.0-rc3", | ||
"lodash": "^4.17.4", | ||
"simple-markdown": "^0.2.1", | ||
"strip-json-comments": "2.0.1", | ||
@@ -61,5 +64,5 @@ "winston": "2.3.1" | ||
"nyc": "^10.0.0", | ||
"sinon": "^1.17.6", | ||
"sinon": "^2.0.0", | ||
"sinon-chai": "^2.8.0" | ||
} | ||
} |
@@ -76,3 +76,4 @@ # discord-irc [](https://travis-ci.org/reactiflux/discord-irc) [](https://coveralls.io/github/reactiflux/discord-irc?branch=master) | ||
// with one of these characters (commands): | ||
"commandCharacters": ["!", "."] | ||
"commandCharacters": ["!", "."], | ||
"ircStatusNotices": true // Enables notifications in Discord when people join/part in the relevant IRC channel | ||
} | ||
@@ -79,0 +80,0 @@ ] |
135514
16
442
97
10
+ Addedirc-colors@^1.3.2
+ Addedirc-formatting@^1.0.0-rc3
+ Addedsimple-markdown@^0.2.1
+ Addedirc-formatting@1.0.0-rc3(transitive)
+ Addednegative-zero@1.0.0(transitive)
+ Addedsimple-markdown@0.2.2(transitive)
+ Addedzeropad@1.1.0(transitive)