الاثنين، 12 أغسطس 2013

writing SMS Gateway Apps with clickatell ruby scripts


Update: After contacting the guys from Clickatell they sorted out my billing issues and were friendly enough to throw in some free credits. Very nice of them, thanks guys!

I’m always a big fan of interfacing with as many possible data inputs and outputs when i’m working on projects. So much so, that sometimes I do a project purely to plan with novel ways to interact with people. After being introduces to the CEO of Clickatell, a international messaging company that runs a very nifty SMS (Text Message) API, I figured I’d better build something with it.
Two interesting problems came up almost simultaneously that I attacked with a little text messaging scripts in both cases – server monitoring and, well, roommate monitoring!
As one of the development members on 2draw.net, an online art community started by Marcello Bastae-Forte, I’ve been dealing with keeping the server alive and running. Since we’re a team of only 4 at the moment, there is the distinct possibility that the server can go down, and without adequate monitoring utilities, none of us will realize this for a significant amount of time. Thus, what could be better than a text message crying for help if something goes wrong! In the same gist, I would like to remind my roommates (and myself) to go take out the trash and run the dishwasher according to our very intricate schedule we posted on the fridge. Thus, I registered a Clickatell account to start playing with text gateways.
Clickatell gave me a great initial impression. Their website is clean and informative, and their API is great to use. Once you’ve registered, you request an application ID and corresponding secret ID. Using these numbers for authentication you can send batch message jobs easily and securely. Most attractive to my problem at hand was their, as I call it, “one request, one message” API call. With one HTTP POST I can send all the necessary information to get a text message sent to multiple phone numbers. This allowed me to write a total of 12 lines of Ruby to wrap their API in a simple Ruby object.
Unfortunately, I hit quite a snag in trying to procure some text message credits from them. For some strange reason, I kept getting a message saying “Required Field” next to the State form field on their billing page. I did, quite naturally, fill out the form multiple times and made sure to fill out every field I could find, but to no avail. Their customer service response was prompt, but unfortunately did not help to solve my problem. Being slightly confused about how to continue using their service, I shopped around to see what else is out there. (I did manage to fix this issue, so keep reading!) I gave Ez TextingUpsideWireless and CellTrust a try to compare. Unfortunately, each of these services has caveats that, if I had some credit on Clickatell, I would not have bothered to register. Since I did not, I pressed on and gave them all a try.
Ez Texting is, as their name suggests, super easy. Register, and you get 10 messages to use. They have the cheapest rates going (over half the price of Clickatell – $12 for 500 credits versus $12 for 200 credits on Clickatell), and their site indicates this strongly with a design that doesn’t exactly spell professional. I was here for the API, though, and it was a big disappointment when I was notified that I needed special permission to use the API, and to please send an email to their customer support group. Seriously, I don’t want to waste the time waiting for them. I did send them an email though, but have yet to hear back. They do have the same feature as Clickatell to send a text message with a single HTTP call, but since they do not support HTTPS your password will be floating along the lines in cleartext. Need I say more about security. Their messages also contain “Subject: ” and “Message: ” parts that you cannot get rid of, which looks stupid and annoyed me to no end. As an easy to use, online text center, they work well though.
UpsideWireless and CellTrust both looked like strong competitors to Clickatell, and probably are in the business world. Neither catered to the hackers out there, though, and to buy credit or get access to the API you had to get quotes from their sales department and access rights to their APIs. (I’m generalizing now, and each has their own process, but lets get to the code shall we?)
By now, 2 days later, I hoped that whatever bug was in Clickatell’s billing script would be sorted out by now. Alas, it wasn’t, but in filling out all my details on both the Administrative and Billing profile sections, and filling out their billing page that forms part of the buying process, I made it to the checkout screen. I was taken aback that they required a phone call to verify my credit card (for a total of $13), but they called within 10 minutes after filling out the form, so I did not complain too loudly! With such a prompt response, I applaud them for taking the security measures.
Once I had my credits and my ruby code, I could finally start doing some cool stuff.
To wrap the Clickatell API, I put together a Notify object and, with some Monkey-patching to the URI class, I was all set:
<br />require 'net/http'<br />require 'uri'<br />require 'cgi'<br /><br />#Slight modification to the URI class:<br />class URI::Generic<br /> #appends more data to the current query.<br /> def append_query(param, arg)<br /> if self.query<br /> self.query += "&#{param.to_s}=#{arg.to_s}"<br /> else<br /> self.query = "#{param.to_s}=#{arg.to_s}"<br /> end<br /> return self<br /> end<br />end<br /> <br />class Notifier<br />public<br /> #Takes a YAML object that contains the <br /> #hashes "phones" and "emails" to notify people<br /> def initialize(yaml_conf)<br /> @yaml_conf = yaml_conf<br /> end<br /> <br /> #see https://www.clickatell.com/downloads/http/Clickatell_HTTP.pdf<br /> def clickatell_text(message, phonenrs)<br /> if (message == false)<br /> message = "_hmm, nothing's up. _is the script buggy?"<br /> end<br /> url = URI.parse(@yaml_conf["clickatell"]["send_uri"].to_s)<br /> url.append_query("api_id", CGI::escape(@yaml_conf["clickatell"]["api_id"].to_s))<br /> url.append_query("user", CGI::escape(@yaml_conf["clickatell"]["user"].to_s))<br /> url.append_query("password", CGI::escape(@yaml_conf["clickatell"]["password"].to_s))<br /> nrs = ""<br /> phonenrs.each do |value| <br /> nrs += value.to_s + "," <br /> end<br /> nrs[-1] = ''<br /> url.append_query("to", CGI::escape(nrs.to_s))<br /> url.append_query("text", CGI::escape(message))<br /> response = Net::HTTP.get_response(url)<br /> puts " code = #{response.code}"<br /> puts " message = #{response.message}"<br /> puts " response = #{response.body}"<br /> return (response.code.to_i == 200 && response.body.to_s.include?("id: "))<br /> end<br />end<br />
I tend to use YAML to store my config files, which is exactly what I did in this case. My config.yml file looked something like this:

