Skip to content
This repository has been archived by the owner on Feb 5, 2020. It is now read-only.

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
malditogeek committed Feb 18, 2015
0 parents commit f927db4
Show file tree
Hide file tree
Showing 10 changed files with 336 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
@@ -0,0 +1,3 @@
*.swp
node_modules
npm-debug.log
57 changes: 57 additions & 0 deletions lib/client.js
@@ -0,0 +1,57 @@
/* jshint unused:true, node:true */
"use strict";

var util = require('util');
var events = require('events');
var carrier = require('carrier');
var ircMessage = require('irc-message');

var pingInterval = 5*1000;

function Client(socket) {
events.EventEmitter.call(this);

this.socket = socket;
this.socket.on('end', this.teardown.bind(this));
this.socket.on('error', this.teardown.bind(this));

this.carry = carrier.carry(socket);
this.carry.on('line', this.parse.bind(this));

this.pingInterval = setInterval(this.ping.bind(this), pingInterval);

this.nick = 'foo';
this.username = 'foo';
this.hostname = 'bar';
}

util.inherits(Client, events.EventEmitter);

Client.prototype.parse = function(line) {
console.log('[received]', line);
var msg = ircMessage.parseMessage(line);
// queue unauthed messages
this.emit.apply(this, [msg.command].concat(msg.params));
}

Client.prototype.mask = function() {
return ':' + this.nick + '!' + this.username + '@' + this.hostname;
},

Client.prototype.ping = function() {
this.emit('PING');
}

Client.prototype.send = function(msg) {
var message = msg.join(' ');
console.log('[sent]', message);
this.socket.write(msg.join(' ') + '\r\n');
}

Client.prototype.teardown = function() {
this.socket.end();
clearInterval(this.pingInterval);
this.emit('disconnected');
}

