Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import logger from 'winston';
import discord from 'discord.js';
import { ConfigurationError } from './errors';
import { validateChannelMapping } from './validators';
import { formatFromDiscordToIRC, formatFromIRCToDiscord } from './formatting';

const REQUIRED_FIELDS = ['server', 'nickname', 'channelMapping', 'discordToken'];
const NICK_COLORS = ['light_blue', 'dark_blue', 'light_red', 'dark_red', 'light_green',
Expand Down Expand Up @@ -173,6 +174,9 @@ class Bot {
this.ircClient.say(ircChannel, text);
} else {
if (text !== '') {
// Convert formatting
text = formatFromDiscordToIRC(text);

text = `<${displayUsername}> ${text}`;
logger.debug('Sending message to IRC', ircChannel, text);
this.ircClient.say(ircChannel, text);
Expand Down Expand Up @@ -203,7 +207,10 @@ class Bot {
return;
}

const withMentions = text.replace(/@[^\s]+\b/g, (match) => {
// Convert text formatting (bold, italics, underscore)
const withFormat = formatFromIRCToDiscord(text);

const withMentions = withFormat.replace(/@[^\s]+\b/g, (match) => {
const search = match.substring(1);
const guild = discordChannel.guild;
const nickUser = guild.members.find('nickname', search);
Expand Down
47 changes: 47 additions & 0 deletions lib/formatting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import ircFormatting from 'irc-formatting';
import SimpleMarkdown from 'simple-markdown';
import colors from 'irc-colors';

function mdNodeToIRC(node) {
let content = node.content;
if (Array.isArray(content)) content = content.map(mdNodeToIRC).join('');
if (node.type === 'em') return colors.italic(content);
if (node.type === 'strong') return colors.bold(content);
if (node.type === 'u') return colors.underline(content);
return content;
}

export function formatFromDiscordToIRC(text) {
const markdownAST = SimpleMarkdown.defaultInlineParse(text);
return markdownAST.map(mdNodeToIRC).join('');
}

export function formatFromIRCToDiscord(text) {
const blocks = ircFormatting.parse(text).map(block => ({
// Consider reverse as italic, some IRC clients use that
...block,
italic: block.italic || block.reverse
}));
let mdText = '';

for (let i = 0; i <= blocks.length; i += 1) {
// Default to unstyled blocks when index out of range
const block = blocks[i] || {};
Comment on lines +27 to +29
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When can blocks[i] ever be undefined?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, i <= blocks.length not i < blocks.length. Sneaky code.

const prevBlock = blocks[i - 1] || {};

// Add start markers when style turns from false to true
if (!prevBlock.italic && block.italic) mdText += '*';
if (!prevBlock.bold && block.bold) mdText += '**';
if (!prevBlock.underline && block.underline) mdText += '__';

// Add end markers when style turns from true to false
// (and apply in reverse order to maintain nesting)
if (prevBlock.underline && !block.underline) mdText += '__';
if (prevBlock.bold && !block.bold) mdText += '**';
if (prevBlock.italic && !block.italic) mdText += '*';

mdText += block.text || '';
}

return mdText;
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@
"commander": "2.9.0",
"discord.js": "11.0.0",
"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",
"winston": "2.3.1"
},
Expand Down
64 changes: 64 additions & 0 deletions test/formatting.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* eslint-disable prefer-arrow-callback */

import chai from 'chai';
import { formatFromDiscordToIRC, formatFromIRCToDiscord } from '../lib/formatting';

chai.should();

describe('Formatting', () => {
describe('Discord to IRC', () => {
it('should convert bold markdown', () => {
formatFromDiscordToIRC('**text**').should.equal('\x02text\x02');
});

it('should convert italic markdown', () => {
formatFromDiscordToIRC('*text*').should.equal('\x16text\x16');
formatFromDiscordToIRC('_text_').should.equal('\x16text\x16');
});

it('should convert underline markdown', () => {
formatFromDiscordToIRC('__text__').should.equal('\x1ftext\x1f');
});

it('should ignore strikethrough markdown', () => {
formatFromDiscordToIRC('~~text~~').should.equal('text');
});

it('should convert nested markdown', () => {
formatFromDiscordToIRC('**bold *italics***')
.should.equal('\x02bold \x16italics\x16\x02');
});
});

describe('IRC to Discord', () => {
it('should convert bold IRC format', () => {
formatFromIRCToDiscord('\x02text\x02').should.equal('**text**');
});

it('should convert reverse IRC format', () => {
formatFromIRCToDiscord('\x16text\x16').should.equal('*text*');
});

it('should convert italic IRC format', () => {
formatFromIRCToDiscord('\x1dtext\x1d').should.equal('*text*');
});

it('should convert underline IRC format', () => {
formatFromIRCToDiscord('\x1ftext\x1f').should.equal('__text__');
});

it('should ignore color IRC format', () => {
formatFromIRCToDiscord('\x0306,08text\x03').should.equal('text');
});

it('should convert nested IRC format', () => {
formatFromIRCToDiscord('\x02bold \x16italics\x16\x02')
.should.equal('**bold *italics***');
});

it('should convert nested IRC format', () => {
formatFromIRCToDiscord('\x02bold \x1funderline\x1f\x02')
.should.equal('**bold __underline__**');
});
});
});