Monthly Archives: January 2012

A node.js bot in XMPP

Yesterday Danbri and I invested a few hours in a rapid node.js prototype for NoTube. We’ll blog about it properly elsewhere, but this is just a little note about a bit of curious behaviour we found, in case anyone runs into the same problem.

Just before christmas Dan made a node.js xmpp bot that could appear in N-Screen and take commands via drag and drop (if you don’t care about this, the point is that it uses node.js with node-xmpp). Dan got it showing up in the N-Screen interface and reflecting back whatever you dropped on it. I thought it would be trivial to hook in one of the item-to-item recommenders I have working via a json http api. Basically to do http GETs in node.js you need something like this:

var http = require('http');

var data_client = http.createClient(80, "nscreen.notu.be");
var request = data_client.request('GET', '/iplayer_dev/api/suggest?pid='+pid', {'host': 'nscreen.notu.be'});
request.end();

request.on('response', function (response) {
response.setEncoding('utf8');
var myStr = "";
response.on('data', function (chunk) {
console.log('BODY: ' + chunk);
myStr += chunk;
});
response.on('end', function (response) {
console.log(myStr);
}
});

Then you can parse myStr e.g.

var j = JSON.parse(myStr);

What we wanted to do was send that myStr as a string content of an xmpp message like this:

var cl = new xmpp.Client({
jid: jid + '/bot',
password: password
});

cl.on('stanza', function(stanza) {
var msg = { to: stanza.attrs.from , type: 'chat' };

... get myStr of recommendations based on that message

cl.send(new xmpp.Element('message', msg ).c('body').t(myStr) );
});

It really should have been simple, but in practice the myStr existed when printed out to console but was never sent. At first we thought it was something to do with Buffers - if you don't do response.setEncoding(...) you get Buffers back and perhaps some stringification of those wasn't working, but no. To add to the confusion we could create Json objects from the string but they still would not send, even if copied to new strings.

In retrospect it's obvious it was the XMPP that was the issue, but it took line by line trial and error sending of some sample input before I found it: & characters in the input were causing silent failure when the message was sent - presumably due to an XML parsing problem that for some reason didn't show up as an error (I know almost nothing about node.js so there could have been some user error there too). Escaping these & didn't seem to work, so for now we've just removed them and it all works fine. We need to raise a bug report, but thought I'd blog for now in case it helps anyone else. The code is here.