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);
        }
    });
});



Classical and ES5 JavaScript inheritance

The inheritance and OOP concept is in JavaScript really hard to learn because there is not any standards for that like in Java or PHP. There is no structure like class, the keyword is in strict mode reserved keyword but no implementation or use. In JavaScript there are functions and using prototype to implement some of the OOP conception. That is why I made small example how to use the JavaScript objects in classical and ES5 way. This is not the complete example of OO.

Classical example and using the NEW keyword:

(function(document) {
'use strict';

  var Shape = function() { };
  
  Shape.prototype = {
    x: 30,
    y: 30,
    width: 25,
    height: 25,
    
    draw: function(ctx) {
      throw new Error("This is parent method");
    },
    
    print: function() {
      console.log(this.x + ':' + this.y + ' ' + this.width + '<>' + this.height);
    }
  };
  
  var Circle = function() { this.radius = 20; };
  Circle.prototype = new Shape();
  Circle.prototype.draw = function(ctx) {
    ctx.arc(12, 22, 66, 0, 2 * Math.PI, false);
  };
  
  var Square = function() { };
  Square.prototype = new Shape();
  Square.prototype.draw = function(ctx) {
    ctx.fillRect(this.x, this.y, this.width, this.height);
  };  
    
  var canvas = document.getElementById('panel');
  if (canvas.getContext) {
    var ctx = canvas.getContext('2d');
    var perfectCircle = new Circle();
    var mySquare = new Square();
    
    mySquare.draw(ctx);
    mySquare.print();
    
    perfectCircle.draw(ctx);
    perfectCircle.print();
    
  }
  
})(document);

ES5 example:

(function(document, console) {
'use strict';

  var Shape = Object.create({
    x: 30,
    y: 30,
    width: 25,
    height: 25,
    
    draw: function(ctx) {
      throw new Error("This is parent method");
    },
    
    print: function() {
      console.log(this.x + ':' + this.y + ' ' + this.width + '<>' + this.height);
    }
  });

 
  var Circle = Object.create(Shape);
  Circle.radius = 10;
  Circle.draw = function(ctx) {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
    ctx.stroke();
  };
  
  var Square = Object.create(Shape);
  Square.draw = function(ctx) {
    ctx.fillRect(this.x, this.y, this.width, this.height);
  };  
  
  // Drawing to canvas
  var canvas = document.getElementById('panel');
  if (canvas.getContext) {
    var ctx = canvas.getContext('2d');
    var perfectCircle = Object.create(Circle);
    var mySquare = Object.create(Square);
    
    mySquare.draw(ctx);
    mySquare.print();
    
    perfectCircle.draw(ctx);
    perfectCircle.print();
    
  }
  
})(document, console);

Also the html to get the example working:

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Inheritance example</title>
</head>
<body>
  <canvas id="panel" width="150" height="150">Canvas not supported get better browser</canvas>
</body>
</html>

Result image should be something like this(well only the shapes not gradient):

jQuery too slow ?

jQuery is great JavaScript library, only that in time the core code has changed too heavy and most of the functionality is not used. Also jQuery has great support for cross browser functions, which need additional checks and boilerplate. This all slows down performance and may not be suitable for the mobiles.

What could be alternatives is to use some of the lightweight versions of jQuery like zepto.js, snack.js etc. Well even if these libraries seems to be too heavy, the last thing is to use JavaScript without any library or create your own layer top of the functions you need.

I did some of the performance test with jQuery, Zepto.js and using pure JavaScript DOM. All of the tests are done with , which runs the testing code in loop and counts the operations per second. ALl the benchmark tests are pushed to Github.

Example code of the JSlitmus test:

/*
 * Simple DOM object creation without adding to html.
 */
JSLitmus.test('DOM element creation', function() {
  document.createElement('div');
});


As you can see the winner of benchmark is JavaScript DOM API, also if the development is clearly mobile platform you should take advantage from lighter libraries.

Some of the Javascript DOM methods

Even if the JQuery or any other Javascript library dominates the DOM manipulation, there is old Javascript DOM API which is used by the libraries.

For debug or to test out the methods use the, browser consoles where you can execute the code.

Selecting elements, selector methods. DOM methods can be accessed under the document object.

First method allows to select all the elements by tag name, I have not seen many cases where it’s used.

document.getElementsByTagName('tag name')

Second selecting by name, is very useful when you have to do validation for forms.

document.getElementsByName('content')

There is list of other selectors which can be used to select by Id and class name.

// Get by ID
document.getElementById('wp_fs_link')</code>

// By class names
document.getElementsByClassName('mceButton')

Another set of methods are querySelector finds only one element and querySelectorAll find all the matching elements. Only problem is the compatibility with older browsers of IE(5,6,7), FF(2.0,3.0) and some Opera versions, you can look the overall table .
These methods are special because you can use the CSS selectors. Most of the JQuery element selections are based on querySelector.

document.querySelector('a + img')</code>

document.querySelectorAll('ul &gt; li')

document.querySelectorAll('li[class="menupop"]')

