One of my favorite features back when I used to use AOL Instant
Messanger was the ability to send messages to any cell phone and
basically get SMS messages for free (back before most people had fancy
“unlimited” plans). Similarly, I really like the equivalent feature in
Gmail that lets me send SMS message directly from my email page with
Google Voice. It’s especially useful since my phone and gmail contacts
are synced.

I decided I’d try to implement this feature for my favorite XMPP server,
ejabberd. There is actually a mod_sms for
version 1.x of ejabberd, but it uses the SMS over SMTP trick that has a
lot of limitations. You need to be able to figure out which carrier each
phone number is on, the received message looks ugly (email headers) and
there isn’t a way for the receiver to reply back to the jabber user.
I’ll be using the Twilio Cloud
Communications Platform, so I don’t have to worry about all that
garbage. Being able to route incoming message is going to be slightly
tricky, but that will be covered in a future post.

Ejabberd and its modules are written in
Erlang,
a language that really puts the FUN in fun-ctional programming. While Erlang has
been gaining popularity due to its powerful message passing and
concurrency features, it isn’t quite popular
enough
to have an officially supported Twilio
library. So, my first step was writing a Twilio API wrapper in Erlang.
Before this week, my experience in Erlang was limited to: debugging
ejabberd, an elevator simulator for a concurrency class in college, and
trying to impress ladies with an elegant implementation of quicksort
(spoiler: this doesn’t work). Also, I bought Joe Armstrong’s excellant
Programming Erlang,
but I’ve only read a few chapters. Erlang has some crazy syntax, but
it’s a syntax that slowly grows on you. I’m not going to try to explain
the language too much, it’s way out of the scope of this post.

Ok, so since my Erlang experience was largely just playing around, I
realized I didn’t know how an idiomatic Erlang API should look. I asked
for some help on reddit’s /r/erlang and got some helpful feedback. In
particular, I struggled with how to represent optional parameters in
Twilio’s REST requests. What I ended up doing is having a generic
twilio:request/3 method that just takes the method (get or post), a
URL, and a list of 2-tuples for GET or POST arguments. Using this
method, I implemented some wrappers around some common Twilio API calls
with the most common arguments used. So if you’re doing basic stuff, use
a convenience method, otherwise just manually list out your URL and
arguments. Not too bad, since my request method takes care of the basic
auth and encoding parameters for you. For example, here is how I
implemented making an outbound call:

Since I can’t simply hardcode my AccountSid into the URL, and since
there’s no need to repeat the “https://api.twilio.com/2010-04-01/”
everytime, I looked in to how to do string formatting in Erlang. Sadly,
string stuff is really awkward in Erlang. User jamiiecb on reddit showed
me a simple trick that uses a list of strings and atoms, looks a little
bit like Python name based string formatting. So instead, I can replace
the above line with this:

ApiUrl=[server,api_version,"/Accounts/",account_sid,"/Calls"],

In order to maintain the state (which is simply your Twilio AccountSid
and AuthToken) I use the “gen_server” behavior. This means that there
is an Erlang process (not to be confused with an operating system
process) that runs and waits to receive commands to send request Twilio
URLs. It’s a little counter intuitive that my Twilio client is a server
to other processes in my script. This was initially inspired by an
Erlang Facebook wrapper, called ErlyFace; but unless I wanted to pass
the credentials in every request, it was going to have to be like that
anyway.

I’m mostly happy with the code in its current state, so I’ll be posting
it to github pretty soon and then subsequently linking it back to this
blog post. The next post I have will be about writing and distributing
ejabberd modules, and translating Jabber messages into an SMS message.