<br />clickatell:<br />&nbsp&nbsp user: user<br />&nbsp&nbsp password: pass<br />&nbsp&nbsp api_id: appid<br />&nbsp&nbsp send_uri: http://api.clickatell.com/http/sendmsg?<br /> <br />phones:<br />&nbsp&nbsp person1: 19999999999<br />&nbsp&nbsp person2: 19999999999<br />
The script to remind my roommates and I of our daily duties was a simple couple of lines on top of this:
<br />require 'notifier.rb'<br />require 'yaml'<br /><br />$LOAD_PATH.unshift(File.dirname(__FILE__)) <br />CHECKERCONF_FILE = "dutiesconf.yml"<br /><br />yaml_conf = YAML.load_file("#{File.dirname(__FILE__)}/#{CHECKERCONF_FILE}")<br />notify = Notifier.new(yaml_conf)<br />message = "Yo " + yaml_conf["people"][Time.now.wday].to_s + "! Letting you know that House Duties is yours today. Aiight peace! -KitchenBot"<br /><br />notify.clickatell_text(message, [yaml_conf["phones"][Time.now.wday]]).to_s<br />
I added a “people” and “phones” field, and indexed both of these by the day of the week, thus sending personalized text messages to whoever is the lucky person that day. A simple cron job entry on my little home server, and I was all set for a blissfully clean kitchen. (I’ll have to let you guys know how that works out though…)
Overall, Clickatell is easy to use once you have it set up, their response time if fast, and their service works great. Once their initial process of buying credits is more streamlined, they will undoubtedly be the top choice for anyone wanting to do some text message hacking. I haven’t yet tried using their 2-way text messaging, but if this is as easy to use as their one-way API, I’m sold.