Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SASL support #47

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
52 changes: 51 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ var replies = require('irc-replies');
* Core plugins.
*/

var authenticate = require('./lib/plugins/authenticate');
var away = require('./lib/plugins/away');
var cap = require('./lib/plugins/cap');
var disconnect = require('./lib/plugins/disconnect');
var errors = require('./lib/plugins/errors');
var invite = require('./lib/plugins/invite');
Expand All @@ -27,6 +29,8 @@ var part = require('./lib/plugins/part');
var pong = require('./lib/plugins/pong');
var privmsg = require('./lib/plugins/privmsg');
var quit = require('./lib/plugins/quit');
var rplloggedin = require('./lib/plugins/rplloggedin');
var rplsaslsuccess = require('./lib/plugins/rplsaslsuccess');
var topic = require('./lib/plugins/topic');
var welcome = require('./lib/plugins/welcome');
var whois = require('./lib/plugins/whois');
Expand Down Expand Up @@ -55,7 +59,9 @@ function Client(stream, parser, encoding) {
this.parser.on('message', this.onmessage.bind(this));
stream.pipe(this.parser);
this.setMaxListeners(100);
this.use(authenticate());
this.use(away());
this.use(cap());
this.use(disconnect());
this.use(errors());
this.use(invite());
Expand All @@ -70,6 +76,8 @@ function Client(stream, parser, encoding) {
this.use(pong());
this.use(privmsg());
this.use(quit());
this.use(rplloggedin());
this.use(rplsaslsuccess());
this.use(topic());
this.use(welcome());
this.use(whois());
Expand All @@ -88,11 +96,53 @@ Client.prototype.__proto__ = Emitter.prototype;
* @param {Function} [fn]
* @api public
*/

Client.prototype.write = function(str, fn) {
debug('write %s', str);
this.stream.write(str + '\r\n', fn);
};

/**
* CAP REQ <reqs>
*
* @param {String} reqs
* @api public
*/
Client.prototype.cap_req = function(reqs) {
this.write('CAP REQ :' + reqs);
};

/**
* CAP END
*
* @api public
*/
Client.prototype.cap_end = function() {
this.write('CAP END');
};

/**
* AUTHENTICATE <msg>
*
* @param {String} msg
* @api public
*/
Client.prototype.authenticate = function(msg) {
this.write('AUTHENTICATE ' + msg)
};

/**
* AUTHENTICATE base64(<username>\0<username>\0<password>)
*
* @param {String} username
* @param {String} password
* @api public
*/
Client.prototype.authenticate64 = function(username, password) {
var b = new Buffer(username + "\0" + username + "\0" + password, 'utf8');
var b64 = b.toString('base64');
this.write('AUTHENTICATE ' + b64)
};

/**
* PASS <pass>
*
Expand Down
17 changes: 17 additions & 0 deletions lib/plugins/authenticate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* AUTHENTICATE plugin to emit "authenticate" events.
*
* @return {Function}
* @api public
*/

module.exports = function () {
return function (irc) {
irc.on('data', function (msg) {
if ('AUTHENTICATE' != msg.command) return;
var e = {};
e.message = msg.params;
irc.emit('authenticate', e);
});
}
};
20 changes: 20 additions & 0 deletions lib/plugins/cap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* CAP plugin to emit "cap" events.
*
* @return {Function}
* @api public
*/

module.exports = function () {
return function (irc) {
irc.on('data', function (msg) {
if ('CAP' != msg.command) return;
var params = msg.params.split(' ');
var e = {};
e.nick = params[0];
e.command = params[1];
e.capabilities = msg.trailing.split(' ');
irc.emit('cap', e);
});
}
};
17 changes: 17 additions & 0 deletions lib/plugins/rplloggedin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* RPL_LOGGEDIN plugin to emit "loggedin" events.
*
* @return {Function}
* @api public
*/

module.exports = function () {
return function (irc) {
irc.on('data', function (msg) {
if ('900' != msg.command && 'RPL_LOGGEDIN' != msg.command) return;
var e = {};
e.message = msg.trailing;
irc.emit('loggedin', e);
});
}
};
17 changes: 17 additions & 0 deletions lib/plugins/rplsaslsuccess.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* RPL_SASLSUCCESS plugin to emit "saslsuccess" events.
*
* @return {Function}
* @api public
*/

module.exports = function () {
return function (irc) {
irc.on('data', function (msg) {
if ('903' != msg.command && 'RPL_SASLSUCCESS' != msg.command) return;
var e = {};
e.message = msg.trailing;
irc.emit('saslsuccess', e);
});
}
};
22 changes: 22 additions & 0 deletions test/authenticate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var irc = require('..');
var Stream = require('stream').PassThrough;

describe('authenticate()', function () {
var stream, client;
beforeEach(function () {
stream = new Stream;
stream.setTimeout = function () {
};
client = irc(stream);
});
describe('on AUTHENTICATE', function () {
it('should emit "AUTHENTICATE"', function (done) {
client.on('authenticate', function (e) {
e.message.should.equal('+')
done();
});

stream.write('AUTHENTICATE +\r\n');
});
});
});
12 changes: 9 additions & 3 deletions test/away.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ var irc = require('..');
var Stream = require('stream').PassThrough;

describe('away()', function() {
var stream, client;

beforeEach(function () {
stream = new Stream;
stream.setTimeout = function () {
};
client = irc(stream);
});

describe('on RPL_AWAY', function() {
it('should emit "away"', function(done) {
var stream = new Stream;
var client = irc(stream);

client.on('away', function(e) {
e.nick.should.equal('colinm');
e.message.should.eql('brb food time');
Expand Down
46 changes: 46 additions & 0 deletions test/cap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
var irc = require('..');
var Stream = require('stream').PassThrough;

describe('cap()', function () {
var stream, client;
beforeEach(function () {
stream = new Stream;
stream.setTimeout = function () {
};
client = irc(stream);
});
describe('on CAP', function () {
it('should emit "CAP" and parse ACK with capabilities', function (done) {
client.on('cap', function (e) {
e.nick.should.equal('jilles');
e.command.should.eql('ACK');
e.should.have.property('capabilities').with.lengthOf(1);
e.capabilities[0].should.eql('sasl');
done();
});

stream.write(':jaguar.test CAP jilles ACK :sasl\r\n');
});
it('should emit "CAP" and parse ACK with multiple capabilities', function (done) {
client.on('cap', function (e) {
e.nick.should.equal('jilles');
e.command.should.eql('ACK');
e.should.have.property('capabilities').with.lengthOf(3);
done();
});

stream.write(':jaguar.test CAP jilles ACK :sasl foo bar\r\n');
});
it('should emit "CAP" and parse LS with capabilites', function (done) {
client.on('cap', function (e) {
e.nick.should.eql('*');
e.command.should.eql('LS');
e.should.have.property('capabilities').with.lengthOf(2);
e.capabilities.should.containDeep(['multi-prefix', 'sasl']);
done();
});

stream.write(':jaguar.test CAP * LS :multi-prefix sasl\r\n');
});
});
});
12 changes: 9 additions & 3 deletions test/invite.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ var irc = require('..');
var Stream = require('stream').PassThrough;

describe('invite()', function() {
var stream, client;

beforeEach(function () {
stream = new Stream;
stream.setTimeout = function () {
};
client = irc(stream);
});

describe('on INVITE', function() {
it('should emit "invite"', function(done) {
var stream = new Stream;
var client = irc(stream);

client.on('invite', function(e) {
e.from.should.equal('test');
e.to.should.equal('astranger');
Expand Down
12 changes: 9 additions & 3 deletions test/join.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ var irc = require('..');
var Stream = require('stream').PassThrough;

describe('join()', function() {
var stream, client;

beforeEach(function () {
stream = new Stream;
stream.setTimeout = function () {
};
client = irc(stream);
});

describe('on JOIN', function() {
it('should emit "join"', function(done) {
var stream = new Stream;
var client = irc(stream);

client.on('join', function(e) {
e.nick.should.equal('tjholowaychuk');
e.channel.should.equal('#express');
Expand Down
12 changes: 9 additions & 3 deletions test/kick.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ var irc = require('..');
var Stream = require('stream').PassThrough;

describe('kick()', function() {
var stream, client;

beforeEach(function () {
stream = new Stream;
stream.setTimeout = function () {
};
client = irc(stream);
});

describe('on KICK', function() {
it('should emit "kick"', function(done) {
var stream = new Stream;
var client = irc(stream);

client.on('kick', function(e) {
e.nick.should.equal('tjholowaychuk');
e.client.should.equal('tobi');
Expand Down
18 changes: 9 additions & 9 deletions test/names.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ var irc = require('..');
var Stream = require('stream').PassThrough;

describe('names()', function() {
var stream, client;

beforeEach(function () {
stream = new Stream;
stream.setTimeout = function () {
};
client = irc(stream);
});

describe('client.names(chan, fn)', function() {
it('should respond with user names', function(done) {
var stream = new Stream;
var client = irc(stream);

client.names('#luna-lang', function(err, names) {
if (err) return done(err);
names.should.eql([
Expand All @@ -30,9 +36,6 @@ describe('names()', function() {
});

it('should emit "names"', function(done) {
var stream = new Stream;
var client = irc(stream);

client.on('names', function(e) {
e.channel.should.equal('#luna-lang');
e.names.should.eql([
Expand All @@ -53,9 +56,6 @@ describe('names()', function() {
});

it('should retain ~ / @ / % / +', function(done) {
var stream = new Stream;
var client = irc(stream);

client.on('names', function(e) {
e.channel.should.equal('##luna-lang');
e.names.should.eql([
Expand Down
13 changes: 9 additions & 4 deletions test/nick.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ var irc = require('..');
var Stream = require('stream').PassThrough;

describe('nick()', function() {
describe('on NICK', function() {
var stream, client;

it('should emit "nick"', function(done) {
var stream = new Stream;
var client = irc(stream);
beforeEach(function () {
stream = new Stream;
stream.setTimeout = function () {
};
client = irc(stream);
});

describe('on NICK', function() {
it('should emit "nick"', function(done) {
client.on('nick', function(e) {
e.nick.should.eql('colinm');
e.new.should.equal('cmilhench');
Expand Down
Loading