IRC bot with Node.js

The old IRC protocol remains still pretty active as it is main communication for people who does not like to use Facebook. I have used IRC chat for long time and there are plenty of helpful people for discussing about programming.

Main thing is that you can connect to irc server by opening TCP connection and simply sending the commands. Lets give example with telnet, to connect you only need to:

  • telnet irc.freenode.net 6667
  • NICK username
  • USER username 8 * : Full Name
  • JOIN #node.js

As a result these command should bring you to node.js channel and you should see all the text stream. To send message to channel PRIVMSG #node.js :Test message, before sending message you have to specify who(user) or what channel receives the message. Another important thing is to follow the PING messages sent by server. If the user does not replay to the PING with PONG, user gets timeout and is disconnected from server.


All this can be really simply implemented in Node.js, the evented programming comes helpful when dealing with network. Here comes small example of IRC bot, which sends the user uptime if command @uptime is written to channel.

var net = require('net')
  , util = require('util')
  , exec = require('child_process').exec;

var options = {
    PORT: 6667
  , HOST: 'irc.freenode.net'
  , NICK: 'Miska'
  , CHANNELS: [ '#node.js', '#javascript', '#randomChan' ]
  , USER: {
        ALLOWED: [ 'risto_' ]
  }
};

var command = [
    { match: /^PING/, emit: 'pong' }
  , { match: '@uptime', emit: 'uptime' }
];

var socket = net.connect(options.PORT, options.HOST, function() {
    console.log('Connection up to irc server');
});

socket.setEncoding('ascii');
socket.setNoDelay();

socket.on('connect', function() {

    setTimeout(function() {
        socket.write(util.format('NICK %s\n', options.NICK));
        socket.write(util.format('USER %s 8 *: %s\n', options.NICK, 'Full Name'));
        socket.write(util.format('JOIN %s\n', options.CHANNELS.join(','))); 
    }, 10000);
});

socket.on('timeout', function() {
    console.log('TIMEOUT for connection');
    console.log('Total of bytes written: ' + socket.bytesWritten);
});

/**
 * Custom command for bot send the uptime
 */
socket.on('uptime', function() {
    var child = exec('uptime', function(err, stdout, stderr) {
        if (err) throw err;
        else {
            options.CHANNELS.forEach(function(elem) {
                var response = util.format('PRIVMSG %s :%s\n', elem, stdout);
                console.log(response);
                socket.write(response);
            });
        }
    });
});

socket.on('pong', function() {
    console.log('PONG message back');
    socket.write('PONG\n');
});

socket.on('data', function(data) {
    var cleanedData = data.toString().trim();
    console.log(cleanedData);

    command.forEach(function(command) {
        if (cleanedData.match(command.match)) {
            socket.emit(command.emit);
        }
    });
});



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s