More and more the web sites get dynamic(AJAX) and you need to create the DOM on the fly. Also the code blocks are heavier and contains more then just one element. So it is cleaner to use some html template library like JQuery templates, Mustache, Handlebars and others. But for one element DOM appending use the createElement method.

var p = document.createElement('p');
p.innerHTML = 'This is <em>the</em> content';</code>

// Add the element into heading elemnt
document.getElementsByTagName('h2')[0].appendChild(p)

Each call to methods innerHTML, appendChild or any methods which changes DOM structures are slow when you are making the massive changes, so be aware of that!

Same example in JQuery

// JQuery
$('h2:first').append($('<p>', { text: 'This is the content' }));

As an last example we create typical form and change the border color to red if the text box is empty, demo is.

Well I can not put HTML code because it is not escaped, but the Javascript one is here:

var form = document.forms['check-username']
, username = form['username']
, button = form['check'];</code>

button.onclick = function(e) {
var len = username.value.length;
username.style.border = (len &lt;= 0) ? 'solid 2px red' : '';
}

As you can see lot of the Javascript’s official DOM methods are really long to type, so make sure your IDE/text editor has good auto complete feature. Besides the verbose of method names it is good to use these methods when you need performance without the bells and whistles which comes with libraries.

Expressive way to handle errors in expressjs

When you have created new express project, the errors get handled a bit differently in dev mode and in production mode. In development mode the errors are show in express error template with some error stack if showStack is set to true. But in production mode you will be shown as less as you need the ‘Internal Server Error’ on plain text page. Here is our plan to make the production side errors more fancier and keep the development side informative.

First take of the production mode default error handling.

app.configure('production', function(){
  //app.use(express.errorHandler()); 
});

Add app.error which will be run on if error is caught. I have already created views for errors which needs some customization on jade template.

app.error(function(err, req, res, next){
  if (err instanceof NotFound) {
    res.render('error/404.jade', { title: 'Not found 404' });
  } else {
    res.render('error/500.jade', { title: 'Error', error: err });
  }
});

And in the end of app.js, added the /* router which routes all the unknown pages to 404 page by throwing NotFound errror. So by going to url like this localhost:3000/path/that/does/not/exist does not lead you to the some GET that route does not exist, but into 404 page.

// The 404
app.get('/*', function(req, res){
    throw new NotFound;
});

function NotFound(msg){
    this.name = 'NotFound';
    Error.call(this, msg);
    Error.captureStackTrace(this, arguments.callee);
}

Running now the server in production mode NODE_ENV=production node app.js, should give on visiting unknown page this:

And on the 500 error which are thrown when user tries to go in /add/post page without permission:

This is one way to handle the errors in expressjs, if you know any better methods feel free to post. The code is also added into github.

Creating simple blog with Node.js: flash messages

One way to give user feedback is to use the flash messages, after certain action you display information. Example user deletes the post and is redirected to main page, now display the information if all were successful or not.

To make use of the flash messages you need to add the cookieParser

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.logger());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser());
  app.use(express.session({ secret: 'wasdsafeAD' }));
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

This is the way to add information to flash messages, you can acces the object by req.flash().

if (!err) {
  req.flash('info', 'Post has been sucessfully edited');
}

To use it in all the view so I would not have to pass the flash object into every render function, is to register helper.

app.dynamicHelpers({
...
  flash: function(req, res) {
    return req.flash();
  }
});

Also i have added into layout.jade before header partial !=partial(‘alert’, flash) and in view partial is the message look.

mixin showAlert(alerts)
    for alert in alerts
      div #{alert}

- if (flash.info)
  div.alert.alert-info
    mixin showAlert(flash.info)

- if (flash.success)
  div.alert.alert-success
    mixin showAlert(flash.success)

- if (flash.error)
  div.alert.alert-error
    mixin showAlert(flash.error)

Select box and other choice

Sometimes there is need for dynamical forms where in select box you got the other choice which needs to trigger out the textbox. Only the problem is that this would create new POST field with different name and this needs more checks and ifs on the server side.

Here is one simple way to solve this, when user picks from list ‘other’ we show additional textbox but in the same time change the form names also so if the other is chosen then the value from textbox is posted and the select box uses temporary name suffixed ‘-input’. Added the jsfiddle address for demo http://jsfiddle.net/staar2/Hsq3j/

(function() {
    var name = 'Grizly'
      , $select = $('select[name="' + name + '"]')
      , nameAttr = $select.attr('name');
    
    $select.change(function(e) {
        if ($(this).val() === 'Other') {
            $select.attr('name', nameAttr + '-input');
            $select.after($('<input>', {
                'type': 'text',
                'name': nameAttr
            }));            
        } else {
            $('select[name="' + name + '-input"]')
                .attr('name', name);
            $('input[name="' + name + '"]').remove();
        }         
    });        
})();​
<form action="" method="post">
    
<select name="Grizly">
    <option>First</option>
    <option>Second</option>
    <option>Third</option>
    <option>Fourth</option>
    <option>Other</option>
</select>
<input type="submit" name="send" value="Send" />
</form>
​