module.exports = Client;
23 changes: 23 additions & 0 deletions lib/commands.js
@@ -0,0 +1,23 @@
PONG: function(user) {
PING: function(user) {
PASS: function(user, password) {
AWAY: function(user, message) {
VERSION: function(user) {
TIME: function(user) {
NICK: function(user, nick) {
USER: function(user, username, hostname, servername, realname) {
JOIN: function(user, channelNames, key) {
PART: function(user, channelName) {
KICK: function(/*user, channels, users, kickMessage*/) {
TOPIC: function(user, channelName, topic) {
PRIVMSG: function(user, target, message) {
INVITE: function(user, nick, channelName) {
MODE: function(/*user, target, modes, arg*/) {
LIST: function(user, targets) {
NAMES: function(user, targets) {
WHO: function(user, target) {
WHOIS: function(user, nickmask) {
WHOWAS: function(/*user, nicknames, count, serverName*/) {
OPER: function(/*user, name, password*/) {
QUIT: function(user, message) {
MOTD: function(user) {
77 changes: 77 additions & 0 deletions lib/gitter-adapter.js
@@ -0,0 +1,77 @@
/* jshint unused:true, node:true */
"use strict";

var irc = require('./protocol');
var Gitter = require('node-gitter');

// Commands currently supported by IRCd.js

// PONG: function()
// PING: function()
// PASS: function(password)
// AWAY: function(message)
// VERSION: function()
// TIME: function()
// NICK: function(nick)
// USER: function(username, hostname, servername, realname)
// JOIN: function(channelNames, key)
// PART: function(channelName)
// KICK: function(channels, users, kickMessage)
// TOPIC: function(channelName, topic)
// PRIVMSG: function(target, message)
// INVITE: function(nick, channelName)
// MODE: function(target, modes, arg)
// LIST: function(targets)
// NAMES: function(targets)
// WHO: function(target)
// WHOIS: function(nickmask)
// WHOWAS: function(nicknames, count, serverName)
// OPER: function(name, password)
// QUIT: function(message)
// MOTD: function()

var gitterAdapter = function(client) {

var gitter;

client.on('PING', function() {
client.send(['PING', 'gitter.im', ':gitter.im']);
})

client.on('PONG', function() {
});

client.on('NICK', function(nick) {
client.nick = nick;
client.send([client.mask(), 'NICK', ':' + nick]);
})

client.on('USER', function(username, hostname, servername, realname) {
console.log('USER', username, hostname, servername, realname);
})

client.on('PASS', function(password) {
var gitter = new Gitter(password);
});

client.on('JOIN', function(channelNames, key) {
var channels = channelNames.replace('#', '').split(',');

channels.forEach(function(chan) {
gitter.rooms.join(chan)
.then(function(room) {
// TODO notify other users in the channel
//channel.users.forEach(function(channelUser) {
// channelUser.send(user.mask, 'JOIN', channel.name);
//});

client.send('gitter.im', irc.reply.topic, client.nick, chan, ':' + room.topic);
client.send('gitter.im', irc.reply.nameReply, client.nick, channel.type, channel.name, ':' + channelUsers.join(' '));
client.send('gitter.im', irc.reply.endNames, client.nick, channel.name, ':End of /NAMES list.');
})
});
});

}

module.exports = gitterAdapter;
81 changes: 81 additions & 0 deletions lib/protocol.js
@@ -0,0 +1,81 @@
/* jshint unused:true, node:true */
"use strict";

var reply = {
welcome: '001',
yourHost: '002',
created: '003',
myInfo: '004',

away: '301',
unaway: '305',
nowAway: '306',
whoIsUser: '311',
whoIsServer: '312',
whoIsOperator: '313',
whoWasUser: '314',
whoIsIdle: '317',
endOfWhoIs: '318',
whoIsChannels: '319',

topic: '332',
noTopic: '331',
inviting: '341',
nameReply: '353',
endNames: '366',
endWhoWas: '369',

listStart: '321',
list: '322',
listEnd: '323',

version: '351',

motdStart: '375',
motd: '372',
motdEnd: '376',
who: '352',
endWho: '315',
channelModes: '324',
banList: '367',
endBan: '368',

youAreOper: '381',

time: '391'
};

var errors = {
noSuchNick: '401',
noSuchServer: '402',
cannotSend: '404',
wasNoSuchNick: '406',
noRecipient: '411',
noTextToSend: '412',
noNickGiven: '431',
badNick: '432',
nameInUse: '433',
userNotInChannel: '441',
userOnChannel: '443',
noSuchChannel: '403',
notOnChannel: '442',
needMoreParams: '461',
passwordWrong: '464',
youAreBanned: '465',
keySet: '467',
channelIsFull: '471',
inviteOnly: '473',
banned: '474',
badChannelKey: '475',
noPrivileges: '481',
channelOpsReq: '482',
noOperHost: '491',

usersDoNotMatch: '502'
};


module.exports = {
reply: reply,
errors: errors
};
34 changes: 34 additions & 0 deletions lib/server.js
@@ -0,0 +1,34 @@
/* jshint unused:true, node:true */
"use strict";

var net = require('net');
var Client = require('./client');
var gitterAdapter = require('./gitter-adapter');

function Server() {
this.clients = {};
}

Server.prototype.start = function(port) {
var server = net.createServer(this.connectionListener);
server.listen(port);
}

Server.prototype.connectionListener = function(conn) {
try {
var client = new Client(conn);

gitterAdapter(client);

client.on('disconnected', function() {
client.removeAllListeners();
client = null;
});

} catch (err) {
console.log("FATAL:", err, err.stack)
throw err;
}
}

module.exports = Server;
18 changes: 18 additions & 0 deletions package.json
@@ -0,0 +1,18 @@
{
"name": "irc-bridge",
"version": "1.0.0",
"description": "Gitter IRC bridge",
"main": "runner.js",
"scripts": {
"start": "node runner.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "The Gitter Team",
"license": "MIT",
"dependencies": {
"carrier": "^0.1.14",
"eventemitter3": "^0.1.6",
"irc-message": "^2.0.1",
"node-gitter": "^1.2.6"
}
}
12 changes: 12 additions & 0 deletions runner.js
@@ -0,0 +1,12 @@
/* jshint unused:true, node:true */
"use strict";

var Server = require('./lib/server');

var server = new Server();

// TODO: Handle signals
//process.on('SIGHUP', function() {})
//process.on('SIGTERM', function() {})

server.start(process.env.PORT || 6667);
13 changes: 13 additions & 0 deletions test/client_test.js
@@ -0,0 +1,13 @@
var assert = require('assert');
var events = require('events');
var net = require('net');

var Client = require('../lib/client.js');

describe('Client', function(){
it('should be an event emitter', function() {
var mockSocket = new events.EventEmitter();
var client = new Client(mockSocket);
assert(client instanceof events.EventEmitter);
});
});
18 changes: 18 additions & 0 deletions test/server_test.js
@@ -0,0 +1,18 @@
var assert = require('assert')
var net = require('net');

var Server = require('../lib/server.js');

var port = 9876;

describe('Server', function(){
it('should allow incoming connections', function(done) {
var server = new Server;
server.start(port);

var client = net.connect({port: PORT});
client.on('end', done);
client.end();
})
})

0 comments on commit f927db4

Please sign in to comment.