With the news that Tropo is shutting down their instant messaging API, we're in a pickle. We're already using IM to get instant notifications of the things that are important to us internally, and we have a bunch of people using it too.
But now what? Well, we do what any self-respecting software engineer does: we build one ourselves!
All we really need is the ability to send out notifications via OSCAR (which is AIM) and Jabber (which covers GTalk among others). That makes it a lot easier to get started, as we won't be worried about that nasty back-and-forth logic that is the hallmark of a bot. Its just one way, out.
Further, we need to be able to interact with it via a simple REST API, that way we can plug it in along side the dozens of other services we natively integrate with. Not that complicated it would see.
I'm used to Python and Django, so my first though was Twisted, a non-blocking server written in Python. As I started to dig around, I noticed that Twisted is no lightweight beast. The XMPP (Jabber) and AIM protocol was there with Twisted Words, but it wasn't the cleanest. It would probably work, but I was fighting it and the learning curve was steep.
So I explored some of the other options like Ruby's EventMachine and Node.js. EventMachine seemed awesome (I'm a bit jealous it isn't a Python project…) but my Ruby chops are horrible. That would have ended in frustration.
Spoiler: those couple hours I set aside to learn Node.js left me with… a finished product. Wow!
First thing was first: install Node. I'm on a Mac, so using brew:
brew install nodejs. As always, brew made that easy. I had known about npm, the pip of the Node world, so I installed that too according to their docs:
curl http://npmjs.org/install.sh | sh. Easy.
Let's try something that I am familiar with: a single endpoint API. Easy, right? So, having heard of the Node web framework express at a talk given by local good fellow James Carr, I installed it globally (assuming that meant system wide):
npm install -g express. Easy again.
I also wanted to use Coffeescript, so using coffee script (which apparently is the new hotness)
npm install -g coffee-script. Easy again. After that a simple command compiles to js:
coffee --watch --compile index.coffee, which you run with node:
Disclaimer: I had used Coffeescript before, so my Node virginity isn't as pure as I've suggested.
Then I just followed the express docs to get something logging to the console (baby steps, right?):
Next, I needed three things to be passed in: to, message, network. So I grabbed those according to the express docs and restarted the server:
At this point, everything just working and I was getting giddy. Desiring to kick it up, I decided it was time to move onto XMPP. I found the excellent node-xmpp package. A quick
npm install node-xmpp and I was golden (well, after a minor detour for
brew install icu4c).
I started by converting an echo bot example from their package to a simplified Coffeescript version:
Again, beside for the usual syntax errors, it worked pretty much first time. It was right about then when I rushed out the door to buy some lottery tickets because I was on fire baby!
High on geek fumes, I plunge into OSCAR and AIM. I find the venerable node-oscar package, do the npm dance and convert the relevant bits from their test.js for an echo bot:
And… I hit my first snag. Wild TypeError appears! But someone posted an issue and fix, so I do the proper thing and fix it in a fork, tag it and
npm uninstall node-oscar and
npm install https://github.com/zapier/node-oscar/tarball/v0.1.3 (npm docs state you can install from a tarball, sick!).
After ensuring all is well, I realized I already had all the relevant functionality built. All I had to to was glue it together, which took another half hour or so. Easy again. Skip to the end for the full snippet, glue and all.
Node.js surprised me. I don't think I've ever had such a good first impression of a language, framework, etc… NPM is slick, Express is well thought out, Coffeescript hides the warts and so far third party libraries were easy and abundant.
Deployment was a breeze too with our Nginx reverse proxy. I'll do a write up later on that process, but needless to say, it was par for the course. Let's hope maintenance is as carefree as development has been.
Color me impressed.